Current File : /home/mmdealscpanel/yummmdeals.com/dns.tar
message.py000064400000124171150351404270006551 0ustar00# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS Messages"""

from __future__ import absolute_import

from io import StringIO
import struct
import time

import dns.edns
import dns.exception
import dns.flags
import dns.name
import dns.opcode
import dns.entropy
import dns.rcode
import dns.rdata
import dns.rdataclass
import dns.rdatatype
import dns.rrset
import dns.renderer
import dns.tsig
import dns.wiredata

from ._compat import long, xrange, string_types


class ShortHeader(dns.exception.FormError):

    """The DNS packet passed to from_wire() is too short."""


class TrailingJunk(dns.exception.FormError):

    """The DNS packet passed to from_wire() has extra junk at the end of it."""


class UnknownHeaderField(dns.exception.DNSException):

    """The header field name was not recognized when converting from text
    into a message."""


class BadEDNS(dns.exception.FormError):

    """OPT record occurred somewhere other than the start of
    the additional data section."""


class BadTSIG(dns.exception.FormError):

    """A TSIG record occurred somewhere other than the end of
    the additional data section."""


class UnknownTSIGKey(dns.exception.DNSException):

    """A TSIG with an unknown key was received."""


class Message(object):

    """A DNS message.

    @ivar id: The query id; the default is a randomly chosen id.
    @type id: int
    @ivar flags: The DNS flags of the message.  @see: RFC 1035 for an
    explanation of these flags.
    @type flags: int
    @ivar question: The question section.
    @type question: list of dns.rrset.RRset objects
    @ivar answer: The answer section.
    @type answer: list of dns.rrset.RRset objects
    @ivar authority: The authority section.
    @type authority: list of dns.rrset.RRset objects
    @ivar additional: The additional data section.
    @type additional: list of dns.rrset.RRset objects
    @ivar edns: The EDNS level to use.  The default is -1, no Edns.
    @type edns: int
    @ivar ednsflags: The EDNS flags
    @type ednsflags: long
    @ivar payload: The EDNS payload size.  The default is 0.
    @type payload: int
    @ivar options: The EDNS options
    @type options: list of dns.edns.Option objects
    @ivar request_payload: The associated request's EDNS payload size.
    @type request_payload: int
    @ivar keyring: The TSIG keyring to use.  The default is None.
    @type keyring: dict
    @ivar keyname: The TSIG keyname to use.  The default is None.
    @type keyname: dns.name.Name object
    @ivar keyalgorithm: The TSIG algorithm to use; defaults to
    dns.tsig.default_algorithm.  Constants for TSIG algorithms are defined
    in dns.tsig, and the currently implemented algorithms are
    HMAC_MD5, HMAC_SHA1, HMAC_SHA224, HMAC_SHA256, HMAC_SHA384, and
    HMAC_SHA512.
    @type keyalgorithm: string
    @ivar request_mac: The TSIG MAC of the request message associated with
    this message; used when validating TSIG signatures.   @see: RFC 2845 for
    more information on TSIG fields.
    @type request_mac: string
    @ivar fudge: TSIG time fudge; default is 300 seconds.
    @type fudge: int
    @ivar original_id: TSIG original id; defaults to the message's id
    @type original_id: int
    @ivar tsig_error: TSIG error code; default is 0.
    @type tsig_error: int
    @ivar other_data: TSIG other data.
    @type other_data: string
    @ivar mac: The TSIG MAC for this message.
    @type mac: string
    @ivar xfr: Is the message being used to contain the results of a DNS
    zone transfer?  The default is False.
    @type xfr: bool
    @ivar origin: The origin of the zone in messages which are used for
    zone transfers or for DNS dynamic updates.  The default is None.
    @type origin: dns.name.Name object
    @ivar tsig_ctx: The TSIG signature context associated with this
    message.  The default is None.
    @type tsig_ctx: hmac.HMAC object
    @ivar had_tsig: Did the message decoded from wire format have a TSIG
    signature?
    @type had_tsig: bool
    @ivar multi: Is this message part of a multi-message sequence?  The
    default is false.  This variable is used when validating TSIG signatures
    on messages which are part of a zone transfer.
    @type multi: bool
    @ivar first: Is this message standalone, or the first of a multi
    message sequence?  This variable is used when validating TSIG signatures
    on messages which are part of a zone transfer.
    @type first: bool
    @ivar index: An index of rrsets in the message.  The index key is
    (section, name, rdclass, rdtype, covers, deleting).  Indexing can be
    disabled by setting the index to None.
    @type index: dict
    """

    def __init__(self, id=None):
        if id is None:
            self.id = dns.entropy.random_16()
        else:
            self.id = id
        self.flags = 0
        self.question = []
        self.answer = []
        self.authority = []
        self.additional = []
        self.edns = -1
        self.ednsflags = 0
        self.payload = 0
        self.options = []
        self.request_payload = 0
        self.keyring = None
        self.keyname = None
        self.keyalgorithm = dns.tsig.default_algorithm
        self.request_mac = ''
        self.other_data = ''
        self.tsig_error = 0
        self.fudge = 300
        self.original_id = self.id
        self.mac = ''
        self.xfr = False
        self.origin = None
        self.tsig_ctx = None
        self.had_tsig = False
        self.multi = False
        self.first = True
        self.index = {}

    def __repr__(self):
        return '<DNS message, ID ' + repr(self.id) + '>'

    def __str__(self):
        return self.to_text()

    def to_text(self, origin=None, relativize=True, **kw):
        """Convert the message to text.

        The I{origin}, I{relativize}, and any other keyword
        arguments are passed to the rrset to_wire() method.

        @rtype: string
        """

        s = StringIO()
        s.write(u'id %d\n' % self.id)
        s.write(u'opcode %s\n' %
                dns.opcode.to_text(dns.opcode.from_flags(self.flags)))
        rc = dns.rcode.from_flags(self.flags, self.ednsflags)
        s.write(u'rcode %s\n' % dns.rcode.to_text(rc))
        s.write(u'flags %s\n' % dns.flags.to_text(self.flags))
        if self.edns >= 0:
            s.write(u'edns %s\n' % self.edns)
            if self.ednsflags != 0:
                s.write(u'eflags %s\n' %
                        dns.flags.edns_to_text(self.ednsflags))
            s.write(u'payload %d\n' % self.payload)
        is_update = dns.opcode.is_update(self.flags)
        if is_update:
            s.write(u';ZONE\n')
        else:
            s.write(u';QUESTION\n')
        for rrset in self.question:
            s.write(rrset.to_text(origin, relativize, **kw))
            s.write(u'\n')
        if is_update:
            s.write(u';PREREQ\n')
        else:
            s.write(u';ANSWER\n')
        for rrset in self.answer:
            s.write(rrset.to_text(origin, relativize, **kw))
            s.write(u'\n')
        if is_update:
            s.write(u';UPDATE\n')
        else:
            s.write(u';AUTHORITY\n')
        for rrset in self.authority:
            s.write(rrset.to_text(origin, relativize, **kw))
            s.write(u'\n')
        s.write(u';ADDITIONAL\n')
        for rrset in self.additional:
            s.write(rrset.to_text(origin, relativize, **kw))
            s.write(u'\n')
        #
        # We strip off the final \n so the caller can print the result without
        # doing weird things to get around eccentricities in Python print
        # formatting
        #
        return s.getvalue()[:-1]

    def __eq__(self, other):
        """Two messages are equal if they have the same content in the
        header, question, answer, and authority sections.
        @rtype: bool"""
        if not isinstance(other, Message):
            return False
        if self.id != other.id:
            return False
        if self.flags != other.flags:
            return False
        for n in self.question:
            if n not in other.question:
                return False
        for n in other.question:
            if n not in self.question:
                return False
        for n in self.answer:
            if n not in other.answer:
                return False
        for n in other.answer:
            if n not in self.answer:
                return False
        for n in self.authority:
            if n not in other.authority:
                return False
        for n in other.authority:
            if n not in self.authority:
                return False
        return True

    def __ne__(self, other):
        """Are two messages not equal?
        @rtype: bool"""
        return not self.__eq__(other)

    def is_response(self, other):
        """Is other a response to self?
        @rtype: bool"""
        if other.flags & dns.flags.QR == 0 or \
           self.id != other.id or \
           dns.opcode.from_flags(self.flags) != \
           dns.opcode.from_flags(other.flags):
            return False
        if dns.rcode.from_flags(other.flags, other.ednsflags) != \
                dns.rcode.NOERROR:
            return True
        if dns.opcode.is_update(self.flags):
            return True
        for n in self.question:
            if n not in other.question:
                return False
        for n in other.question:
            if n not in self.question:
                return False
        return True

    def section_number(self, section):
        if section is self.question:
            return 0
        elif section is self.answer:
            return 1
        elif section is self.authority:
            return 2
        elif section is self.additional:
            return 3
        else:
            raise ValueError('unknown section')

    def find_rrset(self, section, name, rdclass, rdtype,
                   covers=dns.rdatatype.NONE, deleting=None, create=False,
                   force_unique=False):
        """Find the RRset with the given attributes in the specified section.

        @param section: the section of the message to look in, e.g.
        self.answer.
        @type section: list of dns.rrset.RRset objects
        @param name: the name of the RRset
        @type name: dns.name.Name object
        @param rdclass: the class of the RRset
        @type rdclass: int
        @param rdtype: the type of the RRset
        @type rdtype: int
        @param covers: the covers value of the RRset
        @type covers: int
        @param deleting: the deleting value of the RRset
        @type deleting: int
        @param create: If True, create the RRset if it is not found.
        The created RRset is appended to I{section}.
        @type create: bool
        @param force_unique: If True and create is also True, create a
        new RRset regardless of whether a matching RRset exists already.
        @type force_unique: bool
        @raises KeyError: the RRset was not found and create was False
        @rtype: dns.rrset.RRset object"""

        key = (self.section_number(section),
               name, rdclass, rdtype, covers, deleting)
        if not force_unique:
            if self.index is not None:
                rrset = self.index.get(key)
                if rrset is not None:
                    return rrset
            else:
                for rrset in section:
                    if rrset.match(name, rdclass, rdtype, covers, deleting):
                        return rrset
        if not create:
            raise KeyError
        rrset = dns.rrset.RRset(name, rdclass, rdtype, covers, deleting)
        section.append(rrset)
        if self.index is not None:
            self.index[key] = rrset
        return rrset

    def get_rrset(self, section, name, rdclass, rdtype,
                  covers=dns.rdatatype.NONE, deleting=None, create=False,
                  force_unique=False):
        """Get the RRset with the given attributes in the specified section.

        If the RRset is not found, None is returned.

        @param section: the section of the message to look in, e.g.
        self.answer.
        @type section: list of dns.rrset.RRset objects
        @param name: the name of the RRset
        @type name: dns.name.Name object
        @param rdclass: the class of the RRset
        @type rdclass: int
        @param rdtype: the type of the RRset
        @type rdtype: int
        @param covers: the covers value of the RRset
        @type covers: int
        @param deleting: the deleting value of the RRset
        @type deleting: int
        @param create: If True, create the RRset if it is not found.
        The created RRset is appended to I{section}.
        @type create: bool
        @param force_unique: If True and create is also True, create a
        new RRset regardless of whether a matching RRset exists already.
        @type force_unique: bool
        @rtype: dns.rrset.RRset object or None"""

        try:
            rrset = self.find_rrset(section, name, rdclass, rdtype, covers,
                                    deleting, create, force_unique)
        except KeyError:
            rrset = None
        return rrset

    def to_wire(self, origin=None, max_size=0, **kw):
        """Return a string containing the message in DNS compressed wire
        format.

        Additional keyword arguments are passed to the rrset to_wire()
        method.

        @param origin: The origin to be appended to any relative names.
        @type origin: dns.name.Name object
        @param max_size: The maximum size of the wire format output; default
        is 0, which means 'the message's request payload, if nonzero, or
        65536'.
        @type max_size: int
        @raises dns.exception.TooBig: max_size was exceeded
        @rtype: string
        """

        if max_size == 0:
            if self.request_payload != 0:
                max_size = self.request_payload
            else:
                max_size = 65535
        if max_size < 512:
            max_size = 512
        elif max_size > 65535:
            max_size = 65535
        r = dns.renderer.Renderer(self.id, self.flags, max_size, origin)
        for rrset in self.question:
            r.add_question(rrset.name, rrset.rdtype, rrset.rdclass)
        for rrset in self.answer:
            r.add_rrset(dns.renderer.ANSWER, rrset, **kw)
        for rrset in self.authority:
            r.add_rrset(dns.renderer.AUTHORITY, rrset, **kw)
        if self.edns >= 0:
            r.add_edns(self.edns, self.ednsflags, self.payload, self.options)
        for rrset in self.additional:
            r.add_rrset(dns.renderer.ADDITIONAL, rrset, **kw)
        r.write_header()
        if self.keyname is not None:
            r.add_tsig(self.keyname, self.keyring[self.keyname],
                       self.fudge, self.original_id, self.tsig_error,
                       self.other_data, self.request_mac,
                       self.keyalgorithm)
            self.mac = r.mac
        return r.get_wire()

    def use_tsig(self, keyring, keyname=None, fudge=300,
                 original_id=None, tsig_error=0, other_data='',
                 algorithm=dns.tsig.default_algorithm):
        """When sending, a TSIG signature using the specified keyring
        and keyname should be added.

        @param keyring: The TSIG keyring to use; defaults to None.
        @type keyring: dict
        @param keyname: The name of the TSIG key to use; defaults to None.
        The key must be defined in the keyring.  If a keyring is specified
        but a keyname is not, then the key used will be the first key in the
        keyring.  Note that the order of keys in a dictionary is not defined,
        so applications should supply a keyname when a keyring is used, unless
        they know the keyring contains only one key.
        @type keyname: dns.name.Name or string
        @param fudge: TSIG time fudge; default is 300 seconds.
        @type fudge: int
        @param original_id: TSIG original id; defaults to the message's id
        @type original_id: int
        @param tsig_error: TSIG error code; default is 0.
        @type tsig_error: int
        @param other_data: TSIG other data.
        @type other_data: string
        @param algorithm: The TSIG algorithm to use; defaults to
        dns.tsig.default_algorithm
        """

        self.keyring = keyring
        if keyname is None:
            self.keyname = list(self.keyring.keys())[0]
        else:
            if isinstance(keyname, string_types):
                keyname = dns.name.from_text(keyname)
            self.keyname = keyname
        self.keyalgorithm = algorithm
        self.fudge = fudge
        if original_id is None:
            self.original_id = self.id
        else:
            self.original_id = original_id
        self.tsig_error = tsig_error
        self.other_data = other_data

    def use_edns(self, edns=0, ednsflags=0, payload=1280, request_payload=None,
                 options=None):
        """Configure EDNS behavior.
        @param edns: The EDNS level to use.  Specifying None, False, or -1
        means 'do not use EDNS', and in this case the other parameters are
        ignored.  Specifying True is equivalent to specifying 0, i.e. 'use
        EDNS0'.
        @type edns: int or bool or None
        @param ednsflags: EDNS flag values.
        @type ednsflags: int
        @param payload: The EDNS sender's payload field, which is the maximum
        size of UDP datagram the sender can handle.
        @type payload: int
        @param request_payload: The EDNS payload size to use when sending
        this message.  If not specified, defaults to the value of payload.
        @type request_payload: int or None
        @param options: The EDNS options
        @type options: None or list of dns.edns.Option objects
        @see: RFC 2671
        """
        if edns is None or edns is False:
            edns = -1
        if edns is True:
            edns = 0
        if request_payload is None:
            request_payload = payload
        if edns < 0:
            ednsflags = 0
            payload = 0
            request_payload = 0
            options = []
        else:
            # make sure the EDNS version in ednsflags agrees with edns
            ednsflags &= long(0xFF00FFFF)
            ednsflags |= (edns << 16)
            if options is None:
                options = []
        self.edns = edns
        self.ednsflags = ednsflags
        self.payload = payload
        self.options = options
        self.request_payload = request_payload

    def want_dnssec(self, wanted=True):
        """Enable or disable 'DNSSEC desired' flag in requests.
        @param wanted: Is DNSSEC desired?  If True, EDNS is enabled if
        required, and then the DO bit is set.  If False, the DO bit is
        cleared if EDNS is enabled.
        @type wanted: bool
        """
        if wanted:
            if self.edns < 0:
                self.use_edns()
            self.ednsflags |= dns.flags.DO
        elif self.edns >= 0:
            self.ednsflags &= ~dns.flags.DO

    def rcode(self):
        """Return the rcode.
        @rtype: int
        """
        return dns.rcode.from_flags(self.flags, self.ednsflags)

    def set_rcode(self, rcode):
        """Set the rcode.
        @param rcode: the rcode
        @type rcode: int
        """
        (value, evalue) = dns.rcode.to_flags(rcode)
        self.flags &= 0xFFF0
        self.flags |= value
        self.ednsflags &= long(0x00FFFFFF)
        self.ednsflags |= evalue
        if self.ednsflags != 0 and self.edns < 0:
            self.edns = 0

    def opcode(self):
        """Return the opcode.
        @rtype: int
        """
        return dns.opcode.from_flags(self.flags)

    def set_opcode(self, opcode):
        """Set the opcode.
        @param opcode: the opcode
        @type opcode: int
        """
        self.flags &= 0x87FF
        self.flags |= dns.opcode.to_flags(opcode)


class _WireReader(object):

    """Wire format reader.

    @ivar wire: the wire-format message.
    @type wire: string
    @ivar message: The message object being built
    @type message: dns.message.Message object
    @ivar current: When building a message object from wire format, this
    variable contains the offset from the beginning of wire of the next octet
    to be read.
    @type current: int
    @ivar updating: Is the message a dynamic update?
    @type updating: bool
    @ivar one_rr_per_rrset: Put each RR into its own RRset?
    @type one_rr_per_rrset: bool
    @ivar ignore_trailing: Ignore trailing junk at end of request?
    @type ignore_trailing: bool
    @ivar zone_rdclass: The class of the zone in messages which are
    DNS dynamic updates.
    @type zone_rdclass: int
    """

    def __init__(self, wire, message, question_only=False,
                 one_rr_per_rrset=False, ignore_trailing=False):
        self.wire = dns.wiredata.maybe_wrap(wire)
        self.message = message
        self.current = 0
        self.updating = False
        self.zone_rdclass = dns.rdataclass.IN
        self.question_only = question_only
        self.one_rr_per_rrset = one_rr_per_rrset
        self.ignore_trailing = ignore_trailing

    def _get_question(self, qcount):
        """Read the next I{qcount} records from the wire data and add them to
        the question section.
        @param qcount: the number of questions in the message
        @type qcount: int"""

        if self.updating and qcount > 1:
            raise dns.exception.FormError

        for i in xrange(0, qcount):
            (qname, used) = dns.name.from_wire(self.wire, self.current)
            if self.message.origin is not None:
                qname = qname.relativize(self.message.origin)
            self.current = self.current + used
            (rdtype, rdclass) = \
                struct.unpack('!HH',
                              self.wire[self.current:self.current + 4])
            self.current = self.current + 4
            self.message.find_rrset(self.message.question, qname,
                                    rdclass, rdtype, create=True,
                                    force_unique=True)
            if self.updating:
                self.zone_rdclass = rdclass

    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 dns.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) = dns.name.from_wire(self.wire, self.current)
            absolute_name = name
            if self.message.origin is not 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 == dns.rdatatype.OPT:
                if section is not 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 = dns.edns.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 == dns.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.keyname = absolute_name
                (self.message.keyalgorithm, self.message.mac) = \
                    dns.tsig.get_algorithm_and_mac(self.wire, self.current,
                                                   rdlen)
                self.message.tsig_ctx = \
                    dns.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 == dns.rdataclass.ANY or
                        rdclass == dns.rdataclass.NONE):
                    deleting = rdclass
                    rdclass = self.zone_rdclass
                else:
                    deleting = None
                if deleting == dns.rdataclass.ANY or \
                   (deleting == dns.rdataclass.NONE and
                        section is self.message.answer):
                    covers = dns.rdatatype.NONE
                    rd = None
                else:
                    rd = dns.rdata.from_wire(rdclass, rdtype, self.wire,
                                             self.current, rdlen,
                                             self.message.origin)
                    covers = rd.covers()
                if self.message.xfr and rdtype == dns.rdatatype.SOA:
                    force_unique = True
                rrset = self.message.find_rrset(section, name,
                                                rdclass, rdtype, covers,
                                                deleting, True, force_unique)
                if rd is not None:
                    rrset.add(rd, ttl)
            self.current = self.current + rdlen

    def read(self):
        """Read a wire format DNS message and build a dns.message.Message
        object."""

        l = len(self.wire)
        if l < 12:
            raise ShortHeader
        (self.message.id, self.message.flags, qcount, ancount,
         aucount, adcount) = struct.unpack('!HHHHHH', self.wire[:12])
        self.current = 12
        if dns.opcode.is_update(self.message.flags):
            self.updating = True
        self._get_question(qcount)
        if self.question_only:
            return
        self._get_section(self.message.answer, ancount)
        self._get_section(self.message.authority, aucount)
        self._get_section(self.message.additional, adcount)
        if not self.ignore_trailing and self.current != l:
            raise TrailingJunk
        if self.message.multi and self.message.tsig_ctx and \
                not self.message.had_tsig:
            self.message.tsig_ctx.update(self.wire)


def from_wire(wire, keyring=None, request_mac='', xfr=False, origin=None,
              tsig_ctx=None, multi=False, first=True,
              question_only=False, one_rr_per_rrset=False,
              ignore_trailing=False):
    """Convert a DNS wire format message into a message
    object.

    @param keyring: The keyring to use if the message is signed.
    @type keyring: dict
    @param request_mac: If the message is a response to a TSIG-signed request,
    I{request_mac} should be set to the MAC of that request.
    @type request_mac: string
    @param xfr: Is this message part of a zone transfer?
    @type xfr: bool
    @param origin: If the message is part of a zone transfer, I{origin}
    should be the origin name of the zone.
    @type origin: dns.name.Name object
    @param tsig_ctx: The ongoing TSIG context, used when validating zone
    transfers.
    @type tsig_ctx: hmac.HMAC object
    @param multi: Is this message part of a multiple message sequence?
    @type multi: bool
    @param first: Is this message standalone, or the first of a multi
    message sequence?
    @type first: bool
    @param question_only: Read only up to the end of the question section?
    @type question_only: bool
    @param one_rr_per_rrset: Put each RR into its own RRset
    @type one_rr_per_rrset: bool
    @param ignore_trailing: Ignore trailing junk at end of request?
    @type ignore_trailing: bool
    @raises ShortHeader: The message is less than 12 octets long.
    @raises TrailingJunk: There were octets in the message past the end
    of the proper DNS message.
    @raises BadEDNS: An OPT record was in the wrong section, or occurred more
    than once.
    @raises BadTSIG: A TSIG record was not the last record of the additional
    data section.
    @rtype: dns.message.Message object"""

    m = Message(id=0)
    m.keyring = keyring
    m.request_mac = request_mac
    m.xfr = xfr
    m.origin = origin
    m.tsig_ctx = tsig_ctx
    m.multi = multi
    m.first = first

    reader = _WireReader(wire, m, question_only, one_rr_per_rrset,
                         ignore_trailing)
    reader.read()

    return m


class _TextReader(object):

    """Text format reader.

    @ivar tok: the tokenizer
    @type tok: dns.tokenizer.Tokenizer object
    @ivar message: The message object being built
    @type message: dns.message.Message object
    @ivar updating: Is the message a dynamic update?
    @type updating: bool
    @ivar zone_rdclass: The class of the zone in messages which are
    DNS dynamic updates.
    @type zone_rdclass: int
    @ivar last_name: The most recently read name when building a message object
    from text format.
    @type last_name: dns.name.Name object
    """

    def __init__(self, text, message):
        self.message = message
        self.tok = dns.tokenizer.Tokenizer(text)
        self.last_name = None
        self.zone_rdclass = dns.rdataclass.IN
        self.updating = False

    def _header_line(self, section):
        """Process one line from the text format header section."""

        token = self.tok.get()
        what = token.value
        if what == 'id':
            self.message.id = self.tok.get_int()
        elif what == 'flags':
            while True:
                token = self.tok.get()
                if not token.is_identifier():
                    self.tok.unget(token)
                    break
                self.message.flags = self.message.flags | \
                    dns.flags.from_text(token.value)
            if dns.opcode.is_update(self.message.flags):
                self.updating = True
        elif what == 'edns':
            self.message.edns = self.tok.get_int()
            self.message.ednsflags = self.message.ednsflags | \
                (self.message.edns << 16)
        elif what == 'eflags':
            if self.message.edns < 0:
                self.message.edns = 0
            while True:
                token = self.tok.get()
                if not token.is_identifier():
                    self.tok.unget(token)
                    break
                self.message.ednsflags = self.message.ednsflags | \
                    dns.flags.edns_from_text(token.value)
        elif what == 'payload':
            self.message.payload = self.tok.get_int()
            if self.message.edns < 0:
                self.message.edns = 0
        elif what == 'opcode':
            text = self.tok.get_string()
            self.message.flags = self.message.flags | \
                dns.opcode.to_flags(dns.opcode.from_text(text))
        elif what == 'rcode':
            text = self.tok.get_string()
            self.message.set_rcode(dns.rcode.from_text(text))
        else:
            raise UnknownHeaderField
        self.tok.get_eol()

    def _question_line(self, section):
        """Process one line from the text format question section."""

        token = self.tok.get(want_leading=True)
        if not token.is_whitespace():
            self.last_name = dns.name.from_text(token.value, None)
        name = self.last_name
        token = self.tok.get()
        if not token.is_identifier():
            raise dns.exception.SyntaxError
        # Class
        try:
            rdclass = dns.rdataclass.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.exception.SyntaxError:
            raise dns.exception.SyntaxError
        except Exception:
            rdclass = dns.rdataclass.IN
        # Type
        rdtype = dns.rdatatype.from_text(token.value)
        self.message.find_rrset(self.message.question, name,
                                rdclass, rdtype, create=True,
                                force_unique=True)
        if self.updating:
            self.zone_rdclass = rdclass
        self.tok.get_eol()

    def _rr_line(self, section):
        """Process one line from the text format answer, authority, or
        additional data sections.
        """

        deleting = None
        # Name
        token = self.tok.get(want_leading=True)
        if not token.is_whitespace():
            self.last_name = dns.name.from_text(token.value, None)
        name = self.last_name
        token = self.tok.get()
        if not token.is_identifier():
            raise dns.exception.SyntaxError
        # TTL
        try:
            ttl = int(token.value, 0)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.exception.SyntaxError:
            raise dns.exception.SyntaxError
        except Exception:
            ttl = 0
        # Class
        try:
            rdclass = dns.rdataclass.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
            if rdclass == dns.rdataclass.ANY or rdclass == dns.rdataclass.NONE:
                deleting = rdclass
                rdclass = self.zone_rdclass
        except dns.exception.SyntaxError:
            raise dns.exception.SyntaxError
        except Exception:
            rdclass = dns.rdataclass.IN
        # Type
        rdtype = dns.rdatatype.from_text(token.value)
        token = self.tok.get()
        if not token.is_eol_or_eof():
            self.tok.unget(token)
            rd = dns.rdata.from_text(rdclass, rdtype, self.tok, None)
            covers = rd.covers()
        else:
            rd = None
            covers = dns.rdatatype.NONE
        rrset = self.message.find_rrset(section, name,
                                        rdclass, rdtype, covers,
                                        deleting, True, self.updating)
        if rd is not None:
            rrset.add(rd, ttl)

    def read(self):
        """Read a text format DNS message and build a dns.message.Message
        object."""

        line_method = self._header_line
        section = None
        while 1:
            token = self.tok.get(True, True)
            if token.is_eol_or_eof():
                break
            if token.is_comment():
                u = token.value.upper()
                if u == 'HEADER':
                    line_method = self._header_line
                elif u == 'QUESTION' or u == 'ZONE':
                    line_method = self._question_line
                    section = self.message.question
                elif u == 'ANSWER' or u == 'PREREQ':
                    line_method = self._rr_line
                    section = self.message.answer
                elif u == 'AUTHORITY' or u == 'UPDATE':
                    line_method = self._rr_line
                    section = self.message.authority
                elif u == 'ADDITIONAL':
                    line_method = self._rr_line
                    section = self.message.additional
                self.tok.get_eol()
                continue
            self.tok.unget(token)
            line_method(section)


def from_text(text):
    """Convert the text format message into a message object.

    @param text: The text format message.
    @type text: string
    @raises UnknownHeaderField:
    @raises dns.exception.SyntaxError:
    @rtype: dns.message.Message object"""

    # 'text' can also be a file, but we don't publish that fact
    # since it's an implementation detail.  The official file
    # interface is from_file().

    m = Message()

    reader = _TextReader(text, m)
    reader.read()

    return m


def from_file(f):
    """Read the next text format message from the specified file.

    @param f: file or string.  If I{f} is a string, it is treated
    as the name of a file to open.
    @raises UnknownHeaderField:
    @raises dns.exception.SyntaxError:
    @rtype: dns.message.Message object"""

    str_type = string_types
    opts = 'rU'

    if isinstance(f, str_type):
        f = open(f, opts)
        want_close = True
    else:
        want_close = False

    try:
        m = from_text(f)
    finally:
        if want_close:
            f.close()
    return m


def make_query(qname, rdtype, rdclass=dns.rdataclass.IN, use_edns=None,
               want_dnssec=False, ednsflags=None, payload=None,
               request_payload=None, options=None):
    """Make a query message.

    The query name, type, and class may all be specified either
    as objects of the appropriate type, or as strings.

    The query will have a randomly chosen query id, and its DNS flags
    will be set to dns.flags.RD.

    @param qname: The query name.
    @type qname: dns.name.Name object or string
    @param rdtype: The desired rdata type.
    @type rdtype: int
    @param rdclass: The desired rdata class; the default is class IN.
    @type rdclass: int
    @param use_edns: The EDNS level to use; the default is None (no EDNS).
    See the description of dns.message.Message.use_edns() for the possible
    values for use_edns and their meanings.
    @type use_edns: int or bool or None
    @param want_dnssec: Should the query indicate that DNSSEC is desired?
    @type want_dnssec: bool
    @param ednsflags: EDNS flag values.
    @type ednsflags: int
    @param payload: The EDNS sender's payload field, which is the maximum
    size of UDP datagram the sender can handle.
    @type payload: int
    @param request_payload: The EDNS payload size to use when sending
    this message.  If not specified, defaults to the value of payload.
    @type request_payload: int or None
    @param options: The EDNS options
    @type options: None or list of dns.edns.Option objects
    @see: RFC 2671
    @rtype: dns.message.Message object"""

    if isinstance(qname, string_types):
        qname = dns.name.from_text(qname)
    if isinstance(rdtype, string_types):
        rdtype = dns.rdatatype.from_text(rdtype)
    if isinstance(rdclass, string_types):
        rdclass = dns.rdataclass.from_text(rdclass)
    m = Message()
    m.flags |= dns.flags.RD
    m.find_rrset(m.question, qname, rdclass, rdtype, create=True,
                 force_unique=True)
    # only pass keywords on to use_edns if they have been set to a
    # non-None value.  Setting a field will turn EDNS on if it hasn't
    # been configured.
    kwargs = {}
    if ednsflags is not None:
        kwargs['ednsflags'] = ednsflags
        if use_edns is None:
            use_edns = 0
    if payload is not None:
        kwargs['payload'] = payload
        if use_edns is None:
            use_edns = 0
    if request_payload is not None:
        kwargs['request_payload'] = request_payload
        if use_edns is None:
            use_edns = 0
    if options is not None:
        kwargs['options'] = options
        if use_edns is None:
            use_edns = 0
    kwargs['edns'] = use_edns
    m.use_edns(**kwargs)
    m.want_dnssec(want_dnssec)
    return m


def make_response(query, recursion_available=False, our_payload=8192,
                  fudge=300):
    """Make a message which is a response for the specified query.
    The message returned is really a response skeleton; it has all
    of the infrastructure required of a response, but none of the
    content.

    The response's question section is a shallow copy of the query's
    question section, so the query's question RRsets should not be
    changed.

    @param query: the query to respond to
    @type query: dns.message.Message object
    @param recursion_available: should RA be set in the response?
    @type recursion_available: bool
    @param our_payload: payload size to advertise in EDNS responses; default
    is 8192.
    @type our_payload: int
    @param fudge: TSIG time fudge; default is 300 seconds.
    @type fudge: int
    @rtype: dns.message.Message object"""

    if query.flags & dns.flags.QR:
        raise dns.exception.FormError('specified query message is not a query')
    response = dns.message.Message(query.id)
    response.flags = dns.flags.QR | (query.flags & dns.flags.RD)
    if recursion_available:
        response.flags |= dns.flags.RA
    response.set_opcode(query.opcode())
    response.question = list(query.question)
    if query.edns >= 0:
        response.use_edns(0, 0, our_payload, query.payload)
    if query.had_tsig:
        response.use_tsig(query.keyring, query.keyname, fudge, None, 0, '',
                          query.keyalgorithm)
        response.request_mac = query.mac
    return response
rrset.py000064400000013553150351404270006265 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS RRsets (an RRset is a named rdataset)"""


import dns.name
import dns.rdataset
import dns.rdataclass
import dns.renderer
from ._compat import string_types


class RRset(dns.rdataset.Rdataset):

    """A DNS RRset (named rdataset).

    RRset inherits from Rdataset, and RRsets can be treated as
    Rdatasets in most cases.  There are, however, a few notable
    exceptions.  RRsets have different to_wire() and to_text() method
    arguments, reflecting the fact that RRsets always have an owner
    name.
    """

    __slots__ = ['name', 'deleting']

    def __init__(self, name, rdclass, rdtype, covers=dns.rdatatype.NONE,
                 deleting=None):
        """Create a new RRset."""

        super(RRset, self).__init__(rdclass, rdtype, covers)
        self.name = name
        self.deleting = deleting

    def _clone(self):
        obj = super(RRset, self)._clone()
        obj.name = self.name
        obj.deleting = self.deleting
        return obj

    def __repr__(self):
        if self.covers == 0:
            ctext = ''
        else:
            ctext = '(' + dns.rdatatype.to_text(self.covers) + ')'
        if self.deleting is not None:
            dtext = ' delete=' + dns.rdataclass.to_text(self.deleting)
        else:
            dtext = ''
        return '<DNS ' + str(self.name) + ' ' + \
               dns.rdataclass.to_text(self.rdclass) + ' ' + \
               dns.rdatatype.to_text(self.rdtype) + ctext + dtext + ' RRset>'

    def __str__(self):
        return self.to_text()

    def __eq__(self, other):
        """Two RRsets are equal if they have the same name and the same
        rdataset

        @rtype: bool"""
        if not isinstance(other, RRset):
            return False
        if self.name != other.name:
            return False
        return super(RRset, self).__eq__(other)

    def match(self, name, rdclass, rdtype, covers, deleting=None):
        """Returns True if this rrset matches the specified class, type,
        covers, and deletion state."""

        if not super(RRset, self).match(rdclass, rdtype, covers):
            return False
        if self.name != name or self.deleting != deleting:
            return False
        return True

    def to_text(self, origin=None, relativize=True, **kw):
        """Convert the RRset into DNS master file format.

        @see: L{dns.name.Name.choose_relativity} for more information
        on how I{origin} and I{relativize} determine the way names
        are emitted.

        Any additional keyword arguments are passed on to the rdata
        to_text() method.

        @param origin: The origin for relative names, or None.
        @type origin: dns.name.Name object
        @param relativize: True if names should names be relativized
        @type relativize: bool"""

        return super(RRset, self).to_text(self.name, origin, relativize,
                                          self.deleting, **kw)

    def to_wire(self, file, compress=None, origin=None, **kw):
        """Convert the RRset to wire format."""

        return super(RRset, self).to_wire(self.name, file, compress, origin,
                                          self.deleting, **kw)

    def to_rdataset(self):
        """Convert an RRset into an Rdataset.

        @rtype: dns.rdataset.Rdataset object
        """
        return dns.rdataset.from_rdata_list(self.ttl, list(self))


def from_text_list(name, ttl, rdclass, rdtype, text_rdatas,
                   idna_codec=None):
    """Create an RRset with the specified name, TTL, class, and type, and with
    the specified list of rdatas in text format.

    @rtype: dns.rrset.RRset object
    """

    if isinstance(name, string_types):
        name = dns.name.from_text(name, None, idna_codec=idna_codec)
    if isinstance(rdclass, string_types):
        rdclass = dns.rdataclass.from_text(rdclass)
    if isinstance(rdtype, string_types):
        rdtype = dns.rdatatype.from_text(rdtype)
    r = RRset(name, rdclass, rdtype)
    r.update_ttl(ttl)
    for t in text_rdatas:
        rd = dns.rdata.from_text(r.rdclass, r.rdtype, t)
        r.add(rd)
    return r


def from_text(name, ttl, rdclass, rdtype, *text_rdatas):
    """Create an RRset with the specified name, TTL, class, and type and with
    the specified rdatas in text format.

    @rtype: dns.rrset.RRset object
    """

    return from_text_list(name, ttl, rdclass, rdtype, text_rdatas)


def from_rdata_list(name, ttl, rdatas, idna_codec=None):
    """Create an RRset with the specified name and TTL, and with
    the specified list of rdata objects.

    @rtype: dns.rrset.RRset object
    """

    if isinstance(name, string_types):
        name = dns.name.from_text(name, None, idna_codec=idna_codec)

    if len(rdatas) == 0:
        raise ValueError("rdata list must not be empty")
    r = None
    for rd in rdatas:
        if r is None:
            r = RRset(name, rd.rdclass, rd.rdtype)
            r.update_ttl(ttl)
        r.add(rd)
    return r


def from_rdata(name, ttl, *rdatas):
    """Create an RRset with the specified name and TTL, and with
    the specified rdata objects.

    @rtype: dns.rrset.RRset object
    """

    return from_rdata_list(name, ttl, rdatas)
__init__.py000064400000002457150351404270006666 0ustar00# Copyright (C) 2003-2007, 2009, 2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""dnspython DNS toolkit"""

__all__ = [
    'dnssec',
    'e164',
    'edns',
    'entropy',
    'exception',
    'flags',
    'hash',
    'inet',
    'ipv4',
    'ipv6',
    'message',
    'name',
    'namedict',
    'node',
    'opcode',
    'query',
    'rcode',
    'rdata',
    'rdataclass',
    'rdataset',
    'rdatatype',
    'renderer',
    'resolver',
    'reversename',
    'rrset',
    'set',
    'tokenizer',
    'tsig',
    'tsigkeyring',
    'ttl',
    'rdtypes',
    'update',
    'version',
    'wiredata',
    'zone',
]
tokenizer.py000064400000043611150351404270007136 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""Tokenize DNS master file format"""

from io import StringIO
import sys

import dns.exception
import dns.name
import dns.ttl
from ._compat import long, text_type, binary_type

_DELIMITERS = {
    ' ': True,
    '\t': True,
    '\n': True,
    ';': True,
    '(': True,
    ')': True,
    '"': True}

_QUOTING_DELIMITERS = {'"': True}

EOF = 0
EOL = 1
WHITESPACE = 2
IDENTIFIER = 3
QUOTED_STRING = 4
COMMENT = 5
DELIMITER = 6


class UngetBufferFull(dns.exception.DNSException):

    """An attempt was made to unget a token when the unget buffer was full."""


class Token(object):

    """A DNS master file format token.

    @ivar ttype: The token type
    @type ttype: int
    @ivar value: The token value
    @type value: string
    @ivar has_escape: Does the token value contain escapes?
    @type has_escape: bool
    """

    def __init__(self, ttype, value='', has_escape=False):
        """Initialize a token instance.

        @param ttype: The token type
        @type ttype: int
        @param value: The token value
        @type value: string
        @param has_escape: Does the token value contain escapes?
        @type has_escape: bool
        """
        self.ttype = ttype
        self.value = value
        self.has_escape = has_escape

    def is_eof(self):
        return self.ttype == EOF

    def is_eol(self):
        return self.ttype == EOL

    def is_whitespace(self):
        return self.ttype == WHITESPACE

    def is_identifier(self):
        return self.ttype == IDENTIFIER

    def is_quoted_string(self):
        return self.ttype == QUOTED_STRING

    def is_comment(self):
        return self.ttype == COMMENT

    def is_delimiter(self):
        return self.ttype == DELIMITER

    def is_eol_or_eof(self):
        return self.ttype == EOL or self.ttype == EOF

    def __eq__(self, other):
        if not isinstance(other, Token):
            return False
        return (self.ttype == other.ttype and
                self.value == other.value)

    def __ne__(self, other):
        if not isinstance(other, Token):
            return True
        return (self.ttype != other.ttype or
                self.value != other.value)

    def __str__(self):
        return '%d "%s"' % (self.ttype, self.value)

    def unescape(self):
        if not self.has_escape:
            return self
        unescaped = ''
        l = len(self.value)
        i = 0
        while i < l:
            c = self.value[i]
            i += 1
            if c == '\\':
                if i >= l:
                    raise dns.exception.UnexpectedEnd
                c = self.value[i]
                i += 1
                if c.isdigit():
                    if i >= l:
                        raise dns.exception.UnexpectedEnd
                    c2 = self.value[i]
                    i += 1
                    if i >= l:
                        raise dns.exception.UnexpectedEnd
                    c3 = self.value[i]
                    i += 1
                    if not (c2.isdigit() and c3.isdigit()):
                        raise dns.exception.SyntaxError
                    c = chr(int(c) * 100 + int(c2) * 10 + int(c3))
            unescaped += c
        return Token(self.ttype, unescaped)

    # compatibility for old-style tuple tokens

    def __len__(self):
        return 2

    def __iter__(self):
        return iter((self.ttype, self.value))

    def __getitem__(self, i):
        if i == 0:
            return self.ttype
        elif i == 1:
            return self.value
        else:
            raise IndexError


class Tokenizer(object):

    """A DNS master file format tokenizer.

    A token is a (type, value) tuple, where I{type} is an int, and
    I{value} is a string.  The valid types are EOF, EOL, WHITESPACE,
    IDENTIFIER, QUOTED_STRING, COMMENT, and DELIMITER.

    @ivar file: The file to tokenize
    @type file: file
    @ivar ungotten_char: The most recently ungotten character, or None.
    @type ungotten_char: string
    @ivar ungotten_token: The most recently ungotten token, or None.
    @type ungotten_token: (int, string) token tuple
    @ivar multiline: The current multiline level.  This value is increased
    by one every time a '(' delimiter is read, and decreased by one every time
    a ')' delimiter is read.
    @type multiline: int
    @ivar quoting: This variable is true if the tokenizer is currently
    reading a quoted string.
    @type quoting: bool
    @ivar eof: This variable is true if the tokenizer has encountered EOF.
    @type eof: bool
    @ivar delimiters: The current delimiter dictionary.
    @type delimiters: dict
    @ivar line_number: The current line number
    @type line_number: int
    @ivar filename: A filename that will be returned by the L{where} method.
    @type filename: string
    """

    def __init__(self, f=sys.stdin, filename=None):
        """Initialize a tokenizer instance.

        @param f: The file to tokenize.  The default is sys.stdin.
        This parameter may also be a string, in which case the tokenizer
        will take its input from the contents of the string.
        @type f: file or string
        @param filename: the name of the filename that the L{where} method
        will return.
        @type filename: string
        """

        if isinstance(f, text_type):
            f = StringIO(f)
            if filename is None:
                filename = '<string>'
        elif isinstance(f, binary_type):
            f = StringIO(f.decode())
            if filename is None:
                filename = '<string>'
        else:
            if filename is None:
                if f is sys.stdin:
                    filename = '<stdin>'
                else:
                    filename = '<file>'
        self.file = f
        self.ungotten_char = None
        self.ungotten_token = None
        self.multiline = 0
        self.quoting = False
        self.eof = False
        self.delimiters = _DELIMITERS
        self.line_number = 1
        self.filename = filename

    def _get_char(self):
        """Read a character from input.
        @rtype: string
        """

        if self.ungotten_char is None:
            if self.eof:
                c = ''
            else:
                c = self.file.read(1)
                if c == '':
                    self.eof = True
                elif c == '\n':
                    self.line_number += 1
        else:
            c = self.ungotten_char
            self.ungotten_char = None
        return c

    def where(self):
        """Return the current location in the input.

        @rtype: (string, int) tuple.  The first item is the filename of
        the input, the second is the current line number.
        """

        return (self.filename, self.line_number)

    def _unget_char(self, c):
        """Unget a character.

        The unget buffer for characters is only one character large; it is
        an error to try to unget a character when the unget buffer is not
        empty.

        @param c: the character to unget
        @type c: string
        @raises UngetBufferFull: there is already an ungotten char
        """

        if self.ungotten_char is not None:
            raise UngetBufferFull
        self.ungotten_char = c

    def skip_whitespace(self):
        """Consume input until a non-whitespace character is encountered.

        The non-whitespace character is then ungotten, and the number of
        whitespace characters consumed is returned.

        If the tokenizer is in multiline mode, then newlines are whitespace.

        @rtype: int
        """

        skipped = 0
        while True:
            c = self._get_char()
            if c != ' ' and c != '\t':
                if (c != '\n') or not self.multiline:
                    self._unget_char(c)
                    return skipped
            skipped += 1

    def get(self, want_leading=False, want_comment=False):
        """Get the next token.

        @param want_leading: If True, return a WHITESPACE token if the
        first character read is whitespace.  The default is False.
        @type want_leading: bool
        @param want_comment: If True, return a COMMENT token if the
        first token read is a comment.  The default is False.
        @type want_comment: bool
        @rtype: Token object
        @raises dns.exception.UnexpectedEnd: input ended prematurely
        @raises dns.exception.SyntaxError: input was badly formed
        """

        if self.ungotten_token is not None:
            token = self.ungotten_token
            self.ungotten_token = None
            if token.is_whitespace():
                if want_leading:
                    return token
            elif token.is_comment():
                if want_comment:
                    return token
            else:
                return token
        skipped = self.skip_whitespace()
        if want_leading and skipped > 0:
            return Token(WHITESPACE, ' ')
        token = ''
        ttype = IDENTIFIER
        has_escape = False
        while True:
            c = self._get_char()
            if c == '' or c in self.delimiters:
                if c == '' and self.quoting:
                    raise dns.exception.UnexpectedEnd
                if token == '' and ttype != QUOTED_STRING:
                    if c == '(':
                        self.multiline += 1
                        self.skip_whitespace()
                        continue
                    elif c == ')':
                        if self.multiline <= 0:
                            raise dns.exception.SyntaxError
                        self.multiline -= 1
                        self.skip_whitespace()
                        continue
                    elif c == '"':
                        if not self.quoting:
                            self.quoting = True
                            self.delimiters = _QUOTING_DELIMITERS
                            ttype = QUOTED_STRING
                            continue
                        else:
                            self.quoting = False
                            self.delimiters = _DELIMITERS
                            self.skip_whitespace()
                            continue
                    elif c == '\n':
                        return Token(EOL, '\n')
                    elif c == ';':
                        while 1:
                            c = self._get_char()
                            if c == '\n' or c == '':
                                break
                            token += c
                        if want_comment:
                            self._unget_char(c)
                            return Token(COMMENT, token)
                        elif c == '':
                            if self.multiline:
                                raise dns.exception.SyntaxError(
                                    'unbalanced parentheses')
                            return Token(EOF)
                        elif self.multiline:
                            self.skip_whitespace()
                            token = ''
                            continue
                        else:
                            return Token(EOL, '\n')
                    else:
                        # This code exists in case we ever want a
                        # delimiter to be returned.  It never produces
                        # a token currently.
                        token = c
                        ttype = DELIMITER
                else:
                    self._unget_char(c)
                break
            elif self.quoting:
                if c == '\\':
                    c = self._get_char()
                    if c == '':
                        raise dns.exception.UnexpectedEnd
                    if c.isdigit():
                        c2 = self._get_char()
                        if c2 == '':
                            raise dns.exception.UnexpectedEnd
                        c3 = self._get_char()
                        if c == '':
                            raise dns.exception.UnexpectedEnd
                        if not (c2.isdigit() and c3.isdigit()):
                            raise dns.exception.SyntaxError
                        c = chr(int(c) * 100 + int(c2) * 10 + int(c3))
                elif c == '\n':
                    raise dns.exception.SyntaxError('newline in quoted string')
            elif c == '\\':
                #
                # It's an escape.  Put it and the next character into
                # the token; it will be checked later for goodness.
                #
                token += c
                has_escape = True
                c = self._get_char()
                if c == '' or c == '\n':
                    raise dns.exception.UnexpectedEnd
            token += c
        if token == '' and ttype != QUOTED_STRING:
            if self.multiline:
                raise dns.exception.SyntaxError('unbalanced parentheses')
            ttype = EOF
        return Token(ttype, token, has_escape)

    def unget(self, token):
        """Unget a token.

        The unget buffer for tokens is only one token large; it is
        an error to try to unget a token when the unget buffer is not
        empty.

        @param token: the token to unget
        @type token: Token object
        @raises UngetBufferFull: there is already an ungotten token
        """

        if self.ungotten_token is not None:
            raise UngetBufferFull
        self.ungotten_token = token

    def next(self):
        """Return the next item in an iteration.
        @rtype: (int, string)
        """

        token = self.get()
        if token.is_eof():
            raise StopIteration
        return token

    __next__ = next

    def __iter__(self):
        return self

    # Helpers

    def get_int(self):
        """Read the next token and interpret it as an integer.

        @raises dns.exception.SyntaxError:
        @rtype: int
        """

        token = self.get().unescape()
        if not token.is_identifier():
            raise dns.exception.SyntaxError('expecting an identifier')
        if not token.value.isdigit():
            raise dns.exception.SyntaxError('expecting an integer')
        return int(token.value)

    def get_uint8(self):
        """Read the next token and interpret it as an 8-bit unsigned
        integer.

        @raises dns.exception.SyntaxError:
        @rtype: int
        """

        value = self.get_int()
        if value < 0 or value > 255:
            raise dns.exception.SyntaxError(
                '%d is not an unsigned 8-bit integer' % value)
        return value

    def get_uint16(self):
        """Read the next token and interpret it as a 16-bit unsigned
        integer.

        @raises dns.exception.SyntaxError:
        @rtype: int
        """

        value = self.get_int()
        if value < 0 or value > 65535:
            raise dns.exception.SyntaxError(
                '%d is not an unsigned 16-bit integer' % value)
        return value

    def get_uint32(self):
        """Read the next token and interpret it as a 32-bit unsigned
        integer.

        @raises dns.exception.SyntaxError:
        @rtype: int
        """

        token = self.get().unescape()
        if not token.is_identifier():
            raise dns.exception.SyntaxError('expecting an identifier')
        if not token.value.isdigit():
            raise dns.exception.SyntaxError('expecting an integer')
        value = long(token.value)
        if value < 0 or value > long(4294967296):
            raise dns.exception.SyntaxError(
                '%d is not an unsigned 32-bit integer' % value)
        return value

    def get_string(self, origin=None):
        """Read the next token and interpret it as a string.

        @raises dns.exception.SyntaxError:
        @rtype: string
        """

        token = self.get().unescape()
        if not (token.is_identifier() or token.is_quoted_string()):
            raise dns.exception.SyntaxError('expecting a string')
        return token.value

    def get_identifier(self, origin=None):
        """Read the next token and raise an exception if it is not an identifier.

        @raises dns.exception.SyntaxError:
        @rtype: string
        """

        token = self.get().unescape()
        if not token.is_identifier():
            raise dns.exception.SyntaxError('expecting an identifier')
        return token.value

    def get_name(self, origin=None):
        """Read the next token and interpret it as a DNS name.

        @raises dns.exception.SyntaxError:
        @rtype: dns.name.Name object"""

        token = self.get()
        if not token.is_identifier():
            raise dns.exception.SyntaxError('expecting an identifier')
        return dns.name.from_text(token.value, origin)

    def get_eol(self):
        """Read the next token and raise an exception if it isn't EOL or
        EOF.

        @raises dns.exception.SyntaxError:
        @rtype: string
        """

        token = self.get()
        if not token.is_eol_or_eof():
            raise dns.exception.SyntaxError(
                'expected EOL or EOF, got %d "%s"' % (token.ttype,
                                                      token.value))
        return token.value

    def get_ttl(self):
        token = self.get().unescape()
        if not token.is_identifier():
            raise dns.exception.SyntaxError('expecting an identifier')
        return dns.ttl.from_text(token.value)
reversename.py000064400000006357150351404300007440 0ustar00# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS Reverse Map Names.

@var ipv4_reverse_domain: The DNS IPv4 reverse-map domain, in-addr.arpa.
@type ipv4_reverse_domain: dns.name.Name object
@var ipv6_reverse_domain: The DNS IPv6 reverse-map domain, ip6.arpa.
@type ipv6_reverse_domain: dns.name.Name object
"""

import binascii
import sys

import dns.name
import dns.ipv6
import dns.ipv4

ipv4_reverse_domain = dns.name.from_text('in-addr.arpa.')
ipv6_reverse_domain = dns.name.from_text('ip6.arpa.')


def from_address(text):
    """Convert an IPv4 or IPv6 address in textual form into a Name object whose
    value is the reverse-map domain name of the address.
    @param text: an IPv4 or IPv6 address in textual form (e.g. '127.0.0.1',
    '::1')
    @type text: str
    @rtype: dns.name.Name object
    """
    try:
        v6 = dns.ipv6.inet_aton(text)
        if dns.ipv6.is_mapped(v6):
            if sys.version_info >= (3,):
                parts = ['%d' % byte for byte in v6[12:]]
            else:
                parts = ['%d' % ord(byte) for byte in v6[12:]]
            origin = ipv4_reverse_domain
        else:
            parts = [x for x in str(binascii.hexlify(v6).decode())]
            origin = ipv6_reverse_domain
    except Exception:
        parts = ['%d' %
                 byte for byte in bytearray(dns.ipv4.inet_aton(text))]
        origin = ipv4_reverse_domain
    parts.reverse()
    return dns.name.from_text('.'.join(parts), origin=origin)


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: 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 dns.ipv4.inet_ntoa(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 dns.ipv6.inet_ntoa(dns.ipv6.inet_aton(text))
    else:
        raise dns.exception.SyntaxError('unknown reverse-map address family')
grange.py000064400000003665150351404300006366 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS GENERATE range conversion."""

import dns


def from_text(text):
    """Convert the text form of a range in a GENERATE statement to an
    integer.

    @param text: the textual range
    @type text: string
    @return: The start, stop and step values.
    @rtype: tuple
    """
    # TODO, figure out the bounds on start, stop and step.

    step = 1
    cur = ''
    state = 0
    # state   0 1 2 3 4
    #         x - y / z

    if text and text[0] == '-':
        raise dns.exception.SyntaxError("Start cannot be a negative number")

    for c in text:
        if c == '-' and state == 0:
            start = int(cur)
            cur = ''
            state = 2
        elif c == '/':
            stop = int(cur)
            cur = ''
            state = 4
        elif c.isdigit():
            cur += c
        else:
            raise dns.exception.SyntaxError("Could not parse %s" % (c))

    if state in (1, 3):
        raise dns.exception.SyntaxError()

    if state == 2:
        stop = int(cur)

    if state == 4:
        step = int(cur)

    assert step >= 1
    assert start >= 0
    assert start <= stop
    # TODO, can start == stop?

    return (start, stop, step)
ttl.py000064400000004353150351404300005721 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS TTL conversion."""

import dns.exception
from ._compat import long


class BadTTL(dns.exception.SyntaxError):

    """DNS TTL value is not well-formed."""


def from_text(text):
    """Convert the text form of a TTL to an integer.

    The BIND 8 units syntax for TTLs (e.g. '1w6d4h3m10s') is supported.

    @param text: the textual TTL
    @type text: string
    @raises dns.ttl.BadTTL: the TTL is not well-formed
    @rtype: int
    """

    if text.isdigit():
        total = long(text)
    else:
        if not text[0].isdigit():
            raise BadTTL
        total = long(0)
        current = long(0)
        for c in text:
            if c.isdigit():
                current *= 10
                current += long(c)
            else:
                c = c.lower()
                if c == 'w':
                    total += current * long(604800)
                elif c == 'd':
                    total += current * long(86400)
                elif c == 'h':
                    total += current * long(3600)
                elif c == 'm':
                    total += current * long(60)
                elif c == 's':
                    total += current
                else:
                    raise BadTTL("unknown unit '%s'" % c)
                current = 0
        if not current == 0:
            raise BadTTL("trailing integer")
    if total < long(0) or total > long(2147483647):
        raise BadTTL("TTL should be between 0 and 2^31 - 1 (inclusive)")
    return total
node.py000064400000013650150351404300006043 0ustar00# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS nodes.  A node is a set of rdatasets."""

from io import StringIO

import dns.rdataset
import dns.rdatatype
import dns.renderer


class Node(object):

    """A DNS node.

    A node is a set of rdatasets

    @ivar rdatasets: the node's rdatasets
    @type rdatasets: list of dns.rdataset.Rdataset objects"""

    __slots__ = ['rdatasets']

    def __init__(self):
        """Initialize a DNS node.
        """

        self.rdatasets = []

    def to_text(self, name, **kw):
        """Convert a node to text format.

        Each rdataset at the node is printed.  Any keyword arguments
        to this method are passed on to the rdataset's to_text() method.
        @param name: the owner name of the rdatasets
        @type name: dns.name.Name object
        @rtype: string
        """

        s = StringIO()
        for rds in self.rdatasets:
            if len(rds) > 0:
                s.write(rds.to_text(name, **kw))
                s.write(u'\n')
        return s.getvalue()[:-1]

    def __repr__(self):
        return '<DNS node ' + str(id(self)) + '>'

    def __eq__(self, other):
        """Two nodes are equal if they have the same rdatasets.

        @rtype: bool
        """
        #
        # This is inefficient.  Good thing we don't need to do it much.
        #
        for rd in self.rdatasets:
            if rd not in other.rdatasets:
                return False
        for rd in other.rdatasets:
            if rd not in self.rdatasets:
                return False
        return True

    def __ne__(self, other):
        return not self.__eq__(other)

    def __len__(self):
        return len(self.rdatasets)

    def __iter__(self):
        return iter(self.rdatasets)

    def find_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE,
                      create=False):
        """Find an rdataset matching the specified properties in the
        current node.

        @param rdclass: The class of the rdataset
        @type rdclass: int
        @param rdtype: The type of the rdataset
        @type rdtype: int
        @param covers: The covered type.  Usually this value is
        dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or
        dns.rdatatype.RRSIG, then the covers value will be the rdata
        type the SIG/RRSIG covers.  The library treats the SIG and RRSIG
        types as if they were a family of
        types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA).  This makes RRSIGs much
        easier to work with than if RRSIGs covering different rdata
        types were aggregated into a single RRSIG rdataset.
        @type covers: int
        @param create: If True, create the rdataset if it is not found.
        @type create: bool
        @raises KeyError: An rdataset of the desired type and class does
        not exist and I{create} is not True.
        @rtype: dns.rdataset.Rdataset object
        """

        for rds in self.rdatasets:
            if rds.match(rdclass, rdtype, covers):
                return rds
        if not create:
            raise KeyError
        rds = dns.rdataset.Rdataset(rdclass, rdtype)
        self.rdatasets.append(rds)
        return rds

    def get_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE,
                     create=False):
        """Get an rdataset matching the specified properties in the
        current node.

        None is returned if an rdataset of the specified type and
        class does not exist and I{create} is not True.

        @param rdclass: The class of the rdataset
        @type rdclass: int
        @param rdtype: The type of the rdataset
        @type rdtype: int
        @param covers: The covered type.
        @type covers: int
        @param create: If True, create the rdataset if it is not found.
        @type create: bool
        @rtype: dns.rdataset.Rdataset object or None
        """

        try:
            rds = self.find_rdataset(rdclass, rdtype, covers, create)
        except KeyError:
            rds = None
        return rds

    def delete_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE):
        """Delete the rdataset matching the specified properties in the
        current node.

        If a matching rdataset does not exist, it is not an error.

        @param rdclass: The class of the rdataset
        @type rdclass: int
        @param rdtype: The type of the rdataset
        @type rdtype: int
        @param covers: The covered type.
        @type covers: int
        """

        rds = self.get_rdataset(rdclass, rdtype, covers)
        if rds is not None:
            self.rdatasets.remove(rds)

    def replace_rdataset(self, replacement):
        """Replace an rdataset.

        It is not an error if there is no rdataset matching I{replacement}.

        Ownership of the I{replacement} object is transferred to the node;
        in other words, this method does not store a copy of I{replacement}
        at the node, it stores I{replacement} itself.
        """

        if not isinstance(replacement, dns.rdataset.Rdataset):
            raise ValueError('replacement is not an rdataset')
        self.delete_rdataset(replacement.rdclass, replacement.rdtype,
                             replacement.covers)
        self.rdatasets.append(replacement)
tsig.py000064400000017046150351404300006067 0ustar00# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS TSIG support."""

import hmac
import struct

import dns.exception
import dns.hash
import dns.rdataclass
import dns.name
from ._compat import long, string_types, text_type

class BadTime(dns.exception.DNSException):

    """The current time is not within the TSIG's validity time."""


class BadSignature(dns.exception.DNSException):

    """The TSIG signature fails to verify."""


class PeerError(dns.exception.DNSException):

    """Base class for all TSIG errors generated by the remote peer"""


class PeerBadKey(PeerError):

    """The peer didn't know the key we used"""


class PeerBadSignature(PeerError):

    """The peer didn't like the signature we sent"""


class PeerBadTime(PeerError):

    """The peer didn't like the time we sent"""


class PeerBadTruncation(PeerError):

    """The peer didn't like amount of truncation in the TSIG we sent"""

# TSIG Algorithms

HMAC_MD5 = dns.name.from_text("HMAC-MD5.SIG-ALG.REG.INT")
HMAC_SHA1 = dns.name.from_text("hmac-sha1")
HMAC_SHA224 = dns.name.from_text("hmac-sha224")
HMAC_SHA256 = dns.name.from_text("hmac-sha256")
HMAC_SHA384 = dns.name.from_text("hmac-sha384")
HMAC_SHA512 = dns.name.from_text("hmac-sha512")

_hashes = {
    HMAC_SHA224: 'SHA224',
    HMAC_SHA256: 'SHA256',
    HMAC_SHA384: 'SHA384',
    HMAC_SHA512: 'SHA512',
    HMAC_SHA1: 'SHA1',
    HMAC_MD5: 'MD5',
}

default_algorithm = HMAC_MD5

BADSIG = 16
BADKEY = 17
BADTIME = 18
BADTRUNC = 22


def sign(wire, keyname, secret, time, fudge, original_id, error,
         other_data, request_mac, ctx=None, multi=False, first=True,
         algorithm=default_algorithm):
    """Return a (tsig_rdata, mac, ctx) tuple containing the HMAC TSIG rdata
    for the input parameters, the HMAC MAC calculated by applying the
    TSIG signature algorithm, and the TSIG digest context.
    @rtype: (string, string, hmac.HMAC object)
    @raises ValueError: I{other_data} is too long
    @raises NotImplementedError: I{algorithm} is not supported
    """

    if isinstance(other_data, text_type):
        other_data = other_data.encode()
    (algorithm_name, digestmod) = get_algorithm(algorithm)
    if first:
        ctx = hmac.new(secret, digestmod=digestmod)
        ml = len(request_mac)
        if ml > 0:
            ctx.update(struct.pack('!H', ml))
            ctx.update(request_mac)
    id = struct.pack('!H', original_id)
    ctx.update(id)
    ctx.update(wire[2:])
    if first:
        ctx.update(keyname.to_digestable())
        ctx.update(struct.pack('!H', dns.rdataclass.ANY))
        ctx.update(struct.pack('!I', 0))
    long_time = time + long(0)
    upper_time = (long_time >> 32) & long(0xffff)
    lower_time = long_time & long(0xffffffff)
    time_mac = struct.pack('!HIH', upper_time, lower_time, fudge)
    pre_mac = algorithm_name + time_mac
    ol = len(other_data)
    if ol > 65535:
        raise ValueError('TSIG Other Data is > 65535 bytes')
    post_mac = struct.pack('!HH', error, ol) + other_data
    if first:
        ctx.update(pre_mac)
        ctx.update(post_mac)
    else:
        ctx.update(time_mac)
    mac = ctx.digest()
    mpack = struct.pack('!H', len(mac))
    tsig_rdata = pre_mac + mpack + mac + id + post_mac
    if multi:
        ctx = hmac.new(secret, digestmod=digestmod)
        ml = len(mac)
        ctx.update(struct.pack('!H', ml))
        ctx.update(mac)
    else:
        ctx = None
    return (tsig_rdata, mac, ctx)


def hmac_md5(wire, keyname, secret, time, fudge, original_id, error,
             other_data, request_mac, ctx=None, multi=False, first=True,
             algorithm=default_algorithm):
    return sign(wire, keyname, secret, time, fudge, original_id, error,
                other_data, request_mac, ctx, multi, first, algorithm)


def validate(wire, keyname, secret, now, request_mac, tsig_start, tsig_rdata,
             tsig_rdlen, ctx=None, multi=False, first=True):
    """Validate the specified TSIG rdata against the other input parameters.

    @raises FormError: The TSIG is badly formed.
    @raises BadTime: There is too much time skew between the client and the
    server.
    @raises BadSignature: The TSIG signature did not validate
    @rtype: hmac.HMAC object"""

    (adcount,) = struct.unpack("!H", wire[10:12])
    if adcount == 0:
        raise dns.exception.FormError
    adcount -= 1
    new_wire = wire[0:10] + struct.pack("!H", adcount) + wire[12:tsig_start]
    current = tsig_rdata
    (aname, used) = dns.name.from_wire(wire, current)
    current = current + used
    (upper_time, lower_time, fudge, mac_size) = \
        struct.unpack("!HIHH", wire[current:current + 10])
    time = ((upper_time + long(0)) << 32) + (lower_time + long(0))
    current += 10
    mac = wire[current:current + mac_size]
    current += mac_size
    (original_id, error, other_size) = \
        struct.unpack("!HHH", wire[current:current + 6])
    current += 6
    other_data = wire[current:current + other_size]
    current += other_size
    if current != tsig_rdata + tsig_rdlen:
        raise dns.exception.FormError
    if error != 0:
        if error == BADSIG:
            raise PeerBadSignature
        elif error == BADKEY:
            raise PeerBadKey
        elif error == BADTIME:
            raise PeerBadTime
        elif error == BADTRUNC:
            raise PeerBadTruncation
        else:
            raise PeerError('unknown TSIG error code %d' % error)
    time_low = time - fudge
    time_high = time + fudge
    if now < time_low or now > time_high:
        raise BadTime
    (junk, our_mac, ctx) = sign(new_wire, keyname, secret, time, fudge,
                                original_id, error, other_data,
                                request_mac, ctx, multi, first, aname)
    if our_mac != mac:
        raise BadSignature
    return ctx


def get_algorithm(algorithm):
    """Returns the wire format string and the hash module to use for the
    specified TSIG algorithm

    @rtype: (string, hash constructor)
    @raises NotImplementedError: I{algorithm} is not supported
    """

    if isinstance(algorithm, string_types):
        algorithm = dns.name.from_text(algorithm)

    try:
        return (algorithm.to_digestable(), dns.hash.hashes[_hashes[algorithm]])
    except KeyError:
        raise NotImplementedError("TSIG algorithm " + str(algorithm) +
                                  " is not supported")


def get_algorithm_and_mac(wire, tsig_rdata, tsig_rdlen):
    """Return the tsig algorithm for the specified tsig_rdata
    @raises FormError: The TSIG is badly formed.
    """
    current = tsig_rdata
    (aname, used) = dns.name.from_wire(wire, current)
    current = current + used
    (upper_time, lower_time, fudge, mac_size) = \
        struct.unpack("!HIHH", wire[current:current + 10])
    current += 10
    mac = wire[current:current + mac_size]
    current += mac_size
    if current > tsig_rdata + tsig_rdlen:
        raise dns.exception.FormError
    return (aname, mac)
_compat.py000064400000002441150351404300006534 0ustar00import sys
import decimal
from decimal import Context

if sys.version_info > (3,):
    long = int
    xrange = range
else:
    long = long  # pylint: disable=long-builtin
    xrange = xrange  # pylint: disable=xrange-builtin

# unicode / binary types
if sys.version_info > (3,):
    text_type = str
    binary_type = bytes
    string_types = (str,)
    unichr = chr
    def maybe_decode(x):
        return x.decode()
    def maybe_encode(x):
        return x.encode()
else:
    text_type = unicode  # pylint: disable=unicode-builtin, undefined-variable
    binary_type = str
    string_types = (
        basestring,  # pylint: disable=basestring-builtin, undefined-variable
    )
    unichr = unichr  # pylint: disable=unichr-builtin
    def maybe_decode(x):
        return x
    def maybe_encode(x):
        return x


def round_py2_compat(what):
    """
    Python 2 and Python 3 use different rounding strategies in round(). This
    function ensures that results are python2/3 compatible and backward
    compatible with previous py2 releases
    :param what: float
    :return: rounded long
    """
    d = Context(
        prec=len(str(long(what))),  # round to integer with max precision
        rounding=decimal.ROUND_HALF_UP
    ).create_decimal(str(what))  # str(): python 2.6 compat
    return long(d)
entropy.py000064400000010561150351404300006614 0ustar00# Copyright (C) 2009, 2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import os
import random
import time
from ._compat import long, binary_type
try:
    import threading as _threading
except ImportError:
    import dummy_threading as _threading


class EntropyPool(object):

    def __init__(self, seed=None):
        self.pool_index = 0
        self.digest = None
        self.next_byte = 0
        self.lock = _threading.Lock()
        try:
            import hashlib
            self.hash = hashlib.sha1()
            self.hash_len = 20
        except ImportError:
            try:
                import sha
                self.hash = sha.new()
                self.hash_len = 20
            except ImportError:
                import md5  # pylint: disable=import-error
                self.hash = md5.new()
                self.hash_len = 16
        self.pool = bytearray(b'\0' * self.hash_len)
        if seed is not None:
            self.stir(bytearray(seed))
            self.seeded = True
            self.seed_pid = os.getpid()
        else:
            self.seeded = False
            self.seed_pid = 0

    def stir(self, entropy, already_locked=False):
        if not already_locked:
            self.lock.acquire()
        try:
            for c in entropy:
                if self.pool_index == self.hash_len:
                    self.pool_index = 0
                b = c & 0xff
                self.pool[self.pool_index] ^= b
                self.pool_index += 1
        finally:
            if not already_locked:
                self.lock.release()

    def _maybe_seed(self):
        if not self.seeded or self.seed_pid != os.getpid():
            try:
                seed = os.urandom(16)
            except Exception:
                try:
                    r = open('/dev/urandom', 'rb', 0)
                    try:
                        seed = r.read(16)
                    finally:
                        r.close()
                except Exception:
                    seed = str(time.time())
            self.seeded = True
            self.seed_pid = os.getpid()
            self.digest = None
            seed = bytearray(seed)
            self.stir(seed, True)

    def random_8(self):
        self.lock.acquire()
        try:
            self._maybe_seed()
            if self.digest is None or self.next_byte == self.hash_len:
                self.hash.update(binary_type(self.pool))
                self.digest = bytearray(self.hash.digest())
                self.stir(self.digest, True)
                self.next_byte = 0
            value = self.digest[self.next_byte]
            self.next_byte += 1
        finally:
            self.lock.release()
        return value

    def random_16(self):
        return self.random_8() * 256 + self.random_8()

    def random_32(self):
        return self.random_16() * 65536 + self.random_16()

    def random_between(self, first, last):
        size = last - first + 1
        if size > long(4294967296):
            raise ValueError('too big')
        if size > 65536:
            rand = self.random_32
            max = long(4294967295)
        elif size > 256:
            rand = self.random_16
            max = 65535
        else:
            rand = self.random_8
            max = 255
        return first + size * rand() // (max + 1)

pool = EntropyPool()

try:
    system_random = random.SystemRandom()
except Exception:
    system_random = None

def random_16():
    if system_random is not None:
        return system_random.randrange(0, 65536)
    else:
        return pool.random_16()

def between(first, last):
    if system_random is not None:
        return system_random.randrange(first, last + 1)
    else:
        return pool.random_between(first, last)
opcode.py000064400000004752150351404300006372 0ustar00# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS Opcodes."""

import dns.exception

QUERY = 0
IQUERY = 1
STATUS = 2
NOTIFY = 4
UPDATE = 5

_by_text = {
    'QUERY': QUERY,
    'IQUERY': IQUERY,
    'STATUS': STATUS,
    'NOTIFY': NOTIFY,
    'UPDATE': UPDATE
}

# We construct the inverse mapping programmatically to ensure that we
# cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
# would cause the mapping not to be true inverse.

_by_value = dict((y, x) for x, y in _by_text.items())


class UnknownOpcode(dns.exception.DNSException):

    """An DNS opcode is unknown."""


def from_text(text):
    """Convert text into an opcode.

    @param text: the textual opcode
    @type text: string
    @raises UnknownOpcode: the opcode is unknown
    @rtype: int
    """

    if text.isdigit():
        value = int(text)
        if value >= 0 and value <= 15:
            return value
    value = _by_text.get(text.upper())
    if value is None:
        raise UnknownOpcode
    return value


def from_flags(flags):
    """Extract an opcode from DNS message flags.

    @param flags: int
    @rtype: int
    """

    return (flags & 0x7800) >> 11


def to_flags(value):
    """Convert an opcode to a value suitable for ORing into DNS message
    flags.
    @rtype: int
    """

    return (value << 11) & 0x7800


def to_text(value):
    """Convert an opcode to text.

    @param value: the opcdoe
    @type value: int
    @raises UnknownOpcode: the opcode is unknown
    @rtype: string
    """

    text = _by_value.get(value)
    if text is None:
        text = str(value)
    return text


def is_update(flags):
    """True if the opcode in flags is UPDATE.

    @param flags: DNS flags
    @type flags: int
    @rtype: bool
    """

    return from_flags(flags) == UPDATE
rdtypes/nsbase.py000064400000005443150351404300010064 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""NS-like base classes."""

from io import BytesIO

import dns.exception
import dns.rdata
import dns.name


class NSBase(dns.rdata.Rdata):

    """Base class for rdata that is like an NS record.

    @ivar target: the target name of the rdata
    @type target: dns.name.Name object"""

    __slots__ = ['target']

    def __init__(self, rdclass, rdtype, target):
        super(NSBase, self).__init__(rdclass, rdtype)
        self.target = target

    def to_text(self, origin=None, relativize=True, **kw):
        target = self.target.choose_relativity(origin, relativize)
        return str(target)

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        target = tok.get_name()
        target = target.choose_relativity(origin, relativize)
        tok.get_eol()
        return cls(rdclass, rdtype, target)

    def to_wire(self, file, compress=None, origin=None):
        self.target.to_wire(file, compress, origin)

    def to_digestable(self, origin=None):
        return self.target.to_digestable(origin)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        (target, cused) = dns.name.from_wire(wire[: current + rdlen],
                                             current)
        if cused != rdlen:
            raise dns.exception.FormError
        if origin is not None:
            target = target.relativize(origin)
        return cls(rdclass, rdtype, target)

    def choose_relativity(self, origin=None, relativize=True):
        self.target = self.target.choose_relativity(origin, relativize)


class UncompressedNS(NSBase):

    """Base class for rdata that is like an NS record, but whose name
    is not compressed when convert to DNS wire format, and whose
    digestable form is not downcased."""

    def to_wire(self, file, compress=None, origin=None):
        super(UncompressedNS, self).to_wire(file, None, origin)

    def to_digestable(self, origin=None):
        f = BytesIO()
        self.to_wire(f, None, origin)
        return f.getvalue()
rdtypes/__init__.py000064400000001577150351404300010354 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS rdata type classes"""

__all__ = [
    'ANY',
    'IN',
    'euibase',
    'mxbase',
    'nsbase',
]
rdtypes/IN/APL.py000064400000012164150351404300007531 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct
import binascii

import dns.exception
import dns.inet
import dns.rdata
import dns.tokenizer
from dns._compat import xrange


class APLItem(object):

    """An APL list item.

    @ivar family: the address family (IANA address family registry)
    @type family: int
    @ivar negation: is this item negated?
    @type negation: bool
    @ivar address: the address
    @type address: string
    @ivar prefix: the prefix length
    @type prefix: int
    """

    __slots__ = ['family', 'negation', 'address', 'prefix']

    def __init__(self, family, negation, address, prefix):
        self.family = family
        self.negation = negation
        self.address = address
        self.prefix = prefix

    def __str__(self):
        if self.negation:
            return "!%d:%s/%s" % (self.family, self.address, self.prefix)
        else:
            return "%d:%s/%s" % (self.family, self.address, self.prefix)

    def to_wire(self, file):
        if self.family == 1:
            address = dns.inet.inet_pton(dns.inet.AF_INET, self.address)
        elif self.family == 2:
            address = dns.inet.inet_pton(dns.inet.AF_INET6, self.address)
        else:
            address = binascii.unhexlify(self.address)
        #
        # Truncate least significant zero bytes.
        #
        last = 0
        for i in xrange(len(address) - 1, -1, -1):
            if address[i] != chr(0):
                last = i + 1
                break
        address = address[0: last]
        l = len(address)
        assert l < 128
        if self.negation:
            l |= 0x80
        header = struct.pack('!HBB', self.family, self.prefix, l)
        file.write(header)
        file.write(address)


class APL(dns.rdata.Rdata):

    """APL record.

    @ivar items: a list of APL items
    @type items: list of APL_Item
    @see: RFC 3123"""

    __slots__ = ['items']

    def __init__(self, rdclass, rdtype, items):
        super(APL, self).__init__(rdclass, rdtype)
        self.items = items

    def to_text(self, origin=None, relativize=True, **kw):
        return ' '.join(map(str, self.items))

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        items = []
        while 1:
            token = tok.get().unescape()
            if token.is_eol_or_eof():
                break
            item = token.value
            if item[0] == '!':
                negation = True
                item = item[1:]
            else:
                negation = False
            (family, rest) = item.split(':', 1)
            family = int(family)
            (address, prefix) = rest.split('/', 1)
            prefix = int(prefix)
            item = APLItem(family, negation, address, prefix)
            items.append(item)

        return cls(rdclass, rdtype, items)

    def to_wire(self, file, compress=None, origin=None):
        for item in self.items:
            item.to_wire(file)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        items = []
        while 1:
            if rdlen == 0:
                break
            if rdlen < 4:
                raise dns.exception.FormError
            header = struct.unpack('!HBB', wire[current: current + 4])
            afdlen = header[2]
            if afdlen > 127:
                negation = True
                afdlen -= 128
            else:
                negation = False
            current += 4
            rdlen -= 4
            if rdlen < afdlen:
                raise dns.exception.FormError
            address = wire[current: current + afdlen].unwrap()
            l = len(address)
            if header[0] == 1:
                if l < 4:
                    address += '\x00' * (4 - l)
                address = dns.inet.inet_ntop(dns.inet.AF_INET, address)
            elif header[0] == 2:
                if l < 16:
                    address += '\x00' * (16 - l)
                address = dns.inet.inet_ntop(dns.inet.AF_INET6, address)
            else:
                #
                # This isn't really right according to the RFC, but it
                # seems better than throwing an exception
                #
                address = address.encode('hex_codec')
            current += afdlen
            rdlen -= afdlen
            item = APLItem(header[0], negation, address, header[1])
            items.append(item)
        return cls(rdclass, rdtype, items)
rdtypes/IN/__init__.py000064400000001705150351404300010653 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""Class IN rdata type classes."""

__all__ = [
    'A',
    'AAAA',
    'APL',
    'DHCID',
    'KX',
    'NAPTR',
    'NSAP',
    'NSAP_PTR',
    'PX',
    'SRV',
    'WKS',
]
rdtypes/IN/DHCID.py000064400000003743150351404300007733 0ustar00# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import base64

import dns.exception


class DHCID(dns.rdata.Rdata):

    """DHCID record

    @ivar data: the data (the content of the RR is opaque as far as the
    DNS is concerned)
    @type data: string
    @see: RFC 4701"""

    __slots__ = ['data']

    def __init__(self, rdclass, rdtype, data):
        super(DHCID, self).__init__(rdclass, rdtype)
        self.data = data

    def to_text(self, origin=None, relativize=True, **kw):
        return dns.rdata._base64ify(self.data)

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        chunks = []
        while 1:
            t = tok.get().unescape()
            if t.is_eol_or_eof():
                break
            if not t.is_identifier():
                raise dns.exception.SyntaxError
            chunks.append(t.value.encode())
        b64 = b''.join(chunks)
        data = base64.b64decode(b64)
        return cls(rdclass, rdtype, data)

    def to_wire(self, file, compress=None, origin=None):
        file.write(self.data)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        data = wire[current: current + rdlen].unwrap()
        return cls(rdclass, rdtype, data)
rdtypes/IN/NSAP_PTR.py000064400000001575150351404300010407 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.nsbase


class NSAP_PTR(dns.rdtypes.nsbase.UncompressedNS):

    """NSAP-PTR record"""
rdtypes/IN/IPSECKEY.py000064400000013061150351404300010326 0ustar00# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct
import base64

import dns.exception
import dns.inet
import dns.name


class IPSECKEY(dns.rdata.Rdata):

    """IPSECKEY record

    @ivar precedence: the precedence for this key data
    @type precedence: int
    @ivar gateway_type: the gateway type
    @type gateway_type: int
    @ivar algorithm: the algorithm to use
    @type algorithm: int
    @ivar gateway: the public key
    @type gateway: None, IPv4 address, IPV6 address, or domain name
    @ivar key: the public key
    @type key: string
    @see: RFC 4025"""

    __slots__ = ['precedence', 'gateway_type', 'algorithm', 'gateway', 'key']

    def __init__(self, rdclass, rdtype, precedence, gateway_type, algorithm,
                 gateway, key):
        super(IPSECKEY, self).__init__(rdclass, rdtype)
        if gateway_type == 0:
            if gateway != '.' and gateway is not None:
                raise SyntaxError('invalid gateway for gateway type 0')
            gateway = None
        elif gateway_type == 1:
            # check that it's OK
            dns.inet.inet_pton(dns.inet.AF_INET, gateway)
        elif gateway_type == 2:
            # check that it's OK
            dns.inet.inet_pton(dns.inet.AF_INET6, gateway)
        elif gateway_type == 3:
            pass
        else:
            raise SyntaxError(
                'invalid IPSECKEY gateway type: %d' % gateway_type)
        self.precedence = precedence
        self.gateway_type = gateway_type
        self.algorithm = algorithm
        self.gateway = gateway
        self.key = key

    def to_text(self, origin=None, relativize=True, **kw):
        if self.gateway_type == 0:
            gateway = '.'
        elif self.gateway_type == 1:
            gateway = self.gateway
        elif self.gateway_type == 2:
            gateway = self.gateway
        elif self.gateway_type == 3:
            gateway = str(self.gateway.choose_relativity(origin, relativize))
        else:
            raise ValueError('invalid gateway type')
        return '%d %d %d %s %s' % (self.precedence, self.gateway_type,
                                   self.algorithm, gateway,
                                   dns.rdata._base64ify(self.key))

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        precedence = tok.get_uint8()
        gateway_type = tok.get_uint8()
        algorithm = tok.get_uint8()
        if gateway_type == 3:
            gateway = tok.get_name().choose_relativity(origin, relativize)
        else:
            gateway = tok.get_string()
        chunks = []
        while 1:
            t = tok.get().unescape()
            if t.is_eol_or_eof():
                break
            if not t.is_identifier():
                raise dns.exception.SyntaxError
            chunks.append(t.value.encode())
        b64 = b''.join(chunks)
        key = base64.b64decode(b64)
        return cls(rdclass, rdtype, precedence, gateway_type, algorithm,
                   gateway, key)

    def to_wire(self, file, compress=None, origin=None):
        header = struct.pack("!BBB", self.precedence, self.gateway_type,
                             self.algorithm)
        file.write(header)
        if self.gateway_type == 0:
            pass
        elif self.gateway_type == 1:
            file.write(dns.inet.inet_pton(dns.inet.AF_INET, self.gateway))
        elif self.gateway_type == 2:
            file.write(dns.inet.inet_pton(dns.inet.AF_INET6, self.gateway))
        elif self.gateway_type == 3:
            self.gateway.to_wire(file, None, origin)
        else:
            raise ValueError('invalid gateway type')
        file.write(self.key)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        if rdlen < 3:
            raise dns.exception.FormError
        header = struct.unpack('!BBB', wire[current: current + 3])
        gateway_type = header[1]
        current += 3
        rdlen -= 3
        if gateway_type == 0:
            gateway = None
        elif gateway_type == 1:
            gateway = dns.inet.inet_ntop(dns.inet.AF_INET,
                                         wire[current: current + 4])
            current += 4
            rdlen -= 4
        elif gateway_type == 2:
            gateway = dns.inet.inet_ntop(dns.inet.AF_INET6,
                                         wire[current: current + 16])
            current += 16
            rdlen -= 16
        elif gateway_type == 3:
            (gateway, cused) = dns.name.from_wire(wire[: current + rdlen],
                                                  current)
            current += cused
            rdlen -= cused
        else:
            raise dns.exception.FormError('invalid IPSECKEY gateway type')
        key = wire[current: current + rdlen].unwrap()
        return cls(rdclass, rdtype, header[0], gateway_type, header[2],
                   gateway, key)
rdtypes/IN/__pycache__/NSAP_PTR.cpython-36.opt-1.pyc000064400000000562150351404300015625 0ustar003

�b�W}�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�NSAP_PTRzNSAP-PTR recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/NSAP_PTR.pyrsr)Zdns.rdtypes.nsbaseZdnsZrdtypesZnsbaseZUncompressedNSrrrrr�<module>srdtypes/IN/__pycache__/KX.cpython-36.opt-1.pyc000064400000000540150351404300014655 0ustar003

�b�Wq�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�KXz	KX recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/KX.pyrsr)Zdns.rdtypes.mxbaseZdnsZrdtypesZmxbaseZUncompressedMXrrrrr�<module>srdtypes/IN/__pycache__/NSAP.cpython-36.opt-1.pyc000064400000003262150351404300015100 0ustar003

�b�W�@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�NcsVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�NSAPzTNSAP record.

    @ivar address: a NASP
    @type address: string
    @see: RFC 1706�addresscstt|�j||�||_dS)N)�superr�__init__r)�self�rdclass�rdtyper)�	__class__��/usr/lib/python3.6/NSAP.pyr!sz
NSAP.__init__NTcKsdtj|j�j�S)Nz0x%s)�binasciiZhexlifyr�decode)r�origin�
relativize�kwr
r
r�to_text%szNSAP.to_textcCsv|j�}|j�|dd�dkr,tjjd��|dd�jdd�}t|�ddkr\tjjd��tj|j	��}||||�S)Nr�Z0xzstring does not start with 0x�.�zhexstring has odd length)
Z
get_stringZget_eol�dnsZ	exception�SyntaxError�replace�lenrZ	unhexlify�encode)�clsrr�tokrrrr
r
r�	from_text(szNSAP.from_textcCs|j|j�dS)N)�writer)r�file�compressrr
r
r�to_wire4szNSAP.to_wirecCs ||||�j�}||||�S)N)Zunwrap)rrrZwireZcurrentZrdlenrrr
r
r�	from_wire7szNSAP.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrr r!�
__classcell__r
r
)r	rrs

r)rZ
dns.exceptionrZ	dns.rdataZ
dns.tokenizerZrdataZRdatarr
r
r
r�<module>srdtypes/IN/__pycache__/APL.cpython-36.pyc000064400000007331150351404300014015 0ustar003

�b�Wt�@sdddlZddlZddlZddlZddlZddlZddlmZGdd�de	�Z
Gdd�dejj�Z
dS)�N)�xrangec@s4eZdZdZddddgZdd�Zdd	�Zd
d�ZdS)
�APLItema'An APL list item.

    @ivar family: the address family (IANA address family registry)
    @type family: int
    @ivar negation: is this item negated?
    @type negation: bool
    @ivar address: the address
    @type address: string
    @ivar prefix: the prefix length
    @type prefix: int
    �family�negation�address�prefixcCs||_||_||_||_dS)N)rrrr)�selfrrrr�r	�/usr/lib/python3.6/APL.py�__init__*szAPLItem.__init__cCs2|jrd|j|j|jfSd|j|j|jfSdS)Nz	!%d:%s/%sz%d:%s/%s)rrrr)rr	r	r
�__str__0szAPLItem.__str__cCs�|jdkr tjjtjj|j�}n,|jdkr@tjjtjj|j�}ntj|j�}d}x6t	t
|�ddd�D]}||td�krf|d}PqfW|d|�}t
|�}|dks�t�|j
r�|dO}tjd|j|j|�}|j|�|j|�dS)N��r�z!HBB���r)r�dns�inetZ	inet_pton�AF_INETr�AF_INET6�binasciiZ	unhexlifyr�len�chr�AssertionErrorr�struct�packr�write)r�filerZlast�i�l�headerr	r	r
�to_wire6s$


zAPLItem.to_wireN)�__name__�
__module__�__qualname__�__doc__�	__slots__rrr r	r	r	r
rs
rcsVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�APLzfAPL record.

    @ivar items: a list of APL items
    @type items: list of APL_Item
    @see: RFC 3123�itemscstt|�j||�||_dS)N)�superr&rr')r�rdclass�rdtyper')�	__class__r	r
rYszAPL.__init__NTcKsdjtt|j��S)N� )�join�map�strr')r�origin�
relativize�kwr	r	r
�to_text]szAPL.to_textcCs�g}x�|j�j�}|j�rP|j}|ddkr@d}	|dd�}nd}	|jdd�\}
}t|
�}
|jdd�\}}
t|
�}
t|
|	||
�}|j|�qW||||�S)Nr�!Tr
F�:�/)�getZunescapeZ
is_eol_or_eof�value�split�intr�append)�clsr)r*�tokr0r1r'�token�itemrr�restrrr	r	r
�	from_text`s"z
APL.from_textcCsx|jD]}|j|�qWdS)N)r'r )rr�compressr0r?r	r	r
r vszAPL.to_wirecCsTg}�x@|dkrP|dkr"tjj�tjd|||d��}|d}	|	dkrXd}
|	d8}	nd}
|d7}|d8}||	kr|tjj�||||	�j�}t|�}|dd	kr�|dkr�|d
d|7}tjjtjj	|�}nD|ddk�r
|dkr�|d
d|7}tjjtjj
|�}n
|jd�}||	7}||	8}t|d|
||d	�}
|j
|
�qW||||�S)
Nr�z!HBBr�TrFr
���	hex_codec)rZ	exceptionZ	FormErrorr�unpackZunwraprrZ	inet_ntoprr�encoderr;)r<r)r*ZwireZcurrentZrdlenr0r'rZafdlenrrrr?r	r	r
�	from_wirezs@

z
APL.from_wire)NT)NT)NN)N)r!r"r#r$r%rr3�classmethodrAr rJ�
__classcell__r	r	)r+r
r&Os

r&)rrZ
dns.exceptionrZdns.inetZ	dns.rdataZ
dns.tokenizerZdns._compatr�objectrZrdataZRdatar&r	r	r	r
�<module>s5rdtypes/IN/__pycache__/SRV.cpython-36.pyc000064400000004363150351404300014055 0ustar003

�b�W��@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�NcsfeZdZdZddddgZ�fdd�Zdd
d�Zeddd
��Zddd�Z	eddd��Z
ddd�Z�ZS)�SRVaSRV record

    @ivar priority: the priority
    @type priority: int
    @ivar weight: the weight
    @type weight: int
    @ivar port: the port of the service
    @type port: int
    @ivar target: the target host
    @type target: dns.name.Name object
    @see: RFC 2782�priority�weight�port�targetcs.tt|�j||�||_||_||_||_dS)N)�superr�__init__rrrr)�self�rdclass�rdtyperrrr)�	__class__��/usr/lib/python3.6/SRV.pyr's
zSRV.__init__NTcKs$|jj||�}d|j|j|j|fS)Nz%d %d %d %s)r�choose_relativityrrr)r	�origin�
relativize�kwrr
r
r�to_text.szSRV.to_textc
CsH|j�}|j�}|j�}|jd�}	|	j||�}	|j�|||||||	�S)N)Z
get_uint16Zget_namerZget_eol)
�clsr
r�tokrrrrrrr
r
r�	from_text3s
z
SRV.from_textcCs4tjd|j|j|j�}|j|�|jj|||�dS)Nz!HHH)�struct�packrrr�writer�to_wire)r	�file�compressrZ
three_intsr
r
rr=s
zSRV.to_wirecCs�tjd|||d��\}}}	|d7}|d8}tjj|d||�|�\}
}||kr\tjj�|dk	rn|
j|�}
||||||	|
�S)Nz!HHH�)r�unpack�dns�name�	from_wireZ	exceptionZ	FormErrorr)rr
rZwireZcurrentZrdlenrrrrrZcusedr
r
rr!Bs

z
SRV.from_wirecCs|jj||�|_dS)N)rr)r	rrr
r
rrPszSRV.choose_relativity)NT)NT)NN)N)NT)
�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrr!r�
__classcell__r
r
)rrrs
	

r)rZ
dns.exceptionrZ	dns.rdataZdns.nameZrdataZRdatarr
r
r
r�<module>srdtypes/IN/__pycache__/NAPTR.cpython-36.pyc000064400000006354150351404300014271 0ustar003

�b�Wv�@sXddlZddlZddlZddlZddlmZmZdd�Zdd�Z	Gdd�dej
j�ZdS)	�N)�xrange�	text_typecCs4t|�}|dkst�|jtjd|��|j|�dS)N�z!B)�len�AssertionError�write�struct�pack)�file�s�l�r
�/usr/lib/python3.6/NAPTR.py�
_write_stringsrcCst|t�r|j�S|S)N)�
isinstancer�encode)�valuer
r
r�	_sanitizes
rcsjeZdZdZddddddgZ�fdd	�Zddd
�Zeddd��Zddd�Z	eddd��Z
ddd�Z�ZS)�NAPTRa}NAPTR record

    @ivar order: order
    @type order: int
    @ivar preference: preference
    @type preference: int
    @ivar flags: flags
    @type flags: string
    @ivar service: service
    @type service: string
    @ivar regexp: regular expression
    @type regexp: string
    @ivar replacement: replacement name
    @type replacement: dns.name.Name object
    @see: RFC 3403�order�
preference�flags�service�regexp�replacementc		sFtt|�j||�t|�|_t|�|_t|�|_||_||_||_	dS)N)
�superr�__init__rrrrrrr)	�self�rdclass�rdtyperrrrrr)�	__class__r
rr:s


zNAPTR.__init__NTcKsD|jj||�}d|j|jtjj|j�tjj|j�tjj|j	�|fS)Nz%d %d "%s" "%s" "%s" %s)
r�choose_relativityrr�dns�rdataZ	_escapifyrrr)r�origin�
relativize�kwrr
r
r�to_textDsz
NAPTR.to_textc	CsZ|j�}|j�}|j�}|j�}	|j�}
|j�}|j||�}|j�|||||||	|
|�S)N)Z
get_uint16Z
get_stringZget_namer!Zget_eol)�clsrr�tokr$r%rrrrrrr
r
r�	from_textMszNAPTR.from_textcCsTtjd|j|j�}|j|�t||j�t||j�t||j�|j	j
|||�dS)Nz!HH)rr	rrrrrrrr�to_wire)rr
�compressr$Ztwo_intsr
r
rr+Zs
z
NAPTR.to_wirec	Cstjd|||d��\}}|d7}|d8}g}	xntd�D]b}
||}|d7}|d8}||ksf|dkrntjj�||||�j�}||7}||8}|	j|�q:Wtjj	|d||�|�\}
}||kr�tjj�|dk	r�|
j
|�}
||||||	d|	d|	d|
�S)Nz!HH���r�)r�unpackrr"Z	exceptionZ	FormErrorZunwrap�append�name�	from_wirer%)r(rrZwireZcurrentZrdlenr$rrZstrings�irrrZcusedr
r
rr4bs,

zNAPTR.from_wirecCs|jj||�|_dS)N)rr!)rr$r%r
r
rr!{szNAPTR.choose_relativity)NT)NT)NN)N)NT)
�__name__�
__module__�__qualname__�__doc__�	__slots__rr'�classmethodr*r+r4r!�
__classcell__r
r
)r rr%s


	
r)
rZ
dns.exceptionr"Zdns.nameZ	dns.rdataZdns._compatrrrrr#ZRdatarr
r
r
r�<module>srdtypes/IN/__pycache__/IPSECKEY.cpython-36.pyc000064400000007032150351404300014613 0ustar003

�b�W1�@s@ddlZddlZddlZddlZddlZGdd�dejj�ZdS)�Ncs^eZdZdZdddddgZ�fdd�Zddd�Zedd
d��Zddd�Z	eddd��Z
�ZS)�IPSECKEYa�IPSECKEY record

    @ivar precedence: the precedence for this key data
    @type precedence: int
    @ivar gateway_type: the gateway type
    @type gateway_type: int
    @ivar algorithm: the algorithm to use
    @type algorithm: int
    @ivar gateway: the public key
    @type gateway: None, IPv4 address, IPV6 address, or domain name
    @ivar key: the public key
    @type key: string
    @see: RFC 4025�
precedence�gateway_type�	algorithm�gateway�keycs�tt|�j||�|dkr8|dkr2|dk	r2td��d}nN|dkrTtjjtjj|�n2|dkrptjjtjj|�n|dkrzntd|��||_	||_
||_||_||_
dS)Nr�.z"invalid gateway for gateway type 0���z!invalid IPSECKEY gateway type: %d)�superr�__init__�SyntaxError�dns�inet�	inet_pton�AF_INET�AF_INET6rrrrr)�self�rdclass�rdtyperrrrr)�	__class__��/usr/lib/python3.6/IPSECKEY.pyr
*s$
zIPSECKEY.__init__NTcKs||jdkrd}nJ|jdkr"|j}n8|jdkr4|j}n&|jdkrRt|jj||��}ntd��d|j|j|j|tjj	|j
�fS)Nrrr	r
rzinvalid gateway typez%d %d %d %s %s)rr�str�choose_relativity�
ValueErrorrrr�rdataZ
_base64ifyr)r�origin�
relativize�kwrrrr�to_textBs




zIPSECKEY.to_textcCs�|j�}|j�}|j�}|dkr2|j�j||�}	n|j�}	g}
x:|j�j�}|j�rVP|j�sftj	j
�|
j|jj
��q@Wdj|
�}tj|�}
|||||||	|
�S)Nr�)Z	get_uint8Zget_namerZ
get_string�getZunescapeZ
is_eol_or_eofZ
is_identifierr�	exceptionr�append�value�encode�join�base64Z	b64decode)�clsrr�tokrrrrrrZchunks�tZb64rrrr�	from_textQs$

zIPSECKEY.from_textcCs�tjd|j|j|j�}|j|�|jdkr,np|jdkrR|jtjjtjj	|j
��nJ|jdkrx|jtjjtjj|j
��n$|jdkr�|j
j|d|�nt
d��|j|j�dS)Nz!BBBrr	r
rzinvalid gateway type)�struct�packrrr�writerrrrrr�to_wirerr)r�file�compressr�headerrrrr1gs




zIPSECKEY.to_wirecCs2|dkrtjj�tjd|||d��}|d}|d7}|d8}|dkrNd}	n�|dkr�tjjtjj|||d��}	|d7}|d8}n||dkr�tjjtjj|||d��}	|d7}|d8}nD|dkr�tj	j
|d||�|�\}	}
||
7}||
8}ntjjd��||||�j�}||||d||d|	|�S)	Nrz!BBBr	r�r
�zinvalid IPSECKEY gateway type)rr$Z	FormErrorr.�unpackrZ	inet_ntoprr�name�	from_wireZunwrap)r*rrZwireZcurrentZrdlenrr4rrZcusedrrrrr9ws6



zIPSECKEY.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__r
r!�classmethodr-r1r9�
__classcell__rr)rrrs

r)	r.r)Z
dns.exceptionrZdns.inetZdns.namerZRdatarrrrr�<module>s
rdtypes/IN/__pycache__/NSAP_PTR.cpython-36.pyc000064400000000562150351404300014666 0ustar003

�b�W}�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�NSAP_PTRzNSAP-PTR recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/NSAP_PTR.pyrsr)Zdns.rdtypes.nsbaseZdnsZrdtypesZnsbaseZUncompressedNSrrrrr�<module>srdtypes/IN/__pycache__/NSAP.cpython-36.pyc000064400000003262150351404300014141 0ustar003

�b�W�@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�NcsVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�NSAPzTNSAP record.

    @ivar address: a NASP
    @type address: string
    @see: RFC 1706�addresscstt|�j||�||_dS)N)�superr�__init__r)�self�rdclass�rdtyper)�	__class__��/usr/lib/python3.6/NSAP.pyr!sz
NSAP.__init__NTcKsdtj|j�j�S)Nz0x%s)�binasciiZhexlifyr�decode)r�origin�
relativize�kwr
r
r�to_text%szNSAP.to_textcCsv|j�}|j�|dd�dkr,tjjd��|dd�jdd�}t|�ddkr\tjjd��tj|j	��}||||�S)Nr�Z0xzstring does not start with 0x�.�zhexstring has odd length)
Z
get_stringZget_eol�dnsZ	exception�SyntaxError�replace�lenrZ	unhexlify�encode)�clsrr�tokrrrr
r
r�	from_text(szNSAP.from_textcCs|j|j�dS)N)�writer)r�file�compressrr
r
r�to_wire4szNSAP.to_wirecCs ||||�j�}||||�S)N)Zunwrap)rrrZwireZcurrentZrdlenrrr
r
r�	from_wire7szNSAP.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrr r!�
__classcell__r
r
)r	rrs

r)rZ
dns.exceptionrZ	dns.rdataZ
dns.tokenizerZrdataZRdatarr
r
r
r�<module>srdtypes/IN/__pycache__/NAPTR.cpython-36.opt-1.pyc000064400000006311150351404300015221 0ustar003

�b�Wv�@sXddlZddlZddlZddlZddlmZmZdd�Zdd�Z	Gdd�dej
j�ZdS)	�N)�xrange�	text_typecCs(t|�}|jtjd|��|j|�dS)Nz!B)�len�write�struct�pack)�file�s�l�r�/usr/lib/python3.6/NAPTR.py�
_write_stringsr
cCst|t�r|j�S|S)N)�
isinstancer�encode)�valuerrr�	_sanitizes
rcsjeZdZdZddddddgZ�fdd	�Zddd
�Zeddd��Zddd�Z	eddd��Z
ddd�Z�ZS)�NAPTRa}NAPTR record

    @ivar order: order
    @type order: int
    @ivar preference: preference
    @type preference: int
    @ivar flags: flags
    @type flags: string
    @ivar service: service
    @type service: string
    @ivar regexp: regular expression
    @type regexp: string
    @ivar replacement: replacement name
    @type replacement: dns.name.Name object
    @see: RFC 3403�order�
preference�flags�service�regexp�replacementc		sFtt|�j||�t|�|_t|�|_t|�|_||_||_||_	dS)N)
�superr�__init__rrrrrrr)	�self�rdclass�rdtyperrrrrr)�	__class__rrr:s


zNAPTR.__init__NTcKsD|jj||�}d|j|jtjj|j�tjj|j�tjj|j	�|fS)Nz%d %d "%s" "%s" "%s" %s)
r�choose_relativityrr�dns�rdataZ	_escapifyrrr)r�origin�
relativize�kwrrrr�to_textDsz
NAPTR.to_textc	CsZ|j�}|j�}|j�}|j�}	|j�}
|j�}|j||�}|j�|||||||	|
|�S)N)Z
get_uint16Z
get_stringZget_namerZget_eol)�clsrr�tokr"r#rrrrrrrrr�	from_textMszNAPTR.from_textcCsTtjd|j|j�}|j|�t||j�t||j�t||j�|j	j
|||�dS)Nz!HH)rrrrrr
rrrr�to_wire)rr�compressr"Ztwo_intsrrrr)Zs
z
NAPTR.to_wirec	Cstjd|||d��\}}|d7}|d8}g}	xntd�D]b}
||}|d7}|d8}||ksf|dkrntjj�||||�j�}||7}||8}|	j|�q:Wtjj	|d||�|�\}
}||kr�tjj�|dk	r�|
j
|�}
||||||	d|	d|	d|
�S)Nz!HH���r�)r�unpackrr Z	exceptionZ	FormErrorZunwrap�append�name�	from_wirer#)r&rrZwireZcurrentZrdlenr"rrZstrings�ir
r	rZcusedrrrr2bs,

zNAPTR.from_wirecCs|jj||�|_dS)N)rr)rr"r#rrrr{szNAPTR.choose_relativity)NT)NT)NN)N)NT)
�__name__�
__module__�__qualname__�__doc__�	__slots__rr%�classmethodr(r)r2r�
__classcell__rr)rrr%s


	
r)
rZ
dns.exceptionr Zdns.nameZ	dns.rdataZdns._compatrrr
rr!ZRdatarrrrr�<module>srdtypes/IN/__pycache__/AAAA.cpython-36.pyc000064400000003037150351404300014063 0ustar003

�b�W��@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�NcsVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�AAAAzhAAAA record.

    @ivar address: an IPv6 address
    @type address: string (in the standard IPv6 format)�addresscs.tt|�j||�tjjtjj|�||_dS)N)�superr�__init__�dns�inet�	inet_pton�AF_INET6r)�self�rdclass�rdtyper)�	__class__��/usr/lib/python3.6/AAAA.pyrsz
AAAA.__init__NTcKs|jS)N)r)r
�origin�
relativize�kwrrr�to_text%szAAAA.to_textcCs|j�}|j�||||�S)N)Zget_identifierZget_eol)�clsrr�tokrrrrrr�	from_text(szAAAA.from_textcCs|jtjjtjj|j��dS)N)�writerrrr	r)r
�file�compressrrrr�to_wire.szAAAA.to_wirecCs*tjjtjj||||��}||||�S)N)rrZ	inet_ntopr	)rrrZwireZcurrentZrdlenrrrrr�	from_wire1szAAAA.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrr�
__classcell__rr)r
rrs

r)Z
dns.exceptionrZdns.inetZ	dns.rdataZ
dns.tokenizerZrdataZRdatarrrrr�<module>srdtypes/IN/__pycache__/PX.cpython-36.pyc000064400000004441150351404300013727 0ustar003

�b�WB
�@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�NcsdeZdZdZdddgZ�fdd�Zdd	d
�Zeddd��Zdd
d�Z	eddd��Z
ddd�Z�ZS)�PXz�PX record.

    @ivar preference: the preference value
    @type preference: int
    @ivar map822: the map822 name
    @type map822: dns.name.Name object
    @ivar mapx400: the mapx400 name
    @type mapx400: dns.name.Name object
    @see: RFC 2163�
preference�map822�mapx400cs(tt|�j||�||_||_||_dS)N)�superr�__init__rrr)�self�rdclass�rdtyperrr)�	__class__��/usr/lib/python3.6/PX.pyr%szPX.__init__NTcKs,|jj||�}|jj||�}d|j||fS)Nz%d %s %s)r�choose_relativityrr)r�origin�
relativize�kwrrrrr
�to_text+sz
PX.to_textc	CsJ|j�}|j�}|j||�}|jd�}|j||�}|j�||||||�S)N)Z
get_uint16Zget_namerZget_eol)	�clsr	r
�tokrrrrrrrr
�	from_text0s
zPX.from_textcCs<tjd|j�}|j|�|jj|d|�|jj|d|�dS)Nz!H)�struct�packr�writer�to_wirer)r�file�compressrZprefrrr
r:s
z
PX.to_wirecCs�tjd|||d��\}|d7}|d8}tjj|d||�|�\}}	|	|krXtjj�||	7}||	8}|dk	rz|j|�}tjj|d||�|�\}
}	|	|kr�tjj�|dk	r�|
j|�}
||||||
�S)Nz!H�)r�unpack�dns�name�	from_wireZ	exceptionZ	FormErrorr)rr	r
ZwireZcurrentZrdlenrrrZcusedrrrr
r @s$



zPX.from_wirecCs$|jj||�|_|jj||�|_dS)N)rrr)rrrrrr
rUszPX.choose_relativity)NT)NT)NN)N)NT)
�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrr r�
__classcell__rr)rr
rs


	
r)rZ
dns.exceptionrZ	dns.rdataZdns.nameZrdataZRdatarrrrr
�<module>srdtypes/IN/__pycache__/AAAA.cpython-36.opt-1.pyc000064400000003037150351404300015022 0ustar003

�b�W��@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�NcsVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�AAAAzhAAAA record.

    @ivar address: an IPv6 address
    @type address: string (in the standard IPv6 format)�addresscs.tt|�j||�tjjtjj|�||_dS)N)�superr�__init__�dns�inet�	inet_pton�AF_INET6r)�self�rdclass�rdtyper)�	__class__��/usr/lib/python3.6/AAAA.pyrsz
AAAA.__init__NTcKs|jS)N)r)r
�origin�
relativize�kwrrr�to_text%szAAAA.to_textcCs|j�}|j�||||�S)N)Zget_identifierZget_eol)�clsrr�tokrrrrrr�	from_text(szAAAA.from_textcCs|jtjjtjj|j��dS)N)�writerrrr	r)r
�file�compressrrrr�to_wire.szAAAA.to_wirecCs*tjjtjj||||��}||||�S)N)rrZ	inet_ntopr	)rrrZwireZcurrentZrdlenrrrrr�	from_wire1szAAAA.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrr�
__classcell__rr)r
rrs

r)Z
dns.exceptionrZdns.inetZ	dns.rdataZ
dns.tokenizerZrdataZRdatarrrrr�<module>srdtypes/IN/__pycache__/WKS.cpython-36.pyc000064400000005276150351404300014053 0ustar003

�b�W��@sXddlZddlZddlZddlZddlmZejd�Zejd�Z	Gdd�dej
j�ZdS)�N)�xrange�tcp�udpcsZeZdZdZdddgZ�fdd�Zdd	d
�Zeddd��Zdd
d�Z	eddd��Z
�ZS)�WKSz�WKS record

    @ivar address: the address
    @type address: string
    @ivar protocol: the protocol
    @type protocol: int
    @ivar bitmap: the bitmap
    @type bitmap: string
    @see: RFC 1035�address�protocol�bitmapcs>tt|�j||�||_||_t|t�s4t|�|_n||_dS)N)�superr�__init__rr�
isinstance�	bytearrayr)�self�rdclass�rdtyperrr)�	__class__��/usr/lib/python3.6/WKS.pyr
)s
zWKS.__init__NTc	Kszg}xXtdt|j��D]D}|j|}x4tdd�D]&}|d|?@r0|jt|d|��q0WqWdj|�}d|j|j|fS)Nr��� z%s %d %s)r�lenr�append�str�joinrr)	r
�origin�
relativize�kw�bits�iZbyte�j�textrrr�to_text2s

zWKS.to_textcCs|j�}|j�}|j�r"t|�}n
tj|�}t�}x�|j�j�}	|	j�rJP|	j	j�r`t|	j	�}
n8|t
krx|tkrxtd��|t
kr�d}nd}tj
|	j	|�}
|
d}t|�}
|
|dkr�x t|
|d�D]}|jd�q�W||d|
d?B||<q4Wtjj|�}||||||�S)Nzprotocol must be TCP or UDPrrr�rr)Z
get_string�isdigit�int�socket�getprotobynamer�getZunescapeZ
is_eol_or_eof�value�
_proto_udp�
_proto_tcp�NotImplementedErrorZ
getservbynamerrr�dns�rdataZ_truncate_bitmap)�clsrr�tokrrrrr�tokenZservZ
protocol_textr�lrrrr�	from_text<s4


z
WKS.from_textcCs<|jtjj|j��tjd|j�}|j|�|j|j�dS)Nz!B)	�writer,�ipv4Z	inet_atonr�struct�packrr)r
�file�compressrrrrr�to_wire\s
zWKS.to_wirec
Csjtjj|||d��}tjd||d|d��\}|d7}|d8}||||�j�}	||||||	�S)N�z!B�)r,r4Z	inet_ntoar5�unpackZunwrap)
r.rrZwireZcurrentZrdlenrrrrrrr�	from_wirebsz
WKS.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__r
r!�classmethodr2r9r=�
__classcell__rr)rrrs

	


r)
r%r5Zdns.ipv4r,Z	dns.rdataZdns._compatrr&r*r)r-ZRdatarrrrr�<module>s

rdtypes/IN/__pycache__/IPSECKEY.cpython-36.opt-1.pyc000064400000007032150351404300015552 0ustar003

�b�W1�@s@ddlZddlZddlZddlZddlZGdd�dejj�ZdS)�Ncs^eZdZdZdddddgZ�fdd�Zddd�Zedd
d��Zddd�Z	eddd��Z
�ZS)�IPSECKEYa�IPSECKEY record

    @ivar precedence: the precedence for this key data
    @type precedence: int
    @ivar gateway_type: the gateway type
    @type gateway_type: int
    @ivar algorithm: the algorithm to use
    @type algorithm: int
    @ivar gateway: the public key
    @type gateway: None, IPv4 address, IPV6 address, or domain name
    @ivar key: the public key
    @type key: string
    @see: RFC 4025�
precedence�gateway_type�	algorithm�gateway�keycs�tt|�j||�|dkr8|dkr2|dk	r2td��d}nN|dkrTtjjtjj|�n2|dkrptjjtjj|�n|dkrzntd|��||_	||_
||_||_||_
dS)Nr�.z"invalid gateway for gateway type 0���z!invalid IPSECKEY gateway type: %d)�superr�__init__�SyntaxError�dns�inet�	inet_pton�AF_INET�AF_INET6rrrrr)�self�rdclass�rdtyperrrrr)�	__class__��/usr/lib/python3.6/IPSECKEY.pyr
*s$
zIPSECKEY.__init__NTcKs||jdkrd}nJ|jdkr"|j}n8|jdkr4|j}n&|jdkrRt|jj||��}ntd��d|j|j|j|tjj	|j
�fS)Nrrr	r
rzinvalid gateway typez%d %d %d %s %s)rr�str�choose_relativity�
ValueErrorrrr�rdataZ
_base64ifyr)r�origin�
relativize�kwrrrr�to_textBs




zIPSECKEY.to_textcCs�|j�}|j�}|j�}|dkr2|j�j||�}	n|j�}	g}
x:|j�j�}|j�rVP|j�sftj	j
�|
j|jj
��q@Wdj|
�}tj|�}
|||||||	|
�S)Nr�)Z	get_uint8Zget_namerZ
get_string�getZunescapeZ
is_eol_or_eofZ
is_identifierr�	exceptionr�append�value�encode�join�base64Z	b64decode)�clsrr�tokrrrrrrZchunks�tZb64rrrr�	from_textQs$

zIPSECKEY.from_textcCs�tjd|j|j|j�}|j|�|jdkr,np|jdkrR|jtjjtjj	|j
��nJ|jdkrx|jtjjtjj|j
��n$|jdkr�|j
j|d|�nt
d��|j|j�dS)Nz!BBBrr	r
rzinvalid gateway type)�struct�packrrr�writerrrrrr�to_wirerr)r�file�compressr�headerrrrr1gs




zIPSECKEY.to_wirecCs2|dkrtjj�tjd|||d��}|d}|d7}|d8}|dkrNd}	n�|dkr�tjjtjj|||d��}	|d7}|d8}n||dkr�tjjtjj|||d��}	|d7}|d8}nD|dkr�tj	j
|d||�|�\}	}
||
7}||
8}ntjjd��||||�j�}||||d||d|	|�S)	Nrz!BBBr	r�r
�zinvalid IPSECKEY gateway type)rr$Z	FormErrorr.�unpackrZ	inet_ntoprr�name�	from_wireZunwrap)r*rrZwireZcurrentZrdlenrr4rrZcusedrrrrr9ws6



zIPSECKEY.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__r
r!�classmethodr-r1r9�
__classcell__rr)rrrs

r)	r.r)Z
dns.exceptionrZdns.inetZdns.namerZRdatarrrrr�<module>s
rdtypes/IN/__pycache__/APL.cpython-36.opt-1.pyc000064400000007273150351404300014761 0ustar003

�b�Wt�@sdddlZddlZddlZddlZddlZddlZddlmZGdd�de	�Z
Gdd�dejj�Z
dS)�N)�xrangec@s4eZdZdZddddgZdd�Zdd	�Zd
d�ZdS)
�APLItema'An APL list item.

    @ivar family: the address family (IANA address family registry)
    @type family: int
    @ivar negation: is this item negated?
    @type negation: bool
    @ivar address: the address
    @type address: string
    @ivar prefix: the prefix length
    @type prefix: int
    �family�negation�address�prefixcCs||_||_||_||_dS)N)rrrr)�selfrrrr�r	�/usr/lib/python3.6/APL.py�__init__*szAPLItem.__init__cCs2|jrd|j|j|jfSd|j|j|jfSdS)Nz	!%d:%s/%sz%d:%s/%s)rrrr)rr	r	r
�__str__0szAPLItem.__str__cCs�|jdkr tjjtjj|j�}n,|jdkr@tjjtjj|j�}ntj|j�}d}x6t	t
|�ddd�D]}||td�krf|d}PqfW|d|�}t
|�}|jr�|dO}t
jd|j|j|�}|j|�|j|�dS)N��r�z!HBB���r)r�dns�inetZ	inet_pton�AF_INETr�AF_INET6�binasciiZ	unhexlifyr�len�chrr�struct�packr�write)r�filerZlast�i�l�headerr	r	r
�to_wire6s"


zAPLItem.to_wireN)�__name__�
__module__�__qualname__�__doc__�	__slots__rrrr	r	r	r
rs
rcsVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�APLzfAPL record.

    @ivar items: a list of APL items
    @type items: list of APL_Item
    @see: RFC 3123�itemscstt|�j||�||_dS)N)�superr%rr&)r�rdclass�rdtyper&)�	__class__r	r
rYszAPL.__init__NTcKsdjtt|j��S)N� )�join�map�strr&)r�origin�
relativize�kwr	r	r
�to_text]szAPL.to_textcCs�g}x�|j�j�}|j�rP|j}|ddkr@d}	|dd�}nd}	|jdd�\}
}t|
�}
|jdd�\}}
t|
�}
t|
|	||
�}|j|�qW||||�S)Nr�!Tr
F�:�/)�getZunescapeZ
is_eol_or_eof�value�split�intr�append)�clsr(r)�tokr/r0r&�token�itemrr�restrrr	r	r
�	from_text`s"z
APL.from_textcCsx|jD]}|j|�qWdS)N)r&r)rr�compressr/r>r	r	r
rvszAPL.to_wirecCsTg}�x@|dkrP|dkr"tjj�tjd|||d��}|d}	|	dkrXd}
|	d8}	nd}
|d7}|d8}||	kr|tjj�||||	�j�}t|�}|dd	kr�|dkr�|d
d|7}tjjtjj	|�}nD|ddk�r
|dkr�|d
d|7}tjjtjj
|�}n
|jd�}||	7}||	8}t|d|
||d	�}
|j
|
�qW||||�S)
Nr�z!HBBr�TrFr
���	hex_codec)rZ	exceptionZ	FormErrorr�unpackZunwraprrZ	inet_ntoprr�encoderr:)r;r(r)ZwireZcurrentZrdlenr/r&rZafdlenrrrr>r	r	r
�	from_wirezs@

z
APL.from_wire)NT)NT)NN)N)r r!r"r#r$rr2�classmethodr@rrI�
__classcell__r	r	)r*r
r%Os

r%)rrZ
dns.exceptionrZdns.inetZ	dns.rdataZ
dns.tokenizerZdns._compatr�objectrZrdataZRdatar%r	r	r	r
�<module>s5rdtypes/IN/__pycache__/KX.cpython-36.pyc000064400000000540150351404300013716 0ustar003

�b�Wq�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�KXz	KX recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/KX.pyrsr)Zdns.rdtypes.mxbaseZdnsZrdtypesZmxbaseZUncompressedMXrrrrr�<module>srdtypes/IN/__pycache__/WKS.cpython-36.opt-1.pyc000064400000005276150351404300015012 0ustar003

�b�W��@sXddlZddlZddlZddlZddlmZejd�Zejd�Z	Gdd�dej
j�ZdS)�N)�xrange�tcp�udpcsZeZdZdZdddgZ�fdd�Zdd	d
�Zeddd��Zdd
d�Z	eddd��Z
�ZS)�WKSz�WKS record

    @ivar address: the address
    @type address: string
    @ivar protocol: the protocol
    @type protocol: int
    @ivar bitmap: the bitmap
    @type bitmap: string
    @see: RFC 1035�address�protocol�bitmapcs>tt|�j||�||_||_t|t�s4t|�|_n||_dS)N)�superr�__init__rr�
isinstance�	bytearrayr)�self�rdclass�rdtyperrr)�	__class__��/usr/lib/python3.6/WKS.pyr
)s
zWKS.__init__NTc	Kszg}xXtdt|j��D]D}|j|}x4tdd�D]&}|d|?@r0|jt|d|��q0WqWdj|�}d|j|j|fS)Nr��� z%s %d %s)r�lenr�append�str�joinrr)	r
�origin�
relativize�kw�bits�iZbyte�j�textrrr�to_text2s

zWKS.to_textcCs|j�}|j�}|j�r"t|�}n
tj|�}t�}x�|j�j�}	|	j�rJP|	j	j�r`t|	j	�}
n8|t
krx|tkrxtd��|t
kr�d}nd}tj
|	j	|�}
|
d}t|�}
|
|dkr�x t|
|d�D]}|jd�q�W||d|
d?B||<q4Wtjj|�}||||||�S)Nzprotocol must be TCP or UDPrrr�rr)Z
get_string�isdigit�int�socket�getprotobynamer�getZunescapeZ
is_eol_or_eof�value�
_proto_udp�
_proto_tcp�NotImplementedErrorZ
getservbynamerrr�dns�rdataZ_truncate_bitmap)�clsrr�tokrrrrr�tokenZservZ
protocol_textr�lrrrr�	from_text<s4


z
WKS.from_textcCs<|jtjj|j��tjd|j�}|j|�|j|j�dS)Nz!B)	�writer,�ipv4Z	inet_atonr�struct�packrr)r
�file�compressrrrrr�to_wire\s
zWKS.to_wirec
Csjtjj|||d��}tjd||d|d��\}|d7}|d8}||||�j�}	||||||	�S)N�z!B�)r,r4Z	inet_ntoar5�unpackZunwrap)
r.rrZwireZcurrentZrdlenrrrrrrr�	from_wirebsz
WKS.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__r
r!�classmethodr2r9r=�
__classcell__rr)rrrs

	


r)
r%r5Zdns.ipv4r,Z	dns.rdataZdns._compatrr&r*r)r-ZRdatarrrrr�<module>s

rdtypes/IN/__pycache__/A.cpython-36.opt-1.pyc000064400000002764150351404300014525 0ustar003

�b�W=�@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�NcsVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�AznA record.

    @ivar address: an IPv4 address
    @type address: string (in the standard "dotted quad" format)�addresscs(tt|�j||�tjj|�||_dS)N)�superr�__init__�dns�ipv4�	inet_atonr)�self�rdclass�rdtyper)�	__class__��/usr/lib/python3.6/A.pyrsz
A.__init__NTcKs|jS)N)r)r	�origin�
relativize�kwr
r
r�to_text%sz	A.to_textcCs|j�}|j�||||�S)N)Zget_identifierZget_eol)�clsr
r�tokrrrr
r
r�	from_text(szA.from_textcCs|jtjj|j��dS)N)�writerrrr)r	�file�compressrr
r
r�to_wire.sz	A.to_wirecCs(tjj||||��j�}||||�S)N)rrZ	inet_ntoa�decode)rr
rZwireZcurrentZrdlenrrr
r
r�	from_wire1szA.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrr�
__classcell__r
r
)rrrs

r)Z
dns.exceptionrZdns.ipv4Z	dns.rdataZ
dns.tokenizerZrdataZRdatarr
r
r
r�<module>srdtypes/IN/__pycache__/A.cpython-36.pyc000064400000002764150351404300013566 0ustar003

�b�W=�@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�NcsVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�AznA record.

    @ivar address: an IPv4 address
    @type address: string (in the standard "dotted quad" format)�addresscs(tt|�j||�tjj|�||_dS)N)�superr�__init__�dns�ipv4�	inet_atonr)�self�rdclass�rdtyper)�	__class__��/usr/lib/python3.6/A.pyrsz
A.__init__NTcKs|jS)N)r)r	�origin�
relativize�kwr
r
r�to_text%sz	A.to_textcCs|j�}|j�||||�S)N)Zget_identifierZget_eol)�clsr
r�tokrrrr
r
r�	from_text(szA.from_textcCs|jtjj|j��dS)N)�writerrrr)r	�file�compressrr
r
r�to_wire.sz	A.to_wirecCs(tjj||||��j�}||||�S)N)rrZ	inet_ntoa�decode)rr
rZwireZcurrentZrdlenrrr
r
r�	from_wire1szA.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrr�
__classcell__r
r
)rrrs

r)Z
dns.exceptionrZdns.ipv4Z	dns.rdataZ
dns.tokenizerZrdataZRdatarr
r
r
r�<module>srdtypes/IN/__pycache__/__init__.cpython-36.pyc000064400000000420150351404300015130 0ustar003

�b�W��@s"dZddddddddd	d
dgZdS)
zClass IN rdata type classes.�AZAAAAZAPLZDHCIDZKXZNAPTRZNSAPZNSAP_PTRZPXZSRVZWKSN)�__doc__�__all__�rr�/usr/lib/python3.6/__init__.py�<module>srdtypes/IN/__pycache__/__init__.cpython-36.opt-1.pyc000064400000000420150351404300016067 0ustar003

�b�W��@s"dZddddddddd	d
dgZdS)
zClass IN rdata type classes.�AZAAAAZAPLZDHCIDZKXZNAPTRZNSAPZNSAP_PTRZPXZSRVZWKSN)�__doc__�__all__�rr�/usr/lib/python3.6/__init__.py�<module>srdtypes/IN/__pycache__/SRV.cpython-36.opt-1.pyc000064400000004363150351404300015014 0ustar003

�b�W��@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�NcsfeZdZdZddddgZ�fdd�Zdd
d�Zeddd
��Zddd�Z	eddd��Z
ddd�Z�ZS)�SRVaSRV record

    @ivar priority: the priority
    @type priority: int
    @ivar weight: the weight
    @type weight: int
    @ivar port: the port of the service
    @type port: int
    @ivar target: the target host
    @type target: dns.name.Name object
    @see: RFC 2782�priority�weight�port�targetcs.tt|�j||�||_||_||_||_dS)N)�superr�__init__rrrr)�self�rdclass�rdtyperrrr)�	__class__��/usr/lib/python3.6/SRV.pyr's
zSRV.__init__NTcKs$|jj||�}d|j|j|j|fS)Nz%d %d %d %s)r�choose_relativityrrr)r	�origin�
relativize�kwrr
r
r�to_text.szSRV.to_textc
CsH|j�}|j�}|j�}|jd�}	|	j||�}	|j�|||||||	�S)N)Z
get_uint16Zget_namerZget_eol)
�clsr
r�tokrrrrrrr
r
r�	from_text3s
z
SRV.from_textcCs4tjd|j|j|j�}|j|�|jj|||�dS)Nz!HHH)�struct�packrrr�writer�to_wire)r	�file�compressrZ
three_intsr
r
rr=s
zSRV.to_wirecCs�tjd|||d��\}}}	|d7}|d8}tjj|d||�|�\}
}||kr\tjj�|dk	rn|
j|�}
||||||	|
�S)Nz!HHH�)r�unpack�dns�name�	from_wireZ	exceptionZ	FormErrorr)rr
rZwireZcurrentZrdlenrrrrrZcusedr
r
rr!Bs

z
SRV.from_wirecCs|jj||�|_dS)N)rr)r	rrr
r
rrPszSRV.choose_relativity)NT)NT)NN)N)NT)
�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrr!r�
__classcell__r
r
)rrrs
	

r)rZ
dns.exceptionrZ	dns.rdataZdns.nameZrdataZRdatarr
r
r
r�<module>srdtypes/IN/__pycache__/DHCID.cpython-36.pyc000064400000003221150351404300014206 0ustar003

�b�W��@s(ddlZddlZGdd�dejj�ZdS)�NcsVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�DHCIDz�DHCID record

    @ivar data: the data (the content of the RR is opaque as far as the
    DNS is concerned)
    @type data: string
    @see: RFC 4701�datacstt|�j||�||_dS)N)�superr�__init__r)�self�rdclass�rdtyper)�	__class__��/usr/lib/python3.6/DHCID.pyr szDHCID.__init__NTcKstjj|j�S)N)�dns�rdataZ
_base64ifyr)r�origin�
relativize�kwr
r
r�to_text$sz
DHCID.to_textc
Cs`g}x:|j�j�}|j�rP|j�s,tjj�|j|jj	��qWdj
|�}tj|�}	||||	�S)N�)
�getZunescapeZ
is_eol_or_eofZ
is_identifierrZ	exception�SyntaxError�append�value�encode�join�base64Z	b64decode)
�clsrr�tokrrZchunks�tZb64rr
r
r�	from_text's

zDHCID.from_textcCs|j|j�dS)N)�writer)r�file�compressrr
r
r�to_wire5sz
DHCID.to_wirecCs ||||�j�}||||�S)N)Zunwrap)rrrZwireZcurrentZrdlenrrr
r
r�	from_wire8szDHCID.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrr!r"�
__classcell__r
r
)r	rrs

r)rZ
dns.exceptionrr
ZRdatarr
r
r
r�<module>srdtypes/IN/__pycache__/DHCID.cpython-36.opt-1.pyc000064400000003221150351404300015145 0ustar003

�b�W��@s(ddlZddlZGdd�dejj�ZdS)�NcsVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�DHCIDz�DHCID record

    @ivar data: the data (the content of the RR is opaque as far as the
    DNS is concerned)
    @type data: string
    @see: RFC 4701�datacstt|�j||�||_dS)N)�superr�__init__r)�self�rdclass�rdtyper)�	__class__��/usr/lib/python3.6/DHCID.pyr szDHCID.__init__NTcKstjj|j�S)N)�dns�rdataZ
_base64ifyr)r�origin�
relativize�kwr
r
r�to_text$sz
DHCID.to_textc
Cs`g}x:|j�j�}|j�rP|j�s,tjj�|j|jj	��qWdj
|�}tj|�}	||||	�S)N�)
�getZunescapeZ
is_eol_or_eofZ
is_identifierrZ	exception�SyntaxError�append�value�encode�join�base64Z	b64decode)
�clsrr�tokrrZchunks�tZb64rr
r
r�	from_text's

zDHCID.from_textcCs|j|j�dS)N)�writer)r�file�compressrr
r
r�to_wire5sz
DHCID.to_wirecCs ||||�j�}||||�S)N)Zunwrap)rrrZwireZcurrentZrdlenrrr
r
r�	from_wire8szDHCID.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrr!r"�
__classcell__r
r
)r	rrs

r)rZ
dns.exceptionrr
ZRdatarr
r
r
r�<module>srdtypes/IN/__pycache__/PX.cpython-36.opt-1.pyc000064400000004441150351404300014666 0ustar003

�b�WB
�@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�NcsdeZdZdZdddgZ�fdd�Zdd	d
�Zeddd��Zdd
d�Z	eddd��Z
ddd�Z�ZS)�PXz�PX record.

    @ivar preference: the preference value
    @type preference: int
    @ivar map822: the map822 name
    @type map822: dns.name.Name object
    @ivar mapx400: the mapx400 name
    @type mapx400: dns.name.Name object
    @see: RFC 2163�
preference�map822�mapx400cs(tt|�j||�||_||_||_dS)N)�superr�__init__rrr)�self�rdclass�rdtyperrr)�	__class__��/usr/lib/python3.6/PX.pyr%szPX.__init__NTcKs,|jj||�}|jj||�}d|j||fS)Nz%d %s %s)r�choose_relativityrr)r�origin�
relativize�kwrrrrr
�to_text+sz
PX.to_textc	CsJ|j�}|j�}|j||�}|jd�}|j||�}|j�||||||�S)N)Z
get_uint16Zget_namerZget_eol)	�clsr	r
�tokrrrrrrrr
�	from_text0s
zPX.from_textcCs<tjd|j�}|j|�|jj|d|�|jj|d|�dS)Nz!H)�struct�packr�writer�to_wirer)r�file�compressrZprefrrr
r:s
z
PX.to_wirecCs�tjd|||d��\}|d7}|d8}tjj|d||�|�\}}	|	|krXtjj�||	7}||	8}|dk	rz|j|�}tjj|d||�|�\}
}	|	|kr�tjj�|dk	r�|
j|�}
||||||
�S)Nz!H�)r�unpack�dns�name�	from_wireZ	exceptionZ	FormErrorr)rr	r
ZwireZcurrentZrdlenrrrZcusedrrrr
r @s$



zPX.from_wirecCs$|jj||�|_|jj||�|_dS)N)rrr)rrrrrr
rUszPX.choose_relativity)NT)NT)NN)N)NT)
�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrr r�
__classcell__rr)rr
rs


	
r)rZ
dns.exceptionrZ	dns.rdataZdns.nameZrdataZRdatarrrrr
�<module>srdtypes/IN/WKS.py000064400000007343150351404300007564 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import socket
import struct

import dns.ipv4
import dns.rdata
from dns._compat import xrange

_proto_tcp = socket.getprotobyname('tcp')
_proto_udp = socket.getprotobyname('udp')


class WKS(dns.rdata.Rdata):

    """WKS record

    @ivar address: the address
    @type address: string
    @ivar protocol: the protocol
    @type protocol: int
    @ivar bitmap: the bitmap
    @type bitmap: string
    @see: RFC 1035"""

    __slots__ = ['address', 'protocol', 'bitmap']

    def __init__(self, rdclass, rdtype, address, protocol, bitmap):
        super(WKS, self).__init__(rdclass, rdtype)
        self.address = address
        self.protocol = protocol
        if not isinstance(bitmap, bytearray):
            self.bitmap = bytearray(bitmap)
        else:
            self.bitmap = bitmap

    def to_text(self, origin=None, relativize=True, **kw):
        bits = []
        for i in xrange(0, len(self.bitmap)):
            byte = self.bitmap[i]
            for j in xrange(0, 8):
                if byte & (0x80 >> j):
                    bits.append(str(i * 8 + j))
        text = ' '.join(bits)
        return '%s %d %s' % (self.address, self.protocol, text)

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        address = tok.get_string()
        protocol = tok.get_string()
        if protocol.isdigit():
            protocol = int(protocol)
        else:
            protocol = socket.getprotobyname(protocol)
        bitmap = bytearray()
        while 1:
            token = tok.get().unescape()
            if token.is_eol_or_eof():
                break
            if token.value.isdigit():
                serv = int(token.value)
            else:
                if protocol != _proto_udp and protocol != _proto_tcp:
                    raise NotImplementedError("protocol must be TCP or UDP")
                if protocol == _proto_udp:
                    protocol_text = "udp"
                else:
                    protocol_text = "tcp"
                serv = socket.getservbyname(token.value, protocol_text)
            i = serv // 8
            l = len(bitmap)
            if l < i + 1:
                for j in xrange(l, i + 1):
                    bitmap.append(0)
            bitmap[i] = bitmap[i] | (0x80 >> (serv % 8))
        bitmap = dns.rdata._truncate_bitmap(bitmap)
        return cls(rdclass, rdtype, address, protocol, bitmap)

    def to_wire(self, file, compress=None, origin=None):
        file.write(dns.ipv4.inet_aton(self.address))
        protocol = struct.pack('!B', self.protocol)
        file.write(protocol)
        file.write(self.bitmap)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        address = dns.ipv4.inet_ntoa(wire[current: current + 4])
        protocol, = struct.unpack('!B', wire[current + 4: current + 5])
        current += 5
        rdlen -= 5
        bitmap = wire[current: current + rdlen].unwrap()
        return cls(rdclass, rdtype, address, protocol, bitmap)
rdtypes/IN/PX.py000064400000006502150351404300007443 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct

import dns.exception
import dns.rdata
import dns.name


class PX(dns.rdata.Rdata):

    """PX record.

    @ivar preference: the preference value
    @type preference: int
    @ivar map822: the map822 name
    @type map822: dns.name.Name object
    @ivar mapx400: the mapx400 name
    @type mapx400: dns.name.Name object
    @see: RFC 2163"""

    __slots__ = ['preference', 'map822', 'mapx400']

    def __init__(self, rdclass, rdtype, preference, map822, mapx400):
        super(PX, self).__init__(rdclass, rdtype)
        self.preference = preference
        self.map822 = map822
        self.mapx400 = mapx400

    def to_text(self, origin=None, relativize=True, **kw):
        map822 = self.map822.choose_relativity(origin, relativize)
        mapx400 = self.mapx400.choose_relativity(origin, relativize)
        return '%d %s %s' % (self.preference, map822, mapx400)

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        preference = tok.get_uint16()
        map822 = tok.get_name()
        map822 = map822.choose_relativity(origin, relativize)
        mapx400 = tok.get_name(None)
        mapx400 = mapx400.choose_relativity(origin, relativize)
        tok.get_eol()
        return cls(rdclass, rdtype, preference, map822, mapx400)

    def to_wire(self, file, compress=None, origin=None):
        pref = struct.pack("!H", self.preference)
        file.write(pref)
        self.map822.to_wire(file, None, origin)
        self.mapx400.to_wire(file, None, origin)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        (preference, ) = struct.unpack('!H', wire[current: current + 2])
        current += 2
        rdlen -= 2
        (map822, cused) = dns.name.from_wire(wire[: current + rdlen],
                                             current)
        if cused > rdlen:
            raise dns.exception.FormError
        current += cused
        rdlen -= cused
        if origin is not None:
            map822 = map822.relativize(origin)
        (mapx400, cused) = dns.name.from_wire(wire[: current + rdlen],
                                              current)
        if cused != rdlen:
            raise dns.exception.FormError
        if origin is not None:
            mapx400 = mapx400.relativize(origin)
        return cls(rdclass, rdtype, preference, map822, mapx400)

    def choose_relativity(self, origin=None, relativize=True):
        self.map822 = self.map822.choose_relativity(origin, relativize)
        self.mapx400 = self.mapx400.choose_relativity(origin, relativize)
rdtypes/IN/AAAA.py000064400000003622150351404300007577 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.exception
import dns.inet
import dns.rdata
import dns.tokenizer


class AAAA(dns.rdata.Rdata):

    """AAAA record.

    @ivar address: an IPv6 address
    @type address: string (in the standard IPv6 format)"""

    __slots__ = ['address']

    def __init__(self, rdclass, rdtype, address):
        super(AAAA, self).__init__(rdclass, rdtype)
        # check that it's OK
        dns.inet.inet_pton(dns.inet.AF_INET6, address)
        self.address = address

    def to_text(self, origin=None, relativize=True, **kw):
        return self.address

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        address = tok.get_identifier()
        tok.get_eol()
        return cls(rdclass, rdtype, address)

    def to_wire(self, file, compress=None, origin=None):
        file.write(dns.inet.inet_pton(dns.inet.AF_INET6, self.address))

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        address = dns.inet.inet_ntop(dns.inet.AF_INET6,
                                     wire[current: current + rdlen])
        return cls(rdclass, rdtype, address)
rdtypes/IN/NAPTR.py000064400000010566150351404300010005 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct

import dns.exception
import dns.name
import dns.rdata
from dns._compat import xrange, text_type


def _write_string(file, s):
    l = len(s)
    assert l < 256
    file.write(struct.pack('!B', l))
    file.write(s)


def _sanitize(value):
    if isinstance(value, text_type):
        return value.encode()
    return value


class NAPTR(dns.rdata.Rdata):

    """NAPTR record

    @ivar order: order
    @type order: int
    @ivar preference: preference
    @type preference: int
    @ivar flags: flags
    @type flags: string
    @ivar service: service
    @type service: string
    @ivar regexp: regular expression
    @type regexp: string
    @ivar replacement: replacement name
    @type replacement: dns.name.Name object
    @see: RFC 3403"""

    __slots__ = ['order', 'preference', 'flags', 'service', 'regexp',
                 'replacement']

    def __init__(self, rdclass, rdtype, order, preference, flags, service,
                 regexp, replacement):
        super(NAPTR, self).__init__(rdclass, rdtype)
        self.flags = _sanitize(flags)
        self.service = _sanitize(service)
        self.regexp = _sanitize(regexp)
        self.order = order
        self.preference = preference
        self.replacement = replacement

    def to_text(self, origin=None, relativize=True, **kw):
        replacement = self.replacement.choose_relativity(origin, relativize)
        return '%d %d "%s" "%s" "%s" %s' % \
               (self.order, self.preference,
                dns.rdata._escapify(self.flags),
                dns.rdata._escapify(self.service),
                dns.rdata._escapify(self.regexp),
                replacement)

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        order = tok.get_uint16()
        preference = tok.get_uint16()
        flags = tok.get_string()
        service = tok.get_string()
        regexp = tok.get_string()
        replacement = tok.get_name()
        replacement = replacement.choose_relativity(origin, relativize)
        tok.get_eol()
        return cls(rdclass, rdtype, order, preference, flags, service,
                   regexp, replacement)

    def to_wire(self, file, compress=None, origin=None):
        two_ints = struct.pack("!HH", self.order, self.preference)
        file.write(two_ints)
        _write_string(file, self.flags)
        _write_string(file, self.service)
        _write_string(file, self.regexp)
        self.replacement.to_wire(file, compress, origin)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        (order, preference) = struct.unpack('!HH', wire[current: current + 4])
        current += 4
        rdlen -= 4
        strings = []
        for i in xrange(3):
            l = wire[current]
            current += 1
            rdlen -= 1
            if l > rdlen or rdlen < 0:
                raise dns.exception.FormError
            s = wire[current: current + l].unwrap()
            current += l
            rdlen -= l
            strings.append(s)
        (replacement, cused) = dns.name.from_wire(wire[: current + rdlen],
                                                  current)
        if cused != rdlen:
            raise dns.exception.FormError
        if origin is not None:
            replacement = replacement.relativize(origin)
        return cls(rdclass, rdtype, order, preference, strings[0], strings[1],
                   strings[2], replacement)

    def choose_relativity(self, origin=None, relativize=True):
        self.replacement = self.replacement.choose_relativity(origin,
                                                              relativize)
rdtypes/IN/NSAP.py000064400000004037150351404300007656 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import binascii

import dns.exception
import dns.rdata
import dns.tokenizer


class NSAP(dns.rdata.Rdata):

    """NSAP record.

    @ivar address: a NASP
    @type address: string
    @see: RFC 1706"""

    __slots__ = ['address']

    def __init__(self, rdclass, rdtype, address):
        super(NSAP, self).__init__(rdclass, rdtype)
        self.address = address

    def to_text(self, origin=None, relativize=True, **kw):
        return "0x%s" % binascii.hexlify(self.address).decode()

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        address = tok.get_string()
        tok.get_eol()
        if address[0:2] != '0x':
            raise dns.exception.SyntaxError('string does not start with 0x')
        address = address[2:].replace('.', '')
        if len(address) % 2 != 0:
            raise dns.exception.SyntaxError('hexstring has odd length')
        address = binascii.unhexlify(address.encode())
        return cls(rdclass, rdtype, address)

    def to_wire(self, file, compress=None, origin=None):
        file.write(self.address)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        address = wire[current: current + rdlen].unwrap()
        return cls(rdclass, rdtype, address)
rdtypes/IN/KX.py000064400000001561150351404300007436 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.mxbase


class KX(dns.rdtypes.mxbase.UncompressedMX):

    """KX record"""
rdtypes/IN/A.py000064400000003475150351404300007302 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.exception
import dns.ipv4
import dns.rdata
import dns.tokenizer


class A(dns.rdata.Rdata):

    """A record.

    @ivar address: an IPv4 address
    @type address: string (in the standard "dotted quad" format)"""

    __slots__ = ['address']

    def __init__(self, rdclass, rdtype, address):
        super(A, self).__init__(rdclass, rdtype)
        # check that it's OK
        dns.ipv4.inet_aton(address)
        self.address = address

    def to_text(self, origin=None, relativize=True, **kw):
        return self.address

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        address = tok.get_identifier()
        tok.get_eol()
        return cls(rdclass, rdtype, address)

    def to_wire(self, file, compress=None, origin=None):
        file.write(dns.ipv4.inet_aton(self.address))

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        address = dns.ipv4.inet_ntoa(wire[current: current + rdlen]).decode()
        return cls(rdclass, rdtype, address)
rdtypes/IN/SRV.py000064400000005756150351404300007600 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct

import dns.exception
import dns.rdata
import dns.name


class SRV(dns.rdata.Rdata):

    """SRV record

    @ivar priority: the priority
    @type priority: int
    @ivar weight: the weight
    @type weight: int
    @ivar port: the port of the service
    @type port: int
    @ivar target: the target host
    @type target: dns.name.Name object
    @see: RFC 2782"""

    __slots__ = ['priority', 'weight', 'port', 'target']

    def __init__(self, rdclass, rdtype, priority, weight, port, target):
        super(SRV, self).__init__(rdclass, rdtype)
        self.priority = priority
        self.weight = weight
        self.port = port
        self.target = target

    def to_text(self, origin=None, relativize=True, **kw):
        target = self.target.choose_relativity(origin, relativize)
        return '%d %d %d %s' % (self.priority, self.weight, self.port,
                                target)

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        priority = tok.get_uint16()
        weight = tok.get_uint16()
        port = tok.get_uint16()
        target = tok.get_name(None)
        target = target.choose_relativity(origin, relativize)
        tok.get_eol()
        return cls(rdclass, rdtype, priority, weight, port, target)

    def to_wire(self, file, compress=None, origin=None):
        three_ints = struct.pack("!HHH", self.priority, self.weight, self.port)
        file.write(three_ints)
        self.target.to_wire(file, compress, origin)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        (priority, weight, port) = struct.unpack('!HHH',
                                                 wire[current: current + 6])
        current += 6
        rdlen -= 6
        (target, cused) = dns.name.from_wire(wire[: current + rdlen],
                                             current)
        if cused != rdlen:
            raise dns.exception.FormError
        if origin is not None:
            target = target.relativize(origin)
        return cls(rdclass, rdtype, priority, weight, port, target)

    def choose_relativity(self, origin=None, relativize=True):
        self.target = self.target.choose_relativity(origin, relativize)
rdtypes/mxbase.py000064400000007114150351404300010065 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""MX-like base classes."""

from io import BytesIO
import struct

import dns.exception
import dns.rdata
import dns.name


class MXBase(dns.rdata.Rdata):

    """Base class for rdata that is like an MX record.

    @ivar preference: the preference value
    @type preference: int
    @ivar exchange: the exchange name
    @type exchange: dns.name.Name object"""

    __slots__ = ['preference', 'exchange']

    def __init__(self, rdclass, rdtype, preference, exchange):
        super(MXBase, self).__init__(rdclass, rdtype)
        self.preference = preference
        self.exchange = exchange

    def to_text(self, origin=None, relativize=True, **kw):
        exchange = self.exchange.choose_relativity(origin, relativize)
        return '%d %s' % (self.preference, exchange)

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        preference = tok.get_uint16()
        exchange = tok.get_name()
        exchange = exchange.choose_relativity(origin, relativize)
        tok.get_eol()
        return cls(rdclass, rdtype, preference, exchange)

    def to_wire(self, file, compress=None, origin=None):
        pref = struct.pack("!H", self.preference)
        file.write(pref)
        self.exchange.to_wire(file, compress, origin)

    def to_digestable(self, origin=None):
        return struct.pack("!H", self.preference) + \
            self.exchange.to_digestable(origin)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        (preference, ) = struct.unpack('!H', wire[current: current + 2])
        current += 2
        rdlen -= 2
        (exchange, cused) = dns.name.from_wire(wire[: current + rdlen],
                                               current)
        if cused != rdlen:
            raise dns.exception.FormError
        if origin is not None:
            exchange = exchange.relativize(origin)
        return cls(rdclass, rdtype, preference, exchange)

    def choose_relativity(self, origin=None, relativize=True):
        self.exchange = self.exchange.choose_relativity(origin, relativize)


class UncompressedMX(MXBase):

    """Base class for rdata that is like an MX record, but whose name
    is not compressed when converted to DNS wire format, and whose
    digestable form is not downcased."""

    def to_wire(self, file, compress=None, origin=None):
        super(UncompressedMX, self).to_wire(file, None, origin)

    def to_digestable(self, origin=None):
        f = BytesIO()
        self.to_wire(f, None, origin)
        return f.getvalue()


class UncompressedDowncasingMX(MXBase):

    """Base class for rdata that is like an MX record, but whose name
    is not compressed when convert to DNS wire format."""

    def to_wire(self, file, compress=None, origin=None):
        super(UncompressedDowncasingMX, self).to_wire(file, None, origin)
rdtypes/euibase.py000064400000005331150351404300010222 0ustar00# Copyright (C) 2015 Red Hat, Inc.
# Author: Petr Spacek <pspacek@redhat.com>
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import binascii

import dns.rdata
from dns._compat import xrange


class EUIBase(dns.rdata.Rdata):

    """EUIxx record

    @ivar fingerprint: xx-bit Extended Unique Identifier (EUI-xx)
    @type fingerprint: string
    @see: rfc7043.txt"""

    __slots__ = ['eui']
    # define these in subclasses
    # byte_len = 6  # 0123456789ab (in hex)
    # text_len = byte_len * 3 - 1  # 01-23-45-67-89-ab

    def __init__(self, rdclass, rdtype, eui):
        super(EUIBase, self).__init__(rdclass, rdtype)
        if len(eui) != self.byte_len:
            raise dns.exception.FormError('EUI%s rdata has to have %s bytes'
                                          % (self.byte_len * 8, self.byte_len))
        self.eui = eui

    def to_text(self, origin=None, relativize=True, **kw):
        return dns.rdata._hexify(self.eui, chunksize=2).replace(' ', '-')

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        text = tok.get_string()
        tok.get_eol()
        if len(text) != cls.text_len:
            raise dns.exception.SyntaxError(
                'Input text must have %s characters' % cls.text_len)
        expected_dash_idxs = xrange(2, cls.byte_len * 3 - 1, 3)
        for i in expected_dash_idxs:
            if text[i] != '-':
                raise dns.exception.SyntaxError('Dash expected at position %s'
                                                % i)
        text = text.replace('-', '')
        try:
            data = binascii.unhexlify(text.encode())
        except (ValueError, TypeError) as ex:
            raise dns.exception.SyntaxError('Hex decoding error: %s' % str(ex))
        return cls(rdclass, rdtype, data)

    def to_wire(self, file, compress=None, origin=None):
        file.write(self.eui)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        eui = wire[current:current + rdlen].unwrap()
        return cls(rdclass, rdtype, eui)
rdtypes/__pycache__/euibase.cpython-36.pyc000064400000004143150351404300014506 0ustar003

�b�W�
�@s4ddlZddlZddlmZGdd�dejj�ZdS)�N)�xrangecsVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�EUIBasez�EUIxx record

    @ivar fingerprint: xx-bit Extended Unique Identifier (EUI-xx)
    @type fingerprint: string
    @see: rfc7043.txt�euicsFtt|�j||�t|�|jkr<tjjd|jd|jf��||_dS)Nz EUI%s rdata has to have %s bytes�)	�superr�__init__�len�byte_len�dns�	exceptionZ	FormErrorr)�self�rdclass�rdtyper)�	__class__��/usr/lib/python3.6/euibase.pyr$s
zEUIBase.__init__NTcKstjj|jdd�jdd�S)N�)Z	chunksize� �-)r
�rdataZ_hexifyr�replace)r�origin�
relativize�kwrrr�to_text+szEUIBase.to_textcCs�|j�}|j�t|�|jkr0tjjd|j��td|jddd�}x(|D] }||dkrLtjjd|��qLW|j	dd�}yt
j|j��}	Wn:t
tfk
r�}
ztjjdt|
���WYdd}
~
XnX||||	�S)	Nz"Input text must have %s charactersr��rzDash expected at position %s�zHex decoding error: %s)Z
get_stringZget_eolrZtext_lenr
r�SyntaxErrorrr	r�binasciiZ	unhexlify�encode�
ValueError�	TypeError�str)�clsr
r�tokrr�textZexpected_dash_idxs�i�dataZexrrr�	from_text.s 
&zEUIBase.from_textcCs|j|j�dS)N)�writer)r�file�compressrrrr�to_wireAszEUIBase.to_wirecCs ||||�j�}||||�S)N)Zunwrap)r$r
rZwireZcurrentZrdlenrrrrr�	from_wireDszEUIBase.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodr)r-r.�
__classcell__rr)rrrs

r)rZ	dns.rdatar
Zdns._compatrrZRdatarrrrr�<module>srdtypes/__pycache__/nsbase.cpython-36.pyc000064400000005165150351404310014352 0ustar003

�b�W#�@sPdZddlmZddlZddlZddlZGdd�dejj�Z	Gdd�de	�Z
dS)zNS-like base classes.�)�BytesIONcsjeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	dd
d�Z
eddd��Zddd�Z�Z
S)�NSBasez�Base class for rdata that is like an NS record.

    @ivar target: the target name of the rdata
    @type target: dns.name.Name object�targetcstt|�j||�||_dS)N)�superr�__init__r)�self�rdclass�rdtyper)�	__class__��/usr/lib/python3.6/nsbase.pyr"szNSBase.__init__NTcKs|jj||�}t|�S)N)r�choose_relativity�str)r�origin�
relativize�kwrrrr�to_text&szNSBase.to_textcCs(|j�}|j||�}|j�||||�S)N)Zget_namer
Zget_eol)�clsrr	�tokrrrrrr�	from_text*szNSBase.from_textcCs|jj|||�dS)N)r�to_wire)r�file�compressrrrrr1szNSBase.to_wirecCs|jj|�S)N)r�
to_digestable)rrrrrr4szNSBase.to_digestablec	CsLtjj|d||�|�\}}||kr.tjj�|dk	r@|j|�}||||�S)N)�dns�name�	from_wireZ	exceptionZ	FormErrorr)	rrr	ZwireZcurrentZrdlenrrZcusedrrrr7s

zNSBase.from_wirecCs|jj||�|_dS)N)rr
)rrrrrrr
AszNSBase.choose_relativity)NT)NT)NN)N)N)NT)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrrrr
�
__classcell__rr)r
rrs


	rcs,eZdZdZd�fdd�	Zddd�Z�ZS)	�UncompressedNSz�Base class for rdata that is like an NS record, but whose name
    is not compressed when convert to DNS wire format, and whose
    digestable form is not downcased.Ncstt|�j|d|�dS)N)rr$r)rrrr)r
rrrKszUncompressedNS.to_wirecCst�}|j|d|�|j�S)N)rr�getvalue)rr�frrrrNszUncompressedNS.to_digestable)NN)N)rrrr rrr#rr)r
rr$Esr$)r �iorZ
dns.exceptionrZ	dns.rdataZdns.nameZrdataZRdatarr$rrrr�<module>s,rdtypes/__pycache__/mxbase.cpython-36.pyc000064400000006627150351404310014362 0ustar003

�b�WL�@shdZddlmZddlZddlZddlZddlZGdd�dejj	�Z
Gdd�de
�ZGdd	�d	e
�ZdS)
zMX-like base classes.�)�BytesIONcsleZdZdZddgZ�fdd�Zddd	�Zedd
d��Zddd
�Z	ddd�Z
eddd��Zddd�Z�Z
S)�MXBasez�Base class for rdata that is like an MX record.

    @ivar preference: the preference value
    @type preference: int
    @ivar exchange: the exchange name
    @type exchange: dns.name.Name object�
preference�exchangecs"tt|�j||�||_||_dS)N)�superr�__init__rr)�self�rdclass�rdtyperr)�	__class__��/usr/lib/python3.6/mxbase.pyr%szMXBase.__init__NTcKs|jj||�}d|j|fS)Nz%d %s)r�choose_relativityr)r�origin�
relativize�kwrrrr
�to_text*szMXBase.to_textcCs2|j�}|j�}|j||�}|j�|||||�S)N)Z
get_uint16Zget_namerZget_eol)�clsr	r
�tokrrrrrrr
�	from_text.s
zMXBase.from_textcCs,tjd|j�}|j|�|jj|||�dS)Nz!H)�struct�packr�writer�to_wire)r�file�compressrZprefrrr
r6s
zMXBase.to_wirecCstjd|j�|jj|�S)Nz!H)rrrr�
to_digestable)rrrrr
r;szMXBase.to_digestablec
Csxtjd|||d��\}|d7}|d8}tjj|d||�|�\}}	|	|krXtjj�|dk	rj|j|�}|||||�S)Nz!H�)r�unpack�dns�name�	from_wireZ	exceptionZ	FormErrorr)
rr	r
ZwireZcurrentZrdlenrrrZcusedrrr
r!?s

zMXBase.from_wirecCs|jj||�|_dS)N)rr)rrrrrr
rLszMXBase.choose_relativity)NT)NT)NN)N)N)NT)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrrr!r�
__classcell__rr)rr
rs


rcs,eZdZdZd�fdd�	Zddd�Z�ZS)	�UncompressedMXz�Base class for rdata that is like an MX record, but whose name
    is not compressed when converted to DNS wire format, and whose
    digestable form is not downcased.Ncstt|�j|d|�dS)N)rr)r)rrrr)rrr
rVszUncompressedMX.to_wirecCst�}|j|d|�|j�S)N)rr�getvalue)rr�frrr
rYszUncompressedMX.to_digestable)NN)N)r"r#r$r%rrr(rr)rr
r)Psr)cs"eZdZdZd�fdd�	Z�ZS)�UncompressedDowncasingMXzuBase class for rdata that is like an MX record, but whose name
    is not compressed when convert to DNS wire format.Ncstt|�j|d|�dS)N)rr,r)rrrr)rrr
rdsz UncompressedDowncasingMX.to_wire)NN)r"r#r$r%rr(rr)rr
r,_sr,)
r%�iorrZ
dns.exceptionrZ	dns.rdataZdns.nameZrdataZRdatarr)r,rrrr
�<module>s6rdtypes/__pycache__/nsbase.cpython-36.opt-1.pyc000064400000005165150351404310015311 0ustar003

�b�W#�@sPdZddlmZddlZddlZddlZGdd�dejj�Z	Gdd�de	�Z
dS)zNS-like base classes.�)�BytesIONcsjeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	dd
d�Z
eddd��Zddd�Z�Z
S)�NSBasez�Base class for rdata that is like an NS record.

    @ivar target: the target name of the rdata
    @type target: dns.name.Name object�targetcstt|�j||�||_dS)N)�superr�__init__r)�self�rdclass�rdtyper)�	__class__��/usr/lib/python3.6/nsbase.pyr"szNSBase.__init__NTcKs|jj||�}t|�S)N)r�choose_relativity�str)r�origin�
relativize�kwrrrr�to_text&szNSBase.to_textcCs(|j�}|j||�}|j�||||�S)N)Zget_namer
Zget_eol)�clsrr	�tokrrrrrr�	from_text*szNSBase.from_textcCs|jj|||�dS)N)r�to_wire)r�file�compressrrrrr1szNSBase.to_wirecCs|jj|�S)N)r�
to_digestable)rrrrrr4szNSBase.to_digestablec	CsLtjj|d||�|�\}}||kr.tjj�|dk	r@|j|�}||||�S)N)�dns�name�	from_wireZ	exceptionZ	FormErrorr)	rrr	ZwireZcurrentZrdlenrrZcusedrrrr7s

zNSBase.from_wirecCs|jj||�|_dS)N)rr
)rrrrrrr
AszNSBase.choose_relativity)NT)NT)NN)N)N)NT)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrrrr
�
__classcell__rr)r
rrs


	rcs,eZdZdZd�fdd�	Zddd�Z�ZS)	�UncompressedNSz�Base class for rdata that is like an NS record, but whose name
    is not compressed when convert to DNS wire format, and whose
    digestable form is not downcased.Ncstt|�j|d|�dS)N)rr$r)rrrr)r
rrrKszUncompressedNS.to_wirecCst�}|j|d|�|j�S)N)rr�getvalue)rr�frrrrNszUncompressedNS.to_digestable)NN)N)rrrr rrr#rr)r
rr$Esr$)r �iorZ
dns.exceptionrZ	dns.rdataZdns.nameZrdataZRdatarr$rrrr�<module>s,rdtypes/__pycache__/txtbase.cpython-36.opt-1.pyc000064400000004371150351404310015506 0ustar003

�b�W��@sHdZddlZddlZddlZddlZddlmZGdd�dejj	�Z
dS)zTXT-like base class.�N)�binary_typecsVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�TXTBasez�Base class for rdata that is like a TXT record

    @ivar strings: the text strings
    @type strings: list of string
    @see: RFC 1035�stringscs4tt|�j||�t|t�r"|g}|dd�|_dS)N)�superr�__init__�
isinstance�strr)�self�rdclass�rdtyper)�	__class__��/usr/lib/python3.6/txtbase.pyr$s
zTXTBase.__init__NTcKs8d}d}x*|jD] }|d|tjj|�f7}d}qW|S)N�z%s"%s"� )r�dns�rdataZ	_escapify)r	�origin�
relativize�kwZtxt�prefix�sr
r
r�to_text*szTXTBase.to_textc	Cs�g}xz|j�j�}|j�rP|j�p*|j�s8tjjd��t|j	�dkrRtjjd��|j	}t
|t�rn|j|�q|j|j
��qWt|�dkr�tjj�||||�S)Nzexpected a string�zstring too longr)�getZunescapeZ
is_eol_or_eofZis_quoted_stringZ
is_identifierr�	exception�SyntaxError�len�valuerr�append�encodeZ
UnexpectedEnd)	�clsr
r�tokrrr�tokenrr
r
r�	from_text2s 
zTXTBase.from_textcCs8x2|jD](}t|�}|jtjd|��|j|�qWdS)Nz!B)rr�write�struct�pack)r	�file�compressrr�lr
r
r�to_wireFszTXTBase.to_wirec
Cstg}xb|dkrf||}|d7}|d8}||kr6tjj�||||�j�}	||7}||8}|j|	�qW||||�S)Nr�)rrZ	FormErrorZunwrapr)
r!r
rZwireZcurrentZrdlenrrr*rr
r
r�	from_wireMs
zTXTBase.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodr$r+r-�
__classcell__r
r
)rrrs

r)r1r&Z
dns.exceptionrZ	dns.rdataZ
dns.tokenizerZdns._compatrrZRdatarr
r
r
r�<module>srdtypes/__pycache__/mxbase.cpython-36.opt-1.pyc000064400000006627150351404310015321 0ustar003

�b�WL�@shdZddlmZddlZddlZddlZddlZGdd�dejj	�Z
Gdd�de
�ZGdd	�d	e
�ZdS)
zMX-like base classes.�)�BytesIONcsleZdZdZddgZ�fdd�Zddd	�Zedd
d��Zddd
�Z	ddd�Z
eddd��Zddd�Z�Z
S)�MXBasez�Base class for rdata that is like an MX record.

    @ivar preference: the preference value
    @type preference: int
    @ivar exchange: the exchange name
    @type exchange: dns.name.Name object�
preference�exchangecs"tt|�j||�||_||_dS)N)�superr�__init__rr)�self�rdclass�rdtyperr)�	__class__��/usr/lib/python3.6/mxbase.pyr%szMXBase.__init__NTcKs|jj||�}d|j|fS)Nz%d %s)r�choose_relativityr)r�origin�
relativize�kwrrrr
�to_text*szMXBase.to_textcCs2|j�}|j�}|j||�}|j�|||||�S)N)Z
get_uint16Zget_namerZget_eol)�clsr	r
�tokrrrrrrr
�	from_text.s
zMXBase.from_textcCs,tjd|j�}|j|�|jj|||�dS)Nz!H)�struct�packr�writer�to_wire)r�file�compressrZprefrrr
r6s
zMXBase.to_wirecCstjd|j�|jj|�S)Nz!H)rrrr�
to_digestable)rrrrr
r;szMXBase.to_digestablec
Csxtjd|||d��\}|d7}|d8}tjj|d||�|�\}}	|	|krXtjj�|dk	rj|j|�}|||||�S)Nz!H�)r�unpack�dns�name�	from_wireZ	exceptionZ	FormErrorr)
rr	r
ZwireZcurrentZrdlenrrrZcusedrrr
r!?s

zMXBase.from_wirecCs|jj||�|_dS)N)rr)rrrrrr
rLszMXBase.choose_relativity)NT)NT)NN)N)N)NT)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrrr!r�
__classcell__rr)rr
rs


rcs,eZdZdZd�fdd�	Zddd�Z�ZS)	�UncompressedMXz�Base class for rdata that is like an MX record, but whose name
    is not compressed when converted to DNS wire format, and whose
    digestable form is not downcased.Ncstt|�j|d|�dS)N)rr)r)rrrr)rrr
rVszUncompressedMX.to_wirecCst�}|j|d|�|j�S)N)rr�getvalue)rr�frrr
rYszUncompressedMX.to_digestable)NN)N)r"r#r$r%rrr(rr)rr
r)Psr)cs"eZdZdZd�fdd�	Z�ZS)�UncompressedDowncasingMXzuBase class for rdata that is like an MX record, but whose name
    is not compressed when convert to DNS wire format.Ncstt|�j|d|�dS)N)rr,r)rrrr)rrr
rdsz UncompressedDowncasingMX.to_wire)NN)r"r#r$r%rr(rr)rr
r,_sr,)
r%�iorrZ
dns.exceptionrZ	dns.rdataZdns.nameZrdataZRdatarr)r,rrrr
�<module>s6rdtypes/__pycache__/dsbase.cpython-36.pyc000064400000004440150351404310014333 0ustar003

�b�W�@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�Ncs\eZdZdZddddgZ�fdd�Zdd
d�Zeddd
��Zddd�Z	eddd��Z
�ZS)�DSBaseaJBase class for rdata that is like a DS record

    @ivar key_tag: the key tag
    @type key_tag: int
    @ivar algorithm: the algorithm
    @type algorithm: int
    @ivar digest_type: the digest type
    @type digest_type: int
    @ivar digest: the digest
    @type digest: int
    @see: draft-ietf-dnsext-delegation-signer-14.txt�key_tag�	algorithm�digest_type�digestcs.tt|�j||�||_||_||_||_dS)N)�superr�__init__rrrr)�self�rdclass�rdtyperrrr)�	__class__��/usr/lib/python3.6/dsbase.pyr's
zDSBase.__init__NTcKs$d|j|j|jtjj|jdd�fS)Nz%d %d %d %s�)Z	chunksize)rrr�dns�rdataZ_hexifyr)r	�origin�
relativize�kwr
r
r�to_text/s

zDSBase.to_textcCs~|j�}|j�}|j�}g}	x:|j�j�}
|
j�r4P|
j�sDtjj�|	j	|
j
j��qWdj|	�}t
j|�}|||||||�S)N�)Z
get_uint16Z	get_uint8�getZunescapeZ
is_eol_or_eofZ
is_identifierrZ	exception�SyntaxError�append�value�encode�join�binasciiZ	unhexlify)�clsr
r�tokrrrrrZchunks�trr
r
r�	from_text5s

zDSBase.from_textcCs0tjd|j|j|j�}|j|�|j|j�dS)Nz!HBB)�struct�packrrr�writer)r	�file�compressr�headerr
r
r�to_wireGs
zDSBase.to_wirec	CsZtjd|||d��}|d7}|d8}||||�j�}||||d|d|d|�S)Nz!HBB�r��)r"�unpackZunwrap)	rr
rZwireZcurrentZrdlenrr'rr
r
r�	from_wireMs
zDSBase.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodr!r(r-�
__classcell__r
r
)rrrs

r)r"rZ	dns.rdatarZ
dns.rdatatyperZRdatarr
r
r
r�<module>srdtypes/__pycache__/dsbase.cpython-36.opt-1.pyc000064400000004440150351404310015272 0ustar003

�b�W�@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�Ncs\eZdZdZddddgZ�fdd�Zdd
d�Zeddd
��Zddd�Z	eddd��Z
�ZS)�DSBaseaJBase class for rdata that is like a DS record

    @ivar key_tag: the key tag
    @type key_tag: int
    @ivar algorithm: the algorithm
    @type algorithm: int
    @ivar digest_type: the digest type
    @type digest_type: int
    @ivar digest: the digest
    @type digest: int
    @see: draft-ietf-dnsext-delegation-signer-14.txt�key_tag�	algorithm�digest_type�digestcs.tt|�j||�||_||_||_||_dS)N)�superr�__init__rrrr)�self�rdclass�rdtyperrrr)�	__class__��/usr/lib/python3.6/dsbase.pyr's
zDSBase.__init__NTcKs$d|j|j|jtjj|jdd�fS)Nz%d %d %d %s�)Z	chunksize)rrr�dns�rdataZ_hexifyr)r	�origin�
relativize�kwr
r
r�to_text/s

zDSBase.to_textcCs~|j�}|j�}|j�}g}	x:|j�j�}
|
j�r4P|
j�sDtjj�|	j	|
j
j��qWdj|	�}t
j|�}|||||||�S)N�)Z
get_uint16Z	get_uint8�getZunescapeZ
is_eol_or_eofZ
is_identifierrZ	exception�SyntaxError�append�value�encode�join�binasciiZ	unhexlify)�clsr
r�tokrrrrrZchunks�trr
r
r�	from_text5s

zDSBase.from_textcCs0tjd|j|j|j�}|j|�|j|j�dS)Nz!HBB)�struct�packrrr�writer)r	�file�compressr�headerr
r
r�to_wireGs
zDSBase.to_wirec	CsZtjd|||d��}|d7}|d8}||||�j�}||||d|d|d|�S)Nz!HBB�r��)r"�unpackZunwrap)	rr
rZwireZcurrentZrdlenrr'rr
r
r�	from_wireMs
zDSBase.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodr!r(r-�
__classcell__r
r
)rrrs

r)r"rZ	dns.rdatarZ
dns.rdatatyperZRdatarr
r
r
r�<module>srdtypes/__pycache__/euibase.cpython-36.opt-1.pyc000064400000004143150351404310015446 0ustar003

�b�W�
�@s4ddlZddlZddlmZGdd�dejj�ZdS)�N)�xrangecsVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�EUIBasez�EUIxx record

    @ivar fingerprint: xx-bit Extended Unique Identifier (EUI-xx)
    @type fingerprint: string
    @see: rfc7043.txt�euicsFtt|�j||�t|�|jkr<tjjd|jd|jf��||_dS)Nz EUI%s rdata has to have %s bytes�)	�superr�__init__�len�byte_len�dns�	exceptionZ	FormErrorr)�self�rdclass�rdtyper)�	__class__��/usr/lib/python3.6/euibase.pyr$s
zEUIBase.__init__NTcKstjj|jdd�jdd�S)N�)Z	chunksize� �-)r
�rdataZ_hexifyr�replace)r�origin�
relativize�kwrrr�to_text+szEUIBase.to_textcCs�|j�}|j�t|�|jkr0tjjd|j��td|jddd�}x(|D] }||dkrLtjjd|��qLW|j	dd�}yt
j|j��}	Wn:t
tfk
r�}
ztjjdt|
���WYdd}
~
XnX||||	�S)	Nz"Input text must have %s charactersr��rzDash expected at position %s�zHex decoding error: %s)Z
get_stringZget_eolrZtext_lenr
r�SyntaxErrorrr	r�binasciiZ	unhexlify�encode�
ValueError�	TypeError�str)�clsr
r�tokrr�textZexpected_dash_idxs�i�dataZexrrr�	from_text.s 
&zEUIBase.from_textcCs|j|j�dS)N)�writer)r�file�compressrrrr�to_wireAszEUIBase.to_wirecCs ||||�j�}||||�S)N)Zunwrap)r$r
rZwireZcurrentZrdlenrrrrr�	from_wireDszEUIBase.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodr)r-r.�
__classcell__rr)rrrs

r)rZ	dns.rdatar
Zdns._compatrrZRdatarrrrr�<module>srdtypes/__pycache__/__init__.cpython-36.pyc000064400000000326150351404310014630 0ustar003

�b�W�@sdZdddddgZdS)zDNS rdata type classes�ANY�INZeuibaseZmxbaseZnsbaseN)�__doc__�__all__�rr�/usr/lib/python3.6/__init__.py�<module>s
rdtypes/__pycache__/dnskeybase.cpython-36.pyc000064400000007065150351404310015230 0ustar003

�b�W#�@s�ddlZddlZddlZddlZddlZdddddgZdZdZd	Z	eee	d
�Z
edd�e
j�D��Z
d
d�Zdd�ZGdd�dejj�ZdS)�N�SEP�REVOKE�ZONE�flags_to_text_set�flags_from_text_set���)rrrccs|]\}}||fVqdS)N�)�.0�x�yr
r
� /usr/lib/python3.6/dnskeybase.py�	<genexpr>)srcCsLt�}d}x<|dkrF||@r<tj|�}|s2t|�}|j|�|dK}qW|S)zCConvert a DNSKEY flags value to set texts
    @rtype: set([string])ri�)�set�_flag_by_value�get�hex�add)�flagsZ	flags_set�mask�textr
r
rr,s


cCsHd}x>|D]6}y|t|7}Wq
tk
r>td|��Yq
Xq
W|S)zNConvert set of DNSKEY flag mnemonic texts to DNSKEY flag value
    @rtype: intrz!DNSKEY flag '%s' is not supported)�
_flag_by_text�KeyError�NotImplementedError)Z	texts_setrrr
r
rr<s
csdeZdZdZddddgZ�fdd�Zdd
d�Zeddd
��Zddd�Z	eddd��Z
dd�Z�ZS)�
DNSKEYBasea?Base class for rdata that is like a DNSKEY record

    @ivar flags: the key flags
    @type flags: int
    @ivar protocol: the protocol for which this key may be used
    @type protocol: int
    @ivar algorithm: the algorithm used for the key
    @type algorithm: int
    @ivar key: the public key
    @type key: stringr�protocol�	algorithm�keycs.tt|�j||�||_||_||_||_dS)N)�superr�__init__rrrr)�self�rdclass�rdtyperrrr)�	__class__r
rr Ys
zDNSKEYBase.__init__NTcKs d|j|j|jtjj|j�fS)Nz%d %d %d %s)rrr�dns�rdataZ
_base64ifyr)r!�origin�
relativize�kwr
r
r�to_text`szDNSKEYBase.to_textc
Cs�|j�}|j�}tjj|j��}g}	x:|j�j�}
|
j�r<P|
j	�sLtj
j�|	j|
j
j��q&Wdj|	�}tj|�}|||||||�S)N�)Z
get_uint16Z	get_uint8r%ZdnssecZalgorithm_from_textZ
get_stringrZunescapeZ
is_eol_or_eofZ
is_identifier�	exception�SyntaxError�append�value�encode�join�base64Z	b64decode)
�clsr"r#�tokr'r(rrrZchunks�tZb64rr
r
r�	from_textds

zDNSKEYBase.from_textcCs0tjd|j|j|j�}|j|�|j|j�dS)Nz!HBB)�struct�packrrr�writer)r!�file�compressr'�headerr
r
r�to_wireus
zDNSKEYBase.to_wirec	Csj|dkrtjj�tjd|||d��}|d7}|d8}||||�j�}||||d|d|d|�S)N�z!HBBrr�)r%r,Z	FormErrorr7�unpackZunwrap)	r3r"r#ZwireZcurrentZrdlenr'r<rr
r
r�	from_wirezszDNSKEYBase.from_wirecCs
t|j�S)zGConvert a DNSKEY flags value to set texts
        @rtype: set([string]))rr)r!r
r
rr�szDNSKEYBase.flags_to_text_set)NT)NT)NN)N)
�__name__�
__module__�__qualname__�__doc__�	__slots__r r*�classmethodr6r=rAr�
__classcell__r
r
)r$rrJs


r)r2r7Z
dns.exceptionr%Z
dns.dnssecZ	dns.rdata�__all__rrrr�dict�itemsrrrr&ZRdatarr
r
r
r�<module>s rdtypes/__pycache__/__init__.cpython-36.opt-1.pyc000064400000000326150351404310015567 0ustar003

�b�W�@sdZdddddgZdS)zDNS rdata type classes�ANY�INZeuibaseZmxbaseZnsbaseN)�__doc__�__all__�rr�/usr/lib/python3.6/__init__.py�<module>s
rdtypes/__pycache__/txtbase.cpython-36.pyc000064400000004434150351404310014547 0ustar003

�b�W��@sHdZddlZddlZddlZddlZddlmZGdd�dejj	�Z
dS)zTXT-like base class.�N)�binary_typecsVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�TXTBasez�Base class for rdata that is like a TXT record

    @ivar strings: the text strings
    @type strings: list of string
    @see: RFC 1035�stringscs4tt|�j||�t|t�r"|g}|dd�|_dS)N)�superr�__init__�
isinstance�strr)�self�rdclass�rdtyper)�	__class__��/usr/lib/python3.6/txtbase.pyr$s
zTXTBase.__init__NTcKs8d}d}x*|jD] }|d|tjj|�f7}d}qW|S)N�z%s"%s"� )r�dns�rdataZ	_escapify)r	�origin�
relativize�kwZtxt�prefix�sr
r
r�to_text*szTXTBase.to_textc	Cs�g}xz|j�j�}|j�rP|j�p*|j�s8tjjd��t|j	�dkrRtjjd��|j	}t
|t�rn|j|�q|j|j
��qWt|�dkr�tjj�||||�S)Nzexpected a string�zstring too longr)�getZunescapeZ
is_eol_or_eofZis_quoted_stringZ
is_identifierr�	exception�SyntaxError�len�valuerr�append�encodeZ
UnexpectedEnd)	�clsr
r�tokrrr�tokenrr
r
r�	from_text2s 
zTXTBase.from_textcCsDx>|jD]4}t|�}|dks t�|jtjd|��|j|�qWdS)N�z!B)rr�AssertionError�write�struct�pack)r	�file�compressrr�lr
r
r�to_wireFs
zTXTBase.to_wirec
Cstg}xb|dkrf||}|d7}|d8}||kr6tjj�||||�j�}	||7}||8}|j|	�qW||||�S)Nr�)rrZ	FormErrorZunwrapr)
r!r
rZwireZcurrentZrdlenrrr,rr
r
r�	from_wireMs
zTXTBase.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodr$r-r/�
__classcell__r
r
)rrrs

r)r3r(Z
dns.exceptionrZ	dns.rdataZ
dns.tokenizerZdns._compatrrZRdatarr
r
r
r�<module>srdtypes/__pycache__/dnskeybase.cpython-36.opt-1.pyc000064400000007065150351404310016167 0ustar003

�b�W#�@s�ddlZddlZddlZddlZddlZdddddgZdZdZd	Z	eee	d
�Z
edd�e
j�D��Z
d
d�Zdd�ZGdd�dejj�ZdS)�N�SEP�REVOKE�ZONE�flags_to_text_set�flags_from_text_set���)rrrccs|]\}}||fVqdS)N�)�.0�x�yr
r
� /usr/lib/python3.6/dnskeybase.py�	<genexpr>)srcCsLt�}d}x<|dkrF||@r<tj|�}|s2t|�}|j|�|dK}qW|S)zCConvert a DNSKEY flags value to set texts
    @rtype: set([string])ri�)�set�_flag_by_value�get�hex�add)�flagsZ	flags_set�mask�textr
r
rr,s


cCsHd}x>|D]6}y|t|7}Wq
tk
r>td|��Yq
Xq
W|S)zNConvert set of DNSKEY flag mnemonic texts to DNSKEY flag value
    @rtype: intrz!DNSKEY flag '%s' is not supported)�
_flag_by_text�KeyError�NotImplementedError)Z	texts_setrrr
r
rr<s
csdeZdZdZddddgZ�fdd�Zdd
d�Zeddd
��Zddd�Z	eddd��Z
dd�Z�ZS)�
DNSKEYBasea?Base class for rdata that is like a DNSKEY record

    @ivar flags: the key flags
    @type flags: int
    @ivar protocol: the protocol for which this key may be used
    @type protocol: int
    @ivar algorithm: the algorithm used for the key
    @type algorithm: int
    @ivar key: the public key
    @type key: stringr�protocol�	algorithm�keycs.tt|�j||�||_||_||_||_dS)N)�superr�__init__rrrr)�self�rdclass�rdtyperrrr)�	__class__r
rr Ys
zDNSKEYBase.__init__NTcKs d|j|j|jtjj|j�fS)Nz%d %d %d %s)rrr�dns�rdataZ
_base64ifyr)r!�origin�
relativize�kwr
r
r�to_text`szDNSKEYBase.to_textc
Cs�|j�}|j�}tjj|j��}g}	x:|j�j�}
|
j�r<P|
j	�sLtj
j�|	j|
j
j��q&Wdj|	�}tj|�}|||||||�S)N�)Z
get_uint16Z	get_uint8r%ZdnssecZalgorithm_from_textZ
get_stringrZunescapeZ
is_eol_or_eofZ
is_identifier�	exception�SyntaxError�append�value�encode�join�base64Z	b64decode)
�clsr"r#�tokr'r(rrrZchunks�tZb64rr
r
r�	from_textds

zDNSKEYBase.from_textcCs0tjd|j|j|j�}|j|�|j|j�dS)Nz!HBB)�struct�packrrr�writer)r!�file�compressr'�headerr
r
r�to_wireus
zDNSKEYBase.to_wirec	Csj|dkrtjj�tjd|||d��}|d7}|d8}||||�j�}||||d|d|d|�S)N�z!HBBrr�)r%r,Z	FormErrorr7�unpackZunwrap)	r3r"r#ZwireZcurrentZrdlenr'r<rr
r
r�	from_wirezszDNSKEYBase.from_wirecCs
t|j�S)zGConvert a DNSKEY flags value to set texts
        @rtype: set([string]))rr)r!r
r
rr�szDNSKEYBase.flags_to_text_set)NT)NT)NN)N)
�__name__�
__module__�__qualname__�__doc__�	__slots__r r*�classmethodr6r=rAr�
__classcell__r
r
)r$rrJs


r)r2r7Z
dns.exceptionr%Z
dns.dnssecZ	dns.rdata�__all__rrrr�dict�itemsrrrr&ZRdatarr
r
r
r�<module>s rdtypes/txtbase.py000064400000005737150351404310010272 0ustar00# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""TXT-like base class."""

import struct

import dns.exception
import dns.rdata
import dns.tokenizer
from dns._compat import binary_type


class TXTBase(dns.rdata.Rdata):

    """Base class for rdata that is like a TXT record

    @ivar strings: the text strings
    @type strings: list of string
    @see: RFC 1035"""

    __slots__ = ['strings']

    def __init__(self, rdclass, rdtype, strings):
        super(TXTBase, self).__init__(rdclass, rdtype)
        if isinstance(strings, str):
            strings = [strings]
        self.strings = strings[:]

    def to_text(self, origin=None, relativize=True, **kw):
        txt = ''
        prefix = ''
        for s in self.strings:
            txt += '%s"%s"' % (prefix, dns.rdata._escapify(s))
            prefix = ' '
        return txt

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        strings = []
        while 1:
            token = tok.get().unescape()
            if token.is_eol_or_eof():
                break
            if not (token.is_quoted_string() or token.is_identifier()):
                raise dns.exception.SyntaxError("expected a string")
            if len(token.value) > 255:
                raise dns.exception.SyntaxError("string too long")
            value = token.value
            if isinstance(value, binary_type):
                strings.append(value)
            else:
                strings.append(value.encode())
        if len(strings) == 0:
            raise dns.exception.UnexpectedEnd
        return cls(rdclass, rdtype, strings)

    def to_wire(self, file, compress=None, origin=None):
        for s in self.strings:
            l = len(s)
            assert l < 256
            file.write(struct.pack('!B', l))
            file.write(s)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        strings = []
        while rdlen > 0:
            l = wire[current]
            current += 1
            rdlen -= 1
            if l > rdlen:
                raise dns.exception.FormError
            s = wire[current: current + l].unwrap()
            current += l
            rdlen -= l
            strings.append(s)
        return cls(rdclass, rdtype, strings)
rdtypes/ANY/PTR.py000064400000001553150351404310007704 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.nsbase


class PTR(dns.rdtypes.nsbase.NSBase):

    """PTR record"""
rdtypes/ANY/__init__.py000064400000002305150351404310010772 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""Class ANY (generic) rdata type classes."""

__all__ = [
    'AFSDB',
    'CDNSKEY',
    'CDS',
    'CERT',
    'CNAME',
    'DLV',
    'DNAME',
    'DNSKEY',
    'DS',
    'EUI48',
    'EUI64',
    'GPOS',
    'HINFO',
    'HIP',
    'ISDN',
    'LOC',
    'MX',
    'NS',
    'NSEC',
    'NSEC3',
    'NSEC3PARAM',
    'TLSA',
    'PTR',
    'RP',
    'RRSIG',
    'RT',
    'SOA',
    'SPF',
    'SSHFP',
    'TXT',
    'X25',
]
rdtypes/ANY/RP.py000064400000005776150351404310007573 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.exception
import dns.rdata
import dns.name


class RP(dns.rdata.Rdata):

    """RP record

    @ivar mbox: The responsible person's mailbox
    @type mbox: dns.name.Name object
    @ivar txt: The owner name of a node with TXT records, or the root name
    if no TXT records are associated with this RP.
    @type txt: dns.name.Name object
    @see: RFC 1183"""

    __slots__ = ['mbox', 'txt']

    def __init__(self, rdclass, rdtype, mbox, txt):
        super(RP, self).__init__(rdclass, rdtype)
        self.mbox = mbox
        self.txt = txt

    def to_text(self, origin=None, relativize=True, **kw):
        mbox = self.mbox.choose_relativity(origin, relativize)
        txt = self.txt.choose_relativity(origin, relativize)
        return "%s %s" % (str(mbox), str(txt))

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        mbox = tok.get_name()
        txt = tok.get_name()
        mbox = mbox.choose_relativity(origin, relativize)
        txt = txt.choose_relativity(origin, relativize)
        tok.get_eol()
        return cls(rdclass, rdtype, mbox, txt)

    def to_wire(self, file, compress=None, origin=None):
        self.mbox.to_wire(file, None, origin)
        self.txt.to_wire(file, None, origin)

    def to_digestable(self, origin=None):
        return self.mbox.to_digestable(origin) + \
            self.txt.to_digestable(origin)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        (mbox, cused) = dns.name.from_wire(wire[: current + rdlen],
                                           current)
        current += cused
        rdlen -= cused
        if rdlen <= 0:
            raise dns.exception.FormError
        (txt, cused) = dns.name.from_wire(wire[: current + rdlen],
                                          current)
        if cused != rdlen:
            raise dns.exception.FormError
        if origin is not None:
            mbox = mbox.relativize(origin)
            txt = txt.relativize(origin)
        return cls(rdclass, rdtype, mbox, txt)

    def choose_relativity(self, origin=None, relativize=True):
        self.mbox = self.mbox.choose_relativity(origin, relativize)
        self.txt = self.txt.choose_relativity(origin, relativize)
rdtypes/ANY/DNSKEY.py000064400000002000150351404310010220 0ustar00# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.dnskeybase
from dns.rdtypes.dnskeybase import flags_to_text_set, flags_from_text_set


__all__ = ['flags_to_text_set', 'flags_from_text_set']


class DNSKEY(dns.rdtypes.dnskeybase.DNSKEYBase):

    """DNSKEY record"""
rdtypes/ANY/RRSIG.py000064400000013037150351404310010125 0ustar00# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import base64
import calendar
import struct
import time

import dns.dnssec
import dns.exception
import dns.rdata
import dns.rdatatype


class BadSigTime(dns.exception.DNSException):

    """Time in DNS SIG or RRSIG resource record cannot be parsed."""


def sigtime_to_posixtime(what):
    if len(what) != 14:
        raise BadSigTime
    year = int(what[0:4])
    month = int(what[4:6])
    day = int(what[6:8])
    hour = int(what[8:10])
    minute = int(what[10:12])
    second = int(what[12:14])
    return calendar.timegm((year, month, day, hour, minute, second,
                            0, 0, 0))


def posixtime_to_sigtime(what):
    return time.strftime('%Y%m%d%H%M%S', time.gmtime(what))


class RRSIG(dns.rdata.Rdata):

    """RRSIG record

    @ivar type_covered: the rdata type this signature covers
    @type type_covered: int
    @ivar algorithm: the algorithm used for the sig
    @type algorithm: int
    @ivar labels: number of labels
    @type labels: int
    @ivar original_ttl: the original TTL
    @type original_ttl: long
    @ivar expiration: signature expiration time
    @type expiration: long
    @ivar inception: signature inception time
    @type inception: long
    @ivar key_tag: the key tag
    @type key_tag: int
    @ivar signer: the signer
    @type signer: dns.name.Name object
    @ivar signature: the signature
    @type signature: string"""

    __slots__ = ['type_covered', 'algorithm', 'labels', 'original_ttl',
                 'expiration', 'inception', 'key_tag', 'signer',
                 'signature']

    def __init__(self, rdclass, rdtype, type_covered, algorithm, labels,
                 original_ttl, expiration, inception, key_tag, signer,
                 signature):
        super(RRSIG, self).__init__(rdclass, rdtype)
        self.type_covered = type_covered
        self.algorithm = algorithm
        self.labels = labels
        self.original_ttl = original_ttl
        self.expiration = expiration
        self.inception = inception
        self.key_tag = key_tag
        self.signer = signer
        self.signature = signature

    def covers(self):
        return self.type_covered

    def to_text(self, origin=None, relativize=True, **kw):
        return '%s %d %d %d %s %s %d %s %s' % (
            dns.rdatatype.to_text(self.type_covered),
            self.algorithm,
            self.labels,
            self.original_ttl,
            posixtime_to_sigtime(self.expiration),
            posixtime_to_sigtime(self.inception),
            self.key_tag,
            self.signer.choose_relativity(origin, relativize),
            dns.rdata._base64ify(self.signature)
        )

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        type_covered = dns.rdatatype.from_text(tok.get_string())
        algorithm = dns.dnssec.algorithm_from_text(tok.get_string())
        labels = tok.get_int()
        original_ttl = tok.get_ttl()
        expiration = sigtime_to_posixtime(tok.get_string())
        inception = sigtime_to_posixtime(tok.get_string())
        key_tag = tok.get_int()
        signer = tok.get_name()
        signer = signer.choose_relativity(origin, relativize)
        chunks = []
        while 1:
            t = tok.get().unescape()
            if t.is_eol_or_eof():
                break
            if not t.is_identifier():
                raise dns.exception.SyntaxError
            chunks.append(t.value.encode())
        b64 = b''.join(chunks)
        signature = base64.b64decode(b64)
        return cls(rdclass, rdtype, type_covered, algorithm, labels,
                   original_ttl, expiration, inception, key_tag, signer,
                   signature)

    def to_wire(self, file, compress=None, origin=None):
        header = struct.pack('!HBBIIIH', self.type_covered,
                             self.algorithm, self.labels,
                             self.original_ttl, self.expiration,
                             self.inception, self.key_tag)
        file.write(header)
        self.signer.to_wire(file, None, origin)
        file.write(self.signature)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        header = struct.unpack('!HBBIIIH', wire[current: current + 18])
        current += 18
        rdlen -= 18
        (signer, cused) = dns.name.from_wire(wire[: current + rdlen], current)
        current += cused
        rdlen -= cused
        if origin is not None:
            signer = signer.relativize(origin)
        signature = wire[current: current + rdlen].unwrap()
        return cls(rdclass, rdtype, header[0], header[1], header[2],
                   header[3], header[4], header[5], header[6], signer,
                   signature)

    def choose_relativity(self, origin=None, relativize=True):
        self.signer = self.signer.choose_relativity(origin, relativize)
rdtypes/ANY/NS.py000064400000001551150351404310007555 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.nsbase


class NS(dns.rdtypes.nsbase.NSBase):

    """NS record"""
rdtypes/ANY/EUI64.py000064400000002156150351404310010033 0ustar00# Copyright (C) 2015 Red Hat, Inc.
# Author: Petr Spacek <pspacek@redhat.com>
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.euibase


class EUI64(dns.rdtypes.euibase.EUIBase):

    """EUI64 record

    @ivar fingerprint: 64-bit Extended Unique Identifier (EUI-64)
    @type fingerprint: string
    @see: rfc7043.txt"""

    byte_len = 8  # 0123456789abcdef (in hex)
    text_len = byte_len * 3 - 1  # 01-23-45-67-89-ab-cd-ef
rdtypes/ANY/SPF.py000064400000001603150351404310007663 0ustar00# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.txtbase


class SPF(dns.rdtypes.txtbase.TXTBase):

    """SPF record

    @see: RFC 4408"""
rdtypes/ANY/CDNSKEY.py000064400000002002150351404310010325 0ustar00# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.dnskeybase
from dns.rdtypes.dnskeybase import flags_to_text_set, flags_from_text_set


__all__ = ['flags_to_text_set', 'flags_from_text_set']


class CDNSKEY(dns.rdtypes.dnskeybase.DNSKEYBase):

    """CDNSKEY record"""
rdtypes/ANY/X25.py000064400000004107150351404310007613 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct

import dns.exception
import dns.rdata
import dns.tokenizer
from dns._compat import text_type


class X25(dns.rdata.Rdata):

    """X25 record

    @ivar address: the PSDN address
    @type address: string
    @see: RFC 1183"""

    __slots__ = ['address']

    def __init__(self, rdclass, rdtype, address):
        super(X25, self).__init__(rdclass, rdtype)
        if isinstance(address, text_type):
            self.address = address.encode()
        else:
            self.address = address

    def to_text(self, origin=None, relativize=True, **kw):
        return '"%s"' % dns.rdata._escapify(self.address)

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        address = tok.get_string()
        tok.get_eol()
        return cls(rdclass, rdtype, address)

    def to_wire(self, file, compress=None, origin=None):
        l = len(self.address)
        assert l < 256
        file.write(struct.pack('!B', l))
        file.write(self.address)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        l = wire[current]
        current += 1
        rdlen -= 1
        if l != rdlen:
            raise dns.exception.FormError
        address = wire[current: current + l].unwrap()
        return cls(rdclass, rdtype, address)
rdtypes/ANY/CERT.py000064400000007557150351404310010006 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct
import base64

import dns.exception
import dns.dnssec
import dns.rdata
import dns.tokenizer

_ctype_by_value = {
    1: 'PKIX',
    2: 'SPKI',
    3: 'PGP',
    253: 'URI',
    254: 'OID',
}

_ctype_by_name = {
    'PKIX': 1,
    'SPKI': 2,
    'PGP': 3,
    'URI': 253,
    'OID': 254,
}


def _ctype_from_text(what):
    v = _ctype_by_name.get(what)
    if v is not None:
        return v
    return int(what)


def _ctype_to_text(what):
    v = _ctype_by_value.get(what)
    if v is not None:
        return v
    return str(what)


class CERT(dns.rdata.Rdata):

    """CERT record

    @ivar certificate_type: certificate type
    @type certificate_type: int
    @ivar key_tag: key tag
    @type key_tag: int
    @ivar algorithm: algorithm
    @type algorithm: int
    @ivar certificate: the certificate or CRL
    @type certificate: string
    @see: RFC 2538"""

    __slots__ = ['certificate_type', 'key_tag', 'algorithm', 'certificate']

    def __init__(self, rdclass, rdtype, certificate_type, key_tag, algorithm,
                 certificate):
        super(CERT, self).__init__(rdclass, rdtype)
        self.certificate_type = certificate_type
        self.key_tag = key_tag
        self.algorithm = algorithm
        self.certificate = certificate

    def to_text(self, origin=None, relativize=True, **kw):
        certificate_type = _ctype_to_text(self.certificate_type)
        return "%s %d %s %s" % (certificate_type, self.key_tag,
                                dns.dnssec.algorithm_to_text(self.algorithm),
                                dns.rdata._base64ify(self.certificate))

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        certificate_type = _ctype_from_text(tok.get_string())
        key_tag = tok.get_uint16()
        algorithm = dns.dnssec.algorithm_from_text(tok.get_string())
        if algorithm < 0 or algorithm > 255:
            raise dns.exception.SyntaxError("bad algorithm type")
        chunks = []
        while 1:
            t = tok.get().unescape()
            if t.is_eol_or_eof():
                break
            if not t.is_identifier():
                raise dns.exception.SyntaxError
            chunks.append(t.value.encode())
        b64 = b''.join(chunks)
        certificate = base64.b64decode(b64)
        return cls(rdclass, rdtype, certificate_type, key_tag,
                   algorithm, certificate)

    def to_wire(self, file, compress=None, origin=None):
        prefix = struct.pack("!HHB", self.certificate_type, self.key_tag,
                             self.algorithm)
        file.write(prefix)
        file.write(self.certificate)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        prefix = wire[current: current + 5].unwrap()
        current += 5
        rdlen -= 5
        if rdlen < 0:
            raise dns.exception.FormError
        (certificate_type, key_tag, algorithm) = struct.unpack("!HHB", prefix)
        certificate = wire[current: current + rdlen].unwrap()
        return cls(rdclass, rdtype, certificate_type, key_tag, algorithm,
                   certificate)
rdtypes/ANY/HINFO.py000064400000005151150351404310010100 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct

import dns.exception
import dns.rdata
import dns.tokenizer
from dns._compat import text_type


class HINFO(dns.rdata.Rdata):

    """HINFO record

    @ivar cpu: the CPU type
    @type cpu: string
    @ivar os: the OS type
    @type os: string
    @see: RFC 1035"""

    __slots__ = ['cpu', 'os']

    def __init__(self, rdclass, rdtype, cpu, os):
        super(HINFO, self).__init__(rdclass, rdtype)
        if isinstance(cpu, text_type):
            self.cpu = cpu.encode()
        else:
            self.cpu = cpu
        if isinstance(os, text_type):
            self.os = os.encode()
        else:
            self.os = os

    def to_text(self, origin=None, relativize=True, **kw):
        return '"%s" "%s"' % (dns.rdata._escapify(self.cpu),
                              dns.rdata._escapify(self.os))

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        cpu = tok.get_string()
        os = tok.get_string()
        tok.get_eol()
        return cls(rdclass, rdtype, cpu, os)

    def to_wire(self, file, compress=None, origin=None):
        l = len(self.cpu)
        assert l < 256
        file.write(struct.pack('!B', l))
        file.write(self.cpu)
        l = len(self.os)
        assert l < 256
        file.write(struct.pack('!B', l))
        file.write(self.os)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        l = wire[current]
        current += 1
        rdlen -= 1
        if l > rdlen:
            raise dns.exception.FormError
        cpu = wire[current:current + l].unwrap()
        current += l
        rdlen -= l
        l = wire[current]
        current += 1
        rdlen -= 1
        if l != rdlen:
            raise dns.exception.FormError
        os = wire[current: current + l].unwrap()
        return cls(rdclass, rdtype, cpu, os)
rdtypes/ANY/__pycache__/DNSKEY.cpython-36.opt-1.pyc000064400000000723150351404310015455 0ustar003

�b�W�@s:ddlZddlmZmZddgZGdd�dejjj�ZdS)�N)�flags_to_text_set�flags_from_text_setrrc@seZdZdZdS)�DNSKEYz
DNSKEY recordN)�__name__�
__module__�__qualname__�__doc__�r	r	�/usr/lib/python3.6/DNSKEY.pyrsr)	Zdns.rdtypes.dnskeybaseZdnsrr�__all__ZrdtypesZ
dnskeybaseZ
DNSKEYBaserr	r	r	r
�<module>srdtypes/ANY/__pycache__/DLV.cpython-36.opt-1.pyc000064400000000533150351404310015104 0ustar003

�b�W`�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�DLVz
DLV recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/DLV.pyrsr)Zdns.rdtypes.dsbaseZdnsZrdtypesZdsbaseZDSBaserrrrr�<module>srdtypes/ANY/__pycache__/CERT.cpython-36.pyc000064400000005736150351404310014267 0ustar003

�b�Wo�@sxddlZddlZddlZddlZddlZddlZdddddd�Zdd	d
ddd
�Zdd�Z	dd�Z
Gdd�dejj�Z
dS)�N�PKIX�SPKI�PGP�URI�OID)�����rrr	r
r)rrrrrcCstj|�}|dk	r|St|�S)N)�_ctype_by_name�get�int)�what�v�r�/usr/lib/python3.6/CERT.py�_ctype_from_text)s
rcCstj|�}|dk	r|St|�S)N)�_ctype_by_valuer
�str)rrrrr�_ctype_to_text0s
rcs\eZdZdZddddgZ�fdd�Zdd
d�Zeddd
��Zddd�Z	eddd��Z
�ZS)�CERTa"CERT record

    @ivar certificate_type: certificate type
    @type certificate_type: int
    @ivar key_tag: key tag
    @type key_tag: int
    @ivar algorithm: algorithm
    @type algorithm: int
    @ivar certificate: the certificate or CRL
    @type certificate: string
    @see: RFC 2538�certificate_type�key_tag�	algorithm�certificatecs.tt|�j||�||_||_||_||_dS)N)�superr�__init__rrrr)�self�rdclass�rdtyperrrr)�	__class__rrrGs
z
CERT.__init__NTcKs0t|j�}d||jtjj|j�tjj|j	�fS)Nz%s %d %s %s)
rrr�dns�dnssecZalgorithm_to_textr�rdataZ
_base64ifyr)r�origin�
relativize�kwrrrr�to_textOs
zCERT.to_textc
Cs�t|j��}|j�}tjj|j��}|dks4|dkr@tjjd��g}	x:|j�j	�}
|
j
�r\P|
j�sltjj�|	j|
j
j��qFWdj|	�}tj|�}|||||||�S)Nr�zbad algorithm type�)rZ
get_stringZ
get_uint16r"r#Zalgorithm_from_text�	exception�SyntaxErrorr
ZunescapeZ
is_eol_or_eofZ
is_identifier�append�value�encode�join�base64Z	b64decode)
�clsrr �tokr%r&rrrZchunks�tZb64rrrr�	from_textUs"


zCERT.from_textcCs0tjd|j|j|j�}|j|�|j|j�dS)Nz!HHB)�struct�packrrr�writer)r�file�compressr%�prefixrrr�to_wireis
zCERT.to_wirecCsl|||d�j�}|d7}|d8}|dkr4tjj�tjd|�\}}	}
||||�j�}|||||	|
|�S)N�rz!HHB)Zunwrapr"r+Z	FormErrorr6�unpack)r2rr ZwireZcurrentZrdlenr%r;rrrrrrr�	from_wireoszCERT.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr(�classmethodr5r<r?�
__classcell__rr)r!rr7s

r)r6r1Z
dns.exceptionr"Z
dns.dnssecZ	dns.rdataZ
dns.tokenizerrrrrr$ZRdatarrrrr�<module>s$rdtypes/ANY/__pycache__/CERT.cpython-36.opt-1.pyc000064400000005736150351404310015226 0ustar003

�b�Wo�@sxddlZddlZddlZddlZddlZddlZdddddd�Zdd	d
ddd
�Zdd�Z	dd�Z
Gdd�dejj�Z
dS)�N�PKIX�SPKI�PGP�URI�OID)�����rrr	r
r)rrrrrcCstj|�}|dk	r|St|�S)N)�_ctype_by_name�get�int)�what�v�r�/usr/lib/python3.6/CERT.py�_ctype_from_text)s
rcCstj|�}|dk	r|St|�S)N)�_ctype_by_valuer
�str)rrrrr�_ctype_to_text0s
rcs\eZdZdZddddgZ�fdd�Zdd
d�Zeddd
��Zddd�Z	eddd��Z
�ZS)�CERTa"CERT record

    @ivar certificate_type: certificate type
    @type certificate_type: int
    @ivar key_tag: key tag
    @type key_tag: int
    @ivar algorithm: algorithm
    @type algorithm: int
    @ivar certificate: the certificate or CRL
    @type certificate: string
    @see: RFC 2538�certificate_type�key_tag�	algorithm�certificatecs.tt|�j||�||_||_||_||_dS)N)�superr�__init__rrrr)�self�rdclass�rdtyperrrr)�	__class__rrrGs
z
CERT.__init__NTcKs0t|j�}d||jtjj|j�tjj|j	�fS)Nz%s %d %s %s)
rrr�dns�dnssecZalgorithm_to_textr�rdataZ
_base64ifyr)r�origin�
relativize�kwrrrr�to_textOs
zCERT.to_textc
Cs�t|j��}|j�}tjj|j��}|dks4|dkr@tjjd��g}	x:|j�j	�}
|
j
�r\P|
j�sltjj�|	j|
j
j��qFWdj|	�}tj|�}|||||||�S)Nr�zbad algorithm type�)rZ
get_stringZ
get_uint16r"r#Zalgorithm_from_text�	exception�SyntaxErrorr
ZunescapeZ
is_eol_or_eofZ
is_identifier�append�value�encode�join�base64Z	b64decode)
�clsrr �tokr%r&rrrZchunks�tZb64rrrr�	from_textUs"


zCERT.from_textcCs0tjd|j|j|j�}|j|�|j|j�dS)Nz!HHB)�struct�packrrr�writer)r�file�compressr%�prefixrrr�to_wireis
zCERT.to_wirecCsl|||d�j�}|d7}|d8}|dkr4tjj�tjd|�\}}	}
||||�j�}|||||	|
|�S)N�rz!HHB)Zunwrapr"r+Z	FormErrorr6�unpack)r2rr ZwireZcurrentZrdlenr%r;rrrrrrr�	from_wireoszCERT.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr(�classmethodr5r<r?�
__classcell__rr)r!rr7s

r)r6r1Z
dns.exceptionr"Z
dns.dnssecZ	dns.rdataZ
dns.tokenizerrrrrr$ZRdatarrrrr�<module>s$rdtypes/ANY/__pycache__/DS.cpython-36.opt-1.pyc000064400000000530150351404310014762 0ustar003

�b�Wi�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�DSz	DS recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/DS.pyrsr)Zdns.rdtypes.dsbaseZdnsZrdtypesZdsbaseZDSBaserrrrr�<module>srdtypes/ANY/__pycache__/CDS.cpython-36.opt-1.pyc000064400000000533150351404310015070 0ustar003

�b�Wk�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�CDSz
CDS recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/CDS.pyrsr)Zdns.rdtypes.dsbaseZdnsZrdtypesZdsbaseZDSBaserrrrr�<module>srdtypes/ANY/__pycache__/CDNSKEY.cpython-36.opt-1.pyc000064400000000726150351404310015563 0ustar003

�b�W�@s:ddlZddlmZmZddgZGdd�dejjj�ZdS)�N)�flags_to_text_set�flags_from_text_setrrc@seZdZdZdS)�CDNSKEYzCDNSKEY recordN)�__name__�
__module__�__qualname__�__doc__�r	r	�/usr/lib/python3.6/CDNSKEY.pyrsr)	Zdns.rdtypes.dnskeybaseZdnsrr�__all__ZrdtypesZ
dnskeybaseZ
DNSKEYBaserr	r	r	r
�<module>srdtypes/ANY/__pycache__/RRSIG.cpython-36.opt-1.pyc000064400000010537150351404310015352 0ustar003

�b�W�@s|ddlZddlZddlZddlZddlZddlZddlZddlZGdd�dej	j
�Zdd�Zdd�Z
Gdd	�d	ejj�ZdS)
�Nc@seZdZdZdS)�
BadSigTimez:Time in DNS SIG or RRSIG resource record cannot be parsed.N)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/RRSIG.pyrsrc
Cs�t|�dkrt�t|dd��}t|dd��}t|dd��}t|dd��}t|dd��}t|dd��}tj||||||dddf	�S)N�r����
�)�lenr�int�calendarZtimegm)�whatZyearZmonthZdayZhourZminute�secondrrr�sigtime_to_posixtime srcCstjdtj|��S)Nz%Y%m%d%H%M%S)�timeZstrftimeZgmtime)rrrr�posixtime_to_sigtime-src	sxeZdZdZdddddddd	d
g	Z�fdd�Zd
d�Zddd�Zeddd��Z	ddd�Z
eddd��Zddd�Z�Z
S) �RRSIGa~RRSIG record

    @ivar type_covered: the rdata type this signature covers
    @type type_covered: int
    @ivar algorithm: the algorithm used for the sig
    @type algorithm: int
    @ivar labels: number of labels
    @type labels: int
    @ivar original_ttl: the original TTL
    @type original_ttl: long
    @ivar expiration: signature expiration time
    @type expiration: long
    @ivar inception: signature inception time
    @type inception: long
    @ivar key_tag: the key tag
    @type key_tag: int
    @ivar signer: the signer
    @type signer: dns.name.Name object
    @ivar signature: the signature
    @type signature: string�type_covered�	algorithm�labels�original_ttl�
expiration�	inception�key_tag�signer�	signaturecsLtt|�j||�||_||_||_||_||_||_|	|_	|
|_
||_dS)N)�superr�__init__rrrrrrrrr )�self�rdclass�rdtyperrrrrrrrr )�	__class__rrr"LszRRSIG.__init__cCs|jS)N)r)r#rrr�coversZszRRSIG.coversNTcKsLdtjj|j�|j|j|jt|j�t|j	�|j
|jj||�tj
j|j�f	S)Nz%s %d %d %d %s %s %d %s %s)�dns�	rdatatype�to_textrrrrrrrrr�choose_relativity�rdataZ
_base64ifyr )r#�origin�
relativize�kwrrrr*]sz
RRSIG.to_textcCs�tjj|j��}tjj|j��}|j�}|j�}	t|j��}
t|j��}|j�}|j	�}
|
j
||�}
g}x:|j�j�}|j
�r�P|j�s�tjj�|j|jj��qjWdj|�}tj|�}|||||||	|
|||
|�S)N�)r(r)�	from_textZ
get_stringZdnssecZalgorithm_from_textZget_intZget_ttlrZget_namer+�getZunescapeZ
is_eol_or_eofZ
is_identifier�	exception�SyntaxError�append�value�encode�join�base64Z	b64decode)�clsr$r%�tokr-r.rrrrrrrrZchunks�tZb64r rrrr1js,


zRRSIG.from_textc	CsPtjd|j|j|j|j|j|j|j�}|j	|�|j
j|d|�|j	|j�dS)Nz!HBBIIIH)
�struct�packrrrrrrr�writer�to_wirer )r#�file�compressr-�headerrrrr@�s

z
RRSIG.to_wirecCs�tjd|||d��}|d7}|d8}tjj|d||�|�\}}	||	7}||	8}|dk	rh|j|�}||||�j�}
||||d|d|d|d|d|d|d	||
�S)
Nz!HBBIIIH�r���r
�r)r=�unpackr(�name�	from_wirer.Zunwrap)r:r$r%ZwireZcurrentZrdlenr-rCrZcusedr rrrrK�s
zRRSIG.from_wirecCs|jj||�|_dS)N)rr+)r#r-r.rrrr+�szRRSIG.choose_relativity)NT)NT)NN)N)NT)rrrr�	__slots__r"r'r*�classmethodr1r@rKr+�
__classcell__rr)r&rr1s


	r)r9rr=rZ
dns.dnssecr(Z
dns.exceptionZ	dns.rdataZ
dns.rdatatyper3ZDNSExceptionrrrr,ZRdatarrrrr�<module>s
rdtypes/ANY/__pycache__/CSYNC.cpython-36.opt-1.pyc000064400000006160150351404310015340 0ustar003

�b�W$�@sLddlZddlZddlZddlZddlZddlmZGdd�dejj	�Z
dS)�N)�xrangecsZeZdZdZdddgZ�fdd�Zdd	d
�Zeddd��Zdd
d�Z	eddd��Z
�ZS)�CSYNCz�CSYNC record

    @ivar serial: the SOA serial number
    @type serial: int
    @ivar flags: the CSYNC flags
    @type flags: int
    @ivar windows: the windowed bitmap list
    @type windows: list of (window number, string) tuples�serial�flags�windowscs(tt|�j||�||_||_||_dS)N)�superr�__init__rrr)�self�rdclass�rdtyperrr)�	__class__��/usr/lib/python3.6/CSYNC.pyr%szCSYNC.__init__NTcKs�d}x�|jD]�\}}g}x`tdt|��D]N}||}	x@tdd�D]2}
|	d|
?@r@|jtjj|d|d|
��q@Wq(W|ddj|�7}qWd|j|j	|fS)N�r���� z%d %d%s)
rr�len�append�dns�	rdatatype�to_text�joinrr)r	�origin�
relativize�kw�text�window�bitmap�bits�i�byte�jr
r
rr+s
 z
CSYNC.to_textcCs@|j�}|j�}g}xZ|j�j�}	|	j�r,Ptjj|	j�}
|
dkrNtj	j
d��|
dkrbtj	j
d��|j|
�qW|j�d}d}d}
t
dd�}g}x�|D]|}
|
|
kr�q�|
}
|
d}||kr�|j||d|�f�t
dd�}|}|
d}|d}|d}|d	}||d
|?B||<q�W|j||d|�f�||||||�S)NrzCSYNC with bit 0i��zCSYNC with bit > 65535�� rr�r)Z
get_uint32Z
get_uint16�getZunescapeZ
is_eol_or_eofrr�	from_text�value�	exception�SyntaxErrorr�sort�	bytearray)�clsr
r�tokrrrrZrdtypes�tokenZnrdtyper�octetsZprior_rdtyperrZ
new_window�offsetr"�bitr
r
rr(8sF
zCSYNC.from_textcCsR|jtjd|j|j��x4|jD]*\}}|jtjd|t|���|j|�q WdS)Nz!IHz!BB)�write�struct�packrrrr)r	�file�compressrrrr
r
r�to_wire_sz
CSYNC.to_wirec
Cs|dkrtjjd��tjd|||d��\}}|d7}|d8}g}	x�|dkr�|dkrbtjjd��||}
||d}|dks�|dkr�tjjd��|d	7}|d	8}||kr�tjjd
��t||||�j��}||7}||8}|	j|
|f�qFW||||||	�S)N�zCSYNC too shortz!IHr�r&r%zbad CSYNC octets�zbad CSYNC bitmap length)rr*Z	FormErrorr5�unpackr-Zunwrapr)
r.r
rZwireZcurrentZrdlenrrrrrr1rr
r
r�	from_wirees,
zCSYNC.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodr(r9r>�
__classcell__r
r
)rrrs	


&
r)r5Z
dns.exceptionrZ	dns.rdataZ
dns.rdatatypeZdns.nameZdns._compatrZrdataZRdatarr
r
r
r�<module>srdtypes/ANY/__pycache__/EUI48.cpython-36.opt-1.pyc000064400000001022150351404310015247 0ustar003

�b�Wd�@s"ddlZGdd�dejjj�ZdS)�Nc@s eZdZdZdZeddZdS)�EUI48z�EUI48 record

    @ivar fingerprint: 48-bit Extended Unique Identifier (EUI-48)
    @type fingerprint: string
    @see: rfc7043.txt���N)�__name__�
__module__�__qualname__�__doc__Zbyte_lenZtext_len�r
r
�/usr/lib/python3.6/EUI48.pyrsr)Zdns.rdtypes.euibaseZdnsZrdtypesZeuibaseZEUIBaserr
r
r
r�<module>srdtypes/ANY/__pycache__/GPOS.cpython-36.opt-1.pyc000064400000007775150351404320015247 0ustar003

�b�W��@sXddlZddlZddlZddlZddlmZmZdd�Zdd�Z	Gdd�dej
j�ZdS)	�N)�long�	text_typecCs�|ddks|ddkr$|dd�}|j�r0dS|jd�\}}|dkrV|dkrVtjj�|dkrv|j�j�rvtjj�|dkr�|j�j�r�tjj�dS)	Nr�-�+��.��-�+)�isdigit�split�dns�	exception�	FormError�decode)Zwhat�left�right�r�/usr/lib/python3.6/GPOS.py�_validate_float_stringsrcCst|t�r|j�S|S)N)�
isinstancer�encode)�valuerrr�	_sanitize&s
rcs�eZdZdZdddgZ�fdd�Zd!d	d
�Zed"dd��Zd#d
d�Z	ed$dd��Z
dd�Zdd�Ze
eedd�Zdd�Zdd�Ze
eedd�Zdd�Zdd�Ze
eed d�Z�ZS)%�GPOSz�GPOS record

    @ivar latitude: latitude
    @type latitude: string
    @ivar longitude: longitude
    @type longitude: string
    @ivar altitude: altitude
    @type altitude: string
    @see: RFC 1712�latitude�	longitude�altitudecs�tt|�j||�t|t�s0t|t�s0t|t�r8t|�}t|t�sVt|t�sVt|t�r^t|�}t|t�s|t|t�s|t|t�r�t|�}t|�}t|�}t|�}t	|�t	|�t	|�||_
||_||_dS)N)
�superr�__init__r�float�intr�strrrrrr)�self�rdclass�rdtyperrr)�	__class__rrr:s,








z
GPOS.__init__NTcKs d|jj�|jj�|jj�fS)Nz%s %s %s)rrrr)r#�origin�
relativize�kwrrr�to_textRs
zGPOS.to_textc	Cs0|j�}|j�}|j�}|j�||||||�S)N)Z
get_stringZget_eol)	�clsr$r%�tokr'r(rrrrrr�	from_textWs
zGPOS.from_textcCs|t|j�}|jtjd|��|j|j�t|j�}|jtjd|��|j|j�t|j�}|jtjd|��|j|j�dS)Nz!B)�lenr�write�struct�packrr)r#�file�compressr'�lrrr�to_wire_s


zGPOS.to_wirecCs�||}|d7}|d8}||kr(tjj�||||�j�}||7}||8}||}|d7}|d8}||krttjj�||||�j�}	||7}||8}||}|d7}|d8}||kr�tjj�||||�j�}
|||||	|
�S)Nr)r
rrZunwrap)r+r$r%ZwireZcurrentZrdlenr'r4rrrrrr�	from_wirems.zGPOS.from_wirecCs
t|j�S)N)r r)r#rrr�_get_float_latitude�szGPOS._get_float_latitudecCst|�|_dS)N)r"r)r#rrrr�_set_float_latitude�szGPOS._set_float_latitudez"latitude as a floating point value)�doccCs
t|j�S)N)r r)r#rrr�_get_float_longitude�szGPOS._get_float_longitudecCst|�|_dS)N)r"r)r#rrrr�_set_float_longitude�szGPOS._set_float_longitudez#longitude as a floating point valuecCs
t|j�S)N)r r)r#rrr�_get_float_altitude�szGPOS._get_float_altitudecCst|�|_dS)N)r"r)r#rrrr�_set_float_altitude�szGPOS._set_float_altitudez"altitude as a floating point value)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr*�classmethodr-r5r6r7r8�propertyZfloat_latituder:r;Zfloat_longituder<r=Zfloat_altitude�
__classcell__rr)r&rr,s*



r)
r0Z
dns.exceptionr
Z	dns.rdataZ
dns.tokenizerZdns._compatrrrrZrdataZRdatarrrrr�<module>srdtypes/ANY/__pycache__/DS.cpython-36.pyc000064400000000530150351404320014024 0ustar003

�b�Wi�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�DSz	DS recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/DS.pyrsr)Zdns.rdtypes.dsbaseZdnsZrdtypesZdsbaseZDSBaserrrrr�<module>srdtypes/ANY/__pycache__/NSEC3PARAM.cpython-36.opt-1.pyc000064400000004451150351404320016057 0ustar003

�b�W�@sDddlZddlZddlZddlZddlmZGdd�dejj�Z	dS)�N)�	text_typecs\eZdZdZddddgZ�fdd�Zdd
d�Zeddd
��Zddd�Z	eddd��Z
�ZS)�
NSEC3PARAMaNSEC3PARAM record

    @ivar algorithm: the hash algorithm number
    @type algorithm: int
    @ivar flags: the flags
    @type flags: int
    @ivar iterations: the number of iterations
    @type iterations: int
    @ivar salt: the salt
    @type salt: string�	algorithm�flags�
iterations�saltcsDtt|�j||�||_||_||_t|t�r:|j�|_	n||_	dS)N)
�superr�__init__rrr�
isinstancer�encoder)�self�rdclass�rdtyperrrr)�	__class__�� /usr/lib/python3.6/NSEC3PARAM.pyr	's
zNSEC3PARAM.__init__NTcKs6|jdkrd}ntj|j�j�}d|j|j|j|fS)N��-z%u %u %u %s)r�binasciiZhexlify�decoderrr)r�origin�
relativize�kwrrrr�to_text1s

zNSEC3PARAM.to_textc
CsV|j�}|j�}|j�}|j�}	|	dkr.d}	ntj|	j��}	|j�|||||||	�S)Nr�)Z	get_uint8Z
get_uint16Z
get_stringrZ	unhexlifyrZget_eol)
�clsr
r�tokrrrrrrrrr�	from_text9szNSEC3PARAM.from_textcCs8t|j�}|jtjd|j|j|j|��|j|j�dS)Nz!BBHB)�lenr�write�struct�packrrr)r�file�compressr�lrrr�to_wireFs
zNSEC3PARAM.to_wirecCsvtjd|||d��\}}}	}
|d7}|d8}||||
�j�}||
7}||
8}|dkrdtjj�||||||	|�S)Nz!BBHB�r)r �unpackZunwrap�dnsZ	exceptionZ	FormError)rr
rZwireZcurrentZrdlenrrrrZslenrrrr�	from_wireLszNSEC3PARAM.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__r	r�classmethodrr%r)�
__classcell__rr)rrrs


r)
r rZ
dns.exceptionr(Z	dns.rdataZdns._compatrZrdataZRdatarrrrr�<module>s
rdtypes/ANY/__pycache__/HINFO.cpython-36.pyc000064400000003772150351404320014374 0ustar003

�b�Wi
�@sDddlZddlZddlZddlZddlmZGdd�dejj�Z	dS)�N)�	text_typecsXeZdZdZddgZ�fdd�Zddd	�Zedd
d��Zddd
�Z	eddd��Z
�ZS)�HINFOz�HINFO record

    @ivar cpu: the CPU type
    @type cpu: string
    @ivar os: the OS type
    @type os: string
    @see: RFC 1035�cpu�oscsNtt|�j||�t|t�r(|j�|_n||_t|t�rD|j�|_n||_dS)N)�superr�__init__�
isinstancer�encoderr)�self�rdclass�rdtyperr)�	__class__��/usr/lib/python3.6/HINFO.pyr$s

zHINFO.__init__NTcKs dtjj|j�tjj|j�fS)Nz	"%s" "%s")�dns�rdataZ	_escapifyrr)r
�origin�
relativize�kwrrr�to_text/sz
HINFO.to_textcCs&|j�}|j�}|j�|||||�S)N)Z
get_stringZget_eol)�clsrr�tokrrrrrrr�	from_text3szHINFO.from_textcCslt|j�}|dkst�|jtjd|��|j|j�t|j�}|dksJt�|jtjd|��|j|j�dS)N�z!B)�lenr�AssertionError�write�struct�packr)r
�file�compressr�lrrr�to_wire:s

z
HINFO.to_wirec
Cs�||}|d7}|d8}||kr(tjj�||||�j�}||7}||8}||}|d7}|d8}||krttjj�||||�j�}	|||||	�S)N�)rZ	exceptionZ	FormErrorZunwrap)
rrrZwireZcurrentZrdlenrr!rrrrr�	from_wireDszHINFO.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrr"r$�
__classcell__rr)r
rrs


r)
rZ
dns.exceptionrZ	dns.rdataZ
dns.tokenizerZdns._compatrrZRdatarrrrr�<module>s
rdtypes/ANY/__pycache__/AFSDB.cpython-36.pyc000064400000002077150351404320014345 0ustar003

�b�W8�@s"ddlZGdd�dejjj�ZdS)�Nc@sDeZdZdZdd�Zdd�Zeee�Zdd�Zdd	�Z	eee	�Z
d
S)�AFSDBz�AFSDB record

    @ivar subtype: the subtype value
    @type subtype: int
    @ivar hostname: the hostname name
    @type hostname: dns.name.Name objectcCs|jS)N)�
preference)�self�r�/usr/lib/python3.6/AFSDB.py�get_subtype'szAFSDB.get_subtypecCs
||_dS)N)r)r�subtyperrr�set_subtype*szAFSDB.set_subtypecCs|jS)N)�exchange)rrrr�get_hostname/szAFSDB.get_hostnamecCs
||_dS)N)r
)r�hostnamerrr�set_hostname2szAFSDB.set_hostnameN)�__name__�
__module__�__qualname__�__doc__rr	�propertyrrr
rrrrrrs

r)Zdns.rdtypes.mxbaseZdnsZrdtypesZmxbaseZUncompressedDowncasingMXrrrrr�<module>srdtypes/ANY/__pycache__/RP.cpython-36.pyc000064400000004377150351404320014054 0ustar003

�b�W��@s0ddlZddlZddlZGdd�dejj�ZdS)�NcsleZdZdZddgZ�fdd�Zddd	�Zedd
d��Zddd
�Z	ddd�Z
eddd��Zddd�Z�Z
S)�RPaRP record

    @ivar mbox: The responsible person's mailbox
    @type mbox: dns.name.Name object
    @ivar txt: The owner name of a node with TXT records, or the root name
    if no TXT records are associated with this RP.
    @type txt: dns.name.Name object
    @see: RFC 1183�mbox�txtcs"tt|�j||�||_||_dS)N)�superr�__init__rr)�self�rdclass�rdtyperr)�	__class__��/usr/lib/python3.6/RP.pyr"szRP.__init__NTcKs0|jj||�}|jj||�}dt|�t|�fS)Nz%s %s)r�choose_relativityr�str)r�origin�
relativize�kwrrrrr�to_text'sz
RP.to_textcCs>|j�}|j�}|j||�}|j||�}|j�|||||�S)N)Zget_namer
Zget_eol)�clsrr	�tokrrrrrrr�	from_text,szRP.from_textcCs$|jj|d|�|jj|d|�dS)N)r�to_wirer)r�file�compressrrrrr5sz
RP.to_wirecCs|jj|�|jj|�S)N)r�
to_digestabler)rrrrrr9s
zRP.to_digestablec
Cs�tjj|d||�|�\}}||7}||8}|dkr>tjj�tjj|d||�|�\}	}||krltjj�|dk	r�|j|�}|	j|�}	|||||	�S)Nr)�dns�name�	from_wireZ	exceptionZ	FormErrorr)
rrr	ZwireZcurrentZrdlenrrZcusedrrrrr=s



zRP.from_wirecCs$|jj||�|_|jj||�|_dS)N)rr
r)rrrrrrr
NszRP.choose_relativity)NT)NT)NN)N)N)NT)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrrrr
�
__classcell__rr)r
rrs	


r)Z
dns.exceptionrZ	dns.rdataZdns.nameZrdataZRdatarrrrr�<module>srdtypes/ANY/__pycache__/EUI48.cpython-36.pyc000064400000001022150351404320014311 0ustar003

�b�Wd�@s"ddlZGdd�dejjj�ZdS)�Nc@s eZdZdZdZeddZdS)�EUI48z�EUI48 record

    @ivar fingerprint: 48-bit Extended Unique Identifier (EUI-48)
    @type fingerprint: string
    @see: rfc7043.txt���N)�__name__�
__module__�__qualname__�__doc__Zbyte_lenZtext_len�r
r
�/usr/lib/python3.6/EUI48.pyrsr)Zdns.rdtypes.euibaseZdnsZrdtypesZeuibaseZEUIBaserr
r
r
r�<module>srdtypes/ANY/__pycache__/TXT.cpython-36.pyc000064400000000536150351404320014203 0ustar003

�b�Wn�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�TXTz
TXT recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/TXT.pyrsr)Zdns.rdtypes.txtbaseZdnsZrdtypesZtxtbaseZTXTBaserrrrr�<module>srdtypes/ANY/__pycache__/PTR.cpython-36.pyc000064400000000533150351404320014166 0ustar003

�b�Wk�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�PTRz
PTR recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/PTR.pyrsr)Zdns.rdtypes.nsbaseZdnsZrdtypesZnsbaseZNSBaserrrrr�<module>srdtypes/ANY/__pycache__/SPF.cpython-36.opt-1.pyc000064400000000562150351404320015112 0ustar003

�b�W��@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�SPFzSPF record

    @see: RFC 4408N)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/SPF.pyrsr)Zdns.rdtypes.txtbaseZdnsZrdtypesZtxtbaseZTXTBaserrrrr�<module>srdtypes/ANY/__pycache__/AFSDB.cpython-36.opt-1.pyc000064400000002077150351404320015304 0ustar003

�b�W8�@s"ddlZGdd�dejjj�ZdS)�Nc@sDeZdZdZdd�Zdd�Zeee�Zdd�Zdd	�Z	eee	�Z
d
S)�AFSDBz�AFSDB record

    @ivar subtype: the subtype value
    @type subtype: int
    @ivar hostname: the hostname name
    @type hostname: dns.name.Name objectcCs|jS)N)�
preference)�self�r�/usr/lib/python3.6/AFSDB.py�get_subtype'szAFSDB.get_subtypecCs
||_dS)N)r)r�subtyperrr�set_subtype*szAFSDB.set_subtypecCs|jS)N)�exchange)rrrr�get_hostname/szAFSDB.get_hostnamecCs
||_dS)N)r
)r�hostnamerrr�set_hostname2szAFSDB.set_hostnameN)�__name__�
__module__�__qualname__�__doc__rr	�propertyrrr
rrrrrrs

r)Zdns.rdtypes.mxbaseZdnsZrdtypesZmxbaseZUncompressedDowncasingMXrrrrr�<module>srdtypes/ANY/__pycache__/CAA.cpython-36.pyc000064400000004050150351404320014103 0ustar003

�b�W>
�@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�NcsZeZdZdZdddgZ�fdd�Zdd	d
�Zeddd��Zdd
d�Z	eddd��Z
�ZS)�CAAz�CAA (Certification Authority Authorization) record

    @ivar flags: the flags
    @type flags: int
    @ivar tag: the tag
    @type tag: string
    @ivar value: the value
    @type value: string
    @see: RFC 6844�flags�tag�valuecs(tt|�j||�||_||_||_dS)N)�superr�__init__rrr)�self�rdclass�rdtyperrr)�	__class__��/usr/lib/python3.6/CAA.pyr%szCAA.__init__NTcKs$d|jtjj|j�tjj|j�fS)Nz
%u %s "%s")r�dns�rdataZ	_escapifyrr)r�origin�
relativize�kwrrr
�to_text+szCAA.to_textc	Cs\|j�}|j�j�}t|�dkr,tjjd��|j�s@tjjd��|j�j�}||||||�S)N�ztag too longztag is not alphanumeric)Z	get_uint8Z
get_string�encode�lenrZ	exception�SyntaxError�isalnum)	�clsr	r
�tokrrrrrrrr
�	from_text0sz
CAA.from_textcCsX|jtjd|j��t|j�}|dks*t�|jtjd|��|j|j�|j|j�dS)Nz!B�)�write�struct�packrrr�AssertionErrorr)r�file�compressr�lrrr
�to_wire;s
zCAA.to_wirecCs\tjd|||d��\}}|d7}||||�}	|||||d�}
|||||	|
�S)Nz!BB�)r�unpack)rr	r
ZwireZcurrentZrdlenrrr#rrrrr
�	from_wireCs
z
CAA.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrr$r'�
__classcell__rr)rr
rs




r)rZ
dns.exceptionrZ	dns.rdataZ
dns.tokenizerrZRdatarrrrr
�<module>srdtypes/ANY/__pycache__/CSYNC.cpython-36.pyc000064400000006160150351404320014402 0ustar003

�b�W$�@sLddlZddlZddlZddlZddlZddlmZGdd�dejj	�Z
dS)�N)�xrangecsZeZdZdZdddgZ�fdd�Zdd	d
�Zeddd��Zdd
d�Z	eddd��Z
�ZS)�CSYNCz�CSYNC record

    @ivar serial: the SOA serial number
    @type serial: int
    @ivar flags: the CSYNC flags
    @type flags: int
    @ivar windows: the windowed bitmap list
    @type windows: list of (window number, string) tuples�serial�flags�windowscs(tt|�j||�||_||_||_dS)N)�superr�__init__rrr)�self�rdclass�rdtyperrr)�	__class__��/usr/lib/python3.6/CSYNC.pyr%szCSYNC.__init__NTcKs�d}x�|jD]�\}}g}x`tdt|��D]N}||}	x@tdd�D]2}
|	d|
?@r@|jtjj|d|d|
��q@Wq(W|ddj|�7}qWd|j|j	|fS)N�r���� z%d %d%s)
rr�len�append�dns�	rdatatype�to_text�joinrr)r	�origin�
relativize�kw�text�window�bitmap�bits�i�byte�jr
r
rr+s
 z
CSYNC.to_textcCs@|j�}|j�}g}xZ|j�j�}	|	j�r,Ptjj|	j�}
|
dkrNtj	j
d��|
dkrbtj	j
d��|j|
�qW|j�d}d}d}
t
dd�}g}x�|D]|}
|
|
kr�q�|
}
|
d}||kr�|j||d|�f�t
dd�}|}|
d}|d}|d}|d	}||d
|?B||<q�W|j||d|�f�||||||�S)NrzCSYNC with bit 0i��zCSYNC with bit > 65535�� rr�r)Z
get_uint32Z
get_uint16�getZunescapeZ
is_eol_or_eofrr�	from_text�value�	exception�SyntaxErrorr�sort�	bytearray)�clsr
r�tokrrrrZrdtypes�tokenZnrdtyper�octetsZprior_rdtyperrZ
new_window�offsetr"�bitr
r
rr(8sF
zCSYNC.from_textcCsR|jtjd|j|j��x4|jD]*\}}|jtjd|t|���|j|�q WdS)Nz!IHz!BB)�write�struct�packrrrr)r	�file�compressrrrr
r
r�to_wire_sz
CSYNC.to_wirec
Cs|dkrtjjd��tjd|||d��\}}|d7}|d8}g}	x�|dkr�|dkrbtjjd��||}
||d}|dks�|dkr�tjjd��|d	7}|d	8}||kr�tjjd
��t||||�j��}||7}||8}|	j|
|f�qFW||||||	�S)N�zCSYNC too shortz!IHr�r&r%zbad CSYNC octets�zbad CSYNC bitmap length)rr*Z	FormErrorr5�unpackr-Zunwrapr)
r.r
rZwireZcurrentZrdlenrrrrrr1rr
r
r�	from_wirees,
zCSYNC.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodr(r9r>�
__classcell__r
r
)rrrs	


&
r)r5Z
dns.exceptionrZ	dns.rdataZ
dns.rdatatypeZdns.nameZdns._compatrZrdataZRdatarr
r
r
r�<module>srdtypes/ANY/__pycache__/ISDN.cpython-36.pyc000064400000004336150351404320014263 0ustar003

�b�W��@sDddlZddlZddlZddlZddlmZGdd�dejj�Z	dS)�N)�	text_typecsXeZdZdZddgZ�fdd�Zddd	�Zedd
d��Zddd
�Z	eddd��Z
�ZS)�ISDNz�ISDN record

    @ivar address: the ISDN address
    @type address: string
    @ivar subaddress: the ISDN subaddress (or '' if not present)
    @type subaddress: string
    @see: RFC 1183�address�
subaddresscsNtt|�j||�t|t�r(|j�|_n||_t|t�rD|j�|_n||_dS)N)�superr�__init__�
isinstancer�encoderr)�self�rdclass�rdtyperr)�	__class__��/usr/lib/python3.6/ISDN.pyr$s

z
ISDN.__init__NTcKs<|jr&dtjj|j�tjj|j�fSdtjj|j�SdS)Nz	"%s" "%s"z"%s")r�dns�rdataZ	_escapifyr)r
�origin�
relativize�kwrrr�to_text/szISDN.to_textc	CsP|j�}|j�}|j�s,|j|�|j�}n|j|�d}|j�|||||�S)N�)Z
get_string�getZ
is_eol_or_eofZungetZget_eol)	�clsrr�tokrrr�trrrr�	from_text6s


zISDN.from_textcCstt|j�}|dkst�|jtjd|��|j|j�t|j�}|dkrp|dksRt�|jtjd|��|j|j�dS)N�z!Br)�lenr�AssertionError�write�struct�packr)r
�file�compressr�lrrr�to_wireCs

zISDN.to_wirec
Cs�||}|d7}|d8}||kr(tjj�||||�j�}||7}||8}|dkr�||}|d7}|d8}||kr|tjj�||||�j�}	nd}	|||||	�S)N�rr)rZ	exceptionZ	FormErrorZunwrap)
rrrZwireZcurrentZrdlenrr$rrrrr�	from_wireNs"zISDN.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrr%r'�
__classcell__rr)r
rrs

r)
r Z
dns.exceptionrZ	dns.rdataZ
dns.tokenizerZdns._compatrrZRdatarrrrr�<module>s
rdtypes/ANY/__pycache__/NSEC.cpython-36.pyc000064400000006251150351404320014254 0ustar003

�b�WR�@sLddlZddlZddlZddlZddlZddlmZGdd�dejj	�Z
dS)�N)�xrangecsbeZdZdZddgZ�fdd�Zddd	�Zedd
d��Zddd
�Z	eddd��Z
ddd�Z�ZS)�NSECz�NSEC record

    @ivar next: the next name
    @type next: dns.name.Name object
    @ivar windows: the windowed bitmap list
    @type windows: list of (window number, string) tuples�next�windowscs"tt|�j||�||_||_dS)N)�superr�__init__rr)�self�rdclass�rdtyperr)�	__class__��/usr/lib/python3.6/NSEC.pyr$sz
NSEC.__init__NTcKs�|jj||�}d}x�|jD]�\}}g}x`tdt|��D]N}	||	}
x@tdd�D]2}|
d|?@rN|jtjj|d|	d|��qNWq6W|ddj	|�7}qWd||fS)N�r���� z%s%s)
r�choose_relativityrr�len�append�dns�	rdatatype�to_text�join)r�origin�
relativize�kwr�text�window�bitmap�bits�i�byte�jrrr
r)s
 zNSEC.to_textcCsB|j�}|j||�}g}xZ|j�j�}|j�r0Ptjj|j�}	|	dkrRtj	j
d��|	dkrftj	j
d��|j|	�qW|j�d}
d}d}t
dd�}
g}x�|D]|}	|	|kr�q�|	}|	d}||
kr�|j|
|
d|�f�t
dd�}
|}
|	d}|d}|d}|d	}|
|d
|?B|
|<q�W|j|
|
d|�f�|||||�S)NrzNSEC with bit 0i��zNSEC with bit > 65535�� rr�r)Zget_namer�getZunescapeZ
is_eol_or_eofrr�	from_text�value�	exception�SyntaxErrorr�sort�	bytearray)�clsr	r
�tokrrrZrdtypes�tokenZnrdtyper�octetsZprior_rdtyperrZ
new_window�offsetr"�bitrrr
r(7sF
zNSEC.from_textcCsJ|jj|d|�x4|jD]*\}}|jtjd|t|���|j|�qWdS)Nz!BB)r�to_wirer�write�struct�packr)r�file�compressrrrrrr
r4^szNSEC.to_wirec
Cs�tjj|d||�|�\}}||7}||8}g}	x�|dkr�|dkrPtjjd��||}
||d}|dkst|dkr�tjjd��|d7}|d8}||kr�tjjd��t||||�j��}||7}||8}|	j|
|f�q4W|dk	r�|j|�}|||||	�S)	Nr�zNSEC too shortr&r%zbad NSEC octets�zbad NSEC bitmap length)	r�name�	from_wirer*Z	FormErrorr-Zunwraprr)
r.r	r
ZwireZcurrentZrdlenrrZcusedrrr1rrrr
r=ds,

zNSEC.from_wirecCs|jj||�|_dS)N)rr)rrrrrr
r}szNSEC.choose_relativity)NT)NT)NN)N)NT)
�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodr(r4r=r�
__classcell__rr)rr
rs
&
r)r6Z
dns.exceptionrZ	dns.rdataZ
dns.rdatatypeZdns.nameZdns._compatrZrdataZRdatarrrrr
�<module>srdtypes/ANY/__pycache__/NSEC.cpython-36.opt-1.pyc000064400000006251150351404320015213 0ustar003

�b�WR�@sLddlZddlZddlZddlZddlZddlmZGdd�dejj	�Z
dS)�N)�xrangecsbeZdZdZddgZ�fdd�Zddd	�Zedd
d��Zddd
�Z	eddd��Z
ddd�Z�ZS)�NSECz�NSEC record

    @ivar next: the next name
    @type next: dns.name.Name object
    @ivar windows: the windowed bitmap list
    @type windows: list of (window number, string) tuples�next�windowscs"tt|�j||�||_||_dS)N)�superr�__init__rr)�self�rdclass�rdtyperr)�	__class__��/usr/lib/python3.6/NSEC.pyr$sz
NSEC.__init__NTcKs�|jj||�}d}x�|jD]�\}}g}x`tdt|��D]N}	||	}
x@tdd�D]2}|
d|?@rN|jtjj|d|	d|��qNWq6W|ddj	|�7}qWd||fS)N�r���� z%s%s)
r�choose_relativityrr�len�append�dns�	rdatatype�to_text�join)r�origin�
relativize�kwr�text�window�bitmap�bits�i�byte�jrrr
r)s
 zNSEC.to_textcCsB|j�}|j||�}g}xZ|j�j�}|j�r0Ptjj|j�}	|	dkrRtj	j
d��|	dkrftj	j
d��|j|	�qW|j�d}
d}d}t
dd�}
g}x�|D]|}	|	|kr�q�|	}|	d}||
kr�|j|
|
d|�f�t
dd�}
|}
|	d}|d}|d}|d	}|
|d
|?B|
|<q�W|j|
|
d|�f�|||||�S)NrzNSEC with bit 0i��zNSEC with bit > 65535�� rr�r)Zget_namer�getZunescapeZ
is_eol_or_eofrr�	from_text�value�	exception�SyntaxErrorr�sort�	bytearray)�clsr	r
�tokrrrZrdtypes�tokenZnrdtyper�octetsZprior_rdtyperrZ
new_window�offsetr"�bitrrr
r(7sF
zNSEC.from_textcCsJ|jj|d|�x4|jD]*\}}|jtjd|t|���|j|�qWdS)Nz!BB)r�to_wirer�write�struct�packr)r�file�compressrrrrrr
r4^szNSEC.to_wirec
Cs�tjj|d||�|�\}}||7}||8}g}	x�|dkr�|dkrPtjjd��||}
||d}|dkst|dkr�tjjd��|d7}|d8}||kr�tjjd��t||||�j��}||7}||8}|	j|
|f�q4W|dk	r�|j|�}|||||	�S)	Nr�zNSEC too shortr&r%zbad NSEC octets�zbad NSEC bitmap length)	r�name�	from_wirer*Z	FormErrorr-Zunwraprr)
r.r	r
ZwireZcurrentZrdlenrrZcusedrrr1rrrr
r=ds,

zNSEC.from_wirecCs|jj||�|_dS)N)rr)rrrrrr
r}szNSEC.choose_relativity)NT)NT)NN)N)NT)
�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodr(r4r=r�
__classcell__rr)rr
rs
&
r)r6Z
dns.exceptionrZ	dns.rdataZ
dns.rdatatypeZdns.nameZdns._compatrZrdataZRdatarrrrr
�<module>srdtypes/ANY/__pycache__/EUI64.cpython-36.opt-1.pyc000064400000001022150351404320015246 0ustar003

�b�Wn�@s"ddlZGdd�dejjj�ZdS)�Nc@s eZdZdZdZeddZdS)�EUI64z�EUI64 record

    @ivar fingerprint: 64-bit Extended Unique Identifier (EUI-64)
    @type fingerprint: string
    @see: rfc7043.txt���N)�__name__�
__module__�__qualname__�__doc__Zbyte_lenZtext_len�r
r
�/usr/lib/python3.6/EUI64.pyrsr)Zdns.rdtypes.euibaseZdnsZrdtypesZeuibaseZEUIBaserr
r
r
r�<module>srdtypes/ANY/__pycache__/TXT.cpython-36.opt-1.pyc000064400000000536150351404320015142 0ustar003

�b�Wn�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�TXTz
TXT recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/TXT.pyrsr)Zdns.rdtypes.txtbaseZdnsZrdtypesZtxtbaseZTXTBaserrrrr�<module>srdtypes/ANY/__pycache__/MX.cpython-36.pyc000064400000000530150351404320014042 0ustar003

�b�Wi�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�MXz	MX recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/MX.pyrsr)Zdns.rdtypes.mxbaseZdnsZrdtypesZmxbaseZMXBaserrrrr�<module>srdtypes/ANY/__pycache__/X25.cpython-36.pyc000064400000003312150351404320014075 0ustar003

�b�WG�@sDddlZddlZddlZddlZddlmZGdd�dejj�Z	dS)�N)�	text_typecsVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�X25z\X25 record

    @ivar address: the PSDN address
    @type address: string
    @see: RFC 1183�addresscs2tt|�j||�t|t�r(|j�|_n||_dS)N)�superr�__init__�
isinstancer�encoder)�self�rdclass�rdtyper)�	__class__��/usr/lib/python3.6/X25.pyr"s
zX25.__init__NTcKsdtjj|j�S)Nz"%s")�dns�rdataZ	_escapifyr)r	�origin�
relativize�kwr
r
r�to_text)szX25.to_textcCs|j�}|j�||||�S)N)Z
get_stringZget_eol)�clsr
r�tokrrrr
r
r�	from_text,sz
X25.from_textcCs8t|j�}|dkst�|jtjd|��|j|j�dS)N�z!B)�lenr�AssertionError�write�struct�pack)r	�file�compressr�lr
r
r�to_wire2s
zX25.to_wirec	CsH||}|d7}|d8}||kr(tjj�||||�j�}||||�S)N�)rZ	exceptionZ	FormErrorZunwrap)	rr
rZwireZcurrentZrdlenrr rr
r
r�	from_wire8sz
X25.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrr!r#�
__classcell__r
r
)rrrs

r)
rZ
dns.exceptionrZ	dns.rdataZ
dns.tokenizerZdns._compatrrZRdatarr
r
r
r�<module>s
rdtypes/ANY/__pycache__/DNAME.cpython-36.pyc000064400000001003150351404320014336 0ustar003

�b�W��@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZddd�ZdS)�DNAMEzDNAME recordNcCs|jj|�S)N)�target�
to_digestable)�self�origin�r�/usr/lib/python3.6/DNAME.pyrszDNAME.to_digestable)N)�__name__�
__module__�__qualname__�__doc__rrrrrrsr)Zdns.rdtypes.nsbaseZdnsZrdtypesZnsbaseZUncompressedNSrrrrr�<module>srdtypes/ANY/__pycache__/CDS.cpython-36.pyc000064400000000533150351404320014132 0ustar003

�b�Wk�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�CDSz
CDS recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/CDS.pyrsr)Zdns.rdtypes.dsbaseZdnsZrdtypesZdsbaseZDSBaserrrrr�<module>srdtypes/ANY/__pycache__/NSEC3.cpython-36.pyc000064400000010726150351404320014341 0ustar003

�b�W��@s�ddlZddlZddlZddlZddlZddlZddlZddlm	Z	m
Z
yejdd�Zejdd�Z
Wn,ek
r�ejdd�Zejdd�Z
YnXdZdZGdd	�d	ejj�ZdS)
�N)�xrange�	text_typeZ 0123456789ABCDEFGHIJKLMNOPQRSTUVZ ABCDEFGHIJKLMNOPQRSTUVWXYZ234567s 0123456789ABCDEFGHIJKLMNOPQRSTUVs ABCDEFGHIJKLMNOPQRSTUVWXYZ234567�cs`eZdZdZddddddgZ�fdd	�Zddd
�Zeddd��Zddd�Z	eddd��Z
�ZS)�NSEC3a�NSEC3 record

    @ivar algorithm: the hash algorithm number
    @type algorithm: int
    @ivar flags: the flags
    @type flags: int
    @ivar iterations: the number of iterations
    @type iterations: int
    @ivar salt: the salt
    @type salt: string
    @ivar next: the next name hash
    @type next: string
    @ivar windows: the windowed bitmap list
    @type windows: list of (window number, string) tuples�	algorithm�flags�
iterations�salt�next�windowsc		sPtt|�j||�||_||_||_t|t�r:|j�|_	n||_	||_
||_dS)N)�superr�__init__rrr�
isinstancer�encoder	r
r)	�self�rdclass�rdtyperrrr	r
r)�	__class__��/usr/lib/python3.6/NSEC3.pyr
?s
zNSEC3.__init__NTc
Ks�tj|j�jt�j�j�}|jdkr*d}ntj	|j�j�}d}x�|j
D]�\}}g}	x`tdt|��D]N}
||
}x@tdd�D]2}|d|?@rz|	j
tjj|d|
d|��qzWqbW|ddj|	�7}qFWd	|j|j|j|||fS)
N��-�r���� z%u %u %u %s %s%s)�base64Z	b32encoder
�	translate�b32_normal_to_hex�lower�decoder	�binasciiZhexlifyrr�len�append�dns�	rdatatype�to_text�joinrrr)
r�origin�
relativize�kwr
r	�text�window�bitmap�bits�i�byte�jrrrr'Ls"

 
z
NSEC3.to_textc	Cs�|j�}|j�}|j�}|j�}	|	dkr.d}	ntj|	jd��}	|j�jd�j�jt�}
t	j
|
�}
g}xZ|j�j�}|j
�r|Ptjj|j�}
|
dkr�tjjd��|
dkr�tjjd��|j|
�qfW|j�d}d}d}tdd	�}g}x�|D]�}
|
|kr�q�|
}|
d
}||k�rD|dk�r4|j|dj|d|��f�tdd	�}|}|
d
}|d}|d}|d
}||d|?B||<q�W|dk�r�|j||d|�f�|||||||	|
|�S)Nrr�asciirzNSEC3 with bit 0i��zNSEC3 with bit > 65535�� rrrrr)Z	get_uint8Z
get_uint16Z
get_stringr"Z	unhexlifyr�upperr�b32_hex_to_normalrZ	b32decode�getZunescapeZ
is_eol_or_eofr%r&�	from_text�value�	exception�SyntaxErrorr$�sort�	bytearrayr()�clsrr�tokr)r*rrrr	r
Zrdtypes�tokenZnrdtyper-�octetsZprior_rdtyper.rZ
new_window�offsetr1�bitrrrr9`s\




zNSEC3.from_textcCs�t|j�}|jtjd|j|j|j|��|j|j�t|j�}|jtjd|��|j|j�x4|j	D]*\}}|jtjd|t|���|j|�qdWdS)Nz!BBHBz!Bz!BB)
r#r	�write�struct�packrrrr
r)r�file�compressr)�lr-r.rrr�to_wire�s

z
NSEC3.to_wirec	CsZtjd|||d��\}}}	}
|d7}|d8}||||
�j�}||
7}||
8}||}|d7}|d8}||||�j�}
||7}||8}g}x�|dk�rB|dkr�tjjd��||}||d}|dks�|dkr�tjjd��|d	7}|d	8}||k�r
tjjd
��t||||�j��}||7}||8}|j||f�q�W||||||	||
|�S)Nz!BBHB�rr�zNSEC3 too shortr5zbad NSEC3 octets�zbad NSEC3 bitmap length)rF�unpackZunwrapr%r;Z	FormErrorr>r$)r?rrZwireZcurrentZrdlenr)rrrZslenr	Znlenr
rr-rBr.rrr�	from_wire�s< 
zNSEC3.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__r
r'�classmethodr9rKrP�
__classcell__rr)rrr,s
1
r)rr"�stringrFZ
dns.exceptionr%Z	dns.rdataZ
dns.rdatatypeZdns._compatrr�	maketransr7r�AttributeError�bytesZSHA1ZOPTOUTZrdataZRdatarrrrr�<module>s(
rdtypes/ANY/__pycache__/CNAME.cpython-36.opt-1.pyc000064400000001056150351404320015304 0ustar003

�b�W<�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�CNAMEz�CNAME record

    Note: although CNAME is officially a singleton type, dnspython allows
    non-singleton CNAME rdatasets because such sets have been commonly
    used by BIND and other nameservers for load balancing.N)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/CNAME.pyrsr)Zdns.rdtypes.nsbaseZdnsZrdtypesZnsbaseZNSBaserrrrr�<module>srdtypes/ANY/__pycache__/SSHFP.cpython-36.opt-1.pyc000064400000004133150351404320015343 0ustar003

�b�W�@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�NcsZeZdZdZdddgZ�fdd�Zdd	d
�Zeddd��Zdd
d�Z	eddd��Z
�ZS)�SSHFPz�SSHFP record

    @ivar algorithm: the algorithm
    @type algorithm: int
    @ivar fp_type: the digest type
    @type fp_type: int
    @ivar fingerprint: the fingerprint
    @type fingerprint: string
    @see: draft-ietf-secsh-dns-05.txt�	algorithm�fp_type�fingerprintcs(tt|�j||�||_||_||_dS)N)�superr�__init__rrr)�self�rdclass�rdtyperrr)�	__class__��/usr/lib/python3.6/SSHFP.pyr%szSSHFP.__init__NTcKs d|j|jtjj|jdd�fS)Nz%d %d %s�)Z	chunksize)rr�dns�rdataZ_hexifyr)r�origin�
relativize�kwrrr
�to_text,s
z
SSHFP.to_textcCst|j�}|j�}g}x:|j�j�}	|	j�r,P|	j�s<tjj�|j|	j	j
��qWdj|�}
tj
|
�}
||||||
�S)N�)Z	get_uint8�getZunescapeZ
is_eol_or_eofZ
is_identifierrZ	exception�SyntaxError�append�value�encode�join�binasciiZ	unhexlify)�clsr	r
�tokrrrrZchunks�trrrr
�	from_text2s

zSSHFP.from_textcCs,tjd|j|j�}|j|�|j|j�dS)Nz!BB)�struct�packrr�writer)r�file�compressr�headerrrr
�to_wireBs
z
SSHFP.to_wirec	CsTtjd|||d��}|d7}|d8}||||�j�}||||d|d|�S)Nz!BB�r�)r!�unpackZunwrap)	rr	r
ZwireZcurrentZrdlenrr&rrrr
�	from_wireGs
zSSHFP.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodr r'r+�
__classcell__rr)rr
rs



r)r!rZ	dns.rdatarZ
dns.rdatatyperZRdatarrrrr
�<module>srdtypes/ANY/__pycache__/PTR.cpython-36.opt-1.pyc000064400000000533150351404320015125 0ustar003

�b�Wk�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�PTRz
PTR recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/PTR.pyrsr)Zdns.rdtypes.nsbaseZdnsZrdtypesZnsbaseZNSBaserrrrr�<module>srdtypes/ANY/__pycache__/AVC.cpython-36.pyc000064400000000666150351404320014141 0ustar003

ӓ�W��@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�AVCzbAVC record

    @see: U{http://www.iana.org/assignments/dns-parameters/AVC/avc-completed-template}N)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/AVC.pyrsr)Zdns.rdtypes.txtbaseZdnsZrdtypesZtxtbaseZTXTBaserrrrr�<module>srdtypes/ANY/__pycache__/CNAME.cpython-36.pyc000064400000001056150351404320014345 0ustar003

�b�W<�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�CNAMEz�CNAME record

    Note: although CNAME is officially a singleton type, dnspython allows
    non-singleton CNAME rdatasets because such sets have been commonly
    used by BIND and other nameservers for load balancing.N)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/CNAME.pyrsr)Zdns.rdtypes.nsbaseZdnsZrdtypesZnsbaseZNSBaserrrrr�<module>srdtypes/ANY/__pycache__/SSHFP.cpython-36.pyc000064400000004133150351404320014404 0ustar003

�b�W�@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�NcsZeZdZdZdddgZ�fdd�Zdd	d
�Zeddd��Zdd
d�Z	eddd��Z
�ZS)�SSHFPz�SSHFP record

    @ivar algorithm: the algorithm
    @type algorithm: int
    @ivar fp_type: the digest type
    @type fp_type: int
    @ivar fingerprint: the fingerprint
    @type fingerprint: string
    @see: draft-ietf-secsh-dns-05.txt�	algorithm�fp_type�fingerprintcs(tt|�j||�||_||_||_dS)N)�superr�__init__rrr)�self�rdclass�rdtyperrr)�	__class__��/usr/lib/python3.6/SSHFP.pyr%szSSHFP.__init__NTcKs d|j|jtjj|jdd�fS)Nz%d %d %s�)Z	chunksize)rr�dns�rdataZ_hexifyr)r�origin�
relativize�kwrrr
�to_text,s
z
SSHFP.to_textcCst|j�}|j�}g}x:|j�j�}	|	j�r,P|	j�s<tjj�|j|	j	j
��qWdj|�}
tj
|
�}
||||||
�S)N�)Z	get_uint8�getZunescapeZ
is_eol_or_eofZ
is_identifierrZ	exception�SyntaxError�append�value�encode�join�binasciiZ	unhexlify)�clsr	r
�tokrrrrZchunks�trrrr
�	from_text2s

zSSHFP.from_textcCs,tjd|j|j�}|j|�|j|j�dS)Nz!BB)�struct�packrr�writer)r�file�compressr�headerrrr
�to_wireBs
z
SSHFP.to_wirec	CsTtjd|||d��}|d7}|d8}||||�j�}||||d|d|�S)Nz!BB�r�)r!�unpackZunwrap)	rr	r
ZwireZcurrentZrdlenrr&rrrr
�	from_wireGs
zSSHFP.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodr r'r+�
__classcell__rr)rr
rs



r)r!rZ	dns.rdatarZ
dns.rdatatyperZRdatarrrrr
�<module>srdtypes/ANY/__pycache__/URI.cpython-36.opt-1.pyc000064400000004323150351404320015120 0ustar003

�b�WR�@sDddlZddlZddlZddlZddlmZGdd�dejj�Z	dS)�N)�	text_typecsZeZdZdZdddgZ�fdd�Zdd	d
�Zeddd��Zdd
d�Z	eddd��Z
�ZS)�URIz�URI record

    @ivar priority: the priority
    @type priority: int
    @ivar weight: the weight
    @type weight: int
    @ivar target: the target host
    @type target: dns.name.Name object
    @see: draft-faltstrom-uri-13�priority�weight�targetcsVtt|�j||�||_||_t|�dkr6tjjd��t	|t
�rL|j�|_n||_dS)N�zURI target cannot be empty)
�superr�__init__rr�len�dns�	exception�SyntaxError�
isinstancer�encoder)�self�rdclass�rdtyperrr)�	__class__��/usr/lib/python3.6/URI.pyr	's
zURI.__init__NTcKsd|j|j|jj�fS)Nz
%d %d "%s")rrr�decode)r�origin�
relativize�kwrrr�to_text2s
zURI.to_textc	CsR|j�}|j�}|j�j�}|j�p*|j�s8tjjd��|j�||||||j	�S)NzURI target must be a string)
Z
get_uint16�getZunescapeZis_quoted_stringZ
is_identifierrrr
Zget_eol�value)	�clsrr�tokrrrrrrrr�	from_text6sz
URI.from_textcCs,tjd|j|j�}|j|�|j|j�dS)Nz!HH)�struct�packrr�writer)r�file�compressrZtwo_intsrrr�to_wire@s
zURI.to_wirec
Csh|dkrtjjd��tjd|||d��\}}|d7}|d8}||||�}	||7}||||||	�S)N�zURI RR is shorter than 5 octetsz!HH�)rrZ	FormErrorr �unpack)
rrrZwireZcurrentZrdlenrrrrrrr�	from_wireEsz
URI.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__r	r�classmethodrr%r)�
__classcell__rr)rrrs


	
r)
r Z
dns.exceptionrZ	dns.rdataZdns.nameZdns._compatrZrdataZRdatarrrrr�<module>s
rdtypes/ANY/__pycache__/NSEC3PARAM.cpython-36.pyc000064400000004451150351404320015120 0ustar003

�b�W�@sDddlZddlZddlZddlZddlmZGdd�dejj�Z	dS)�N)�	text_typecs\eZdZdZddddgZ�fdd�Zdd
d�Zeddd
��Zddd�Z	eddd��Z
�ZS)�
NSEC3PARAMaNSEC3PARAM record

    @ivar algorithm: the hash algorithm number
    @type algorithm: int
    @ivar flags: the flags
    @type flags: int
    @ivar iterations: the number of iterations
    @type iterations: int
    @ivar salt: the salt
    @type salt: string�	algorithm�flags�
iterations�saltcsDtt|�j||�||_||_||_t|t�r:|j�|_	n||_	dS)N)
�superr�__init__rrr�
isinstancer�encoder)�self�rdclass�rdtyperrrr)�	__class__�� /usr/lib/python3.6/NSEC3PARAM.pyr	's
zNSEC3PARAM.__init__NTcKs6|jdkrd}ntj|j�j�}d|j|j|j|fS)N��-z%u %u %u %s)r�binasciiZhexlify�decoderrr)r�origin�
relativize�kwrrrr�to_text1s

zNSEC3PARAM.to_textc
CsV|j�}|j�}|j�}|j�}	|	dkr.d}	ntj|	j��}	|j�|||||||	�S)Nr�)Z	get_uint8Z
get_uint16Z
get_stringrZ	unhexlifyrZget_eol)
�clsr
r�tokrrrrrrrrr�	from_text9szNSEC3PARAM.from_textcCs8t|j�}|jtjd|j|j|j|��|j|j�dS)Nz!BBHB)�lenr�write�struct�packrrr)r�file�compressr�lrrr�to_wireFs
zNSEC3PARAM.to_wirecCsvtjd|||d��\}}}	}
|d7}|d8}||||
�j�}||
7}||
8}|dkrdtjj�||||||	|�S)Nz!BBHB�r)r �unpackZunwrap�dnsZ	exceptionZ	FormError)rr
rZwireZcurrentZrdlenrrrrZslenrrrr�	from_wireLszNSEC3PARAM.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__r	r�classmethodrr%r)�
__classcell__rr)rrrs


r)
r rZ
dns.exceptionr(Z	dns.rdataZdns._compatrZrdataZRdatarrrrr�<module>s
rdtypes/ANY/__pycache__/SOA.cpython-36.pyc000064400000006340150351404320014145 0ustar003

�b�W��@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�NcsveZdZdZdddddddgZ�fd	d
�Zdd
d�Zeddd��Zddd�Z	ddd�Z
eddd��Zddd�Z�Z
S)�SOAa�SOA record

    @ivar mname: the SOA MNAME (master name) field
    @type mname: dns.name.Name object
    @ivar rname: the SOA RNAME (responsible name) field
    @type rname: dns.name.Name object
    @ivar serial: The zone's serial number
    @type serial: int
    @ivar refresh: The zone's refresh value (in seconds)
    @type refresh: int
    @ivar retry: The zone's retry value (in seconds)
    @type retry: int
    @ivar expire: The zone's expiration value (in seconds)
    @type expire: int
    @ivar minimum: The zone's negative caching time (in seconds, called
    "minimum" for historical reasons)
    @type minimum: int
    @see: RFC 1035�mname�rname�serial�refresh�retry�expire�minimumc

s@tt|�j||�||_||_||_||_||_||_|	|_	dS)N)
�superr�__init__rrrrrrr	)
�self�rdclass�rdtyperrrrrrr	)�	__class__��/usr/lib/python3.6/SOA.pyr/szSOA.__init__NTcKs<|jj||�}|jj||�}d|||j|j|j|j|jfS)Nz%s %s %d %d %d %d %d)r�choose_relativityrrrrrr	)r�origin�
relativize�kwrrrrr�to_text:s
zSOA.to_textc

Csp|j�}|j�}|j||�}|j||�}|j�}|j�}	|j�}
|j�}|j�}|j�|||||||	|
||�	S)N)Zget_namerZ
get_uint32Zget_ttlZget_eol)
�clsr
r�tokrrrrrrrrr	rrr�	from_textAsz
SOA.from_textcCsL|jj|||�|jj|||�tjd|j|j|j|j|j	�}|j
|�dS)Nz!IIIII)r�to_wirer�struct�packrrrrr	�write)r�file�compressr�	five_intsrrrrPs
zSOA.to_wirecCs6|jj|�|jj|�tjd|j|j|j|j|j	�S)Nz!IIIII)
r�
to_digestablerrrrrrrr	)rrrrrr!WszSOA.to_digestablecCs�tjj|d||�|�\}}||7}||8}tjj|d||�|�\}	}||7}||8}|dkrltjj�tjd||||��}
|dk	r�|j|�}|	j|�}	|||||	|
d|
d|
d|
d|
d�	S)N�z!IIIIIr����)�dns�name�	from_wireZ	exceptionZ	FormErrorr�unpackr)rr
rZwireZcurrentZrdlenrrZcusedrr rrrr)]s 


z
SOA.from_wirecCs$|jj||�|_|jj||�|_dS)N)rrr)rrrrrrrpszSOA.choose_relativity)NT)NT)NN)N)N)NT)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrr!r)r�
__classcell__rr)rrrs


r)rZ
dns.exceptionr'Z	dns.rdataZdns.nameZrdataZRdatarrrrr�<module>srdtypes/ANY/__pycache__/ISDN.cpython-36.opt-1.pyc000064400000004255150351404320015222 0ustar003

�b�W��@sDddlZddlZddlZddlZddlmZGdd�dejj�Z	dS)�N)�	text_typecsXeZdZdZddgZ�fdd�Zddd	�Zedd
d��Zddd
�Z	eddd��Z
�ZS)�ISDNz�ISDN record

    @ivar address: the ISDN address
    @type address: string
    @ivar subaddress: the ISDN subaddress (or '' if not present)
    @type subaddress: string
    @see: RFC 1183�address�
subaddresscsNtt|�j||�t|t�r(|j�|_n||_t|t�rD|j�|_n||_dS)N)�superr�__init__�
isinstancer�encoderr)�self�rdclass�rdtyperr)�	__class__��/usr/lib/python3.6/ISDN.pyr$s

z
ISDN.__init__NTcKs<|jr&dtjj|j�tjj|j�fSdtjj|j�SdS)Nz	"%s" "%s"z"%s")r�dns�rdataZ	_escapifyr)r
�origin�
relativize�kwrrr�to_text/szISDN.to_textc	CsP|j�}|j�}|j�s,|j|�|j�}n|j|�d}|j�|||||�S)N�)Z
get_string�getZ
is_eol_or_eofZungetZget_eol)	�clsrr�tokrrr�trrrr�	from_text6s


zISDN.from_textcCs\t|j�}|jtjd|��|j|j�t|j�}|dkrX|jtjd|��|j|j�dS)Nz!Br)�lenr�write�struct�packr)r
�file�compressr�lrrr�to_wireCs

zISDN.to_wirec
Cs�||}|d7}|d8}||kr(tjj�||||�j�}||7}||8}|dkr�||}|d7}|d8}||kr|tjj�||||�j�}	nd}	|||||	�S)N�rr)rZ	exceptionZ	FormErrorZunwrap)
rrrZwireZcurrentZrdlenrr"rrrrr�	from_wireNs"zISDN.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrr#r%�
__classcell__rr)r
rrs

r)
rZ
dns.exceptionrZ	dns.rdataZ
dns.tokenizerZdns._compatrrZRdatarrrrr�<module>s
rdtypes/ANY/__pycache__/DNAME.cpython-36.opt-1.pyc000064400000001003150351404320015275 0ustar003

�b�W��@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZddd�ZdS)�DNAMEzDNAME recordNcCs|jj|�S)N)�target�
to_digestable)�self�origin�r�/usr/lib/python3.6/DNAME.pyrszDNAME.to_digestable)N)�__name__�
__module__�__qualname__�__doc__rrrrrrsr)Zdns.rdtypes.nsbaseZdnsZrdtypesZnsbaseZUncompressedNSrrrrr�<module>srdtypes/ANY/__pycache__/DLV.cpython-36.pyc000064400000000533150351404320014146 0ustar003

�b�W`�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�DLVz
DLV recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/DLV.pyrsr)Zdns.rdtypes.dsbaseZdnsZrdtypesZdsbaseZDSBaserrrrr�<module>srdtypes/ANY/__pycache__/SPF.cpython-36.pyc000064400000000562150351404320014153 0ustar003

�b�W��@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�SPFzSPF record

    @see: RFC 4408N)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/SPF.pyrsr)Zdns.rdtypes.txtbaseZdnsZrdtypesZtxtbaseZTXTBaserrrrr�<module>srdtypes/ANY/__pycache__/EUI64.cpython-36.pyc000064400000001022150351404320014307 0ustar003

�b�Wn�@s"ddlZGdd�dejjj�ZdS)�Nc@s eZdZdZdZeddZdS)�EUI64z�EUI64 record

    @ivar fingerprint: 64-bit Extended Unique Identifier (EUI-64)
    @type fingerprint: string
    @see: rfc7043.txt���N)�__name__�
__module__�__qualname__�__doc__Zbyte_lenZtext_len�r
r
�/usr/lib/python3.6/EUI64.pyrsr)Zdns.rdtypes.euibaseZdnsZrdtypesZeuibaseZEUIBaserr
r
r
r�<module>srdtypes/ANY/__pycache__/GPOS.cpython-36.pyc000064400000010074150351404320014272 0ustar003

�b�W��@sXddlZddlZddlZddlZddlmZmZdd�Zdd�Z	Gdd�dej
j�ZdS)	�N)�long�	text_typecCs�|ddks|ddkr$|dd�}|j�r0dS|jd�\}}|dkrV|dkrVtjj�|dkrv|j�j�rvtjj�|dkr�|j�j�r�tjj�dS)	Nr�-�+��.��-�+)�isdigit�split�dns�	exception�	FormError�decode)Zwhat�left�right�r�/usr/lib/python3.6/GPOS.py�_validate_float_stringsrcCst|t�r|j�S|S)N)�
isinstancer�encode)�valuerrr�	_sanitize&s
rcs�eZdZdZdddgZ�fdd�Zd!d	d
�Zed"dd��Zd#d
d�Z	ed$dd��Z
dd�Zdd�Ze
eedd�Zdd�Zdd�Ze
eedd�Zdd�Zdd�Ze
eed d�Z�ZS)%�GPOSz�GPOS record

    @ivar latitude: latitude
    @type latitude: string
    @ivar longitude: longitude
    @type longitude: string
    @ivar altitude: altitude
    @type altitude: string
    @see: RFC 1712�latitude�	longitude�altitudecs�tt|�j||�t|t�s0t|t�s0t|t�r8t|�}t|t�sVt|t�sVt|t�r^t|�}t|t�s|t|t�s|t|t�r�t|�}t|�}t|�}t|�}t	|�t	|�t	|�||_
||_||_dS)N)
�superr�__init__r�float�intr�strrrrrr)�self�rdclass�rdtyperrr)�	__class__rrr:s,








z
GPOS.__init__NTcKs d|jj�|jj�|jj�fS)Nz%s %s %s)rrrr)r#�origin�
relativize�kwrrr�to_textRs
zGPOS.to_textc	Cs0|j�}|j�}|j�}|j�||||||�S)N)Z
get_stringZget_eol)	�clsr$r%�tokr'r(rrrrrr�	from_textWs
zGPOS.from_textcCs�t|j�}|dkst�|jtjd|��|j|j�t|j�}|dksJt�|jtjd|��|j|j�t|j�}|dks~t�|jtjd|��|j|j�dS)N�z!B)�lenr�AssertionError�write�struct�packrr)r#�file�compressr'�lrrr�to_wire_s


zGPOS.to_wirecCs�||}|d7}|d8}||kr(tjj�||||�j�}||7}||8}||}|d7}|d8}||krttjj�||||�j�}	||7}||8}||}|d7}|d8}||kr�tjj�||||�j�}
|||||	|
�S)Nr)r
rrZunwrap)r+r$r%ZwireZcurrentZrdlenr'r6rrrrrr�	from_wirems.zGPOS.from_wirecCs
t|j�S)N)r r)r#rrr�_get_float_latitude�szGPOS._get_float_latitudecCst|�|_dS)N)r"r)r#rrrr�_set_float_latitude�szGPOS._set_float_latitudez"latitude as a floating point value)�doccCs
t|j�S)N)r r)r#rrr�_get_float_longitude�szGPOS._get_float_longitudecCst|�|_dS)N)r"r)r#rrrr�_set_float_longitude�szGPOS._set_float_longitudez#longitude as a floating point valuecCs
t|j�S)N)r r)r#rrr�_get_float_altitude�szGPOS._get_float_altitudecCst|�|_dS)N)r"r)r#rrrr�_set_float_altitude�szGPOS._set_float_altitudez"altitude as a floating point value)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr*�classmethodr-r7r8r9r:�propertyZfloat_latituder<r=Zfloat_longituder>r?Zfloat_altitude�
__classcell__rr)r&rr,s*



r)
r2Z
dns.exceptionr
Z	dns.rdataZ
dns.tokenizerZdns._compatrrrrZrdataZRdatarrrrr�<module>srdtypes/ANY/__pycache__/NSEC3.cpython-36.opt-1.pyc000064400000010726150351404320015300 0ustar003

�b�W��@s�ddlZddlZddlZddlZddlZddlZddlZddlm	Z	m
Z
yejdd�Zejdd�Z
Wn,ek
r�ejdd�Zejdd�Z
YnXdZdZGdd	�d	ejj�ZdS)
�N)�xrange�	text_typeZ 0123456789ABCDEFGHIJKLMNOPQRSTUVZ ABCDEFGHIJKLMNOPQRSTUVWXYZ234567s 0123456789ABCDEFGHIJKLMNOPQRSTUVs ABCDEFGHIJKLMNOPQRSTUVWXYZ234567�cs`eZdZdZddddddgZ�fdd	�Zddd
�Zeddd��Zddd�Z	eddd��Z
�ZS)�NSEC3a�NSEC3 record

    @ivar algorithm: the hash algorithm number
    @type algorithm: int
    @ivar flags: the flags
    @type flags: int
    @ivar iterations: the number of iterations
    @type iterations: int
    @ivar salt: the salt
    @type salt: string
    @ivar next: the next name hash
    @type next: string
    @ivar windows: the windowed bitmap list
    @type windows: list of (window number, string) tuples�	algorithm�flags�
iterations�salt�next�windowsc		sPtt|�j||�||_||_||_t|t�r:|j�|_	n||_	||_
||_dS)N)�superr�__init__rrr�
isinstancer�encoder	r
r)	�self�rdclass�rdtyperrrr	r
r)�	__class__��/usr/lib/python3.6/NSEC3.pyr
?s
zNSEC3.__init__NTc
Ks�tj|j�jt�j�j�}|jdkr*d}ntj	|j�j�}d}x�|j
D]�\}}g}	x`tdt|��D]N}
||
}x@tdd�D]2}|d|?@rz|	j
tjj|d|
d|��qzWqbW|ddj|	�7}qFWd	|j|j|j|||fS)
N��-�r���� z%u %u %u %s %s%s)�base64Z	b32encoder
�	translate�b32_normal_to_hex�lower�decoder	�binasciiZhexlifyrr�len�append�dns�	rdatatype�to_text�joinrrr)
r�origin�
relativize�kwr
r	�text�window�bitmap�bits�i�byte�jrrrr'Ls"

 
z
NSEC3.to_textc	Cs�|j�}|j�}|j�}|j�}	|	dkr.d}	ntj|	jd��}	|j�jd�j�jt�}
t	j
|
�}
g}xZ|j�j�}|j
�r|Ptjj|j�}
|
dkr�tjjd��|
dkr�tjjd��|j|
�qfW|j�d}d}d}tdd	�}g}x�|D]�}
|
|kr�q�|
}|
d
}||k�rD|dk�r4|j|dj|d|��f�tdd	�}|}|
d
}|d}|d}|d
}||d|?B||<q�W|dk�r�|j||d|�f�|||||||	|
|�S)Nrr�asciirzNSEC3 with bit 0i��zNSEC3 with bit > 65535�� rrrrr)Z	get_uint8Z
get_uint16Z
get_stringr"Z	unhexlifyr�upperr�b32_hex_to_normalrZ	b32decode�getZunescapeZ
is_eol_or_eofr%r&�	from_text�value�	exception�SyntaxErrorr$�sort�	bytearrayr()�clsrr�tokr)r*rrrr	r
Zrdtypes�tokenZnrdtyper-�octetsZprior_rdtyper.rZ
new_window�offsetr1�bitrrrr9`s\




zNSEC3.from_textcCs�t|j�}|jtjd|j|j|j|��|j|j�t|j�}|jtjd|��|j|j�x4|j	D]*\}}|jtjd|t|���|j|�qdWdS)Nz!BBHBz!Bz!BB)
r#r	�write�struct�packrrrr
r)r�file�compressr)�lr-r.rrr�to_wire�s

z
NSEC3.to_wirec	CsZtjd|||d��\}}}	}
|d7}|d8}||||
�j�}||
7}||
8}||}|d7}|d8}||||�j�}
||7}||8}g}x�|dk�rB|dkr�tjjd��||}||d}|dks�|dkr�tjjd��|d	7}|d	8}||k�r
tjjd
��t||||�j��}||7}||8}|j||f�q�W||||||	||
|�S)Nz!BBHB�rr�zNSEC3 too shortr5zbad NSEC3 octets�zbad NSEC3 bitmap length)rF�unpackZunwrapr%r;Z	FormErrorr>r$)r?rrZwireZcurrentZrdlenr)rrrZslenr	Znlenr
rr-rBr.rrr�	from_wire�s< 
zNSEC3.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__r
r'�classmethodr9rKrP�
__classcell__rr)rrr,s
1
r)rr"�stringrFZ
dns.exceptionr%Z	dns.rdataZ
dns.rdatatypeZdns._compatrr�	maketransr7r�AttributeError�bytesZSHA1ZOPTOUTZrdataZRdatarrrrr�<module>s(
rdtypes/ANY/__pycache__/DNSKEY.cpython-36.pyc000064400000000723150351404320014517 0ustar003

�b�W�@s:ddlZddlmZmZddgZGdd�dejjj�ZdS)�N)�flags_to_text_set�flags_from_text_setrrc@seZdZdZdS)�DNSKEYz
DNSKEY recordN)�__name__�
__module__�__qualname__�__doc__�r	r	�/usr/lib/python3.6/DNSKEY.pyrsr)	Zdns.rdtypes.dnskeybaseZdnsrr�__all__ZrdtypesZ
dnskeybaseZ
DNSKEYBaserr	r	r	r
�<module>srdtypes/ANY/__pycache__/MX.cpython-36.opt-1.pyc000064400000000530150351404320015001 0ustar003

�b�Wi�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�MXz	MX recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/MX.pyrsr)Zdns.rdtypes.mxbaseZdnsZrdtypesZmxbaseZMXBaserrrrr�<module>srdtypes/ANY/__pycache__/RT.cpython-36.opt-1.pyc000064400000000552150351404320015006 0ustar003

�b�W{�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�RTz	RT recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/RT.pyrsr)Zdns.rdtypes.mxbaseZdnsZrdtypesZmxbaseZUncompressedDowncasingMXrrrrr�<module>srdtypes/ANY/__pycache__/RT.cpython-36.pyc000064400000000552150351404320014047 0ustar003

�b�W{�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�RTz	RT recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/RT.pyrsr)Zdns.rdtypes.mxbaseZdnsZrdtypesZmxbaseZUncompressedDowncasingMXrrrrr�<module>srdtypes/ANY/__pycache__/AVC.cpython-36.opt-1.pyc000064400000000666150351404320015100 0ustar003

ӓ�W��@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�AVCzbAVC record

    @see: U{http://www.iana.org/assignments/dns-parameters/AVC/avc-completed-template}N)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/AVC.pyrsr)Zdns.rdtypes.txtbaseZdnsZrdtypesZtxtbaseZTXTBaserrrrr�<module>srdtypes/ANY/__pycache__/LOC.cpython-36.pyc000064400000020153150351404320014136 0ustar003

�b�W�/�@s�ddlmZddlZddlZddlZddlmZmZm	Z	e
dd�edd�D��ZdZ
dZd	Zd
d�Zdd
�Zdd�Zdd�Zdd�ZGdd�dejj�ZdS)�)�divisionN)�long�xrange�round_py2_compatccs|]}td|�VqdS)�
N)r)�.0�i�r	�/usr/lib/python3.6/LOC.py�	<genexpr>sr�gY@g��.Ag@�@cCsh|dkrdSd}x2ttt��D]"}|t|td�kr|d}PqW|dksT|dkrdtjjd|��|S)Nr�z%s value out of bounds)r�len�_powsr�dns�	exception�SyntaxError)�what�descZexprr	r	r
�_exponent_of!srcCs�|dkrd}|d9}nd}t|d�}t|d�}||d8}t|d�}||d8}t|d�}|t|d�8}t|�}|||||fS)Nrr
i��6i`�i����r)r�int)rZsignZdegreesZminutes�secondsr	r	r
�_float_to_tuple.s
rcCsXt|d�}|t|d�d7}|t|d�d7}|t|d�d7}t|d�|S)	Nrr
gN@�g �@�g@wKA�)�float)r�valuer	r	r
�_tuple_to_float?s
rcCs4t|�}t||�d@}|td|�d@}|d|S)N�r�)rr�pow)rr�exponent�baser	r	r
�_encode_sizeGsr%cCsV|d@}|dkr tjjd|��|d@d?}|dkrDtjjd|��t|�td|�S)Nr �	zbad %s exponent��rzbad %s baser)rrrrr")rrr#r$r	r	r
�_decode_sizeNsr(cs�eZdZdZddddddgZeeef�fdd	�	Zddd
�Z	e
d dd��Zd!dd�Ze
d"dd��Z
dd�Zdd�Zeeedd�Zdd�Zdd�Zeeedd�Z�ZS)#�LOCa�LOC record

    @ivar latitude: latitude
    @type latitude: (int, int, int, int, sign) tuple specifying the degrees, minutes,
    seconds, milliseconds, and sign of the coordinate.
    @ivar longitude: longitude
    @type longitude: (int, int, int, int, sign) tuple specifying the degrees,
    minutes, seconds, milliseconds, and sign of the coordinate.
    @ivar altitude: altitude
    @type altitude: float
    @ivar size: size of the sphere
    @type size: float
    @ivar horizontal_precision: horizontal precision
    @type horizontal_precision: float
    @ivar vertical_precision: vertical precision
    @type vertical_precision: float
    @see: RFC 1876�latitude�	longitude�altitude�size�horizontal_precision�vertical_precisionc		s�tt|�j||�t|t�s&t|t�r.t|�}t|t�r@t|�}||_t|t�sZt|t�rbt|�}t|t�rtt|�}||_	t|�|_
t|�|_t|�|_t|�|_
dS)a�Initialize a LOC record instance.

        The parameters I{latitude} and I{longitude} may be either a 4-tuple
        of integers specifying (degrees, minutes, seconds, milliseconds),
        or they may be floating point values specifying the number of
        degrees. The other parameters are floats. Size, horizontal precision,
        and vertical precision are specified in centimeters.N)�superr)�__init__�
isinstancerrrrr*r+r,r-r.r/)	�self�rdclass�rdtyper*r+r,r-�hprec�vprec)�	__class__r	r
r1os




zLOC.__init__NTc
Ks�|jddkrd}nd}|jddkr,d}nd}d|jd|jd|jd	|jd
||jd|jd|jd	|jd
||jdf}|jtks�|jtks�|jtkr�|d|jd|jd|jdf7}|S)
Nrr�N�S�E�Wz(%d %d %d.%03d %s %d %d %d.%03d %s %0.2fmr
rrgY@z %0.2fm %0.2fm %0.2fm)	r*r+r,r-�
_default_sizer.�_default_hprecr/�_default_vprec)r3�origin�
relativize�kwZlat_hemisphereZlong_hemisphere�textr	r	r
�to_text�s&



zLOC.to_textc	Cs�dddddg}dddddg}t}t}	t}
|j�|d<|j�}|j��r0t|�|d<|j�}d|k�r|jd�\}}
|j�s�tj	j
d��t|�|d<|ddkr�tj	j
d��t|
�}|dks�|dks�|
j�r�tj	j
d	��|dkr�d
}n|dkr�d}nd}|t|
�|d<|j�}n|j��r0t|�|d<|j�}|dk�rDd|d
<n|dk�rZtj	j
d��|j�|d<|j�}|j��rpt|�|d<|j�}d|k�rR|jd�\}}
|j��s�tj	j
d��t|�|d<|ddk�r�tj	j
d��t|
�}|dk�s|dk�s|
j��rtj	j
d��|dk�r$d
}n|dk�r4d}nd}|t|
�|d<|j�}n|j��rpt|�|d<|j�}|dk�r�d|d
<n|dk�r�tj	j
d��|j�}|ddk�r�|dd�}t|�d}|j
�j�}|j��s�|j}|ddk�r�|dd�}t|�d}|j
�j�}|j��s�|j}|ddk�r@|dd�}t|�d}	|j
�j�}|j��s�|j}|d dk�r�|dd!�}t|�d}
|j�||||||||	|
�S)"Nrr
�.zbad latitude seconds valuer�<zlatitude seconds >= 60rzbad latitude milliseconds value�drr:rr9zbad latitude hemisphere valuezbad longitude seconds valuezlongitude seconds >= 60z bad longitude milliseconds valuer<r;zbad longitude hemisphere value�mgY@rrrrrrrrrr)r=r>r?Zget_intZ
get_string�isdigitr�splitrrrrr�getZunescapeZ
is_eol_or_eofrZget_eol)�clsr4r5�tokr@rAr*r+r-r6r7�tr�milliseconds�lrHr,�tokenrr	r	r
�	from_text�s�









 









z
LOC.from_textc	Cs�|jdd|jdd|jdd|jd|jd}td	�|}|jdd|jdd|jdd|jd|jd}td	�|}t|j�td
�}t|jd�}t|jd�}	t|jd
�}
tj	dd||	|
|||�}|j
|�dS)Nri��6r
i`�ri�rrli���r-zhorizontal precisionzvertical precisionz!BBBBIII)r*rr+r,r%r-r.r/�struct�pack�write)r3�file�compressr@rOr*r+r,r-r6r7�wirer	r	r
�to_wires((zLOC.to_wirec	Cstjd||||��\}}}	}
}}}
|td�krHt|td��d}nd
ttd�|�d}|dksp|dkr|tjjd��|td�kr�t|td��d}ndttd�|�d}|dks�|dkr�tjjd��t|
�d	}
t|d
�}t|	d�}	t|
d�}
||||||
||	|
�S)Nz!BBBBIIIli��6r
g�V@zbad latitudeg�f@z
bad longitudeg�cAr-zhorizontal precisionzvertical precisionrg�V�rg�f�)rS�unpackrrrrZ	FormErrorr()rLr4r5rXZcurrentZrdlenr@�versionr-r6r7r*r+r,r	r	r
�	from_wires"&


z
LOC.from_wirecCs
t|j�S)N)rr*)r3r	r	r
�_get_float_latitude5szLOC._get_float_latitudecCst|�|_dS)N)rr*)r3rr	r	r
�_set_float_latitude8szLOC._set_float_latitudez"latitude as a floating point value)�doccCs
t|j�S)N)rr+)r3r	r	r
�_get_float_longitude>szLOC._get_float_longitudecCst|�|_dS)N)rr+)r3rr	r	r
�_set_float_longitudeAszLOC._set_float_longitudez#longitude as a floating point value)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__r=r>r?r1rD�classmethodrRrYr\r]r^�propertyZfloat_latituder`raZfloat_longitude�
__classcell__r	r	)r8r
r)Xs&
e
r))Z
__future__rrSZ
dns.exceptionrZ	dns.rdataZdns._compatrrr�tuple�rangerr=r>r?rrrr%r(ZrdataZRdatar)r	r	r	r
�<module>s

rdtypes/ANY/__pycache__/CDNSKEY.cpython-36.pyc000064400000000726150351404320014625 0ustar003

�b�W�@s:ddlZddlmZmZddgZGdd�dejjj�ZdS)�N)�flags_to_text_set�flags_from_text_setrrc@seZdZdZdS)�CDNSKEYzCDNSKEY recordN)�__name__�
__module__�__qualname__�__doc__�r	r	�/usr/lib/python3.6/CDNSKEY.pyrsr)	Zdns.rdtypes.dnskeybaseZdnsrr�__all__ZrdtypesZ
dnskeybaseZ
DNSKEYBaserr	r	r	r
�<module>srdtypes/ANY/__pycache__/CAA.cpython-36.opt-1.pyc000064400000004005150351404320015042 0ustar003

�b�W>
�@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�NcsZeZdZdZdddgZ�fdd�Zdd	d
�Zeddd��Zdd
d�Z	eddd��Z
�ZS)�CAAz�CAA (Certification Authority Authorization) record

    @ivar flags: the flags
    @type flags: int
    @ivar tag: the tag
    @type tag: string
    @ivar value: the value
    @type value: string
    @see: RFC 6844�flags�tag�valuecs(tt|�j||�||_||_||_dS)N)�superr�__init__rrr)�self�rdclass�rdtyperrr)�	__class__��/usr/lib/python3.6/CAA.pyr%szCAA.__init__NTcKs$d|jtjj|j�tjj|j�fS)Nz
%u %s "%s")r�dns�rdataZ	_escapifyrr)r�origin�
relativize�kwrrr
�to_text+szCAA.to_textc	Cs\|j�}|j�j�}t|�dkr,tjjd��|j�s@tjjd��|j�j�}||||||�S)N�ztag too longztag is not alphanumeric)Z	get_uint8Z
get_string�encode�lenrZ	exception�SyntaxError�isalnum)	�clsr	r
�tokrrrrrrrr
�	from_text0sz
CAA.from_textcCsL|jtjd|j��t|j�}|jtjd|��|j|j�|j|j�dS)Nz!B)�write�struct�packrrrr)r�file�compressr�lrrr
�to_wire;s

zCAA.to_wirecCs\tjd|||d��\}}|d7}||||�}	|||||d�}
|||||	|
�S)Nz!BB�)r�unpack)rr	r
ZwireZcurrentZrdlenrrr!rrrrr
�	from_wireCs
z
CAA.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrr"r%�
__classcell__rr)rr
rs




r)rZ
dns.exceptionrZ	dns.rdataZ
dns.tokenizerrZRdatarrrrr
�<module>srdtypes/ANY/__pycache__/HINFO.cpython-36.opt-1.pyc000064400000003711150351404320015324 0ustar003

�b�Wi
�@sDddlZddlZddlZddlZddlmZGdd�dejj�Z	dS)�N)�	text_typecsXeZdZdZddgZ�fdd�Zddd	�Zedd
d��Zddd
�Z	eddd��Z
�ZS)�HINFOz�HINFO record

    @ivar cpu: the CPU type
    @type cpu: string
    @ivar os: the OS type
    @type os: string
    @see: RFC 1035�cpu�oscsNtt|�j||�t|t�r(|j�|_n||_t|t�rD|j�|_n||_dS)N)�superr�__init__�
isinstancer�encoderr)�self�rdclass�rdtyperr)�	__class__��/usr/lib/python3.6/HINFO.pyr$s

zHINFO.__init__NTcKs dtjj|j�tjj|j�fS)Nz	"%s" "%s")�dns�rdataZ	_escapifyrr)r
�origin�
relativize�kwrrr�to_text/sz
HINFO.to_textcCs&|j�}|j�}|j�|||||�S)N)Z
get_stringZget_eol)�clsrr�tokrrrrrrr�	from_text3szHINFO.from_textcCsTt|j�}|jtjd|��|j|j�t|j�}|jtjd|��|j|j�dS)Nz!B)�lenr�write�struct�packr)r
�file�compressr�lrrr�to_wire:s

z
HINFO.to_wirec
Cs�||}|d7}|d8}||kr(tjj�||||�j�}||7}||8}||}|d7}|d8}||krttjj�||||�j�}	|||||	�S)N�)rZ	exceptionZ	FormErrorZunwrap)
rrrZwireZcurrentZrdlenrrrrrrr�	from_wireDszHINFO.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrr r"�
__classcell__rr)r
rrs


r)
rZ
dns.exceptionrZ	dns.rdataZ
dns.tokenizerZdns._compatrrZRdatarrrrr�<module>s
rdtypes/ANY/__pycache__/TLSA.cpython-36.opt-1.pyc000064400000004336150351404320015230 0ustar003

�b�W��@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�Ncs\eZdZdZddddgZ�fdd�Zdd
d�Zeddd
��Zddd�Z	eddd��Z
�ZS)�TLSAa*TLSA record

    @ivar usage: The certificate usage
    @type usage: int
    @ivar selector: The selector field
    @type selector: int
    @ivar mtype: The 'matching type' field
    @type mtype: int
    @ivar cert: The 'Certificate Association Data' field
    @type cert: string
    @see: RFC 6698�usage�selector�mtype�certcs.tt|�j||�||_||_||_||_dS)N)�superr�__init__rrrr)�self�rdclass�rdtyperrrr)�	__class__��/usr/lib/python3.6/TLSA.pyr's
z
TLSA.__init__NTcKs$d|j|j|jtjj|jdd�fS)Nz%d %d %d %s�)Z	chunksize)rrr�dns�rdataZ_hexifyr)r	�origin�
relativize�kwr
r
r�to_text/s

zTLSA.to_textcCs~|j�}|j�}|j�}g}	x:|j�j�}
|
j�r4P|
j�sDtjj�|	j|
j	j
��qWdj|	�}tj
|�}|||||||�S)N�)Z	get_uint8�getZunescapeZ
is_eol_or_eofZ
is_identifierrZ	exception�SyntaxError�append�value�encode�join�binasciiZ	unhexlify)�clsr
r�tokrrrrrZcert_chunks�trr
r
r�	from_text6s

zTLSA.from_textcCs0tjd|j|j|j�}|j|�|j|j�dS)Nz!BBB)�struct�packrrr�writer)r	�file�compressr�headerr
r
r�to_wireGs
zTLSA.to_wirec	CsZtjd|||d��}|d7}|d8}||||�j�}||||d|d|d|�S)Nz!BBB�r��)r"�unpackZunwrap)	rr
rZwireZcurrentZrdlenrr'rr
r
r�	from_wireLs
zTLSA.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodr!r(r-�
__classcell__r
r
)rrrs

r)r"rZ	dns.rdatarZ
dns.rdatatyperZRdatarr
r
r
r�<module>srdtypes/ANY/__pycache__/RRSIG.cpython-36.pyc000064400000010537150351404320014414 0ustar003

�b�W�@s|ddlZddlZddlZddlZddlZddlZddlZddlZGdd�dej	j
�Zdd�Zdd�Z
Gdd	�d	ejj�ZdS)
�Nc@seZdZdZdS)�
BadSigTimez:Time in DNS SIG or RRSIG resource record cannot be parsed.N)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/RRSIG.pyrsrc
Cs�t|�dkrt�t|dd��}t|dd��}t|dd��}t|dd��}t|dd��}t|dd��}tj||||||dddf	�S)N�r����
�)�lenr�int�calendarZtimegm)�whatZyearZmonthZdayZhourZminute�secondrrr�sigtime_to_posixtime srcCstjdtj|��S)Nz%Y%m%d%H%M%S)�timeZstrftimeZgmtime)rrrr�posixtime_to_sigtime-src	sxeZdZdZdddddddd	d
g	Z�fdd�Zd
d�Zddd�Zeddd��Z	ddd�Z
eddd��Zddd�Z�Z
S) �RRSIGa~RRSIG record

    @ivar type_covered: the rdata type this signature covers
    @type type_covered: int
    @ivar algorithm: the algorithm used for the sig
    @type algorithm: int
    @ivar labels: number of labels
    @type labels: int
    @ivar original_ttl: the original TTL
    @type original_ttl: long
    @ivar expiration: signature expiration time
    @type expiration: long
    @ivar inception: signature inception time
    @type inception: long
    @ivar key_tag: the key tag
    @type key_tag: int
    @ivar signer: the signer
    @type signer: dns.name.Name object
    @ivar signature: the signature
    @type signature: string�type_covered�	algorithm�labels�original_ttl�
expiration�	inception�key_tag�signer�	signaturecsLtt|�j||�||_||_||_||_||_||_|	|_	|
|_
||_dS)N)�superr�__init__rrrrrrrrr )�self�rdclass�rdtyperrrrrrrrr )�	__class__rrr"LszRRSIG.__init__cCs|jS)N)r)r#rrr�coversZszRRSIG.coversNTcKsLdtjj|j�|j|j|jt|j�t|j	�|j
|jj||�tj
j|j�f	S)Nz%s %d %d %d %s %s %d %s %s)�dns�	rdatatype�to_textrrrrrrrrr�choose_relativity�rdataZ
_base64ifyr )r#�origin�
relativize�kwrrrr*]sz
RRSIG.to_textcCs�tjj|j��}tjj|j��}|j�}|j�}	t|j��}
t|j��}|j�}|j	�}
|
j
||�}
g}x:|j�j�}|j
�r�P|j�s�tjj�|j|jj��qjWdj|�}tj|�}|||||||	|
|||
|�S)N�)r(r)�	from_textZ
get_stringZdnssecZalgorithm_from_textZget_intZget_ttlrZget_namer+�getZunescapeZ
is_eol_or_eofZ
is_identifier�	exception�SyntaxError�append�value�encode�join�base64Z	b64decode)�clsr$r%�tokr-r.rrrrrrrrZchunks�tZb64r rrrr1js,


zRRSIG.from_textc	CsPtjd|j|j|j|j|j|j|j�}|j	|�|j
j|d|�|j	|j�dS)Nz!HBBIIIH)
�struct�packrrrrrrr�writer�to_wirer )r#�file�compressr-�headerrrrr@�s

z
RRSIG.to_wirecCs�tjd|||d��}|d7}|d8}tjj|d||�|�\}}	||	7}||	8}|dk	rh|j|�}||||�j�}
||||d|d|d|d|d|d|d	||
�S)
Nz!HBBIIIH�r���r
�r)r=�unpackr(�name�	from_wirer.Zunwrap)r:r$r%ZwireZcurrentZrdlenr-rCrZcusedr rrrrK�s
zRRSIG.from_wirecCs|jj||�|_dS)N)rr+)r#r-r.rrrr+�szRRSIG.choose_relativity)NT)NT)NN)N)NT)rrrr�	__slots__r"r'r*�classmethodr1r@rKr+�
__classcell__rr)r&rr1s


	r)r9rr=rZ
dns.dnssecr(Z
dns.exceptionZ	dns.rdataZ
dns.rdatatyper3ZDNSExceptionrrrr,ZRdatarrrrr�<module>s
rdtypes/ANY/__pycache__/URI.cpython-36.pyc000064400000004323150351404320014161 0ustar003

�b�WR�@sDddlZddlZddlZddlZddlmZGdd�dejj�Z	dS)�N)�	text_typecsZeZdZdZdddgZ�fdd�Zdd	d
�Zeddd��Zdd
d�Z	eddd��Z
�ZS)�URIz�URI record

    @ivar priority: the priority
    @type priority: int
    @ivar weight: the weight
    @type weight: int
    @ivar target: the target host
    @type target: dns.name.Name object
    @see: draft-faltstrom-uri-13�priority�weight�targetcsVtt|�j||�||_||_t|�dkr6tjjd��t	|t
�rL|j�|_n||_dS)N�zURI target cannot be empty)
�superr�__init__rr�len�dns�	exception�SyntaxError�
isinstancer�encoder)�self�rdclass�rdtyperrr)�	__class__��/usr/lib/python3.6/URI.pyr	's
zURI.__init__NTcKsd|j|j|jj�fS)Nz
%d %d "%s")rrr�decode)r�origin�
relativize�kwrrr�to_text2s
zURI.to_textc	CsR|j�}|j�}|j�j�}|j�p*|j�s8tjjd��|j�||||||j	�S)NzURI target must be a string)
Z
get_uint16�getZunescapeZis_quoted_stringZ
is_identifierrrr
Zget_eol�value)	�clsrr�tokrrrrrrrr�	from_text6sz
URI.from_textcCs,tjd|j|j�}|j|�|j|j�dS)Nz!HH)�struct�packrr�writer)r�file�compressrZtwo_intsrrr�to_wire@s
zURI.to_wirec
Csh|dkrtjjd��tjd|||d��\}}|d7}|d8}||||�}	||7}||||||	�S)N�zURI RR is shorter than 5 octetsz!HH�)rrZ	FormErrorr �unpack)
rrrZwireZcurrentZrdlenrrrrrrr�	from_wireEsz
URI.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__r	r�classmethodrr%r)�
__classcell__rr)rrrs


	
r)
r Z
dns.exceptionrZ	dns.rdataZdns.nameZdns._compatrZrdataZRdatarrrrr�<module>s
rdtypes/ANY/__pycache__/SOA.cpython-36.opt-1.pyc000064400000006340150351404320015104 0ustar003

�b�W��@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�NcsveZdZdZdddddddgZ�fd	d
�Zdd
d�Zeddd��Zddd�Z	ddd�Z
eddd��Zddd�Z�Z
S)�SOAa�SOA record

    @ivar mname: the SOA MNAME (master name) field
    @type mname: dns.name.Name object
    @ivar rname: the SOA RNAME (responsible name) field
    @type rname: dns.name.Name object
    @ivar serial: The zone's serial number
    @type serial: int
    @ivar refresh: The zone's refresh value (in seconds)
    @type refresh: int
    @ivar retry: The zone's retry value (in seconds)
    @type retry: int
    @ivar expire: The zone's expiration value (in seconds)
    @type expire: int
    @ivar minimum: The zone's negative caching time (in seconds, called
    "minimum" for historical reasons)
    @type minimum: int
    @see: RFC 1035�mname�rname�serial�refresh�retry�expire�minimumc

s@tt|�j||�||_||_||_||_||_||_|	|_	dS)N)
�superr�__init__rrrrrrr	)
�self�rdclass�rdtyperrrrrrr	)�	__class__��/usr/lib/python3.6/SOA.pyr/szSOA.__init__NTcKs<|jj||�}|jj||�}d|||j|j|j|j|jfS)Nz%s %s %d %d %d %d %d)r�choose_relativityrrrrrr	)r�origin�
relativize�kwrrrrr�to_text:s
zSOA.to_textc

Csp|j�}|j�}|j||�}|j||�}|j�}|j�}	|j�}
|j�}|j�}|j�|||||||	|
||�	S)N)Zget_namerZ
get_uint32Zget_ttlZget_eol)
�clsr
r�tokrrrrrrrrr	rrr�	from_textAsz
SOA.from_textcCsL|jj|||�|jj|||�tjd|j|j|j|j|j	�}|j
|�dS)Nz!IIIII)r�to_wirer�struct�packrrrrr	�write)r�file�compressr�	five_intsrrrrPs
zSOA.to_wirecCs6|jj|�|jj|�tjd|j|j|j|j|j	�S)Nz!IIIII)
r�
to_digestablerrrrrrrr	)rrrrrr!WszSOA.to_digestablecCs�tjj|d||�|�\}}||7}||8}tjj|d||�|�\}	}||7}||8}|dkrltjj�tjd||||��}
|dk	r�|j|�}|	j|�}	|||||	|
d|
d|
d|
d|
d�	S)N�z!IIIIIr����)�dns�name�	from_wireZ	exceptionZ	FormErrorr�unpackr)rr
rZwireZcurrentZrdlenrrZcusedrr rrrr)]s 


z
SOA.from_wirecCs$|jj||�|_|jj||�|_dS)N)rrr)rrrrrrrpszSOA.choose_relativity)NT)NT)NN)N)N)NT)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrr!r)r�
__classcell__rr)rrrs


r)rZ
dns.exceptionr'Z	dns.rdataZdns.nameZrdataZRdatarrrrr�<module>srdtypes/ANY/__pycache__/HIP.cpython-36.pyc000064400000006234150351404320014145 0ustar003

�b�W0�@sHddlZddlZddlZddlZddlZddlZGdd�dejj�Z	dS)�NcsfeZdZdZddddgZ�fdd�Zdd
d�Zeddd
��Zddd�Z	eddd��Z
ddd�Z�ZS)�HIPa=HIP record

    @ivar hit: the host identity tag
    @type hit: string
    @ivar algorithm: the public key cryptographic algorithm
    @type algorithm: int
    @ivar key: the public key
    @type key: string
    @ivar servers: the rendezvous servers
    @type servers: list of dns.name.Name objects
    @see: RFC 5205�hit�	algorithm�key�serverscs.tt|�j||�||_||_||_||_dS)N)�superr�__init__rrrr)�self�rdclass�rdtyperrrr)�	__class__��/usr/lib/python3.6/HIP.pyr)s
zHIP.__init__NTc	Ks�tj|j�j�}tj|j�jdd�j�}d}g}x |jD]}|j	|j
||��q8Wt|�dkrz|ddjdd�|D��7}d|j
|||fS)	N�
��r� css|]}|j�VqdS)N)Z
to_unicode)�.0�xr
r
r�	<genexpr>8szHIP.to_text.<locals>.<genexpr>z
%u %s %s%s)�binasciiZhexlifyr�decode�base64Z	b64encoder�replacer�append�choose_relativity�len�joinr)	r	�origin�
relativize�kwrr�textr�serverr
r
r�to_text0szHIP.to_textcCs�|j�}tj|j�j��}t|�dkr2tjjd��t	j
|j�j��}g}	x<|j�}
|
j�r\Ptj
j|
j|�}|j||�|	j|�qJW|||||||	�S)N�zHIT too long)Z	get_uint8rZ	unhexlifyZ
get_string�encoder�dnsZ	exception�SyntaxErrorrZ	b64decode�getZ
is_eol_or_eof�name�	from_text�valuerr)�clsr
r�tokrrrrrr�tokenr"r
r
rr*;sz
HIP.from_textcCsft|j�}t|j�}|jtjd||j|��|j|j�|j|j�x|jD]}|j|d|�qLWdS)Nz!BBH)	rrr�write�struct�packrr�to_wire)r	�file�compressr�lh�lkr"r
r
rr2Ls

zHIP.to_wirecCs�tjd|||d��\}}}	|d7}|d8}||||�j�}
||7}||8}||||	�j�}||	7}||	8}g}xV|dkr�tjj|d||�|�\}
}||7}||8}|dk	r�|
j|�}
|j|
�q|W||||
|||�S)Nz!BBH�r)r0�unpackZunwrapr&r)�	from_wirerr)r,r
rZwireZcurrentZrdlenrr5rr6rrrr"Zcusedr
r
rr9Us(


z
HIP.from_wirecCs4g}x$|jD]}|j||�}|j|�qW||_dS)N)rrr)r	rrrr"r
r
rrls
zHIP.choose_relativity)NT)NT)NN)N)NT)
�__name__�
__module__�__qualname__�__doc__�	__slots__rr#�classmethodr*r2r9r�
__classcell__r
r
)rrrs

	r)
r0rrZ
dns.exceptionr&Z	dns.rdataZ
dns.rdatatypeZrdataZRdatarr
r
r
r�<module>srdtypes/ANY/__pycache__/NS.cpython-36.pyc000064400000000530150351404320014036 0ustar003

�b�Wi�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�NSz	NS recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/NS.pyrsr)Zdns.rdtypes.nsbaseZdnsZrdtypesZnsbaseZNSBaserrrrr�<module>srdtypes/ANY/__pycache__/__init__.cpython-36.pyc000064400000000750150351404320015261 0ustar003

�b�W��@sJdZddddddddd	d
ddd
ddddddddddddddddddgZd S)!z'Class ANY (generic) rdata type classes.ZAFSDBZCDNSKEYZCDSZCERTZCNAMEZDLVZDNAMEZDNSKEYZDSZEUI48ZEUI64ZGPOSZHINFOZHIPZISDNZLOCZMXZNSZNSECZNSEC3Z
NSEC3PARAMZTLSAZPTRZRPZRRSIGZRTZSOAZSPFZSSHFPZTXTZX25N)�__doc__�__all__�rr�/usr/lib/python3.6/__init__.py�<module>s>rdtypes/ANY/__pycache__/__init__.cpython-36.opt-1.pyc000064400000000750150351404320016220 0ustar003

�b�W��@sJdZddddddddd	d
ddd
ddddddddddddddddddgZd S)!z'Class ANY (generic) rdata type classes.ZAFSDBZCDNSKEYZCDSZCERTZCNAMEZDLVZDNAMEZDNSKEYZDSZEUI48ZEUI64ZGPOSZHINFOZHIPZISDNZLOCZMXZNSZNSECZNSEC3Z
NSEC3PARAMZTLSAZPTRZRPZRRSIGZRTZSOAZSPFZSSHFPZTXTZX25N)�__doc__�__all__�rr�/usr/lib/python3.6/__init__.py�<module>s>rdtypes/ANY/__pycache__/NS.cpython-36.opt-1.pyc000064400000000530150351404320014775 0ustar003

�b�Wi�@s"ddlZGdd�dejjj�ZdS)�Nc@seZdZdZdS)�NSz	NS recordN)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/NS.pyrsr)Zdns.rdtypes.nsbaseZdnsZrdtypesZnsbaseZNSBaserrrrr�<module>srdtypes/ANY/__pycache__/HIP.cpython-36.opt-1.pyc000064400000006234150351404320015104 0ustar003

�b�W0�@sHddlZddlZddlZddlZddlZddlZGdd�dejj�Z	dS)�NcsfeZdZdZddddgZ�fdd�Zdd
d�Zeddd
��Zddd�Z	eddd��Z
ddd�Z�ZS)�HIPa=HIP record

    @ivar hit: the host identity tag
    @type hit: string
    @ivar algorithm: the public key cryptographic algorithm
    @type algorithm: int
    @ivar key: the public key
    @type key: string
    @ivar servers: the rendezvous servers
    @type servers: list of dns.name.Name objects
    @see: RFC 5205�hit�	algorithm�key�serverscs.tt|�j||�||_||_||_||_dS)N)�superr�__init__rrrr)�self�rdclass�rdtyperrrr)�	__class__��/usr/lib/python3.6/HIP.pyr)s
zHIP.__init__NTc	Ks�tj|j�j�}tj|j�jdd�j�}d}g}x |jD]}|j	|j
||��q8Wt|�dkrz|ddjdd�|D��7}d|j
|||fS)	N�
��r� css|]}|j�VqdS)N)Z
to_unicode)�.0�xr
r
r�	<genexpr>8szHIP.to_text.<locals>.<genexpr>z
%u %s %s%s)�binasciiZhexlifyr�decode�base64Z	b64encoder�replacer�append�choose_relativity�len�joinr)	r	�origin�
relativize�kwrr�textr�serverr
r
r�to_text0szHIP.to_textcCs�|j�}tj|j�j��}t|�dkr2tjjd��t	j
|j�j��}g}	x<|j�}
|
j�r\Ptj
j|
j|�}|j||�|	j|�qJW|||||||	�S)N�zHIT too long)Z	get_uint8rZ	unhexlifyZ
get_string�encoder�dnsZ	exception�SyntaxErrorrZ	b64decode�getZ
is_eol_or_eof�name�	from_text�valuerr)�clsr
r�tokrrrrrr�tokenr"r
r
rr*;sz
HIP.from_textcCsft|j�}t|j�}|jtjd||j|��|j|j�|j|j�x|jD]}|j|d|�qLWdS)Nz!BBH)	rrr�write�struct�packrr�to_wire)r	�file�compressr�lh�lkr"r
r
rr2Ls

zHIP.to_wirecCs�tjd|||d��\}}}	|d7}|d8}||||�j�}
||7}||8}||||	�j�}||	7}||	8}g}xV|dkr�tjj|d||�|�\}
}||7}||8}|dk	r�|
j|�}
|j|
�q|W||||
|||�S)Nz!BBH�r)r0�unpackZunwrapr&r)�	from_wirerr)r,r
rZwireZcurrentZrdlenrr5rr6rrrr"Zcusedr
r
rr9Us(


z
HIP.from_wirecCs4g}x$|jD]}|j||�}|j|�qW||_dS)N)rrr)r	rrrr"r
r
rrls
zHIP.choose_relativity)NT)NT)NN)N)NT)
�__name__�
__module__�__qualname__�__doc__�	__slots__rr#�classmethodr*r2r9r�
__classcell__r
r
)rrrs

	r)
r0rrZ
dns.exceptionr&Z	dns.rdataZ
dns.rdatatypeZrdataZRdatarr
r
r
r�<module>srdtypes/ANY/__pycache__/TLSA.cpython-36.pyc000064400000004336150351404320014271 0ustar003

�b�W��@s8ddlZddlZddlZddlZGdd�dejj�ZdS)�Ncs\eZdZdZddddgZ�fdd�Zdd
d�Zeddd
��Zddd�Z	eddd��Z
�ZS)�TLSAa*TLSA record

    @ivar usage: The certificate usage
    @type usage: int
    @ivar selector: The selector field
    @type selector: int
    @ivar mtype: The 'matching type' field
    @type mtype: int
    @ivar cert: The 'Certificate Association Data' field
    @type cert: string
    @see: RFC 6698�usage�selector�mtype�certcs.tt|�j||�||_||_||_||_dS)N)�superr�__init__rrrr)�self�rdclass�rdtyperrrr)�	__class__��/usr/lib/python3.6/TLSA.pyr's
z
TLSA.__init__NTcKs$d|j|j|jtjj|jdd�fS)Nz%d %d %d %s�)Z	chunksize)rrr�dns�rdataZ_hexifyr)r	�origin�
relativize�kwr
r
r�to_text/s

zTLSA.to_textcCs~|j�}|j�}|j�}g}	x:|j�j�}
|
j�r4P|
j�sDtjj�|	j|
j	j
��qWdj|	�}tj
|�}|||||||�S)N�)Z	get_uint8�getZunescapeZ
is_eol_or_eofZ
is_identifierrZ	exception�SyntaxError�append�value�encode�join�binasciiZ	unhexlify)�clsr
r�tokrrrrrZcert_chunks�trr
r
r�	from_text6s

zTLSA.from_textcCs0tjd|j|j|j�}|j|�|j|j�dS)Nz!BBB)�struct�packrrr�writer)r	�file�compressr�headerr
r
r�to_wireGs
zTLSA.to_wirec	CsZtjd|||d��}|d7}|d8}||||�j�}||||d|d|d|�S)Nz!BBB�r��)r"�unpackZunwrap)	rr
rZwireZcurrentZrdlenrr'rr
r
r�	from_wireLs
zTLSA.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodr!r(r-�
__classcell__r
r
)rrrs

r)r"rZ	dns.rdatarZ
dns.rdatatyperZRdatarr
r
r
r�<module>srdtypes/ANY/__pycache__/X25.cpython-36.opt-1.pyc000064400000003247150351404320015043 0ustar003

�b�WG�@sDddlZddlZddlZddlZddlmZGdd�dejj�Z	dS)�N)�	text_typecsVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�X25z\X25 record

    @ivar address: the PSDN address
    @type address: string
    @see: RFC 1183�addresscs2tt|�j||�t|t�r(|j�|_n||_dS)N)�superr�__init__�
isinstancer�encoder)�self�rdclass�rdtyper)�	__class__��/usr/lib/python3.6/X25.pyr"s
zX25.__init__NTcKsdtjj|j�S)Nz"%s")�dns�rdataZ	_escapifyr)r	�origin�
relativize�kwr
r
r�to_text)szX25.to_textcCs|j�}|j�||||�S)N)Z
get_stringZget_eol)�clsr
r�tokrrrr
r
r�	from_text,sz
X25.from_textcCs,t|j�}|jtjd|��|j|j�dS)Nz!B)�lenr�write�struct�pack)r	�file�compressr�lr
r
r�to_wire2s
zX25.to_wirec	CsH||}|d7}|d8}||kr(tjj�||||�j�}||||�S)N�)rZ	exceptionZ	FormErrorZunwrap)	rr
rZwireZcurrentZrdlenrrrr
r
r�	from_wire8sz
X25.from_wire)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrr!�
__classcell__r
r
)rrrs

r)
rZ
dns.exceptionrZ	dns.rdataZ
dns.tokenizerZdns._compatrrZRdatarr
r
r
r�<module>s
rdtypes/ANY/__pycache__/LOC.cpython-36.opt-1.pyc000064400000020153150351404320015075 0ustar003

�b�W�/�@s�ddlmZddlZddlZddlZddlmZmZm	Z	e
dd�edd�D��ZdZ
dZd	Zd
d�Zdd
�Zdd�Zdd�Zdd�ZGdd�dejj�ZdS)�)�divisionN)�long�xrange�round_py2_compatccs|]}td|�VqdS)�
N)r)�.0�i�r	�/usr/lib/python3.6/LOC.py�	<genexpr>sr�gY@g��.Ag@�@cCsh|dkrdSd}x2ttt��D]"}|t|td�kr|d}PqW|dksT|dkrdtjjd|��|S)Nr�z%s value out of bounds)r�len�_powsr�dns�	exception�SyntaxError)�what�descZexprr	r	r
�_exponent_of!srcCs�|dkrd}|d9}nd}t|d�}t|d�}||d8}t|d�}||d8}t|d�}|t|d�8}t|�}|||||fS)Nrr
i��6i`�i����r)r�int)rZsignZdegreesZminutes�secondsr	r	r
�_float_to_tuple.s
rcCsXt|d�}|t|d�d7}|t|d�d7}|t|d�d7}t|d�|S)	Nrr
gN@�g �@�g@wKA�)�float)r�valuer	r	r
�_tuple_to_float?s
rcCs4t|�}t||�d@}|td|�d@}|d|S)N�r�)rr�pow)rr�exponent�baser	r	r
�_encode_sizeGsr%cCsV|d@}|dkr tjjd|��|d@d?}|dkrDtjjd|��t|�td|�S)Nr �	zbad %s exponent��rzbad %s baser)rrrrr")rrr#r$r	r	r
�_decode_sizeNsr(cs�eZdZdZddddddgZeeef�fdd	�	Zddd
�Z	e
d dd��Zd!dd�Ze
d"dd��Z
dd�Zdd�Zeeedd�Zdd�Zdd�Zeeedd�Z�ZS)#�LOCa�LOC record

    @ivar latitude: latitude
    @type latitude: (int, int, int, int, sign) tuple specifying the degrees, minutes,
    seconds, milliseconds, and sign of the coordinate.
    @ivar longitude: longitude
    @type longitude: (int, int, int, int, sign) tuple specifying the degrees,
    minutes, seconds, milliseconds, and sign of the coordinate.
    @ivar altitude: altitude
    @type altitude: float
    @ivar size: size of the sphere
    @type size: float
    @ivar horizontal_precision: horizontal precision
    @type horizontal_precision: float
    @ivar vertical_precision: vertical precision
    @type vertical_precision: float
    @see: RFC 1876�latitude�	longitude�altitude�size�horizontal_precision�vertical_precisionc		s�tt|�j||�t|t�s&t|t�r.t|�}t|t�r@t|�}||_t|t�sZt|t�rbt|�}t|t�rtt|�}||_	t|�|_
t|�|_t|�|_t|�|_
dS)a�Initialize a LOC record instance.

        The parameters I{latitude} and I{longitude} may be either a 4-tuple
        of integers specifying (degrees, minutes, seconds, milliseconds),
        or they may be floating point values specifying the number of
        degrees. The other parameters are floats. Size, horizontal precision,
        and vertical precision are specified in centimeters.N)�superr)�__init__�
isinstancerrrrr*r+r,r-r.r/)	�self�rdclass�rdtyper*r+r,r-�hprec�vprec)�	__class__r	r
r1os




zLOC.__init__NTc
Ks�|jddkrd}nd}|jddkr,d}nd}d|jd|jd|jd	|jd
||jd|jd|jd	|jd
||jdf}|jtks�|jtks�|jtkr�|d|jd|jd|jdf7}|S)
Nrr�N�S�E�Wz(%d %d %d.%03d %s %d %d %d.%03d %s %0.2fmr
rrgY@z %0.2fm %0.2fm %0.2fm)	r*r+r,r-�
_default_sizer.�_default_hprecr/�_default_vprec)r3�origin�
relativize�kwZlat_hemisphereZlong_hemisphere�textr	r	r
�to_text�s&



zLOC.to_textc	Cs�dddddg}dddddg}t}t}	t}
|j�|d<|j�}|j��r0t|�|d<|j�}d|k�r|jd�\}}
|j�s�tj	j
d��t|�|d<|ddkr�tj	j
d��t|
�}|dks�|dks�|
j�r�tj	j
d	��|dkr�d
}n|dkr�d}nd}|t|
�|d<|j�}n|j��r0t|�|d<|j�}|dk�rDd|d
<n|dk�rZtj	j
d��|j�|d<|j�}|j��rpt|�|d<|j�}d|k�rR|jd�\}}
|j��s�tj	j
d��t|�|d<|ddk�r�tj	j
d��t|
�}|dk�s|dk�s|
j��rtj	j
d��|dk�r$d
}n|dk�r4d}nd}|t|
�|d<|j�}n|j��rpt|�|d<|j�}|dk�r�d|d
<n|dk�r�tj	j
d��|j�}|ddk�r�|dd�}t|�d}|j
�j�}|j��s�|j}|ddk�r�|dd�}t|�d}|j
�j�}|j��s�|j}|ddk�r@|dd�}t|�d}	|j
�j�}|j��s�|j}|d dk�r�|dd!�}t|�d}
|j�||||||||	|
�S)"Nrr
�.zbad latitude seconds valuer�<zlatitude seconds >= 60rzbad latitude milliseconds value�drr:rr9zbad latitude hemisphere valuezbad longitude seconds valuezlongitude seconds >= 60z bad longitude milliseconds valuer<r;zbad longitude hemisphere value�mgY@rrrrrrrrrr)r=r>r?Zget_intZ
get_string�isdigitr�splitrrrrr�getZunescapeZ
is_eol_or_eofrZget_eol)�clsr4r5�tokr@rAr*r+r-r6r7�tr�milliseconds�lrHr,�tokenrr	r	r
�	from_text�s�









 









z
LOC.from_textc	Cs�|jdd|jdd|jdd|jd|jd}td	�|}|jdd|jdd|jdd|jd|jd}td	�|}t|j�td
�}t|jd�}t|jd�}	t|jd
�}
tj	dd||	|
|||�}|j
|�dS)Nri��6r
i`�ri�rrli���r-zhorizontal precisionzvertical precisionz!BBBBIII)r*rr+r,r%r-r.r/�struct�pack�write)r3�file�compressr@rOr*r+r,r-r6r7�wirer	r	r
�to_wires((zLOC.to_wirec	Cstjd||||��\}}}	}
}}}
|td�krHt|td��d}nd
ttd�|�d}|dksp|dkr|tjjd��|td�kr�t|td��d}ndttd�|�d}|dks�|dkr�tjjd��t|
�d	}
t|d
�}t|	d�}	t|
d�}
||||||
||	|
�S)Nz!BBBBIIIli��6r
g�V@zbad latitudeg�f@z
bad longitudeg�cAr-zhorizontal precisionzvertical precisionrg�V�rg�f�)rS�unpackrrrrZ	FormErrorr()rLr4r5rXZcurrentZrdlenr@�versionr-r6r7r*r+r,r	r	r
�	from_wires"&


z
LOC.from_wirecCs
t|j�S)N)rr*)r3r	r	r
�_get_float_latitude5szLOC._get_float_latitudecCst|�|_dS)N)rr*)r3rr	r	r
�_set_float_latitude8szLOC._set_float_latitudez"latitude as a floating point value)�doccCs
t|j�S)N)rr+)r3r	r	r
�_get_float_longitude>szLOC._get_float_longitudecCst|�|_dS)N)rr+)r3rr	r	r
�_set_float_longitudeAszLOC._set_float_longitudez#longitude as a floating point value)NT)NT)NN)N)�__name__�
__module__�__qualname__�__doc__�	__slots__r=r>r?r1rD�classmethodrRrYr\r]r^�propertyZfloat_latituder`raZfloat_longitude�
__classcell__r	r	)r8r
r)Xs&
e
r))Z
__future__rrSZ
dns.exceptionrZ	dns.rdataZdns._compatrrr�tuple�rangerr=r>r?rrrr%r(ZrdataZRdatar)r	r	r	r
�<module>s

rdtypes/ANY/__pycache__/RP.cpython-36.opt-1.pyc000064400000004377150351404320015013 0ustar003

�b�W��@s0ddlZddlZddlZGdd�dejj�ZdS)�NcsleZdZdZddgZ�fdd�Zddd	�Zedd
d��Zddd
�Z	ddd�Z
eddd��Zddd�Z�Z
S)�RPaRP record

    @ivar mbox: The responsible person's mailbox
    @type mbox: dns.name.Name object
    @ivar txt: The owner name of a node with TXT records, or the root name
    if no TXT records are associated with this RP.
    @type txt: dns.name.Name object
    @see: RFC 1183�mbox�txtcs"tt|�j||�||_||_dS)N)�superr�__init__rr)�self�rdclass�rdtyperr)�	__class__��/usr/lib/python3.6/RP.pyr"szRP.__init__NTcKs0|jj||�}|jj||�}dt|�t|�fS)Nz%s %s)r�choose_relativityr�str)r�origin�
relativize�kwrrrrr�to_text'sz
RP.to_textcCs>|j�}|j�}|j||�}|j||�}|j�|||||�S)N)Zget_namer
Zget_eol)�clsrr	�tokrrrrrrr�	from_text,szRP.from_textcCs$|jj|d|�|jj|d|�dS)N)r�to_wirer)r�file�compressrrrrr5sz
RP.to_wirecCs|jj|�|jj|�S)N)r�
to_digestabler)rrrrrr9s
zRP.to_digestablec
Cs�tjj|d||�|�\}}||7}||8}|dkr>tjj�tjj|d||�|�\}	}||krltjj�|dk	r�|j|�}|	j|�}	|||||	�S)Nr)�dns�name�	from_wireZ	exceptionZ	FormErrorr)
rrr	ZwireZcurrentZrdlenrrZcusedrrrrr=s



zRP.from_wirecCs$|jj||�|_|jj||�|_dS)N)rr
r)rrrrrrr
NszRP.choose_relativity)NT)NT)NN)N)N)NT)�__name__�
__module__�__qualname__�__doc__�	__slots__rr�classmethodrrrrr
�
__classcell__rr)r
rrs	


r)Z
dns.exceptionrZ	dns.rdataZdns.nameZrdataZRdatarrrrr�<module>srdtypes/ANY/CAA.py000064400000005076150351404320007630 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct

import dns.exception
import dns.rdata
import dns.tokenizer


class CAA(dns.rdata.Rdata):

    """CAA (Certification Authority Authorization) record

    @ivar flags: the flags
    @type flags: int
    @ivar tag: the tag
    @type tag: string
    @ivar value: the value
    @type value: string
    @see: RFC 6844"""

    __slots__ = ['flags', 'tag', 'value']

    def __init__(self, rdclass, rdtype, flags, tag, value):
        super(CAA, self).__init__(rdclass, rdtype)
        self.flags = flags
        self.tag = tag
        self.value = value

    def to_text(self, origin=None, relativize=True, **kw):
        return '%u %s "%s"' % (self.flags,
                               dns.rdata._escapify(self.tag),
                               dns.rdata._escapify(self.value))

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        flags = tok.get_uint8()
        tag = tok.get_string().encode()
        if len(tag) > 255:
            raise dns.exception.SyntaxError("tag too long")
        if not tag.isalnum():
            raise dns.exception.SyntaxError("tag is not alphanumeric")
        value = tok.get_string().encode()
        return cls(rdclass, rdtype, flags, tag, value)

    def to_wire(self, file, compress=None, origin=None):
        file.write(struct.pack('!B', self.flags))
        l = len(self.tag)
        assert l < 256
        file.write(struct.pack('!B', l))
        file.write(self.tag)
        file.write(self.value)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        (flags, l) = struct.unpack('!BB', wire[current: current + 2])
        current += 2
        tag = wire[current: current + l]
        value = wire[current + l:current + rdlen - 2]
        return cls(rdclass, rdtype, flags, tag, value)
rdtypes/ANY/EUI48.py000064400000002144150351404320010033 0ustar00# Copyright (C) 2015 Red Hat, Inc.
# Author: Petr Spacek <pspacek@redhat.com>
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.euibase


class EUI48(dns.rdtypes.euibase.EUIBase):

    """EUI48 record

    @ivar fingerprint: 48-bit Extended Unique Identifier (EUI-48)
    @type fingerprint: string
    @see: rfc7043.txt"""

    byte_len = 6  # 0123456789ab (in hex)
    text_len = byte_len * 3 - 1  # 01-23-45-67-89-ab
rdtypes/ANY/AFSDB.py000064400000003470150351404320010057 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.mxbase


class AFSDB(dns.rdtypes.mxbase.UncompressedDowncasingMX):

    """AFSDB record

    @ivar subtype: the subtype value
    @type subtype: int
    @ivar hostname: the hostname name
    @type hostname: dns.name.Name object"""

    # Use the property mechanism to make "subtype" an alias for the
    # "preference" attribute, and "hostname" an alias for the "exchange"
    # attribute.
    #
    # This lets us inherit the UncompressedMX implementation but lets
    # the caller use appropriate attribute names for the rdata type.
    #
    # We probably lose some performance vs. a cut-and-paste
    # implementation, but this way we don't copy code, and that's
    # good.

    def get_subtype(self):
        return self.preference

    def set_subtype(self, subtype):
        self.preference = subtype

    subtype = property(get_subtype, set_subtype)

    def get_hostname(self):
        return self.exchange

    def set_hostname(self, hostname):
        self.exchange = hostname

    hostname = property(get_hostname, set_hostname)
rdtypes/ANY/SOA.py000064400000010650150351404320007660 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct

import dns.exception
import dns.rdata
import dns.name


class SOA(dns.rdata.Rdata):

    """SOA record

    @ivar mname: the SOA MNAME (master name) field
    @type mname: dns.name.Name object
    @ivar rname: the SOA RNAME (responsible name) field
    @type rname: dns.name.Name object
    @ivar serial: The zone's serial number
    @type serial: int
    @ivar refresh: The zone's refresh value (in seconds)
    @type refresh: int
    @ivar retry: The zone's retry value (in seconds)
    @type retry: int
    @ivar expire: The zone's expiration value (in seconds)
    @type expire: int
    @ivar minimum: The zone's negative caching time (in seconds, called
    "minimum" for historical reasons)
    @type minimum: int
    @see: RFC 1035"""

    __slots__ = ['mname', 'rname', 'serial', 'refresh', 'retry', 'expire',
                 'minimum']

    def __init__(self, rdclass, rdtype, mname, rname, serial, refresh, retry,
                 expire, minimum):
        super(SOA, self).__init__(rdclass, rdtype)
        self.mname = mname
        self.rname = rname
        self.serial = serial
        self.refresh = refresh
        self.retry = retry
        self.expire = expire
        self.minimum = minimum

    def to_text(self, origin=None, relativize=True, **kw):
        mname = self.mname.choose_relativity(origin, relativize)
        rname = self.rname.choose_relativity(origin, relativize)
        return '%s %s %d %d %d %d %d' % (
            mname, rname, self.serial, self.refresh, self.retry,
            self.expire, self.minimum)

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        mname = tok.get_name()
        rname = tok.get_name()
        mname = mname.choose_relativity(origin, relativize)
        rname = rname.choose_relativity(origin, relativize)
        serial = tok.get_uint32()
        refresh = tok.get_ttl()
        retry = tok.get_ttl()
        expire = tok.get_ttl()
        minimum = tok.get_ttl()
        tok.get_eol()
        return cls(rdclass, rdtype, mname, rname, serial, refresh, retry,
                   expire, minimum)

    def to_wire(self, file, compress=None, origin=None):
        self.mname.to_wire(file, compress, origin)
        self.rname.to_wire(file, compress, origin)
        five_ints = struct.pack('!IIIII', self.serial, self.refresh,
                                self.retry, self.expire, self.minimum)
        file.write(five_ints)

    def to_digestable(self, origin=None):
        return self.mname.to_digestable(origin) + \
            self.rname.to_digestable(origin) + \
            struct.pack('!IIIII', self.serial, self.refresh,
                        self.retry, self.expire, self.minimum)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        (mname, cused) = dns.name.from_wire(wire[: current + rdlen], current)
        current += cused
        rdlen -= cused
        (rname, cused) = dns.name.from_wire(wire[: current + rdlen], current)
        current += cused
        rdlen -= cused
        if rdlen != 20:
            raise dns.exception.FormError
        five_ints = struct.unpack('!IIIII',
                                  wire[current: current + rdlen])
        if origin is not None:
            mname = mname.relativize(origin)
            rname = rname.relativize(origin)
        return cls(rdclass, rdtype, mname, rname,
                   five_ints[0], five_ints[1], five_ints[2], five_ints[3],
                   five_ints[4])

    def choose_relativity(self, origin=None, relativize=True):
        self.mname = self.mname.choose_relativity(origin, relativize)
        self.rname = self.rname.choose_relativity(origin, relativize)
rdtypes/ANY/NSEC3.py000064400000015641150351404320010056 0ustar00# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import base64
import binascii
import string
import struct

import dns.exception
import dns.rdata
import dns.rdatatype
from dns._compat import xrange, text_type

try:
    b32_hex_to_normal = string.maketrans('0123456789ABCDEFGHIJKLMNOPQRSTUV',
                                         'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
    b32_normal_to_hex = string.maketrans('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
                                         '0123456789ABCDEFGHIJKLMNOPQRSTUV')
except AttributeError:
    b32_hex_to_normal = bytes.maketrans(b'0123456789ABCDEFGHIJKLMNOPQRSTUV',
                                        b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
    b32_normal_to_hex = bytes.maketrans(b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
                                        b'0123456789ABCDEFGHIJKLMNOPQRSTUV')

# hash algorithm constants
SHA1 = 1

# flag constants
OPTOUT = 1


class NSEC3(dns.rdata.Rdata):

    """NSEC3 record

    @ivar algorithm: the hash algorithm number
    @type algorithm: int
    @ivar flags: the flags
    @type flags: int
    @ivar iterations: the number of iterations
    @type iterations: int
    @ivar salt: the salt
    @type salt: string
    @ivar next: the next name hash
    @type next: string
    @ivar windows: the windowed bitmap list
    @type windows: list of (window number, string) tuples"""

    __slots__ = ['algorithm', 'flags', 'iterations', 'salt', 'next', 'windows']

    def __init__(self, rdclass, rdtype, algorithm, flags, iterations, salt,
                 next, windows):
        super(NSEC3, self).__init__(rdclass, rdtype)
        self.algorithm = algorithm
        self.flags = flags
        self.iterations = iterations
        if isinstance(salt, text_type):
            self.salt = salt.encode()
        else:
            self.salt = salt
        self.next = next
        self.windows = windows

    def to_text(self, origin=None, relativize=True, **kw):
        next = base64.b32encode(self.next).translate(
            b32_normal_to_hex).lower().decode()
        if self.salt == b'':
            salt = '-'
        else:
            salt = binascii.hexlify(self.salt).decode()
        text = u''
        for (window, bitmap) in self.windows:
            bits = []
            for i in xrange(0, len(bitmap)):
                byte = bitmap[i]
                for j in xrange(0, 8):
                    if byte & (0x80 >> j):
                        bits.append(dns.rdatatype.to_text(window * 256 +
                                                          i * 8 + j))
            text += (u' ' + u' '.join(bits))
        return u'%u %u %u %s %s%s' % (self.algorithm, self.flags,
                                      self.iterations, salt, next, text)

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        algorithm = tok.get_uint8()
        flags = tok.get_uint8()
        iterations = tok.get_uint16()
        salt = tok.get_string()
        if salt == u'-':
            salt = b''
        else:
            salt = binascii.unhexlify(salt.encode('ascii'))
        next = tok.get_string().encode(
            'ascii').upper().translate(b32_hex_to_normal)
        next = base64.b32decode(next)
        rdtypes = []
        while 1:
            token = tok.get().unescape()
            if token.is_eol_or_eof():
                break
            nrdtype = dns.rdatatype.from_text(token.value)
            if nrdtype == 0:
                raise dns.exception.SyntaxError("NSEC3 with bit 0")
            if nrdtype > 65535:
                raise dns.exception.SyntaxError("NSEC3 with bit > 65535")
            rdtypes.append(nrdtype)
        rdtypes.sort()
        window = 0
        octets = 0
        prior_rdtype = 0
        bitmap = bytearray(b'\0' * 32)
        windows = []
        for nrdtype in rdtypes:
            if nrdtype == prior_rdtype:
                continue
            prior_rdtype = nrdtype
            new_window = nrdtype // 256
            if new_window != window:
                if octets != 0:
                    windows.append((window, ''.join(bitmap[0:octets])))
                bitmap = bytearray(b'\0' * 32)
                window = new_window
            offset = nrdtype % 256
            byte = offset // 8
            bit = offset % 8
            octets = byte + 1
            bitmap[byte] = bitmap[byte] | (0x80 >> bit)
        if octets != 0:
            windows.append((window, bitmap[0:octets]))
        return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next,
                   windows)

    def to_wire(self, file, compress=None, origin=None):
        l = len(self.salt)
        file.write(struct.pack("!BBHB", self.algorithm, self.flags,
                               self.iterations, l))
        file.write(self.salt)
        l = len(self.next)
        file.write(struct.pack("!B", l))
        file.write(self.next)
        for (window, bitmap) in self.windows:
            file.write(struct.pack("!BB", window, len(bitmap)))
            file.write(bitmap)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        (algorithm, flags, iterations, slen) = \
            struct.unpack('!BBHB', wire[current: current + 5])

        current += 5
        rdlen -= 5
        salt = wire[current: current + slen].unwrap()
        current += slen
        rdlen -= slen
        nlen = wire[current]
        current += 1
        rdlen -= 1
        next = wire[current: current + nlen].unwrap()
        current += nlen
        rdlen -= nlen
        windows = []
        while rdlen > 0:
            if rdlen < 3:
                raise dns.exception.FormError("NSEC3 too short")
            window = wire[current]
            octets = wire[current + 1]
            if octets == 0 or octets > 32:
                raise dns.exception.FormError("bad NSEC3 octets")
            current += 2
            rdlen -= 2
            if rdlen < octets:
                raise dns.exception.FormError("bad NSEC3 bitmap length")
            bitmap = bytearray(wire[current: current + octets].unwrap())
            current += octets
            rdlen -= octets
            windows.append((window, bitmap))
        return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next,
                   windows)
rdtypes/ANY/RT.py000064400000001573150351404320007567 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.mxbase


class RT(dns.rdtypes.mxbase.UncompressedDowncasingMX):

    """RT record"""
rdtypes/ANY/DNAME.py000064400000001723150351404320010063 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.nsbase


class DNAME(dns.rdtypes.nsbase.UncompressedNS):

    """DNAME record"""

    def to_digestable(self, origin=None):
        return self.target.to_digestable(origin)
rdtypes/ANY/LOC.py000064400000027750150351404320007664 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

from __future__ import division

import struct

import dns.exception
import dns.rdata
from dns._compat import long, xrange, round_py2_compat


_pows = tuple(long(10**i) for i in range(0, 11))

# default values are in centimeters
_default_size = 100.0
_default_hprec = 1000000.0
_default_vprec = 1000.0


def _exponent_of(what, desc):
    if what == 0:
        return 0
    exp = None
    for i in xrange(len(_pows)):
        if what // _pows[i] == long(0):
            exp = i - 1
            break
    if exp is None or exp < 0:
        raise dns.exception.SyntaxError("%s value out of bounds" % desc)
    return exp


def _float_to_tuple(what):
    if what < 0:
        sign = -1
        what *= -1
    else:
        sign = 1
    what = round_py2_compat(what * 3600000)
    degrees = int(what // 3600000)
    what -= degrees * 3600000
    minutes = int(what // 60000)
    what -= minutes * 60000
    seconds = int(what // 1000)
    what -= int(seconds * 1000)
    what = int(what)
    return (degrees, minutes, seconds, what, sign)


def _tuple_to_float(what):
    value = float(what[0])
    value += float(what[1]) / 60.0
    value += float(what[2]) / 3600.0
    value += float(what[3]) / 3600000.0
    return float(what[4]) * value


def _encode_size(what, desc):
    what = long(what)
    exponent = _exponent_of(what, desc) & 0xF
    base = what // pow(10, exponent) & 0xF
    return base * 16 + exponent


def _decode_size(what, desc):
    exponent = what & 0x0F
    if exponent > 9:
        raise dns.exception.SyntaxError("bad %s exponent" % desc)
    base = (what & 0xF0) >> 4
    if base > 9:
        raise dns.exception.SyntaxError("bad %s base" % desc)
    return long(base) * pow(10, exponent)


class LOC(dns.rdata.Rdata):

    """LOC record

    @ivar latitude: latitude
    @type latitude: (int, int, int, int, sign) tuple specifying the degrees, minutes,
    seconds, milliseconds, and sign of the coordinate.
    @ivar longitude: longitude
    @type longitude: (int, int, int, int, sign) tuple specifying the degrees,
    minutes, seconds, milliseconds, and sign of the coordinate.
    @ivar altitude: altitude
    @type altitude: float
    @ivar size: size of the sphere
    @type size: float
    @ivar horizontal_precision: horizontal precision
    @type horizontal_precision: float
    @ivar vertical_precision: vertical precision
    @type vertical_precision: float
    @see: RFC 1876"""

    __slots__ = ['latitude', 'longitude', 'altitude', 'size',
                 'horizontal_precision', 'vertical_precision']

    def __init__(self, rdclass, rdtype, latitude, longitude, altitude,
                 size=_default_size, hprec=_default_hprec,
                 vprec=_default_vprec):
        """Initialize a LOC record instance.

        The parameters I{latitude} and I{longitude} may be either a 4-tuple
        of integers specifying (degrees, minutes, seconds, milliseconds),
        or they may be floating point values specifying the number of
        degrees. The other parameters are floats. Size, horizontal precision,
        and vertical precision are specified in centimeters."""

        super(LOC, self).__init__(rdclass, rdtype)
        if isinstance(latitude, int) or isinstance(latitude, long):
            latitude = float(latitude)
        if isinstance(latitude, float):
            latitude = _float_to_tuple(latitude)
        self.latitude = latitude
        if isinstance(longitude, int) or isinstance(longitude, long):
            longitude = float(longitude)
        if isinstance(longitude, float):
            longitude = _float_to_tuple(longitude)
        self.longitude = longitude
        self.altitude = float(altitude)
        self.size = float(size)
        self.horizontal_precision = float(hprec)
        self.vertical_precision = float(vprec)

    def to_text(self, origin=None, relativize=True, **kw):
        if self.latitude[4] > 0:
            lat_hemisphere = 'N'
        else:
            lat_hemisphere = 'S'
        if self.longitude[4] > 0:
            long_hemisphere = 'E'
        else:
            long_hemisphere = 'W'
        text = "%d %d %d.%03d %s %d %d %d.%03d %s %0.2fm" % (
            self.latitude[0], self.latitude[1],
            self.latitude[2], self.latitude[3], lat_hemisphere,
            self.longitude[0], self.longitude[1], self.longitude[2],
            self.longitude[3], long_hemisphere,
            self.altitude / 100.0
        )

        # do not print default values
        if self.size != _default_size or \
            self.horizontal_precision != _default_hprec or \
                self.vertical_precision != _default_vprec:
            text += " %0.2fm %0.2fm %0.2fm" % (
                self.size / 100.0, self.horizontal_precision / 100.0,
                self.vertical_precision / 100.0
            )
        return text

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        latitude = [0, 0, 0, 0, 1]
        longitude = [0, 0, 0, 0, 1]
        size = _default_size
        hprec = _default_hprec
        vprec = _default_vprec

        latitude[0] = tok.get_int()
        t = tok.get_string()
        if t.isdigit():
            latitude[1] = int(t)
            t = tok.get_string()
            if '.' in t:
                (seconds, milliseconds) = t.split('.')
                if not seconds.isdigit():
                    raise dns.exception.SyntaxError(
                        'bad latitude seconds value')
                latitude[2] = int(seconds)
                if latitude[2] >= 60:
                    raise dns.exception.SyntaxError('latitude seconds >= 60')
                l = len(milliseconds)
                if l == 0 or l > 3 or not milliseconds.isdigit():
                    raise dns.exception.SyntaxError(
                        'bad latitude milliseconds value')
                if l == 1:
                    m = 100
                elif l == 2:
                    m = 10
                else:
                    m = 1
                latitude[3] = m * int(milliseconds)
                t = tok.get_string()
            elif t.isdigit():
                latitude[2] = int(t)
                t = tok.get_string()
        if t == 'S':
            latitude[4] = -1
        elif t != 'N':
            raise dns.exception.SyntaxError('bad latitude hemisphere value')

        longitude[0] = tok.get_int()
        t = tok.get_string()
        if t.isdigit():
            longitude[1] = int(t)
            t = tok.get_string()
            if '.' in t:
                (seconds, milliseconds) = t.split('.')
                if not seconds.isdigit():
                    raise dns.exception.SyntaxError(
                        'bad longitude seconds value')
                longitude[2] = int(seconds)
                if longitude[2] >= 60:
                    raise dns.exception.SyntaxError('longitude seconds >= 60')
                l = len(milliseconds)
                if l == 0 or l > 3 or not milliseconds.isdigit():
                    raise dns.exception.SyntaxError(
                        'bad longitude milliseconds value')
                if l == 1:
                    m = 100
                elif l == 2:
                    m = 10
                else:
                    m = 1
                longitude[3] = m * int(milliseconds)
                t = tok.get_string()
            elif t.isdigit():
                longitude[2] = int(t)
                t = tok.get_string()
        if t == 'W':
            longitude[4] = -1
        elif t != 'E':
            raise dns.exception.SyntaxError('bad longitude hemisphere value')

        t = tok.get_string()
        if t[-1] == 'm':
            t = t[0: -1]
        altitude = float(t) * 100.0        # m -> cm

        token = tok.get().unescape()
        if not token.is_eol_or_eof():
            value = token.value
            if value[-1] == 'm':
                value = value[0: -1]
            size = float(value) * 100.0        # m -> cm
            token = tok.get().unescape()
            if not token.is_eol_or_eof():
                value = token.value
                if value[-1] == 'm':
                    value = value[0: -1]
                hprec = float(value) * 100.0        # m -> cm
                token = tok.get().unescape()
                if not token.is_eol_or_eof():
                    value = token.value
                    if value[-1] == 'm':
                        value = value[0: -1]
                    vprec = float(value) * 100.0        # m -> cm
                    tok.get_eol()

        return cls(rdclass, rdtype, latitude, longitude, altitude,
                   size, hprec, vprec)

    def to_wire(self, file, compress=None, origin=None):
        milliseconds = (self.latitude[0] * 3600000 +
                        self.latitude[1] * 60000 +
                        self.latitude[2] * 1000 +
                        self.latitude[3]) * self.latitude[4]
        latitude = long(0x80000000) + milliseconds
        milliseconds = (self.longitude[0] * 3600000 +
                        self.longitude[1] * 60000 +
                        self.longitude[2] * 1000 +
                        self.longitude[3]) * self.longitude[4]
        longitude = long(0x80000000) + milliseconds
        altitude = long(self.altitude) + long(10000000)
        size = _encode_size(self.size, "size")
        hprec = _encode_size(self.horizontal_precision, "horizontal precision")
        vprec = _encode_size(self.vertical_precision, "vertical precision")
        wire = struct.pack("!BBBBIII", 0, size, hprec, vprec, latitude,
                           longitude, altitude)
        file.write(wire)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        (version, size, hprec, vprec, latitude, longitude, altitude) = \
            struct.unpack("!BBBBIII", wire[current: current + rdlen])
        if latitude > long(0x80000000):
            latitude = float(latitude - long(0x80000000)) / 3600000
        else:
            latitude = -1 * float(long(0x80000000) - latitude) / 3600000
        if latitude < -90.0 or latitude > 90.0:
            raise dns.exception.FormError("bad latitude")
        if longitude > long(0x80000000):
            longitude = float(longitude - long(0x80000000)) / 3600000
        else:
            longitude = -1 * float(long(0x80000000) - longitude) / 3600000
        if longitude < -180.0 or longitude > 180.0:
            raise dns.exception.FormError("bad longitude")
        altitude = float(altitude) - 10000000.0
        size = _decode_size(size, "size")
        hprec = _decode_size(hprec, "horizontal precision")
        vprec = _decode_size(vprec, "vertical precision")
        return cls(rdclass, rdtype, latitude, longitude, altitude,
                   size, hprec, vprec)

    def _get_float_latitude(self):
        return _tuple_to_float(self.latitude)

    def _set_float_latitude(self, value):
        self.latitude = _float_to_tuple(value)

    float_latitude = property(_get_float_latitude, _set_float_latitude,
                              doc="latitude as a floating point value")

    def _get_float_longitude(self):
        return _tuple_to_float(self.longitude)

    def _set_float_longitude(self, value):
        self.longitude = _float_to_tuple(value)

    float_longitude = property(_get_float_longitude, _set_float_longitude,
                               doc="longitude as a floating point value")
rdtypes/ANY/URI.py000064400000005522150351404330007700 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
# Copyright (C) 2015 Red Hat, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct

import dns.exception
import dns.rdata
import dns.name
from dns._compat import text_type


class URI(dns.rdata.Rdata):

    """URI record

    @ivar priority: the priority
    @type priority: int
    @ivar weight: the weight
    @type weight: int
    @ivar target: the target host
    @type target: dns.name.Name object
    @see: draft-faltstrom-uri-13"""

    __slots__ = ['priority', 'weight', 'target']

    def __init__(self, rdclass, rdtype, priority, weight, target):
        super(URI, self).__init__(rdclass, rdtype)
        self.priority = priority
        self.weight = weight
        if len(target) < 1:
            raise dns.exception.SyntaxError("URI target cannot be empty")
        if isinstance(target, text_type):
            self.target = target.encode()
        else:
            self.target = target

    def to_text(self, origin=None, relativize=True, **kw):
        return '%d %d "%s"' % (self.priority, self.weight,
                               self.target.decode())

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        priority = tok.get_uint16()
        weight = tok.get_uint16()
        target = tok.get().unescape()
        if not (target.is_quoted_string() or target.is_identifier()):
            raise dns.exception.SyntaxError("URI target must be a string")
        tok.get_eol()
        return cls(rdclass, rdtype, priority, weight, target.value)

    def to_wire(self, file, compress=None, origin=None):
        two_ints = struct.pack("!HH", self.priority, self.weight)
        file.write(two_ints)
        file.write(self.target)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        if rdlen < 5:
            raise dns.exception.FormError('URI RR is shorter than 5 octets')

        (priority, weight) = struct.unpack('!HH', wire[current: current + 4])
        current += 4
        rdlen -= 4
        target = wire[current: current + rdlen]
        current += rdlen

        return cls(rdclass, rdtype, priority, weight, target)
rdtypes/ANY/NSEC.py000064400000011122150351404330007762 0ustar00# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct

import dns.exception
import dns.rdata
import dns.rdatatype
import dns.name
from dns._compat import xrange


class NSEC(dns.rdata.Rdata):

    """NSEC record

    @ivar next: the next name
    @type next: dns.name.Name object
    @ivar windows: the windowed bitmap list
    @type windows: list of (window number, string) tuples"""

    __slots__ = ['next', 'windows']

    def __init__(self, rdclass, rdtype, next, windows):
        super(NSEC, self).__init__(rdclass, rdtype)
        self.next = next
        self.windows = windows

    def to_text(self, origin=None, relativize=True, **kw):
        next = self.next.choose_relativity(origin, relativize)
        text = ''
        for (window, bitmap) in self.windows:
            bits = []
            for i in xrange(0, len(bitmap)):
                byte = bitmap[i]
                for j in xrange(0, 8):
                    if byte & (0x80 >> j):
                        bits.append(dns.rdatatype.to_text(window * 256 +
                                                          i * 8 + j))
            text += (' ' + ' '.join(bits))
        return '%s%s' % (next, text)

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        next = tok.get_name()
        next = next.choose_relativity(origin, relativize)
        rdtypes = []
        while 1:
            token = tok.get().unescape()
            if token.is_eol_or_eof():
                break
            nrdtype = dns.rdatatype.from_text(token.value)
            if nrdtype == 0:
                raise dns.exception.SyntaxError("NSEC with bit 0")
            if nrdtype > 65535:
                raise dns.exception.SyntaxError("NSEC with bit > 65535")
            rdtypes.append(nrdtype)
        rdtypes.sort()
        window = 0
        octets = 0
        prior_rdtype = 0
        bitmap = bytearray(b'\0' * 32)
        windows = []
        for nrdtype in rdtypes:
            if nrdtype == prior_rdtype:
                continue
            prior_rdtype = nrdtype
            new_window = nrdtype // 256
            if new_window != window:
                windows.append((window, bitmap[0:octets]))
                bitmap = bytearray(b'\0' * 32)
                window = new_window
            offset = nrdtype % 256
            byte = offset // 8
            bit = offset % 8
            octets = byte + 1
            bitmap[byte] = bitmap[byte] | (0x80 >> bit)

        windows.append((window, bitmap[0:octets]))
        return cls(rdclass, rdtype, next, windows)

    def to_wire(self, file, compress=None, origin=None):
        self.next.to_wire(file, None, origin)
        for (window, bitmap) in self.windows:
            file.write(struct.pack('!BB', window, len(bitmap)))
            file.write(bitmap)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        (next, cused) = dns.name.from_wire(wire[: current + rdlen], current)
        current += cused
        rdlen -= cused
        windows = []
        while rdlen > 0:
            if rdlen < 3:
                raise dns.exception.FormError("NSEC too short")
            window = wire[current]
            octets = wire[current + 1]
            if octets == 0 or octets > 32:
                raise dns.exception.FormError("bad NSEC octets")
            current += 2
            rdlen -= 2
            if rdlen < octets:
                raise dns.exception.FormError("bad NSEC bitmap length")
            bitmap = bytearray(wire[current: current + octets].unwrap())
            current += octets
            rdlen -= octets
            windows.append((window, bitmap))
        if origin is not None:
            next = next.relativize(origin)
        return cls(rdclass, rdtype, next, windows)

    def choose_relativity(self, origin=None, relativize=True):
        self.next = self.next.choose_relativity(origin, relativize)
rdtypes/ANY/CDS.py000064400000001553150351404330007652 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.dsbase


class CDS(dns.rdtypes.dsbase.DSBase):

    """CDS record"""
rdtypes/ANY/DLV.py000064400000001540150351404330007662 0ustar00# Copyright (C) 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.dsbase


class DLV(dns.rdtypes.dsbase.DSBase):

    """DLV record"""
rdtypes/ANY/CSYNC.py000064400000011044150351404330010114 0ustar00# Copyright (C) 2004-2007, 2009-2011, 2016 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct

import dns.exception
import dns.rdata
import dns.rdatatype
import dns.name
from dns._compat import xrange

class CSYNC(dns.rdata.Rdata):

    """CSYNC record

    @ivar serial: the SOA serial number
    @type serial: int
    @ivar flags: the CSYNC flags
    @type flags: int
    @ivar windows: the windowed bitmap list
    @type windows: list of (window number, string) tuples"""

    __slots__ = ['serial', 'flags', 'windows']

    def __init__(self, rdclass, rdtype, serial, flags, windows):
        super(CSYNC, self).__init__(rdclass, rdtype)
        self.serial = serial
        self.flags = flags
        self.windows = windows

    def to_text(self, origin=None, relativize=True, **kw):
        text = ''
        for (window, bitmap) in self.windows:
            bits = []
            for i in xrange(0, len(bitmap)):
                byte = bitmap[i]
                for j in xrange(0, 8):
                    if byte & (0x80 >> j):
                        bits.append(dns.rdatatype.to_text(window * 256 +
                                                          i * 8 + j))
            text += (' ' + ' '.join(bits))
        return '%d %d%s' % (self.serial, self.flags, text)

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        serial = tok.get_uint32()
        flags = tok.get_uint16()
        rdtypes = []
        while 1:
            token = tok.get().unescape()
            if token.is_eol_or_eof():
                break
            nrdtype = dns.rdatatype.from_text(token.value)
            if nrdtype == 0:
                raise dns.exception.SyntaxError("CSYNC with bit 0")
            if nrdtype > 65535:
                raise dns.exception.SyntaxError("CSYNC with bit > 65535")
            rdtypes.append(nrdtype)
        rdtypes.sort()
        window = 0
        octets = 0
        prior_rdtype = 0
        bitmap = bytearray(b'\0' * 32)
        windows = []
        for nrdtype in rdtypes:
            if nrdtype == prior_rdtype:
                continue
            prior_rdtype = nrdtype
            new_window = nrdtype // 256
            if new_window != window:
                windows.append((window, bitmap[0:octets]))
                bitmap = bytearray(b'\0' * 32)
                window = new_window
            offset = nrdtype % 256
            byte = offset // 8
            bit = offset % 8
            octets = byte + 1
            bitmap[byte] = bitmap[byte] | (0x80 >> bit)

        windows.append((window, bitmap[0:octets]))
        return cls(rdclass, rdtype, serial, flags, windows)

    def to_wire(self, file, compress=None, origin=None):
        file.write(struct.pack('!IH', self.serial, self.flags))
        for (window, bitmap) in self.windows:
            file.write(struct.pack('!BB', window, len(bitmap)))
            file.write(bitmap)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        if rdlen < 6:
            raise dns.exception.FormError("CSYNC too short")
        (serial, flags) = struct.unpack("!IH", wire[current: current + 6])
        current += 6
        rdlen -= 6
        windows = []
        while rdlen > 0:
            if rdlen < 3:
                raise dns.exception.FormError("CSYNC too short")
            window = wire[current]
            octets = wire[current + 1]
            if octets == 0 or octets > 32:
                raise dns.exception.FormError("bad CSYNC octets")
            current += 2
            rdlen -= 2
            if rdlen < octets:
                raise dns.exception.FormError("bad CSYNC bitmap length")
            bitmap = bytearray(wire[current: current + octets].unwrap())
            current += octets
            rdlen -= octets
            windows.append((window, bitmap))
        return cls(rdclass, rdtype, serial, flags, windows)
rdtypes/ANY/NSEC3PARAM.py000064400000006032150351404330010632 0ustar00# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct
import binascii

import dns.exception
import dns.rdata
from dns._compat import text_type


class NSEC3PARAM(dns.rdata.Rdata):

    """NSEC3PARAM record

    @ivar algorithm: the hash algorithm number
    @type algorithm: int
    @ivar flags: the flags
    @type flags: int
    @ivar iterations: the number of iterations
    @type iterations: int
    @ivar salt: the salt
    @type salt: string"""

    __slots__ = ['algorithm', 'flags', 'iterations', 'salt']

    def __init__(self, rdclass, rdtype, algorithm, flags, iterations, salt):
        super(NSEC3PARAM, self).__init__(rdclass, rdtype)
        self.algorithm = algorithm
        self.flags = flags
        self.iterations = iterations
        if isinstance(salt, text_type):
            self.salt = salt.encode()
        else:
            self.salt = salt

    def to_text(self, origin=None, relativize=True, **kw):
        if self.salt == b'':
            salt = '-'
        else:
            salt = binascii.hexlify(self.salt).decode()
        return '%u %u %u %s' % (self.algorithm, self.flags, self.iterations,
                                salt)

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        algorithm = tok.get_uint8()
        flags = tok.get_uint8()
        iterations = tok.get_uint16()
        salt = tok.get_string()
        if salt == '-':
            salt = ''
        else:
            salt = binascii.unhexlify(salt.encode())
        tok.get_eol()
        return cls(rdclass, rdtype, algorithm, flags, iterations, salt)

    def to_wire(self, file, compress=None, origin=None):
        l = len(self.salt)
        file.write(struct.pack("!BBHB", self.algorithm, self.flags,
                               self.iterations, l))
        file.write(self.salt)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        (algorithm, flags, iterations, slen) = \
             struct.unpack('!BBHB',
                           wire[current: current + 5])
        current += 5
        rdlen -= 5
        salt = wire[current: current + slen].unwrap()
        current += slen
        rdlen -= slen
        if rdlen != 0:
            raise dns.exception.FormError
        return cls(rdclass, rdtype, algorithm, flags, iterations, salt)
rdtypes/ANY/TLSA.py000064400000005614150351404330010006 0ustar00# Copyright (C) 2005-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct
import binascii

import dns.rdata
import dns.rdatatype


class TLSA(dns.rdata.Rdata):

    """TLSA record

    @ivar usage: The certificate usage
    @type usage: int
    @ivar selector: The selector field
    @type selector: int
    @ivar mtype: The 'matching type' field
    @type mtype: int
    @ivar cert: The 'Certificate Association Data' field
    @type cert: string
    @see: RFC 6698"""

    __slots__ = ['usage', 'selector', 'mtype', 'cert']

    def __init__(self, rdclass, rdtype, usage, selector,
                 mtype, cert):
        super(TLSA, self).__init__(rdclass, rdtype)
        self.usage = usage
        self.selector = selector
        self.mtype = mtype
        self.cert = cert

    def to_text(self, origin=None, relativize=True, **kw):
        return '%d %d %d %s' % (self.usage,
                                self.selector,
                                self.mtype,
                                dns.rdata._hexify(self.cert,
                                                  chunksize=128))

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        usage = tok.get_uint8()
        selector = tok.get_uint8()
        mtype = tok.get_uint8()
        cert_chunks = []
        while 1:
            t = tok.get().unescape()
            if t.is_eol_or_eof():
                break
            if not t.is_identifier():
                raise dns.exception.SyntaxError
            cert_chunks.append(t.value.encode())
        cert = b''.join(cert_chunks)
        cert = binascii.unhexlify(cert)
        return cls(rdclass, rdtype, usage, selector, mtype, cert)

    def to_wire(self, file, compress=None, origin=None):
        header = struct.pack("!BBB", self.usage, self.selector, self.mtype)
        file.write(header)
        file.write(self.cert)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        header = struct.unpack("!BBB", wire[current: current + 3])
        current += 3
        rdlen -= 3
        cert = wire[current: current + rdlen].unwrap()
        return cls(rdclass, rdtype, header[0], header[1], header[2], cert)
rdtypes/ANY/AVC.py000064400000001666150351404330007657 0ustar00# Copyright (C) 2016 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.txtbase


class AVC(dns.rdtypes.txtbase.TXTBase):

    """AVC record

    @see: U{http://www.iana.org/assignments/dns-parameters/AVC/avc-completed-template}"""
rdtypes/ANY/HIP.py000064400000010060150351404330007652 0ustar00# Copyright (C) 2010, 2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct
import base64
import binascii

import dns.exception
import dns.rdata
import dns.rdatatype


class HIP(dns.rdata.Rdata):

    """HIP record

    @ivar hit: the host identity tag
    @type hit: string
    @ivar algorithm: the public key cryptographic algorithm
    @type algorithm: int
    @ivar key: the public key
    @type key: string
    @ivar servers: the rendezvous servers
    @type servers: list of dns.name.Name objects
    @see: RFC 5205"""

    __slots__ = ['hit', 'algorithm', 'key', 'servers']

    def __init__(self, rdclass, rdtype, hit, algorithm, key, servers):
        super(HIP, self).__init__(rdclass, rdtype)
        self.hit = hit
        self.algorithm = algorithm
        self.key = key
        self.servers = servers

    def to_text(self, origin=None, relativize=True, **kw):
        hit = binascii.hexlify(self.hit).decode()
        key = base64.b64encode(self.key).replace(b'\n', b'').decode()
        text = u''
        servers = []
        for server in self.servers:
            servers.append(server.choose_relativity(origin, relativize))
        if len(servers) > 0:
            text += (u' ' + u' '.join((x.to_unicode() for x in servers)))
        return u'%u %s %s%s' % (self.algorithm, hit, key, text)

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        algorithm = tok.get_uint8()
        hit = binascii.unhexlify(tok.get_string().encode())
        if len(hit) > 255:
            raise dns.exception.SyntaxError("HIT too long")
        key = base64.b64decode(tok.get_string().encode())
        servers = []
        while 1:
            token = tok.get()
            if token.is_eol_or_eof():
                break
            server = dns.name.from_text(token.value, origin)
            server.choose_relativity(origin, relativize)
            servers.append(server)
        return cls(rdclass, rdtype, hit, algorithm, key, servers)

    def to_wire(self, file, compress=None, origin=None):
        lh = len(self.hit)
        lk = len(self.key)
        file.write(struct.pack("!BBH", lh, self.algorithm, lk))
        file.write(self.hit)
        file.write(self.key)
        for server in self.servers:
            server.to_wire(file, None, origin)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        (lh, algorithm, lk) = struct.unpack('!BBH',
                                            wire[current: current + 4])
        current += 4
        rdlen -= 4
        hit = wire[current: current + lh].unwrap()
        current += lh
        rdlen -= lh
        key = wire[current: current + lk].unwrap()
        current += lk
        rdlen -= lk
        servers = []
        while rdlen > 0:
            (server, cused) = dns.name.from_wire(wire[: current + rdlen],
                                                 current)
            current += cused
            rdlen -= cused
            if origin is not None:
                server = server.relativize(origin)
            servers.append(server)
        return cls(rdclass, rdtype, hit, algorithm, key, servers)

    def choose_relativity(self, origin=None, relativize=True):
        servers = []
        for server in self.servers:
            server = server.choose_relativity(origin, relativize)
            servers.append(server)
        self.servers = servers
rdtypes/ANY/CNAME.py000064400000002074150351404330010063 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.nsbase


class CNAME(dns.rdtypes.nsbase.NSBase):

    """CNAME record

    Note: although CNAME is officially a singleton type, dnspython allows
    non-singleton CNAME rdatasets because such sets have been commonly
    used by BIND and other nameservers for load balancing."""
rdtypes/ANY/SSHFP.py000064400000005414150351404330010124 0ustar00# Copyright (C) 2005-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct
import binascii

import dns.rdata
import dns.rdatatype


class SSHFP(dns.rdata.Rdata):

    """SSHFP record

    @ivar algorithm: the algorithm
    @type algorithm: int
    @ivar fp_type: the digest type
    @type fp_type: int
    @ivar fingerprint: the fingerprint
    @type fingerprint: string
    @see: draft-ietf-secsh-dns-05.txt"""

    __slots__ = ['algorithm', 'fp_type', 'fingerprint']

    def __init__(self, rdclass, rdtype, algorithm, fp_type,
                 fingerprint):
        super(SSHFP, self).__init__(rdclass, rdtype)
        self.algorithm = algorithm
        self.fp_type = fp_type
        self.fingerprint = fingerprint

    def to_text(self, origin=None, relativize=True, **kw):
        return '%d %d %s' % (self.algorithm,
                             self.fp_type,
                             dns.rdata._hexify(self.fingerprint,
                                               chunksize=128))

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        algorithm = tok.get_uint8()
        fp_type = tok.get_uint8()
        chunks = []
        while 1:
            t = tok.get().unescape()
            if t.is_eol_or_eof():
                break
            if not t.is_identifier():
                raise dns.exception.SyntaxError
            chunks.append(t.value.encode())
        fingerprint = b''.join(chunks)
        fingerprint = binascii.unhexlify(fingerprint)
        return cls(rdclass, rdtype, algorithm, fp_type, fingerprint)

    def to_wire(self, file, compress=None, origin=None):
        header = struct.pack("!BB", self.algorithm, self.fp_type)
        file.write(header)
        file.write(self.fingerprint)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        header = struct.unpack("!BB", wire[current: current + 2])
        current += 2
        rdlen -= 2
        fingerprint = wire[current: current + rdlen].unwrap()
        return cls(rdclass, rdtype, header[0], header[1], fingerprint)
rdtypes/ANY/MX.py000064400000001551150351404330007563 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.mxbase


class MX(dns.rdtypes.mxbase.MXBase):

    """MX record"""
rdtypes/ANY/TXT.py000064400000001556150351404330007723 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.txtbase


class TXT(dns.rdtypes.txtbase.TXTBase):

    """TXT record"""
rdtypes/ANY/ISDN.py000064400000006305150351404330007776 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct

import dns.exception
import dns.rdata
import dns.tokenizer
from dns._compat import text_type


class ISDN(dns.rdata.Rdata):

    """ISDN record

    @ivar address: the ISDN address
    @type address: string
    @ivar subaddress: the ISDN subaddress (or '' if not present)
    @type subaddress: string
    @see: RFC 1183"""

    __slots__ = ['address', 'subaddress']

    def __init__(self, rdclass, rdtype, address, subaddress):
        super(ISDN, self).__init__(rdclass, rdtype)
        if isinstance(address, text_type):
            self.address = address.encode()
        else:
            self.address = address
        if isinstance(address, text_type):
            self.subaddress = subaddress.encode()
        else:
            self.subaddress = subaddress

    def to_text(self, origin=None, relativize=True, **kw):
        if self.subaddress:
            return '"%s" "%s"' % (dns.rdata._escapify(self.address),
                                  dns.rdata._escapify(self.subaddress))
        else:
            return '"%s"' % dns.rdata._escapify(self.address)

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        address = tok.get_string()
        t = tok.get()
        if not t.is_eol_or_eof():
            tok.unget(t)
            subaddress = tok.get_string()
        else:
            tok.unget(t)
            subaddress = ''
        tok.get_eol()
        return cls(rdclass, rdtype, address, subaddress)

    def to_wire(self, file, compress=None, origin=None):
        l = len(self.address)
        assert l < 256
        file.write(struct.pack('!B', l))
        file.write(self.address)
        l = len(self.subaddress)
        if l > 0:
            assert l < 256
            file.write(struct.pack('!B', l))
            file.write(self.subaddress)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        l = wire[current]
        current += 1
        rdlen -= 1
        if l > rdlen:
            raise dns.exception.FormError
        address = wire[current: current + l].unwrap()
        current += l
        rdlen -= l
        if rdlen > 0:
            l = wire[current]
            current += 1
            rdlen -= 1
            if l != rdlen:
                raise dns.exception.FormError
            subaddress = wire[current: current + l].unwrap()
        else:
            subaddress = ''
        return cls(rdclass, rdtype, address, subaddress)
rdtypes/ANY/DS.py000064400000001551150351404330007545 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import dns.rdtypes.dsbase


class DS(dns.rdtypes.dsbase.DSBase):

    """DS record"""
rdtypes/ANY/GPOS.py000064400000012371150351404330010011 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct

import dns.exception
import dns.rdata
import dns.tokenizer
from dns._compat import long, text_type


def _validate_float_string(what):
    if what[0] == b'-'[0] or what[0] == b'+'[0]:
        what = what[1:]
    if what.isdigit():
        return
    (left, right) = what.split(b'.')
    if left == b'' and right == b'':
        raise dns.exception.FormError
    if not left == b'' and not left.decode().isdigit():
        raise dns.exception.FormError
    if not right == b'' and not right.decode().isdigit():
        raise dns.exception.FormError


def _sanitize(value):
    if isinstance(value, text_type):
        return value.encode()
    return value


class GPOS(dns.rdata.Rdata):

    """GPOS record

    @ivar latitude: latitude
    @type latitude: string
    @ivar longitude: longitude
    @type longitude: string
    @ivar altitude: altitude
    @type altitude: string
    @see: RFC 1712"""

    __slots__ = ['latitude', 'longitude', 'altitude']

    def __init__(self, rdclass, rdtype, latitude, longitude, altitude):
        super(GPOS, self).__init__(rdclass, rdtype)
        if isinstance(latitude, float) or \
           isinstance(latitude, int) or \
           isinstance(latitude, long):
            latitude = str(latitude)
        if isinstance(longitude, float) or \
           isinstance(longitude, int) or \
           isinstance(longitude, long):
            longitude = str(longitude)
        if isinstance(altitude, float) or \
           isinstance(altitude, int) or \
           isinstance(altitude, long):
            altitude = str(altitude)
        latitude = _sanitize(latitude)
        longitude = _sanitize(longitude)
        altitude = _sanitize(altitude)
        _validate_float_string(latitude)
        _validate_float_string(longitude)
        _validate_float_string(altitude)
        self.latitude = latitude
        self.longitude = longitude
        self.altitude = altitude

    def to_text(self, origin=None, relativize=True, **kw):
        return '%s %s %s' % (self.latitude.decode(),
                             self.longitude.decode(),
                             self.altitude.decode())

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        latitude = tok.get_string()
        longitude = tok.get_string()
        altitude = tok.get_string()
        tok.get_eol()
        return cls(rdclass, rdtype, latitude, longitude, altitude)

    def to_wire(self, file, compress=None, origin=None):
        l = len(self.latitude)
        assert l < 256
        file.write(struct.pack('!B', l))
        file.write(self.latitude)
        l = len(self.longitude)
        assert l < 256
        file.write(struct.pack('!B', l))
        file.write(self.longitude)
        l = len(self.altitude)
        assert l < 256
        file.write(struct.pack('!B', l))
        file.write(self.altitude)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        l = wire[current]
        current += 1
        rdlen -= 1
        if l > rdlen:
            raise dns.exception.FormError
        latitude = wire[current: current + l].unwrap()
        current += l
        rdlen -= l
        l = wire[current]
        current += 1
        rdlen -= 1
        if l > rdlen:
            raise dns.exception.FormError
        longitude = wire[current: current + l].unwrap()
        current += l
        rdlen -= l
        l = wire[current]
        current += 1
        rdlen -= 1
        if l != rdlen:
            raise dns.exception.FormError
        altitude = wire[current: current + l].unwrap()
        return cls(rdclass, rdtype, latitude, longitude, altitude)

    def _get_float_latitude(self):
        return float(self.latitude)

    def _set_float_latitude(self, value):
        self.latitude = str(value)

    float_latitude = property(_get_float_latitude, _set_float_latitude,
                              doc="latitude as a floating point value")

    def _get_float_longitude(self):
        return float(self.longitude)

    def _set_float_longitude(self, value):
        self.longitude = str(value)

    float_longitude = property(_get_float_longitude, _set_float_longitude,
                               doc="longitude as a floating point value")

    def _get_float_altitude(self):
        return float(self.altitude)

    def _set_float_altitude(self, value):
        self.altitude = str(value)

    float_altitude = property(_get_float_altitude, _set_float_altitude,
                              doc="altitude as a floating point value")
rdtypes/dsbase.py000064400000006010150351404330010044 0ustar00# Copyright (C) 2010, 2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import struct
import binascii

import dns.rdata
import dns.rdatatype


class DSBase(dns.rdata.Rdata):

    """Base class for rdata that is like a DS record

    @ivar key_tag: the key tag
    @type key_tag: int
    @ivar algorithm: the algorithm
    @type algorithm: int
    @ivar digest_type: the digest type
    @type digest_type: int
    @ivar digest: the digest
    @type digest: int
    @see: draft-ietf-dnsext-delegation-signer-14.txt"""

    __slots__ = ['key_tag', 'algorithm', 'digest_type', 'digest']

    def __init__(self, rdclass, rdtype, key_tag, algorithm, digest_type,
                 digest):
        super(DSBase, self).__init__(rdclass, rdtype)
        self.key_tag = key_tag
        self.algorithm = algorithm
        self.digest_type = digest_type
        self.digest = digest

    def to_text(self, origin=None, relativize=True, **kw):
        return '%d %d %d %s' % (self.key_tag, self.algorithm,
                                self.digest_type,
                                dns.rdata._hexify(self.digest,
                                                  chunksize=128))

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        key_tag = tok.get_uint16()
        algorithm = tok.get_uint8()
        digest_type = tok.get_uint8()
        chunks = []
        while 1:
            t = tok.get().unescape()
            if t.is_eol_or_eof():
                break
            if not t.is_identifier():
                raise dns.exception.SyntaxError
            chunks.append(t.value.encode())
        digest = b''.join(chunks)
        digest = binascii.unhexlify(digest)
        return cls(rdclass, rdtype, key_tag, algorithm, digest_type,
                   digest)

    def to_wire(self, file, compress=None, origin=None):
        header = struct.pack("!HBB", self.key_tag, self.algorithm,
                             self.digest_type)
        file.write(header)
        file.write(self.digest)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        header = struct.unpack("!HBB", wire[current: current + 4])
        current += 4
        rdlen -= 4
        digest = wire[current: current + rdlen].unwrap()
        return cls(rdclass, rdtype, header[0], header[1], header[2], digest)
rdtypes/dnskeybase.py000064400000010443150351404330010740 0ustar00# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import base64
import struct

import dns.exception
import dns.dnssec
import dns.rdata

# wildcard import
__all__ = ["SEP", "REVOKE", "ZONE",
           "flags_to_text_set", "flags_from_text_set"]

# flag constants
SEP = 0x0001
REVOKE = 0x0080
ZONE = 0x0100

_flag_by_text = {
    'SEP': SEP,
    'REVOKE': REVOKE,
    'ZONE': ZONE
}

# We construct the inverse mapping programmatically to ensure that we
# cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
# would cause the mapping not to be true inverse.
_flag_by_value = dict((y, x) for x, y in _flag_by_text.items())


def flags_to_text_set(flags):
    """Convert a DNSKEY flags value to set texts
    @rtype: set([string])"""

    flags_set = set()
    mask = 0x1
    while mask <= 0x8000:
        if flags & mask:
            text = _flag_by_value.get(mask)
            if not text:
                text = hex(mask)
            flags_set.add(text)
        mask <<= 1
    return flags_set


def flags_from_text_set(texts_set):
    """Convert set of DNSKEY flag mnemonic texts to DNSKEY flag value
    @rtype: int"""

    flags = 0
    for text in texts_set:
        try:
            flags += _flag_by_text[text]
        except KeyError:
            raise NotImplementedError(
                "DNSKEY flag '%s' is not supported" % text)
    return flags


class DNSKEYBase(dns.rdata.Rdata):

    """Base class for rdata that is like a DNSKEY record

    @ivar flags: the key flags
    @type flags: int
    @ivar protocol: the protocol for which this key may be used
    @type protocol: int
    @ivar algorithm: the algorithm used for the key
    @type algorithm: int
    @ivar key: the public key
    @type key: string"""

    __slots__ = ['flags', 'protocol', 'algorithm', 'key']

    def __init__(self, rdclass, rdtype, flags, protocol, algorithm, key):
        super(DNSKEYBase, self).__init__(rdclass, rdtype)
        self.flags = flags
        self.protocol = protocol
        self.algorithm = algorithm
        self.key = key

    def to_text(self, origin=None, relativize=True, **kw):
        return '%d %d %d %s' % (self.flags, self.protocol, self.algorithm,
                                dns.rdata._base64ify(self.key))

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        flags = tok.get_uint16()
        protocol = tok.get_uint8()
        algorithm = dns.dnssec.algorithm_from_text(tok.get_string())
        chunks = []
        while 1:
            t = tok.get().unescape()
            if t.is_eol_or_eof():
                break
            if not t.is_identifier():
                raise dns.exception.SyntaxError
            chunks.append(t.value.encode())
        b64 = b''.join(chunks)
        key = base64.b64decode(b64)
        return cls(rdclass, rdtype, flags, protocol, algorithm, key)

    def to_wire(self, file, compress=None, origin=None):
        header = struct.pack("!HBB", self.flags, self.protocol, self.algorithm)
        file.write(header)
        file.write(self.key)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        if rdlen < 4:
            raise dns.exception.FormError
        header = struct.unpack('!HBB', wire[current: current + 4])
        current += 4
        rdlen -= 4
        key = wire[current: current + rdlen].unwrap()
        return cls(rdclass, rdtype, header[0], header[1], header[2],
                   key)

    def flags_to_text_set(self):
        """Convert a DNSKEY flags value to set texts
        @rtype: set([string])"""
        return flags_to_text_set(self.flags)
renderer.py000064400000027223150351404330006730 0ustar00# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""Help for building DNS wire format messages"""

from io import BytesIO
import struct
import random
import time

import dns.exception
import dns.tsig
from ._compat import long


QUESTION = 0
ANSWER = 1
AUTHORITY = 2
ADDITIONAL = 3


class Renderer(object):

    """Helper class for building DNS wire-format messages.

    Most applications can use the higher-level L{dns.message.Message}
    class and its to_wire() method to generate wire-format messages.
    This class is for those applications which need finer control
    over the generation of messages.

    Typical use::

        r = dns.renderer.Renderer(id=1, flags=0x80, max_size=512)
        r.add_question(qname, qtype, qclass)
        r.add_rrset(dns.renderer.ANSWER, rrset_1)
        r.add_rrset(dns.renderer.ANSWER, rrset_2)
        r.add_rrset(dns.renderer.AUTHORITY, ns_rrset)
        r.add_edns(0, 0, 4096)
        r.add_rrset(dns.renderer.ADDTIONAL, ad_rrset_1)
        r.add_rrset(dns.renderer.ADDTIONAL, ad_rrset_2)
        r.write_header()
        r.add_tsig(keyname, secret, 300, 1, 0, '', request_mac)
        wire = r.get_wire()

    @ivar output: where rendering is written
    @type output: BytesIO object
    @ivar id: the message id
    @type id: int
    @ivar flags: the message flags
    @type flags: int
    @ivar max_size: the maximum size of the message
    @type max_size: int
    @ivar origin: the origin to use when rendering relative names
    @type origin: dns.name.Name object
    @ivar compress: the compression table
    @type compress: dict
    @ivar section: the section currently being rendered
    @type section: int (dns.renderer.QUESTION, dns.renderer.ANSWER,
    dns.renderer.AUTHORITY, or dns.renderer.ADDITIONAL)
    @ivar counts: list of the number of RRs in each section
    @type counts: int list of length 4
    @ivar mac: the MAC of the rendered message (if TSIG was used)
    @type mac: string
    """

    def __init__(self, id=None, flags=0, max_size=65535, origin=None):
        """Initialize a new renderer.

        @param id: the message id
        @type id: int
        @param flags: the DNS message flags
        @type flags: int
        @param max_size: the maximum message size; the default is 65535.
        If rendering results in a message greater than I{max_size},
        then L{dns.exception.TooBig} will be raised.
        @type max_size: int
        @param origin: the origin to use when rendering relative names
        @type origin: dns.name.Name or None.
        """

        self.output = BytesIO()
        if id is None:
            self.id = random.randint(0, 65535)
        else:
            self.id = id
        self.flags = flags
        self.max_size = max_size
        self.origin = origin
        self.compress = {}
        self.section = QUESTION
        self.counts = [0, 0, 0, 0]
        self.output.write(b'\x00' * 12)
        self.mac = ''

    def _rollback(self, where):
        """Truncate the output buffer at offset I{where}, and remove any
        compression table entries that pointed beyond the truncation
        point.

        @param where: the offset
        @type where: int
        """

        self.output.seek(where)
        self.output.truncate()
        keys_to_delete = []
        for k, v in self.compress.items():
            if v >= where:
                keys_to_delete.append(k)
        for k in keys_to_delete:
            del self.compress[k]

    def _set_section(self, section):
        """Set the renderer's current section.

        Sections must be rendered order: QUESTION, ANSWER, AUTHORITY,
        ADDITIONAL.  Sections may be empty.

        @param section: the section
        @type section: int
        @raises dns.exception.FormError: an attempt was made to set
        a section value less than the current section.
        """

        if self.section != section:
            if self.section > section:
                raise dns.exception.FormError
            self.section = section

    def add_question(self, qname, rdtype, rdclass=dns.rdataclass.IN):
        """Add a question to the message.

        @param qname: the question name
        @type qname: dns.name.Name
        @param rdtype: the question rdata type
        @type rdtype: int
        @param rdclass: the question rdata class
        @type rdclass: int
        """

        self._set_section(QUESTION)
        before = self.output.tell()
        qname.to_wire(self.output, self.compress, self.origin)
        self.output.write(struct.pack("!HH", rdtype, rdclass))
        after = self.output.tell()
        if after >= self.max_size:
            self._rollback(before)
            raise dns.exception.TooBig
        self.counts[QUESTION] += 1

    def add_rrset(self, section, rrset, **kw):
        """Add the rrset to the specified section.

        Any keyword arguments are passed on to the rdataset's to_wire()
        routine.

        @param section: the section
        @type section: int
        @param rrset: the rrset
        @type rrset: dns.rrset.RRset object
        """

        self._set_section(section)
        before = self.output.tell()
        n = rrset.to_wire(self.output, self.compress, self.origin, **kw)
        after = self.output.tell()
        if after >= self.max_size:
            self._rollback(before)
            raise dns.exception.TooBig
        self.counts[section] += n

    def add_rdataset(self, section, name, rdataset, **kw):
        """Add the rdataset to the specified section, using the specified
        name as the owner name.

        Any keyword arguments are passed on to the rdataset's to_wire()
        routine.

        @param section: the section
        @type section: int
        @param name: the owner name
        @type name: dns.name.Name object
        @param rdataset: the rdataset
        @type rdataset: dns.rdataset.Rdataset object
        """

        self._set_section(section)
        before = self.output.tell()
        n = rdataset.to_wire(name, self.output, self.compress, self.origin,
                             **kw)
        after = self.output.tell()
        if after >= self.max_size:
            self._rollback(before)
            raise dns.exception.TooBig
        self.counts[section] += n

    def add_edns(self, edns, ednsflags, payload, options=None):
        """Add an EDNS OPT record to the message.

        @param edns: The EDNS level to use.
        @type edns: int
        @param ednsflags: EDNS flag values.
        @type ednsflags: int
        @param payload: The EDNS sender's payload field, which is the maximum
        size of UDP datagram the sender can handle.
        @type payload: int
        @param options: The EDNS options list
        @type options: list of dns.edns.Option instances
        @see: RFC 2671
        """

        # make sure the EDNS version in ednsflags agrees with edns
        ednsflags &= long(0xFF00FFFF)
        ednsflags |= (edns << 16)
        self._set_section(ADDITIONAL)
        before = self.output.tell()
        self.output.write(struct.pack('!BHHIH', 0, dns.rdatatype.OPT, payload,
                                      ednsflags, 0))
        if options is not None:
            lstart = self.output.tell()
            for opt in options:
                stuff = struct.pack("!HH", opt.otype, 0)
                self.output.write(stuff)
                start = self.output.tell()
                opt.to_wire(self.output)
                end = self.output.tell()
                assert end - start < 65536
                self.output.seek(start - 2)
                stuff = struct.pack("!H", end - start)
                self.output.write(stuff)
                self.output.seek(0, 2)
            lend = self.output.tell()
            assert lend - lstart < 65536
            self.output.seek(lstart - 2)
            stuff = struct.pack("!H", lend - lstart)
            self.output.write(stuff)
            self.output.seek(0, 2)
        after = self.output.tell()
        if after >= self.max_size:
            self._rollback(before)
            raise dns.exception.TooBig
        self.counts[ADDITIONAL] += 1

    def add_tsig(self, keyname, secret, fudge, id, tsig_error, other_data,
                 request_mac, algorithm=dns.tsig.default_algorithm):
        """Add a TSIG signature to the message.

        @param keyname: the TSIG key name
        @type keyname: dns.name.Name object
        @param secret: the secret to use
        @type secret: string
        @param fudge: TSIG time fudge
        @type fudge: int
        @param id: the message id to encode in the tsig signature
        @type id: int
        @param tsig_error: TSIG error code; default is 0.
        @type tsig_error: int
        @param other_data: TSIG other data.
        @type other_data: string
        @param request_mac: This message is a response to the request which
        had the specified MAC.
        @type request_mac: string
        @param algorithm: the TSIG algorithm to use
        @type algorithm: dns.name.Name object
        """

        self._set_section(ADDITIONAL)
        before = self.output.tell()
        s = self.output.getvalue()
        (tsig_rdata, self.mac, ctx) = dns.tsig.sign(s,
                                                    keyname,
                                                    secret,
                                                    int(time.time()),
                                                    fudge,
                                                    id,
                                                    tsig_error,
                                                    other_data,
                                                    request_mac,
                                                    algorithm=algorithm)
        keyname.to_wire(self.output, self.compress, self.origin)
        self.output.write(struct.pack('!HHIH', dns.rdatatype.TSIG,
                                      dns.rdataclass.ANY, 0, 0))
        rdata_start = self.output.tell()
        self.output.write(tsig_rdata)
        after = self.output.tell()
        assert after - rdata_start < 65536
        if after >= self.max_size:
            self._rollback(before)
            raise dns.exception.TooBig
        self.output.seek(rdata_start - 2)
        self.output.write(struct.pack('!H', after - rdata_start))
        self.counts[ADDITIONAL] += 1
        self.output.seek(10)
        self.output.write(struct.pack('!H', self.counts[ADDITIONAL]))
        self.output.seek(0, 2)

    def write_header(self):
        """Write the DNS message header.

        Writing the DNS message header is done after all sections
        have been rendered, but before the optional TSIG signature
        is added.
        """

        self.output.seek(0)
        self.output.write(struct.pack('!HHHHHH', self.id, self.flags,
                                      self.counts[0], self.counts[1],
                                      self.counts[2], self.counts[3]))
        self.output.seek(0, 2)

    def get_wire(self):
        """Return the wire format message.

        @rtype: string
        """

        return self.output.getvalue()
ipv4.py000064400000003757150351404330006012 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""IPv4 helper functions."""

import struct

import dns.exception
from ._compat import binary_type

def inet_ntoa(address):
    """Convert an IPv4 address in network form to text form.

    @param address: The IPv4 address
    @type address: string
    @returns: string
    """
    if len(address) != 4:
        raise dns.exception.SyntaxError
    if not isinstance(address, bytearray):
        address = bytearray(address)
    return (u'%u.%u.%u.%u' % (address[0], address[1],
                              address[2], address[3])).encode()

def inet_aton(text):
    """Convert an IPv4 address in text form to network form.

    @param text: The IPv4 address
    @type text: string
    @returns: string
    """
    if not isinstance(text, binary_type):
        text = text.encode()
    parts = text.split(b'.')
    if len(parts) != 4:
        raise dns.exception.SyntaxError
    for part in parts:
        if not part.isdigit():
            raise dns.exception.SyntaxError
        if len(part) > 1 and part[0] == '0':
            # No leading zeros
            raise dns.exception.SyntaxError
    try:
        bytes = [int(part) for part in parts]
        return struct.pack('BBBB', *bytes)
    except:
        raise dns.exception.SyntaxError
__pycache__/ipv6.cpython-36.pyc000064400000005654150351404330012276 0ustar003

�b�W��@s�dZddlZddlZddlZddlZddlmZmZm	Z	ej
d�Zdd�Zej
d�Z
ej
d	�Zej
d
�Zdd�ZdZdd�ZdS)zIPv6 helper functions.�N�)�xrange�binary_type�maybe_decodes
0+([0-9a-f]+)cCs�t|�dkrtd��tj|�}g}d}t|�}xJ||krx|||d�}tj|�}|dk	rd|jd�}|j|�|d7}q0Wd}d}d}	d}
xNtd�D]B}||d	kr�|
r�|}||	}||kr�|	}|}d}
q�|
s�|}	d
}
q�W|
�r�d}||	}||k�r�|	}|}|dk�r�|dk�rb|dk�s4|dk�rb|dd
k�rb|dk�rDd}
nd}
|
t	j
j|dd��}n,dj|d|��ddj|||d��}n
dj|�}t
|�S)z�Convert a network format IPv6 address into text.

    @param address: the binary address
    @type address: string
    @rtype: string
    @raises ValueError: the address isn't 16 bytes long
    �z IPv6 addresses are 16 bytes longr�NrF��0T��sffffs::s::ffff:��:���)�len�
ValueError�binasciiZhexlify�
_leading_zero�match�group�appendr�dns�ipv4�	inet_ntoa�joinr)�address�hex�chunks�i�l�chunk�mZ
best_startZbest_len�startZ
last_was_zero�endZcurrent_len�prefix�r$�/usr/lib/python3.6/ipv6.pyrs^	










rs(.*):(\d+\.\d+\.\d+\.\d+)$s::.*s.*::$c
Cs�t|t�s|j�}|dkrd}tj|�}|dk	rvttjj|j	d���}d|j	d�j
�|d|d|d|dfj�}tj|�}|dk	r�|dd�}ntj|�}|dk	r�|dd�}|j
d	�}t|�}|d
kr�tjj�d}g}x�|D]�}|dk�r.|�rtjj�d
}xftdd
|d�D]}|jd��qWq�t|�}	|	dk�rHtjj�|	dk�rbdd|	|}|j|�q�W|d
k�r�|�r�tjj�dj|�}y
tj|�Stjtfk
�r�tjj�YnXdS)z�Convert a text format IPv6 address into network format.

    @param text: the textual address
    @type text: string
    @rtype: string
    @raises dns.exception.SyntaxError: the text was not properly formatted
    s::s0::N�z%s:%02x%02x:%02x%02xrr�r
rF�Ts0000rr	r)�
isinstancer�encode�
_v4_endingr�	bytearrayrr�	inet_atonr�decode�_colon_colon_start�_colon_colon_end�splitrZ	exception�SyntaxErrorrrrrZ	unhexlify�Error�	TypeError)
�textr �brrZ
seen_emptyZ	canonical�crZlcr$r$r%r-bsR










r-��
s��cCs
|jt�S)N)�
startswith�_mapped_prefix)rr$r$r%�	is_mapped�sr<s
s��)�__doc__�rerZ
dns.exceptionrZdns.ipv4Z_compatrrr�compilerrr+r/r0r-r;r<r$r$r$r%�<module>s
C


G__pycache__/namedict.cpython-36.opt-1.pyc000064400000005447150351404330014135 0ustar003

�b�W]�@s6dZddlZddlZddlmZGdd�dej�ZdS)zDNS name dictionary�N�)�xrangec@sbeZdZdZdddgZdd�Zdd�Zd	d
�Zdd�Zd
d�Z	dd�Z
dd�Zdd�Zdd�Z
dS)�NameDictaA dictionary whose keys are dns.name.Name objects.
    @ivar max_depth: the maximum depth of the keys that have ever been
    added to the dictionary.
    @type max_depth: int
    @ivar max_depth_items: the number of items of maximum depth
    @type max_depth_items: int
    �	max_depth�max_depth_itemsZ__storecOs(t�|_d|_d|_|jt||��dS)Nr)�dict�_NameDict__storerr�update)�self�args�kwargs�r
�/usr/lib/python3.6/namedict.py�__init__-szNameDict.__init__cCs>t|�|jkr|jd|_nt|�|jkr:t|�|_d|_dS)Nr)�lenrr)r
�keyr
r
rZ__update_max_depth3s

zNameDict.__update_max_depthcCs
|j|S)N)r)r
rr
r
r�__getitem__:szNameDict.__getitem__cCs.t|tjj�std��||j|<|j|�dS)NzNameDict key must be a name)�
isinstance�dns�name�Name�
ValueErrorr�_NameDict__update_max_depth)r
r�valuer
r
r�__setitem__=s
zNameDict.__setitem__cCsT|jj|�}t|�|jkr&|jd|_|jdkrPd|_x|jD]}|j|�q>WdS)Nrr)r�poprrrr)r
rr�kr
r
r�__delitem__Cs
zNameDict.__delitem__cCs
t|j�S)N)�iterr)r
r
r
r�__iter__LszNameDict.__iter__cCs
t|j�S)N)rr)r
r
r
r�__len__OszNameDict.__len__cCs
||jkS)N)r)r
rr
r
r�has_keyRszNameDict.has_keycCsnt|�}||jkr|j}x<t|d�D],}tjj||d��}||kr&|||fSq&W|tjj}tjj|fS)aFind the deepest match to I{name} in the dictionary.

        The deepest match is the longest name in the dictionary which is
        a superdomain of I{name}.

        @param name: the name
        @type name: dns.name.Name object
        @rtype: (key, value) tuple
        rN)rrrrrr�empty)r
r�depth�i�n�vr
r
r�get_deepest_matchUs
zNameDict.get_deepest_matchN)�__name__�
__module__�__qualname__�__doc__�	__slots__rrrrrrr r!r'r
r
r
rr!s
	r)r+�collectionsZdns.namerZ_compatr�MutableMappingrr
r
r
r�<module>s__pycache__/ipv4.cpython-36.pyc000064400000002516150351404330012266 0ustar003

�b�W��@s4dZddlZddlZddlmZdd�Zdd�ZdS)	zIPv4 helper functions.�N�)�binary_typecCsJt|�dkrtjj�t|t�s&t|�}d|d|d|d|dfj�S)z�Convert an IPv4 address in network form to text form.

    @param address: The IPv4 address
    @type address: string
    @returns: string
    �z%u.%u.%u.%urr��)�len�dns�	exception�SyntaxError�
isinstance�	bytearray�encode)Zaddress�r�/usr/lib/python3.6/ipv4.py�	inet_ntoas
rc	Cs�t|t�s|j�}|jd�}t|�dkr0tjj�x<|D]4}|j�sJtjj�t|�dkr6|ddkr6tjj�q6Wydd�|D�}t	j
d
|��Stjj�YnXd	S)z�Convert an IPv4 address in text form to network form.

    @param text: The IPv4 address
    @type text: string
    @returns: string
    �.rrr�0cSsg|]}t|��qSr)�int)�.0�partrrr�
<listcomp>8szinet_aton.<locals>.<listcomp>�BBBBN)r)rrr
�splitrrr	r
�isdigit�struct�pack)�text�partsr�bytesrrr�	inet_aton%s


r)�__doc__rZ
dns.exceptionrZ_compatrrrrrrr�<module>s
__pycache__/exception.cpython-36.opt-1.pyc000064400000007161150351404330014342 0ustar003

d��W�@shdZGdd�de�ZGdd�de�ZGdd�de�ZGdd�de�ZGd	d
�d
e�ZGdd�de�Zd
S)zCommon DNS Exceptions.csReZdZdZdZe�ZdZ�fdd�Zdd�Z	dd�Z
d	d
�Z�fdd�Z�Z
S)
�DNSExceptiona�Abstract base class shared by all dnspython exceptions.

    It supports two basic modes of operation:

    a) Old/compatible mode is used if __init__ was called with
    empty **kwargs.
    In compatible mode all *args are passed to standard Python Exception class
    as before and all *args are printed by standard __str__ implementation.
    Class variable msg (or doc string if msg is None) is returned from str()
    if *args is empty.

    b) New/parametrized mode is used if __init__ was called with
    non-empty **kwargs.
    In the new mode *args has to be empty and all kwargs has to exactly match
    set in class variable self.supp_kwargs. All kwargs are stored inside
    self.kwargs and used in new __str__ implementation to construct
    formatted message based on self.fmt string.

    In the simplest case it is enough to override supp_kwargs and fmt
    class variables to get nice parametrized messages.
    Ncsp|j||�|r*|jf|�|_t|�|_nt�|_|jdkrD|j|_|rZtt|�j	|�ntt|�j	|j�dS)N)
�
_check_params�
_check_kwargs�kwargs�str�msg�dict�__doc__�superr�__init__)�self�argsr)�	__class__��/usr/lib/python3.6/exception.pyr
.s
zDNSException.__init__cOs|s|rdS)zsOld exceptions supported only args and not kwargs.

        For sanity we do not allow to mix old and new behavior.Nr)rrrrrrr=szDNSException._check_paramscKs|r|S)Nr)rrrrrrEszDNSException._check_kwargscKshi}x^|j�D]R\}}t|ttf�rXttt|��||<t||�dkr`||j�||<q|||<qW|S)z�Format kwargs before printing them.

        Resulting dictionary has to have keys necessary for str.format call
        on fmt class variable.
        �)�items�
isinstance�list�set�mapr�len�pop)rr�fmtargs�kw�datarrr�_fmt_kwargsLszDNSException._fmt_kwargscs:|jr(|jr(|jf|j�}|jjf|�Stt|�j�SdS)N)r�fmtr�formatr	r�__str__)rr)r
rrr^szDNSException.__str__)�__name__�
__module__�__qualname__rrr�supp_kwargsrr
rrrr�
__classcell__rr)r
rrsrc@seZdZdZdS)�	FormErrorzDNS message is malformed.N)rr r!rrrrrr$hsr$c@seZdZdZdS)�SyntaxErrorzText input is malformed.N)rr r!rrrrrr%msr%c@seZdZdZdS)�
UnexpectedEndzText input ended unexpectedly.N)rr r!rrrrrr&rsr&c@seZdZdZdS)�TooBigzThe DNS message is too big.N)rr r!rrrrrr'wsr'c@seZdZdZedg�ZdZdS)�TimeoutzThe DNS operation timed out.Ztimeoutz3The DNS operation timed out after {timeout} secondsN)rr r!rrr"rrrrrr(|s
r(N)r�	Exceptionrr$r%r&r'r(rrrr�<module>sU__pycache__/renderer.cpython-36.pyc000064400000023143150351404330013211 0ustar003

�b�W�.�@shdZddlmZddlZddlZddlZddlZddlZddl	m
Z
dZdZdZ
dZGdd	�d	e�ZdS)
z*Help for building DNS wire format messages�)�BytesION�)�long��c@steZdZdZddd�Zdd�Zd	d
�Zejj	fdd�Z
d
d�Zdd�Zddd�Z
ejjfdd�Zdd�Zdd�ZdS)�RendereraiHelper class for building DNS wire-format messages.

    Most applications can use the higher-level L{dns.message.Message}
    class and its to_wire() method to generate wire-format messages.
    This class is for those applications which need finer control
    over the generation of messages.

    Typical use::

        r = dns.renderer.Renderer(id=1, flags=0x80, max_size=512)
        r.add_question(qname, qtype, qclass)
        r.add_rrset(dns.renderer.ANSWER, rrset_1)
        r.add_rrset(dns.renderer.ANSWER, rrset_2)
        r.add_rrset(dns.renderer.AUTHORITY, ns_rrset)
        r.add_edns(0, 0, 4096)
        r.add_rrset(dns.renderer.ADDTIONAL, ad_rrset_1)
        r.add_rrset(dns.renderer.ADDTIONAL, ad_rrset_2)
        r.write_header()
        r.add_tsig(keyname, secret, 300, 1, 0, '', request_mac)
        wire = r.get_wire()

    @ivar output: where rendering is written
    @type output: BytesIO object
    @ivar id: the message id
    @type id: int
    @ivar flags: the message flags
    @type flags: int
    @ivar max_size: the maximum size of the message
    @type max_size: int
    @ivar origin: the origin to use when rendering relative names
    @type origin: dns.name.Name object
    @ivar compress: the compression table
    @type compress: dict
    @ivar section: the section currently being rendered
    @type section: int (dns.renderer.QUESTION, dns.renderer.ANSWER,
    dns.renderer.AUTHORITY, or dns.renderer.ADDITIONAL)
    @ivar counts: list of the number of RRs in each section
    @type counts: int list of length 4
    @ivar mac: the MAC of the rendered message (if TSIG was used)
    @type mac: string
    Nr�cCsht�|_|dkr tjdd�|_n||_||_||_||_i|_t	|_
ddddg|_|jjd�d|_
dS)a�Initialize a new renderer.

        @param id: the message id
        @type id: int
        @param flags: the DNS message flags
        @type flags: int
        @param max_size: the maximum message size; the default is 65535.
        If rendering results in a message greater than I{max_size},
        then L{dns.exception.TooBig} will be raised.
        @type max_size: int
        @param origin: the origin to use when rendering relative names
        @type origin: dns.name.Name or None.
        Nri�����s)r�output�randomZrandint�id�flags�max_size�origin�compress�QUESTION�section�counts�write�mac)�selfrrrr�r�/usr/lib/python3.6/renderer.py�__init__NszRenderer.__init__cCs^|jj|�|jj�g}x(|jj�D]\}}||kr&|j|�q&Wx|D]}|j|=qJWdS)z�Truncate the output buffer at offset I{where}, and remove any
        compression table entries that pointed beyond the truncation
        point.

        @param where: the offset
        @type where: int
        N)r�seek�truncater�items�append)r�whereZkeys_to_delete�k�vrrr�	_rollbackks	

zRenderer._rollbackcCs&|j|kr"|j|krtjj�||_dS)aZSet the renderer's current section.

        Sections must be rendered order: QUESTION, ANSWER, AUTHORITY,
        ADDITIONAL.  Sections may be empty.

        @param section: the section
        @type section: int
        @raises dns.exception.FormError: an attempt was made to set
        a section value less than the current section.
        N)r�dns�	exceptionZ	FormError)rrrrr�_set_section}s

zRenderer._set_sectioncCsz|jt�|jj�}|j|j|j|j�|jjtj	d||��|jj�}||j
krd|j|�tj
j�|jtd7<dS)aAdd a question to the message.

        @param qname: the question name
        @type qname: dns.name.Name
        @param rdtype: the question rdata type
        @type rdtype: int
        @param rdclass: the question rdata class
        @type rdclass: int
        z!HHrN)r&rr�tell�to_wirerrr�struct�packrr#r$r%�TooBigr)rZqnameZrdtypeZrdclass�before�afterrrr�add_question�s




zRenderer.add_questioncKsh|j|�|jj�}|j|j|j|jf|�}|jj�}||jkrR|j|�tj	j
�|j||7<dS)aAdd the rrset to the specified section.

        Any keyword arguments are passed on to the rdataset's to_wire()
        routine.

        @param section: the section
        @type section: int
        @param rrset: the rrset
        @type rrset: dns.rrset.RRset object
        N)r&rr'r(rrrr#r$r%r+r)rrZrrset�kwr,�nr-rrr�	add_rrset�s




zRenderer.add_rrsetcKsj|j|�|jj�}|j||j|j|jf|�}|jj�}||jkrT|j|�tj	j
�|j||7<dS)a�Add the rdataset to the specified section, using the specified
        name as the owner name.

        Any keyword arguments are passed on to the rdataset's to_wire()
        routine.

        @param section: the section
        @type section: int
        @param name: the owner name
        @type name: dns.name.Name object
        @param rdataset: the rdataset
        @type rdataset: dns.rdataset.Rdataset object
        N)r&rr'r(rrrr#r$r%r+r)rr�nameZrdatasetr/r,r0r-rrr�add_rdataset�s




zRenderer.add_rdatasetc
Cs�|td�M}||d>O}|jt�|jj�}|jjtjddtj	j
||d��|dk	�rJ|jj�}x�|D]�}tjd|jd�}|jj|�|jj�}	|j|j�|jj�}
|
|	dks�t
�|jj|	d�tjd	|
|	�}|jj|�|jjdd�qfW|jj�}||dk�st
�|jj|d�tjd	||�}|jj|�|jjdd�|jj�}||jk�rr|j|�tjj�|jtd
7<dS)a�Add an EDNS OPT record to the message.

        @param edns: The EDNS level to use.
        @type edns: int
        @param ednsflags: EDNS flag values.
        @type ednsflags: int
        @param payload: The EDNS sender's payload field, which is the maximum
        size of UDP datagram the sender can handle.
        @type payload: int
        @param options: The EDNS options list
        @type options: list of dns.edns.Option instances
        @see: RFC 2671
        l�~�z!BHHIHrNz!HHirz!Hr)rr&�
ADDITIONALrr'rr)r*r$�	rdatatype�OPTZotyper(�AssertionErrorrrr#r%r+r)
rZednsZ	ednsflagsZpayloadZoptionsr,Zlstart�optZstuff�start�endZlendr-rrr�add_edns�s<










zRenderer.add_ednsc	CsB|jt�|jj�}	|jj�}
tjj|
||tt	j	��||||||d�
\}|_
}|j|j|j|j
�|jjtjdtjjtjjdd��|jj�}
|jj|�|jj�}||
dks�t�||jkr�|j|	�tjj�|jj|
d�|jjtjd||
��|jtd7<|jjd�|jjtjd|jt��|jjdd�d	S)
a�Add a TSIG signature to the message.

        @param keyname: the TSIG key name
        @type keyname: dns.name.Name object
        @param secret: the secret to use
        @type secret: string
        @param fudge: TSIG time fudge
        @type fudge: int
        @param id: the message id to encode in the tsig signature
        @type id: int
        @param tsig_error: TSIG error code; default is 0.
        @type tsig_error: int
        @param other_data: TSIG other data.
        @type other_data: string
        @param request_mac: This message is a response to the request which
        had the specified MAC.
        @type request_mac: string
        @param algorithm: the TSIG algorithm to use
        @type algorithm: dns.name.Name object
        )�	algorithmz!HHIHrirz!Hr�
N)r&r5rr'�getvaluer$�tsigZsign�int�timerr(rrrr)r*r6ZTSIG�
rdataclass�ANYr8rr#r%r+rr)rZkeynameZsecretZfudgerZ
tsig_errorZ
other_dataZrequest_macr=r,�sZ
tsig_rdataZctxZrdata_startr-rrr�add_tsigs:







zRenderer.add_tsigc
CsX|jjd�|jjtjd|j|j|jd|jd|jd|jd��|jjdd�dS)z�Write the DNS message header.

        Writing the DNS message header is done after all sections
        have been rendered, but before the optional TSIG signature
        is added.
        rz!HHHHHHrrrN)rrrr)r*rrr)rrrr�write_header5s
zRenderer.write_headercCs
|jj�S)z@Return the wire format message.

        @rtype: string
        )rr?)rrrr�get_wireCszRenderer.get_wire)NrrN)N)�__name__�
__module__�__qualname__�__doc__rr#r&r$rC�INr.r1r3r<r@Zdefault_algorithmrFrGrHrrrrr"s*

04r)rL�iorr)r
rBZ
dns.exceptionr$Zdns.tsigZ_compatrrZANSWERZ	AUTHORITYr5�objectrrrrr�<module>s__pycache__/update.cpython-36.pyc000064400000015666150351404330012700 0ustar003

�b�W'�@s`dZddlZddlZddlZddlZddlZddlZddlZddl	m
Z
Gdd�dejj�Z
dS)zDNS Dynamic Update Support�N�)�string_typescsxeZdZejjddejjf�fdd�	Zddd�Z	dd�Z
dd	�Zd
d�Zdd
�Z
dd�Zddd�Zd�fdd�	Z�ZS)�UpdateNcs�tt|�j�|jtjjtjj�O_t|t	�r>tj
j|�}||_t|t	�rZtj
j|�}||_|j|j|j|tjjddd�|dk	r�|j|||d�dS)a�Initialize a new DNS Update object.

        @param zone: The zone which is being updated.
        @type zone: A dns.name.Name or string
        @param rdclass: The class of the zone; defaults to dns.rdataclass.IN.
        @type rdclass: An int designating the class, or a string whose value
        is the name of a class.
        @param keyring: The TSIG keyring to use; defaults to None.
        @type keyring: dict
        @param keyname: The name of the TSIG key to use; defaults to None.
        The key must be defined in the keyring.  If a keyring is specified
        but a keyname is not, then the key used will be the first key in the
        keyring.  Note that the order of keys in a dictionary is not defined,
        so applications should supply a keyname when a keyring is used, unless
        they know the keyring contains only one key.
        @type keyname: dns.name.Name or string
        @param keyalgorithm: The TSIG algorithm to use; defaults to
        dns.tsig.default_algorithm.  Constants for TSIG algorithms are defined
        in dns.tsig, and the currently implemented algorithms are
        HMAC_MD5, HMAC_SHA1, HMAC_SHA224, HMAC_SHA256, HMAC_SHA384, and
        HMAC_SHA512.
        @type keyalgorithm: string
        T)ZcreateZforce_uniqueN)�	algorithm)�superr�__init__�flags�dnsZopcodeZto_flagsZUPDATE�
isinstancer�name�	from_text�origin�
rdataclass�zone_rdclass�
find_rrsetZquestion�	rdatatypeZSOAZuse_tsig)�selfZzoneZrdclassZkeyringZkeynameZkeyalgorithm)�	__class__��/usr/lib/python3.6/update.pyrs


zUpdate.__init__c	CsB|dkr|j}|j�}|j|||j|j||dd�}|j||�dS)z&Add a single RR to the update section.NT)�	authority�coversrr�rdtype�add)rr�ttl�rdZdeleting�sectionrZrrsetrrr�_add_rrEszUpdate._add_rrc
Gs:t|t�rtjj|d�}t|dtjj�rnx@|D]8}|rF|j||j�x |D]}|j	||j
||d�qLWq0Wn�t|�}t|j
d��}t|dtjj�r�|r�|j||dj�x�|D]}|j	||||d�q�Wnh|j
d�}t|t�r�tjj|�}|r�|j||�x6|D].}	tjj|j||	|j�}|j	||||d��qWdS)a�Add records.  The first argument is the replace mode.  If
        false, RRs are added to an existing RRset; if true, the RRset
        is replaced with the specified contents.  The second
        argument is the section to add to.  The third argument
        is always a name.  The other arguments can be:

                - rdataset...

                - ttl, rdata...

                - ttl, rdtype, string...Nr)r)r
rr	rr�rdataset�Rdataset�deleterrr�list�int�pop�rdata�Rdatarrr
)
r�replacerr�args�rdsrrr�srrr�_addOs0






zUpdate._addcGs|jd|j|f|��dS)z�Add records.  The first argument is always a name.  The other
        arguments can be:

                - rdataset...

                - ttl, rdata...

                - ttl, rdtype, string...FN)r*r)rrr'rrrrws	z
Update.addc	Gsft|t�rtjj|d�}t|�dkrR|j|j|tjj	tj
j	tj
jtj
j	dd��nt|dtjj
�r�x�|D]&}x |D]}|j|d|tjj�qtWqjWn�t|�}t|dtjj�r�x�|D]}|j|d|tjj�q�Wn�|jd�}t|t�r�tj
j|�}t|�dk�r(|j|j||j|tj
jtjj	dd�n:x8|D]0}tjj|j|||j�}|j|d|tjj��q.WdS)z�Delete records.  The first argument is always a name.  The other
        arguments can be:

                - I{nothing}

                - rdataset...

                - rdata...

                - rdtype, [string...]NrT)r
rr	rr�lenrrr�ANYr�NONErrrr!r$r%r#rr
)rrr'r(rrr)rrrr �s6








z
Update.deletecGs|jd|j|f|��dS)aQReplace records.  The first argument is always a name.  The other
        arguments can be:

                - rdataset...

                - ttl, rdata...

                - ttl, rdtype, string...

        Note that if you want to replace the entire node, you should do
        a delete of the name followed by one or more calls to add.TN)r*r)rrr'rrrr&�s
zUpdate.replacec	Gs�t|t�rtjj|d�}t|�dkrL|j|j|tjj	tj
j	tj
jddd�n�t|dtjj
�s|t|dtjj�s|t|�dkr�t|dtjj
�s�t|�}|jdd�|jd|j|f|��n@|d}t|t�r�tj
j|�}|j|j|tjj	|tj
jddd�dS)aBRequire that an owner name (and optionally an rdata type,
        or specific rdataset) exists as a prerequisite to the
        execution of the update.  The first argument is always a name.
        The other arguments can be:

                - rdataset...

                - rdata...

                - rdtype, string...NrTrF)r
rr	rrr+r�answerrr,rr-rrr$r%r!�insertr*)rrr'rrrr�present�s*




zUpdate.presentc	Cs�t|t�rtjj|d�}|dkrH|j|j|tjjtj	j
tj	jddd�n8t|t�r^tj	j|�}|j|j|tjj|tj	jddd�dS)z�Require that an owner name (and optionally an rdata type) does
        not exist as a prerequisite to the execution of the update.NT)r
rr	rrrr.rr-rr,)rrrrrr�absent�s




z
Update.absent�cs |dkr|j}tt|�j||�S)zcReturn a string containing the update in DNS compressed wire
        format.
        @rtype: stringN)r
rr�to_wire)rr
Zmax_size)rrrr3�szUpdate.to_wire)NN)N)Nr2)�__name__�
__module__�__qualname__r	r�INZtsigZdefault_algorithmrrr*rr r&r0r1r3�
__classcell__rr)rrrs%

(+$
r)�__doc__Zdns.messager	Zdns.nameZ
dns.opcodeZ	dns.rdataZdns.rdataclassZdns.rdatasetZdns.tsigZ_compatr�messageZMessagerrrrr�<module>s__pycache__/tsigkeyring.cpython-36.opt-1.pyc000064400000002037150351404330014700 0ustar003

�b�W��@s8dZddlmZmZddlZddlZdd�Zdd�ZdS)zA place to store TSIG keys.�)�maybe_decode�maybe_encodeNcCs<i}x2|D]*}tjj|�}tjt||��}|||<q
W|S)z�Convert a dictionary containing (textual DNS name, base64 secret) pairs
    into a binary keyring which has (dns.name.Name, binary secret) pairs.
    @rtype: dict)�dns�name�	from_text�base64Zdecodestringr)�textring�keyring�keytext�keyname�secret�r
�!/usr/lib/python3.6/tsigkeyring.pyrs
rcCs<i}x2|D]*}t|j��}ttj||��}|||<q
W|S)z�Convert a dictionary containing (dns.name.Name, binary secret) pairs
    into a text keyring which has (textual DNS name, base64 secret) pairs.
    @rtype: dict)r�to_textrZencodestring)r	rrr
rr
r
rr&s
r)	�__doc__Zdns._compatrrrZdns.namerrrr
r
r
r�<module>s

__pycache__/version.cpython-36.opt-1.pyc000064400000000702150351404330014023 0ustar003

�b�W��@s�dZdZdZdZdZdZedkr0deeefZn,edkrJdeeeefZndeeeeefZed>ed>Bed	>Bed
>BeBZdS)z&dnspython release version information.���z%d.%d.%dz%d.%d.%dx%dz%d.%d.%d%x%d����N)�__doc__ZMAJORZMINORZMICROZRELEASELEVELZSERIAL�version�
hexversion�rr�/usr/lib/python3.6/version.py�<module>s__pycache__/zone.cpython-36.opt-1.pyc000064400000072671150351404330013327 0ustar003

ӕ�WZ��@sNdZddlmZddlZddlZddlZddlmZddlZ	ddl
Z	ddlZ	ddlZ	ddl
Z	ddlZ	ddlZ	ddlZ	ddlZ	ddlZ	ddlmZmZejdkZGdd	�d	e	jj�ZGd
d�de�ZGdd
�d
e�ZGdd�de�ZGdd�de�ZGdd�de�Z de	j!j"dedddfdd�Z#de	j!j"dedddfdd�Z$eddfdd�Z%dS)z
DNS Zones.�)�
generatorsN)�BytesIO�)�string_types�	text_type�c@seZdZdZdS)�BadZonezThe DNS zone is malformed.N)�__name__�
__module__�__qualname__�__doc__�r
r
�/usr/lib/python3.6/zone.pyr)src@seZdZdZdS)�NoSOAz)The DNS zone has no SOA RR at its origin.N)r	r
rrr
r
r
rr.src@seZdZdZdS)�NoNSz+The DNS zone has no NS RRset at its origin.N)r	r
rrr
r
r
rr3src@seZdZdZdS)�
UnknownOriginz!The DNS zone's origin is unknown.N)r	r
rrr
r
r
rr8src@sjeZdZdZejjZddddgZej	j
dfdd�Zd	d
�Zdd�Z
d
d�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd �ZeZd!d"�Zd#d$�ZdCd&d'�ZdDd(d)�Zd*d+�Zejjd%fd,d-�Z ejjd%fd.d/�Z!ejjfd0d1�Z"d2d3�Z#ejjfd4d5�Z$ejjfd6d7�Z%ejj&ejjfd8d9�Z'ejj&ejjfd:d;�Z(dEd=d>�Z)dFd?d@�Z*dAdB�Z+d<S)G�ZoneaZA DNS zone.

    A Zone is a mapping from names to nodes.  The zone object may be
    treated like a Python dictionary, e.g. zone[name] will retrieve
    the node associated with that name.  The I{name} may be a
    dns.name.Name object, or it may be a string.  In the either case,
    if the name is relative it is treated as relative to the origin of
    the zone.

    @ivar rdclass: The zone's rdata class; the default is class IN.
    @type rdclass: int
    @ivar origin: The origin of the zone.
    @type origin: dns.name.Name object
    @ivar nodes: A dictionary mapping the names of nodes in the zone to the
    nodes themselves.
    @type nodes: dict
    @ivar relativize: should names in the zone be relativized?
    @type relativize: bool
    @cvar node_factory: the factory used to create a new node
    @type node_factory: class or callable
    �rdclass�origin�nodes�
relativizeTcCsb|dk	rFt|t�r tjj|�}nt|tjj�s6td��|j�sFtd��||_||_	i|_
||_dS)z�Initialize a zone object.

        @param origin: The origin of the zone.
        @type origin: dns.name.Name object
        @param rdclass: The zone's rdata class; the default is class IN.
        @type rdclass: intNz2origin parameter must be convertible to a DNS namez)origin parameter must be an absolute name)�
isinstancer�dns�name�	from_text�Name�
ValueError�is_absoluterrrr)�selfrrrr
r
r�__init__Ys
z
Zone.__init__cCs:t|t�sdS|j|jks2|j|jks2|j|jkr6dSdS)ziTwo zones are equal if they have the same origin, class, and
        nodes.
        @rtype: bool
        FT)rrrrr)r�otherr
r
r�__eq__ns
zZone.__eq__cCs|j|�S)z6Are two zones not equal?
        @rtype: bool
        )r!)rr r
r
r�__ne__|szZone.__ne__cCsbt|t�rtjj|d�}nt|tjj�s0td��|j�r^|j|j	�sLtd��|j
r^|j
|j	�}|S)Nz0name parameter must be convertible to a DNS namez5name parameter must be a subdomain of the zone origin)rrrrrr�KeyErrorr�is_subdomainrr)rrr
r
r�_validate_name�s
zZone._validate_namecCs|j|�}|j|S)N)r%r)r�keyr
r
r�__getitem__�s
zZone.__getitem__cCs|j|�}||j|<dS)N)r%r)rr&�valuer
r
r�__setitem__�s
zZone.__setitem__cCs|j|�}|j|=dS)N)r%r)rr&r
r
r�__delitem__�s
zZone.__delitem__cCs
|jj�S)N)r�__iter__)rr
r
rr+�sz
Zone.__iter__cCstr|jj�S|jj�SdS)N)�_py3r�keys�iterkeys)rr
r
rr.�s
z
Zone.iterkeyscCs
|jj�S)N)rr-)rr
r
rr-�sz	Zone.keyscCstr|jj�S|jj�SdS)N)r,r�values�
itervalues)rr
r
rr0�s
zZone.itervaluescCs
|jj�S)N)rr/)rr
r
rr/�szZone.valuescCs
|jj�S)N)r�items)rr
r
rr1�sz
Zone.itemscCs|j|�}|jj|�S)N)r%r�get)rr&r
r
rr2�s
zZone.getcCs
||jkS)N)r)rr r
r
r�__contains__�szZone.__contains__FcCs<|j|�}|jj|�}|dkr8|s&t�|j�}||j|<|S)arFind a node in the zone, possibly creating it.

        @param name: the name of the node to find
        @type name: dns.name.Name object or string
        @param create: should the node be created if it doesn't exist?
        @type create: bool
        @raises KeyError: the name is not known and create was not specified.
        @rtype: dns.node.Node object
        N)r%rr2r#�node_factory)rr�create�noder
r
r�	find_node�s

zZone.find_nodecCs.y|j||�}Wntk
r(d}YnX|S)a�Get a node in the zone, possibly creating it.

        This method is like L{find_node}, except it returns None instead
        of raising an exception if the node does not exist and creation
        has not been requested.

        @param name: the name of the node to find
        @type name: dns.name.Name object or string
        @param create: should the node be created if it doesn't exist?
        @type create: bool
        @rtype: dns.node.Node object or None
        N)r7r#)rrr5r6r
r
r�get_node�s

z
Zone.get_nodecCs |j|�}||jkr|j|=dS)zhDelete the specified node if it exists.

        It is not an error if the node does not exist.
        N)r%r)rrr
r
r�delete_node�s

zZone.delete_nodecCsT|j|�}t|t�r tjj|�}t|t�r6tjj|�}|j||�}|j|j|||�S)a�Look for rdata with the specified name and type in the zone,
        and return an rdataset encapsulating it.

        The I{name}, I{rdtype}, and I{covers} parameters may be
        strings, in which case they will be converted to their proper
        type.

        The rdataset returned is not a copy; changes to it will change
        the zone.

        KeyError is raised if the name or type are not found.
        Use L{get_rdataset} if you want to have None returned instead.

        @param name: the owner name to look for
        @type name: DNS.name.Name object or string
        @param rdtype: the rdata type desired
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        @param create: should the node and rdataset be created if they do not
        exist?
        @type create: bool
        @raises KeyError: the node or rdata could not be found
        @rtype: dns.rrset.RRset object
        )	r%rrr�	rdatatyperr7�
find_rdatasetr)rr�rdtype�coversr5r6r
r
rr;�s


zZone.find_rdatasetcCs2y|j||||�}Wntk
r,d}YnX|S)a�Look for rdata with the specified name and type in the zone,
        and return an rdataset encapsulating it.

        The I{name}, I{rdtype}, and I{covers} parameters may be
        strings, in which case they will be converted to their proper
        type.

        The rdataset returned is not a copy; changes to it will change
        the zone.

        None is returned if the name or type are not found.
        Use L{find_rdataset} if you want to have KeyError raised instead.

        @param name: the owner name to look for
        @type name: DNS.name.Name object or string
        @param rdtype: the rdata type desired
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        @param create: should the node and rdataset be created if they do not
        exist?
        @type create: bool
        @rtype: dns.rrset.RRset object
        N)r;r#)rrr<r=r5�rdatasetr
r
r�get_rdatasets

zZone.get_rdatasetcCsr|j|�}t|t�r tjj|�}t|t�r6tjj|�}|j|�}|dk	rn|j|j||�t	|�dkrn|j
|�dS)a�Delete the rdataset matching I{rdtype} and I{covers}, if it
        exists at the node specified by I{name}.

        The I{name}, I{rdtype}, and I{covers} parameters may be
        strings, in which case they will be converted to their proper
        type.

        It is not an error if the node does not exist, or if there is no
        matching rdataset at the node.

        If the node has no rdatasets after the deletion, it will itself
        be deleted.

        @param name: the owner name to look for
        @type name: DNS.name.Name object or string
        @param rdtype: the rdata type desired
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        Nr)r%rrrr:rr8�delete_rdatasetr�lenr9)rrr<r=r6r
r
rr@4s



zZone.delete_rdatasetcCs.|j|jkrtd��|j|d�}|j|�dS)a:Replace an rdataset at name.

        It is not an error if there is no rdataset matching I{replacement}.

        Ownership of the I{replacement} object is transferred to the zone;
        in other words, this method does not store a copy of I{replacement}
        at the node, it stores I{replacement} itself.

        If the I{name} node does not exist, it is created.

        @param name: the owner name
        @type name: DNS.name.Name object or string
        @param replacement: the replacement rdataset
        @type replacement: dns.rdataset.Rdataset
        z#replacement.rdclass != zone.rdclassTN)rrr7�replace_rdataset)rrZreplacementr6r
r
rrBUszZone.replace_rdatasetcCsn|j|�}t|t�r tjj|�}t|t�r6tjj|�}|j|j|j||�}tj	j
||j||�}|j|�|S)a�Look for rdata with the specified name and type in the zone,
        and return an RRset encapsulating it.

        The I{name}, I{rdtype}, and I{covers} parameters may be
        strings, in which case they will be converted to their proper
        type.

        This method is less efficient than the similar
        L{find_rdataset} because it creates an RRset instead of
        returning the matching rdataset.  It may be more convenient
        for some uses since it returns an object which binds the owner
        name to the rdata.

        This method may not be used to create new nodes or rdatasets;
        use L{find_rdataset} instead.

        KeyError is raised if the name or type are not found.
        Use L{get_rrset} if you want to have None returned instead.

        @param name: the owner name to look for
        @type name: DNS.name.Name object or string
        @param rdtype: the rdata type desired
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        @raises KeyError: the node or rdata could not be found
        @rtype: dns.rrset.RRset object
        )r%rrrr:rrr;r�rrsetZRRset�update)rrr<r=r>rCr
r
r�
find_rrsetks



zZone.find_rrsetcCs0y|j|||�}Wntk
r*d}YnX|S)aJLook for rdata with the specified name and type in the zone,
        and return an RRset encapsulating it.

        The I{name}, I{rdtype}, and I{covers} parameters may be
        strings, in which case they will be converted to their proper
        type.

        This method is less efficient than the similar L{get_rdataset}
        because it creates an RRset instead of returning the matching
        rdataset.  It may be more convenient for some uses since it
        returns an object which binds the owner name to the rdata.

        This method may not be used to create new nodes or rdatasets;
        use L{find_rdataset} instead.

        None is returned if the name or type are not found.
        Use L{find_rrset} if you want to have KeyError raised instead.

        @param name: the owner name to look for
        @type name: DNS.name.Name object or string
        @param rdtype: the rdata type desired
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        @rtype: dns.rrset.RRset object
        N)rEr#)rrr<r=rCr
r
r�	get_rrset�s

zZone.get_rrsetccs~t|t�rtjj|�}t|t�r,tjj|�}xL|j�D]@\}}x6|D].}|tjjksh|j|krD|j|krD||fVqDWq6WdS)a�Return a generator which yields (name, rdataset) tuples for
        all rdatasets in the zone which have the specified I{rdtype}
        and I{covers}.  If I{rdtype} is dns.rdatatype.ANY, the default,
        then all rdatasets will be matched.

        @param rdtype: int or string
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        N)	rrrr:r�	iteritems�ANYr<r=)rr<r=rr6�rdsr
r
r�iterate_rdatasets�s


zZone.iterate_rdatasetsccs�t|t�rtjj|�}t|t�r,tjj|�}x^|j�D]R\}}xH|D]@}|tjjksh|j|krD|j|krDx|D]}||j	|fVqnWqDWq6WdS)a�Return a generator which yields (name, ttl, rdata) tuples for
        all rdatas in the zone which have the specified I{rdtype}
        and I{covers}.  If I{rdtype} is dns.rdatatype.ANY, the default,
        then all rdatas will be matched.

        @param rdtype: int or string
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        N)
rrrr:rrGrHr<r=�ttl)rr<r=rr6rI�rdatar
r
r�iterate_rdatas�s



zZone.iterate_rdatasNcCs8t|t�rt|d�}d}nd}t|dd�}|dkr6d}|dkrPtjj|�}d}n"t|t�rf|j|�}n|}|j�}z�|r�t|j	��}|j
�n|j�}x�|D]�}	||	j|	|j
|d�}
t|
t�r�|
j|�}n|
}|
j�}
y|j|�|j|�Wq�tk
�r|j|
�|j|�Yq�Xq�WWd|�r2|j�XdS)	aWrite a zone to a file.

        @param f: file or string.  If I{f} is a string, it is treated
        as the name of a file to open.
        @param sorted: if True, the file will be written with the
        names sorted in DNSSEC order from least to greatest.  Otherwise
        the names will be written in whatever order they happen to have
        in the zone's dictionary.
        @param relativize: if True, domain names in the output will be
        relativized to the zone's origin (if possible).
        @type relativize: bool
        @param nl: The end of line string.  If not specified, the
        output will use the platform's native end-of-line marker (i.e.
        LF on POSIX, CRLF on Windows, CR on Macintosh).
        @type nl: string or None
        �wbTF�encodingNzutf-8�
)rr)rr�open�getattr�os�linesep�encode�decode�listr-�sortr.�to_textrr�write�	TypeError�close)r�f�sortedr�nl�
want_closeZfile_encZnl_b�names�n�lZl_br
r
r�to_file�sD







zZone.to_filecCs*t�}|j||||�|j�}|j�|S)a�Return a zone's text as though it were written to a file.

        @param sorted: if True, the file will be written with the
        names sorted in DNSSEC order from least to greatest.  Otherwise
        the names will be written in whatever order they happen to have
        in the zone's dictionary.
        @param relativize: if True, domain names in the output will be
        relativized to the zone's origin (if possible).
        @type relativize: bool
        @param nl: The end of line string.  If not specified, the
        output will use the platform's native end-of-line marker (i.e.
        LF on POSIX, CRLF on Windows, CR on Macintosh).
        @type nl: string or None
        )rrd�getvaluer\)rr^rr_Ztemp_bufferZreturn_valuer
r
rrY$s
zZone.to_textcCsJ|jrtjj}n|j}|j|tjj�dkr.t�|j|tjj	�dkrFt
�dS)z�Do some simple checking of the zone's origin.

        @raises dns.zone.NoSOA: there is no SOA RR
        @raises dns.zone.NoNS: there is no NS RRset
        @raises KeyError: there is no origin node
        N)rrr�emptyrr?r:ZSOArZNSr)rrr
r
r�check_origin9s
zZone.check_origin)F)F)TTN)TTN),r	r
rrrr6ZNoder4�	__slots__�
rdataclass�INrr!r"r%r'r)r*r+r.r-r0r/r1rGr2r3r7r8r9r:ZNONEr;r?r@rBrErFrHrJrMrdrYrgr
r
r
rr=sJ



# !("
@
rc@sHeZdZdZeddfdd�Zdd�Zdd	�Zd
d�Zdd
�Z	dd�Z
dS)�
_MasterReadera�Read a DNS master file

    @ivar tok: The tokenizer
    @type tok: dns.tokenizer.Tokenizer object
    @ivar ttl: The default TTL
    @type ttl: int
    @ivar last_name: The last name read
    @type last_name: dns.name.Name object
    @ivar current_origin: The current origin
    @type current_origin: dns.name.Name object
    @ivar relativize: should names in the zone be relativized?
    @type relativize: bool
    @ivar zone: the zone
    @type zone: dns.zone.Zone object
    @ivar saved_state: saved reader state (used when processing $INCLUDE)
    @type saved_state: list of (tokenizer, current_origin, last_name, file)
    tuples.
    @ivar current_file: the file object of the $INCLUDed file being parsed
    (None if no $INCLUDE is active).
    @ivar allow_include: is $INCLUDE allowed?
    @type allow_include: bool
    @ivar check_origin: should sanity checks of the origin node be done?
    The default is True.
    @type check_origin: bool
    FTcCsbt|t�rtjj|�}||_||_||_d|_|j|_	||||d�|_
g|_d|_||_
||_dS)Nr)r)rrrrr�tok�current_originrrK�	last_name�zone�saved_state�current_file�
allow_includerg)rrlrrr�zone_factoryrrrgr
r
rrfs
z_MasterReader.__init__cCsx|jj�}|j�rPqWdS)N)rlr2�
is_eol_or_eof)r�tokenr
r
r�	_eat_lineus
z_MasterReader._eat_linec"Cs�|jdkrt�|jjdd�}|j�s:tjj|j|j�|_	n"|jj�}|j
�rPdS|jj|�|j	}|j|j
j�s||j�dS|jr�|j|j
j�}|jj�}|j�s�tjj�y,tjj|j�}|jj�}|j�s�tjj�Wntjjk
r�|j}YnXy.tjj|j�}|jj�}|j��s"tjj�Wn>tjjk
�rFtjj�Yntk
�rb|j
j}YnX||j
jk�r~tjjd��ytjj|j�}Wntjjd|j��YnX|j
jj|�}|dk�r�|j
j�}||j
j|<ytjj|||j|jd�}Wnltjjk
�r,tj�dd�\}}	|	�Yn<tj�dd�\}}	tjjdt|�t|	�f��YnX|j |j
j|j�|j!�}
|j"|||
d�}|j#||�dS)	z(Process one line from a DNS master file.NT)Zwant_leadingzRR class is not zone's classzunknown rdatatype '%s'F�zcaught exception %s: %s)$rmrrlr2Z
is_whitespacerrrr(rnrt�ungetr$rorrvr�
is_identifier�	exception�SyntaxErrorrK�BadTTLri�	Exceptionrr:rr4rL�sys�exc_info�str�choose_relativityr=r;�add)rrurrKrr<rb�rd�ty�var=rIr
r
r�_rr_line{sx







z_MasterReader._rr_linec
Cs�tjd�}tjd�}tjd�}|j|�}|rJ|j�\}}}}	}
|dkrJd}|j|�}|rz|j�\}}}|dkrrd}d}	d}
|j|�}|r�|j�\}}}}	|dkr�d}|j�d}	d}
|p�|p�|s�d}d}d}d}	d}
|
dkr�t��||||	|
fS)	Nz"^.*\$({(\+|-?)(\d+),(\d+),(.)}).*$z^.*\$({(\+|-?)(\d+)}).*$z^.*\$({(\+|-?)(\d+),(\d+)}).*$��+r�drw)�re�compile�match�groups�NotImplementedError)
rZsideZis_generate1Zis_generate2Zis_generate3Zg1�modZsign�offset�width�baseZg2Zg3r
r
r�
_parse_modify�s>





z_MasterReader._parse_modifyc!7Cs|jdkrt�|jj�}y2tjj|j�\}}}|jj�}|j�sHtj	j
�Wntj	j
�YnXy$|j}|jj�}|j�s�tj	j
�Wntj	j
�YnXy,tjj|j�}|jj�}|j�s�tj	j
�Wntjjk
r�|j}YnXy.tj
j|j�}|jj�}|j��stj	j
�Wn>tj	j
k
�r6tj	j
�Yntk
�rR|jj}YnX||jjk�rntj	j
d��y.tjj|j�}|jj�}|j��s�tj	j
�Wn(tk
�r�tj	j
d|j��YnXy
|j}	Wntj	j
�YnX|j|�\}
}}}
}|j|	�\}}}}}�x�t||d|�D�]�}|dk�r@|t|�}n|dk�rV|t|�}|dk�rn|t|�}n|dk�r�|t|�}t|�jt|
��}t|�jt|��}|jd|
|�}|	jd||�}tjj||j�|_|j}|j|jj��s�|j�dS|j�r|j|jj�}|jjj|�}|dk�r@|jj�}||jj|<ytj j||||jd�}Wnltj	j
k
�r�t!j"�dd	�\}}|�Yn<t!j"�dd	�\}}tj	j
d
t|�t|�f��YnX|j#|jj|j�|j$�}|j%|||d�} | j&||��q"WdS)zRProcess one line containing the GENERATE statement from a DNS
        master file.NzRR class is not zone's classzunknown rdatatype '%s'rr��-z$%sFrwzcaught exception %s: %sT)'rmrrlr2rZgrangerr(ryrzr{rKr|rir}rorr:r��range�intr��zfill�replacerrnr$rrvrrr4rLr~rr�r=r;r�)!rru�start�stop�stepZlhsrKrr<ZrhsZlmodZlsignZloffsetZlwidthZlbaseZrmodZrsignZroffsetZrwidthZrbase�iZlindex�rindexZlzfindexZrzfindexrrLrbr�r�r�r=rIr
r
r�_generate_line�s�















z_MasterReader._generate_linecCs��y�x|jjdd�}|j�rh|jdk	r2|jj�t|j�dkrb|jjd�\|_|_|_	|_|_
qP�n�|j�rvq�n�|j�r�|jj
�q�nx|jddk�r|jj�}|dkr�|jj�}|j�s�tjjd��tj
j|j�|_
|jj
�q|dk�r$|jj�|_|jj
�|jjdk�r|j|j_q|d	k�r�|j�r�|jj�}|j}|jj�}|j��rxtjj|j|j�}|jj
�n|j��s�tjjd
��n|j}|jj|j|j|j	|j|j
f�t|d�|_tjj|j|�|_||_q|dk�r�|j�qtjjd
|d��q|jj |�|j!�qWWnZtjjk
�rz}z8|jj"�\}}|dk�rTd}tjjd|||f��WYdd}~XnX|j#�r�|jj#�dS)z�Read a DNS master file and build a zone object.

        @raises dns.zone.NoSOA: No SOA RR was found at the zone origin
        @raises dns.zone.NoNS: No NS RRset was found at the zone origin
        TNrr�$z$TTLzbad $TTLz$ORIGINz$INCLUDEzbad origin in $INCLUDE�rz	$GENERATEzUnknown master file directive '�'zsyntax errorz	%s:%d: %s���)$rlr2Zis_eofrqr\rArp�poprmrnrKZis_eolZ
is_commentZget_eolr(�upperryrrzr{rZget_namerorrrrrt�appendrQ�	tokenizer�	Tokenizerr�rxr��whererg)rru�c�filenameZ
new_originZdetailZline_numberr
r
r�reades�

 















"z_MasterReader.readN)r	r
rrrrrvr�r�r�r�r
r
r
rrkJsL)urkTFc
	Cs>|dkrd}tjj||�}t|||||||d�}	|	j�|	jS)arBuild a zone object from a master file format string.

    @param text: the master file format input
    @type text: string.
    @param origin: The origin of the zone; if not specified, the first
    $ORIGIN statement in the master file will determine the origin of the
    zone.
    @type origin: dns.name.Name object or string
    @param rdclass: The zone's rdata class; the default is class IN.
    @type rdclass: int
    @param relativize: should names be relativized?  The default is True
    @type relativize: bool
    @param zone_factory: The zone factory to use
    @type zone_factory: function returning a Zone
    @param filename: The filename to emit when describing where an error
    occurred; the default is '<string>'.
    @type filename: string
    @param allow_include: is $INCLUDE allowed?
    @type allow_include: bool
    @param check_origin: should sanity checks of the origin node be done?
    The default is True.
    @type check_origin: bool
    @raises dns.zone.NoSOA: No SOA RR was found at the zone origin
    @raises dns.zone.NoNS: No NS RRset was found at the zone origin
    @rtype: dns.zone.Zone object
    Nz<string>)rrrg)rr�r�rkr�ro)
�textrrrrsr�rrrgrl�readerr
r
rr�s"rcCslt}d}	t||�r.|dkr|}t||	�}d}
n|dkr:d}d}
zt||||||||�}Wd|
rf|j�X|S)a�Read a master file and build a zone object.

    @param f: file or string.  If I{f} is a string, it is treated
    as the name of a file to open.
    @param origin: The origin of the zone; if not specified, the first
    $ORIGIN statement in the master file will determine the origin of the
    zone.
    @type origin: dns.name.Name object or string
    @param rdclass: The zone's rdata class; the default is class IN.
    @type rdclass: int
    @param relativize: should names be relativized?  The default is True
    @type relativize: bool
    @param zone_factory: The zone factory to use
    @type zone_factory: function returning a Zone
    @param filename: The filename to emit when describing where an error
    occurred; the default is '<file>', or the value of I{f} if I{f} is a
    string.
    @type filename: string
    @param allow_include: is $INCLUDE allowed?
    @type allow_include: bool
    @param check_origin: should sanity checks of the origin node be done?
    The default is True.
    @type check_origin: bool
    @raises dns.zone.NoSOA: No SOA RR was found at the zone origin
    @raises dns.zone.NoNS: No NS RRset was found at the zone origin
    @rtype: dns.zone.Zone object
    ZrUNTz<file>F)rrrQrr\)r]rrrrsr�rrrgZstr_typeZoptsr`�zr
r
r�	from_file�s 


r�cCs�d}x�|D]�}|dkrH|r"|j}n|jdj}|jdj}||||d�}x||jD]r}|jj|j�}	|	sz|j�}	|	|j|j<|	j|j|j|j	d�}
|
j
|j�x$|D]}|j|j|�|
j
|�q�WqPWq
W|r�|j�|S)a�Convert the output of a zone transfer generator into a zone object.

    @param xfr: The xfr generator
    @type xfr: generator of dns.message.Message objects
    @param relativize: should names be relativized?  The default is True.
    It is essential that the relativize setting matches the one specified
    to dns.query.xfr().
    @type relativize: bool
    @param check_origin: should sanity checks of the origin node be done?
    The default is True.
    @type check_origin: bool
    @raises dns.zone.NoSOA: No SOA RR was found at the zone origin
    @raises dns.zone.NoNS: No NS RRset was found at the zone origin
    @rtype: dns.zone.Zone object
    Nr)rT)rZanswerrrrr2r4r;r<r=Z
update_ttlrKr�r�rg)Zxfrrsrrgr�r�rrrCZznodeZzrdsr�r
r
r�from_xfrs,


r�)r)&rZ
__future__rr~r�rS�iorZ
dns.exceptionrZdns.nameZdns.nodeZdns.rdataclassZ
dns.rdatatypeZ	dns.rdataZ	dns.rrsetZ
dns.tokenizerZdns.ttlZ
dns.grangeZ_compatrr�version_infor,rzZDNSExceptionrrrr�objectrrkrirjrr�r�r
r
r
r�<module>sH
o*3__pycache__/query.cpython-36.opt-1.pyc000064400000032664150351404330013517 0ustar003

�Of�L�@s�dZddlmZddlZddlZddlZddlZddlZddlZddl	Z
ddlZ
ddlZ
ddl
Z
ddlZ
ddlZ
ddlmZmZejd/kr�eZnejZejZGdd�de
jj�ZGd	d
�d
e
jj�Zdd�Zd
d�Zdd�Zdd�Z dd�Z!e"ed�r�ea#nea#dd�Z$dd�Z%dd�Z&dd�Z'dd�Z(d0d"d#�Z)d$d%�Z*d&d'�Z+d(d)�Z,d1d*d+�Z-e
j.j/e
j0j1dd ddd,dddddd!e
j2j3fd-d.�Z4dS)2zTalk to a DNS server.�)�
generatorsN�)�long�string_types�c@seZdZdZdS)�UnexpectedSourcez=A DNS query response came from an unexpected address or port.N)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/query.pyr,src@seZdZdZdS)�BadResponsez<A DNS query response does not respond to the question asked.N)rr	r
rrrrr
r1srcCs|dkrdStj�|SdS)N)�time)�timeoutrrr
�_compute_expiration6srcCsjd}|r|tjO}|r |tjO}|r.|tjO}tj�}|j||�|rZ|jt|d��}n|j�}t|�S)aqPoll polling backend.
    @param fd: File descriptor
    @type fd: int
    @param readable: Whether to wait for readability
    @type readable: bool
    @param writable: Whether to wait for writability
    @type writable: bool
    @param timeout: Deadline timeout (expiration time, in seconds)
    @type timeout: float
    @return True on success, False on timeout
    ri�)�selectZPOLLINZPOLLOUTZPOLLERR�poll�registerr�bool)�fd�readable�writable�errorrZ
event_maskZpollableZ
event_listrrr
�	_poll_for=s


rcCsrggg}}}|r|g}|r$|g}|r.|g}|dkrLtj|||�\}}	}
ntj||||�\}}	}
t|pn|	pn|
�S)asSelect polling backend.
    @param fd: File descriptor
    @type fd: int
    @param readable: Whether to wait for readability
    @type readable: bool
    @param writable: Whether to wait for writability
    @type writable: bool
    @param timeout: Deadline timeout (expiration time, in seconds)
    @type timeout: float
    @return True on success, False on timeout
    N)rr)rrrrrZrsetZwsetZxsetZrcountZwcountZxcountrrr
�_select_for\srcCs�d}x�|s�|dkrd}n|tj�}|dkr4tjj�yt|||||�sNtjj�Wn6tk
r�}z|jdtjkrv|�WYdd}~XnXd}qWdS)NFgrT)	r�dns�	exceptionZTimeout�_polling_backend�select_error�args�errnoZEINTR)rrrr�
expiration�doner�errr
�	_wait_forysr%cCs|adS)z#
    Internal API. Do not use.
    N)r)�fnrrr
�_set_polling_backend�sr'rcCst|ddd|�dS)NTF)r%)�sr"rrr
�_wait_for_readable�sr)cCst|ddd|�dS)NFT)r%)r(r"rrr
�_wait_for_writable�sr*cCsDtjj||d�}tjj||d�}||koB|dd�|dd�kS)Nrr)r�inetZ	inet_pton)�afZa1Za2Zn1Zn2rrr
�_addresses_equal�sr-cCs`|sdSt|||�s<tjj|d�r@|dd�|dd�kr@dS|rHdStd|�d|����dS)NTrrFzgot a response from z instead of )r-rr+Zis_multicastr)r,�from_address�destination�ignore_unexpectedrrr
�_matches_destination�s(r1cCs�|dkr6ytjj|�}Wntk
r4tjj}YnX|tjjkrp||f}|dk	sZ|dkr�|dkrfd}||f}n@|tjjkr�||ddf}|dk	s�|dkr�|dkr�d}||ddf}|||fS)Nrz0.0.0.0z::)rr+Zaf_for_address�	ExceptionZAF_INETZAF_INET6)r,�where�port�source�source_portr/rrr
�_destination_and_source�s$
r7�5Fc
Cs"|j�}
t|||||�\}}}t|tjd�}d}
z�t|�}|jd�|dk	rV|j|�t||�t	j	�}
|j
|
|�x�t||�|jd�\}
}t
|j|||�s�qvt	j	�|
}y"tjj|
|j|j|d�}||_	Wntk
r�|	r�wvn�YnX|j|��r�|S|	�rqvqvt�qvWWd|j�XdS)a�Return the response obtained after sending a query via UDP.

    @param q: the query
    @type q: dns.message.Message
    @param where: where to send the message
    @type where: string containing an IPv4 or IPv6 address
    @param timeout: The number of seconds to wait before the query times out.
    If None, the default, wait forever.
    @type timeout: float
    @param port: The port to which to send the message.  The default is 53.
    @type port: int
    @param af: the address family to use.  The default is None, which
    causes the address family to use to be inferred from the form of where.
    If the inference attempt fails, AF_INET is used.
    @type af: int
    @rtype: dns.message.Message object
    @param source: source address.  The default is the wildcard address.
    @type source: string
    @param source_port: The port from which to send the message.
    The default is 0.
    @type source_port: int
    @param ignore_unexpected: If True, ignore responses from unexpected
    sources.  The default is False.
    @type ignore_unexpected: bool
    @param one_rr_per_rrset: Put each RR into its own RRset
    @type one_rr_per_rrset: bool
    rNi��)�keyring�request_mac�one_rr_per_rrset)�to_wirer7�socket_factory�socket�
SOCK_DGRAMr�setblocking�bindr*rZsendtor)�recvfromr1Zfamilyr�message�	from_wirer9�macr2�is_responser�close)�qr3rr4r,r5r6r0r;�
ignore_errors�wirer/r(�
begin_timer"r.�
response_time�rrrr
�udp�sD




rNcCsJd}x@|dkrDt||�|j|�}|dkr.t�|t|�}||}qW|S)z�Read the specified number of bytes from sock.  Keep trying until we
    either get the desired amount, or we hit EOF.
    A Timeout exception will be raised if the operation is not completed
    by the expiration time.
    �r)r)Zrecv�EOFError�len)�sock�countr"r(�nrrr
�	_net_reads


rUcCs>d}t|�}x,||kr8t||�||j||d��7}qWdS)z�Write the specified data to the socket.
    A Timeout exception will be raised if the operation is not completed
    by the expiration time.
    rN)rQr*�send)rR�datar"Zcurrent�lrrr
�
_net_write/s


rYcCspy|j|�Wn\tjk
rjtj�dd�\}}t|d�rF|j}n|d}|tjtjtj	gkrf|�YnXdS)N�r!r)
Zconnectr>r�sys�exc_info�hasattrr!ZEINPROGRESSZEWOULDBLOCKZEALREADY)r(ZaddressZty�vZv_errrrr
�_connect;s
r_cCs|j�}t|||||�\}}	}t|tjd�}
d}z�t|�}|
jd�tj�}|dk	r^|
j|�t	|
|	�t
|�}
tjd|
�|}t
|
||�t|
d|�}tjd|�\}
t|
|
|�}Wd|dkr�d}ntj�|}|
j�Xtjj||j|j|d�}||_|j|��st�|S)aReturn the response obtained after sending a query via TCP.

    @param q: the query
    @type q: dns.message.Message object
    @param where: where to send the message
    @type where: string containing an IPv4 or IPv6 address
    @param timeout: The number of seconds to wait before the query times out.
    If None, the default, wait forever.
    @type timeout: float
    @param port: The port to which to send the message.  The default is 53.
    @type port: int
    @param af: the address family to use.  The default is None, which
    causes the address family to use to be inferred from the form of where.
    If the inference attempt fails, AF_INET is used.
    @type af: int
    @rtype: dns.message.Message object
    @param source: source address.  The default is the wildcard address.
    @type source: string
    @param source_port: The port from which to send the message.
    The default is 0.
    @type source_port: int
    @param one_rr_per_rrset: Put each RR into its own RRset
    @type one_rr_per_rrset: bool
    rNz!HrZ)r9r:r;)r<r7r=r>�SOCK_STREAMrr@rrAr_rQ�struct�packrYrU�unpackrGrrCrDr9rErFr)rHr3rr4r,r5r6r;rJr/r(rKr"rX�tcpmsg�ldatarLrMrrr
�tcpIs8



rfTc&cs�t|t�rtjj|�}t|t�r,tjj|�}tjj|||�}|tjjkrltj	j|dddd|
�}|j
j|�|dk	r�|j|||d�|j
�}t|	||||�\}	}}|r�|tjjkr�td��t|	tjd�}nt|	tjd�}|jd�|dk	r�|j|�t|
�}t||�t|�}|�r*t||�|j|�ntjd|�|}t|||�d	}d
}d	}d}|�rj|}tjj}nd}|}d}d
}�x6|�s�t|�} | dk�s�|dk	�r�| |k�r�|} |�r�t||�|j d�\}}!n&t!|d| �}"tj"d|"�\}t!||| �}|tjjk}#tjj#||j$|j%d
||d
||#d
�	}$|$j&}d	}d}%|dk�r�|$j'�sV|$j'dj|k�rbtj(j)d��|$j'd}|j*tjj+k�r�tj(j)d��d}%|j,�}|tjjk�r�|dj-|
k�r�d
}nd
}x�|$j'|%d�D]�}|�r�tj(j)d��|j*tjj+k�rl|j|k�rl|�r&|dj-|
k�r tj(j)d��d	}n|tjjk�r:|}||k�r~|tjj.k�sf|tjjk�r~|�r~d
}n|�r�tjj.}d	}�q�W|�r�|j$�r�|$j/�r�tj(j)d��|$V�q~W|j0�dS)a�Return a generator for the responses to a zone transfer.

    @param where: where to send the message
    @type where: string containing an IPv4 or IPv6 address
    @param zone: The name of the zone to transfer
    @type zone: dns.name.Name object or string
    @param rdtype: The type of zone transfer.  The default is
    dns.rdatatype.AXFR.
    @type rdtype: int or string
    @param rdclass: The class of the zone transfer.  The default is
    dns.rdataclass.IN.
    @type rdclass: int or string
    @param timeout: The number of seconds to wait for each response message.
    If None, the default, wait forever.
    @type timeout: float
    @param port: The port to which to send the message.  The default is 53.
    @type port: int
    @param keyring: The TSIG keyring to use
    @type keyring: dict
    @param keyname: The name of the TSIG key to use
    @type keyname: dns.name.Name object or string
    @param relativize: If True, all names in the zone will be relativized to
    the zone origin.  It is essential that the relativize setting matches
    the one specified to dns.zone.from_xfr().
    @type relativize: bool
    @param af: the address family to use.  The default is None, which
    causes the address family to use to be inferred from the form of where.
    If the inference attempt fails, AF_INET is used.
    @type af: int
    @param lifetime: The total number of seconds to spend doing the transfer.
    If None, the default, then there is no limit on the time the transfer may
    take.
    @type lifetime: float
    @rtype: generator of dns.message.Message objects.
    @param source: source address.  The default is the wildcard address.
    @type source: string
    @param source_port: The port from which to send the message.
    The default is 0.
    @type source_port: int
    @param serial: The SOA serial number to use as the base for an IXFR diff
    sequence (only meaningful if rdtype == dns.rdatatype.IXFR).
    @type serial: int
    @param use_udp: Use UDP (only meaningful for IXFR)
    @type use_udp: bool
    @param keyalgorithm: The TSIG algorithm to use; defaults to
    dns.tsig.default_algorithm
    @type keyalgorithm: string
    r�IN�SOAz. . %u 0 0 0 0N)�	algorithmzcannot do a UDP AXFRz!HFTi��rZ)r9r:�xfr�origin�tsig_ctxZmulti�firstr;z No answer or RRset not for qnamezfirst RRset is not an SOArzanswers after final SOAzIXFR base serial mismatchzmissing TSIG)1�
isinstancerr�nameZ	from_text�	rdatatyperCZ
make_queryZIXFR�rrsetZ	authority�appendZuse_tsigr<r7�
ValueErrorr=r>r?r`r@rArr_rQr*rVrarbrY�emptyr)rBrUrcrDr9rErlZanswerr�	FormError�rdtyperh�copy�serial�AXFRZhad_tsigrG)&r3ZzonervZrdclassrr4r9ZkeynameZ
relativizer,Zlifetimer5r6rxZuse_udpZkeyalgorithmrHrqrJr/r(r"rXrdr#Zdelete_modeZ
expecting_SOAZ	soa_rrsetrkZonamerlrmZmexpirationr.reZis_ixfrrMZanswer_indexrrr
rj�s�5














rj)r)Nr8NNrFFF)Nr8NNrF)5rZ
__future__rr!rr>rar[rZ
dns.exceptionrZdns.inetZdns.nameZdns.messageZdns.rdataclassZ
dns.rdatatypeZ_compatrr�version_info�OSErrorrrr=rZDNSExceptionrrurrrrr%r'r]rr)r*r-r1r7rNrUrYr_rfrpryZ
rdataclassrgZtsigZdefault_algorithmrjrrrr
�<module>sX

	
I
?

__pycache__/rrset.cpython-36.pyc000064400000012167150351404330012546 0ustar003

�$�Wk�@sldZddlZddlZddlZddlZddlmZGdd�dejj	�Z
ddd�Zd	d
�Zddd�Z
d
d�ZdS)z)DNS RRsets (an RRset is a named rdataset)�N�)�string_typescs�eZdZdZddgZejjdf�fdd�	Z�fdd�Z	d	d
�Z
dd�Z�fd
d�Zd�fdd�	Z
d�fdd�	Zd�fdd�	Zdd�Z�ZS)�RRseta6A DNS RRset (named rdataset).

    RRset inherits from Rdataset, and RRsets can be treated as
    Rdatasets in most cases.  There are, however, a few notable
    exceptions.  RRsets have different to_wire() and to_text() method
    arguments, reflecting the fact that RRsets always have an owner
    name.
    �name�deletingNcs$tt|�j|||�||_||_dS)zCreate a new RRset.N)�superr�__init__rr)�selfr�rdclass�rdtype�coversr)�	__class__��/usr/lib/python3.6/rrset.pyr'szRRset.__init__cs"tt|�j�}|j|_|j|_|S)N)rr�_clonerr)r	�obj)r
rrr/szRRset._clonecCs�|jdkrd}ndtjj|j�d}|jdk	rDdtjj|j�}nd}dt|j�dtjj|j�dtjj|j	�||dS)	Nr��(�)z delete=z<DNS � z RRset>)
r�dns�	rdatatype�to_textr�
rdataclass�strrr
r)r	ZctextZdtextrrr�__repr__5s

zRRset.__repr__cCs|j�S)N)r)r	rrr�__str__Bsz
RRset.__str__cs.t|t�sdS|j|jkrdStt|�j|�S)zcTwo RRsets are equal if they have the same name and the same
        rdataset

        @rtype: boolF)�
isinstancerrr�__eq__)r	�other)r
rrrEs

zRRset.__eq__cs4tt|�j|||�sdS|j|ks,|j|kr0dSdS)zaReturns True if this rrset matches the specified class, type,
        covers, and deletion state.FT)rr�matchrr)r	rr
rrr)r
rrr Ps
zRRset.matchTcstt|�j|j|||jf|�S)a�Convert the RRset into DNS master file format.

        @see: L{dns.name.Name.choose_relativity} for more information
        on how I{origin} and I{relativize} determine the way names
        are emitted.

        Any additional keyword arguments are passed on to the rdata
        to_text() method.

        @param origin: The origin for relative names, or None.
        @type origin: dns.name.Name object
        @param relativize: True if names should names be relativized
        @type relativize: bool)rrrrr)r	�originZ
relativize�kw)r
rrrZsz
RRset.to_textcs tt|�j|j||||jf|�S)z!Convert the RRset to wire format.)rr�to_wirerr)r	�file�compressr!r")r
rrr#lsz
RRset.to_wirecCstjj|jt|��S)zYConvert an RRset into an Rdataset.

        @rtype: dns.rdataset.Rdataset object
        )r�rdataset�from_rdata_list�ttl�list)r	rrr�to_rdatasetrszRRset.to_rdataset)N)NT)NN)�__name__�
__module__�__qualname__�__doc__�	__slots__rrZNONErrrrrr rr#r*�
__classcell__rr)r
rrs	

rc	Cs�t|t�rtjj|d|d�}t|t�r2tjj|�}t|t�rHtjj|�}t|||�}|j|�x*|D]"}tj	j|j
|j|�}|j|�qdW|S)z�Create an RRset with the specified name, TTL, class, and type, and with
    the specified list of rdatas in text format.

    @rtype: dns.rrset.RRset object
    N)�
idna_codec)
rrrr�	from_textrrr�
update_ttlZrdatar
r�add)	rr(r
r�text_rdatasr1�r�t�rdrrr�from_text_listzs




r9cGst|||||�S)z�Create an RRset with the specified name, TTL, class, and type and with
    the specified rdatas in text format.

    @rtype: dns.rrset.RRset object
    )r9)rr(r
rr5rrrr2�sr2cCsrt|t�rtjj|d|d�}t|�dkr0td��d}x8|D]0}|dkr`t||j|j	�}|j
|�|j|�q:W|S)z�Create an RRset with the specified name and TTL, and with
    the specified list of rdata objects.

    @rtype: dns.rrset.RRset object
    N)r1rzrdata list must not be empty)rrrrr2�len�
ValueErrorrr
rr3r4)rr(�rdatasr1r6r8rrrr'�s


r'cGst|||�S)z�Create an RRset with the specified name and TTL, and with
    the specified rdata objects.

    @rtype: dns.rrset.RRset object
    )r')rr(r<rrr�
from_rdata�sr=)N)N)r.Zdns.namerZdns.rdatasetZdns.rdataclassZdns.rendererZ_compatrr&ZRdatasetrr9r2r'r=rrrr�<module>sa


__pycache__/renderer.cpython-36.opt-1.pyc000064400000023014150351404330014145 0ustar003

�b�W�.�@shdZddlmZddlZddlZddlZddlZddlZddl	m
Z
dZdZdZ
dZGdd	�d	e�ZdS)
z*Help for building DNS wire format messages�)�BytesION�)�long��c@steZdZdZddd�Zdd�Zd	d
�Zejj	fdd�Z
d
d�Zdd�Zddd�Z
ejjfdd�Zdd�Zdd�ZdS)�RendereraiHelper class for building DNS wire-format messages.

    Most applications can use the higher-level L{dns.message.Message}
    class and its to_wire() method to generate wire-format messages.
    This class is for those applications which need finer control
    over the generation of messages.

    Typical use::

        r = dns.renderer.Renderer(id=1, flags=0x80, max_size=512)
        r.add_question(qname, qtype, qclass)
        r.add_rrset(dns.renderer.ANSWER, rrset_1)
        r.add_rrset(dns.renderer.ANSWER, rrset_2)
        r.add_rrset(dns.renderer.AUTHORITY, ns_rrset)
        r.add_edns(0, 0, 4096)
        r.add_rrset(dns.renderer.ADDTIONAL, ad_rrset_1)
        r.add_rrset(dns.renderer.ADDTIONAL, ad_rrset_2)
        r.write_header()
        r.add_tsig(keyname, secret, 300, 1, 0, '', request_mac)
        wire = r.get_wire()

    @ivar output: where rendering is written
    @type output: BytesIO object
    @ivar id: the message id
    @type id: int
    @ivar flags: the message flags
    @type flags: int
    @ivar max_size: the maximum size of the message
    @type max_size: int
    @ivar origin: the origin to use when rendering relative names
    @type origin: dns.name.Name object
    @ivar compress: the compression table
    @type compress: dict
    @ivar section: the section currently being rendered
    @type section: int (dns.renderer.QUESTION, dns.renderer.ANSWER,
    dns.renderer.AUTHORITY, or dns.renderer.ADDITIONAL)
    @ivar counts: list of the number of RRs in each section
    @type counts: int list of length 4
    @ivar mac: the MAC of the rendered message (if TSIG was used)
    @type mac: string
    Nr�cCsht�|_|dkr tjdd�|_n||_||_||_||_i|_t	|_
ddddg|_|jjd�d|_
dS)a�Initialize a new renderer.

        @param id: the message id
        @type id: int
        @param flags: the DNS message flags
        @type flags: int
        @param max_size: the maximum message size; the default is 65535.
        If rendering results in a message greater than I{max_size},
        then L{dns.exception.TooBig} will be raised.
        @type max_size: int
        @param origin: the origin to use when rendering relative names
        @type origin: dns.name.Name or None.
        Nri�����s)r�output�randomZrandint�id�flags�max_size�origin�compress�QUESTION�section�counts�write�mac)�selfrrrr�r�/usr/lib/python3.6/renderer.py�__init__NszRenderer.__init__cCs^|jj|�|jj�g}x(|jj�D]\}}||kr&|j|�q&Wx|D]}|j|=qJWdS)z�Truncate the output buffer at offset I{where}, and remove any
        compression table entries that pointed beyond the truncation
        point.

        @param where: the offset
        @type where: int
        N)r�seek�truncater�items�append)r�whereZkeys_to_delete�k�vrrr�	_rollbackks	

zRenderer._rollbackcCs&|j|kr"|j|krtjj�||_dS)aZSet the renderer's current section.

        Sections must be rendered order: QUESTION, ANSWER, AUTHORITY,
        ADDITIONAL.  Sections may be empty.

        @param section: the section
        @type section: int
        @raises dns.exception.FormError: an attempt was made to set
        a section value less than the current section.
        N)r�dns�	exceptionZ	FormError)rrrrr�_set_section}s

zRenderer._set_sectioncCsz|jt�|jj�}|j|j|j|j�|jjtj	d||��|jj�}||j
krd|j|�tj
j�|jtd7<dS)aAdd a question to the message.

        @param qname: the question name
        @type qname: dns.name.Name
        @param rdtype: the question rdata type
        @type rdtype: int
        @param rdclass: the question rdata class
        @type rdclass: int
        z!HHrN)r&rr�tell�to_wirerrr�struct�packrr#r$r%�TooBigr)rZqnameZrdtypeZrdclass�before�afterrrr�add_question�s




zRenderer.add_questioncKsh|j|�|jj�}|j|j|j|jf|�}|jj�}||jkrR|j|�tj	j
�|j||7<dS)aAdd the rrset to the specified section.

        Any keyword arguments are passed on to the rdataset's to_wire()
        routine.

        @param section: the section
        @type section: int
        @param rrset: the rrset
        @type rrset: dns.rrset.RRset object
        N)r&rr'r(rrrr#r$r%r+r)rrZrrset�kwr,�nr-rrr�	add_rrset�s




zRenderer.add_rrsetcKsj|j|�|jj�}|j||j|j|jf|�}|jj�}||jkrT|j|�tj	j
�|j||7<dS)a�Add the rdataset to the specified section, using the specified
        name as the owner name.

        Any keyword arguments are passed on to the rdataset's to_wire()
        routine.

        @param section: the section
        @type section: int
        @param name: the owner name
        @type name: dns.name.Name object
        @param rdataset: the rdataset
        @type rdataset: dns.rdataset.Rdataset object
        N)r&rr'r(rrrr#r$r%r+r)rr�nameZrdatasetr/r,r0r-rrr�add_rdataset�s




zRenderer.add_rdatasetc
Csf|td�M}||d>O}|jt�|jj�}|jjtjddtj	j
||d��|dk	�r(|jj�}x�|D]z}tjd|jd�}|jj|�|jj�}	|j|j�|jj�}
|jj
|	d�tjd|
|	�}|jj|�|jj
dd�qfW|jj�}|jj
|d�tjd||�}|jj|�|jj
dd�|jj�}||jk�rP|j|�tjj�|jtd	7<dS)
a�Add an EDNS OPT record to the message.

        @param edns: The EDNS level to use.
        @type edns: int
        @param ednsflags: EDNS flag values.
        @type ednsflags: int
        @param payload: The EDNS sender's payload field, which is the maximum
        size of UDP datagram the sender can handle.
        @type payload: int
        @param options: The EDNS options list
        @type options: list of dns.edns.Option instances
        @see: RFC 2671
        l�~�z!BHHIHrNz!HHrz!Hr)rr&�
ADDITIONALrr'rr)r*r$�	rdatatype�OPTZotyper(rrr#r%r+r)
rZednsZ	ednsflagsZpayloadZoptionsr,Zlstart�optZstuff�start�endZlendr-rrr�add_edns�s8










zRenderer.add_ednsc	Cs2|jt�|jj�}	|jj�}
tjj|
||tt	j	��||||||d�
\}|_
}|j|j|j|j
�|jjtjdtjjtjjdd��|jj�}
|jj|�|jj�}||jkr�|j|	�tjj�|jj|
d�|jjtjd||
��|jtd7<|jjd�|jjtjd|jt��|jjdd�dS)	a�Add a TSIG signature to the message.

        @param keyname: the TSIG key name
        @type keyname: dns.name.Name object
        @param secret: the secret to use
        @type secret: string
        @param fudge: TSIG time fudge
        @type fudge: int
        @param id: the message id to encode in the tsig signature
        @type id: int
        @param tsig_error: TSIG error code; default is 0.
        @type tsig_error: int
        @param other_data: TSIG other data.
        @type other_data: string
        @param request_mac: This message is a response to the request which
        had the specified MAC.
        @type request_mac: string
        @param algorithm: the TSIG algorithm to use
        @type algorithm: dns.name.Name object
        )�	algorithmz!HHIHrrz!Hr�
N)r&r5rr'�getvaluer$�tsigZsign�int�timerr(rrrr)r*r6ZTSIG�
rdataclass�ANYrr#r%r+rr)rZkeynameZsecretZfudgerZ
tsig_errorZ
other_dataZrequest_macr<r,�sZ
tsig_rdataZctxZrdata_startr-rrr�add_tsigs8







zRenderer.add_tsigc
CsX|jjd�|jjtjd|j|j|jd|jd|jd|jd��|jjdd�dS)z�Write the DNS message header.

        Writing the DNS message header is done after all sections
        have been rendered, but before the optional TSIG signature
        is added.
        rz!HHHHHHrrrN)rrrr)r*rrr)rrrr�write_header5s
zRenderer.write_headercCs
|jj�S)z@Return the wire format message.

        @rtype: string
        )rr>)rrrr�get_wireCszRenderer.get_wire)NrrN)N)�__name__�
__module__�__qualname__�__doc__rr#r&r$rB�INr.r1r3r;r?Zdefault_algorithmrErFrGrrrrr"s*

04r)rK�iorr)r
rAZ
dns.exceptionr$Zdns.tsigZ_compatrrZANSWERZ	AUTHORITYr5�objectrrrrr�<module>s__pycache__/name.cpython-36.pyc000064400000064766150351404330012343 0ustar003

�Of�r�@s�dZddlmZddlZddlZddlZddlZyddlZdZ	Wne
k
rXdZ	YnXddlZddl
ZddlmZmZmZmZmZy
ejZWn.ek
r�ddejd	�>d
dZYnXdZdZd
ZdZdZGd
d�dejj�ZGdd�dejj�ZGdd�dejj �Z!Gdd�dejj �Z"Gdd�dejj#�Z$Gdd�dejj �Z%Gdd�dejj�Z&Gdd�dejj#�Z'Gdd�dejj#�Z(Gdd �d ejj#�Z)Gd!d"�d"ejj#�Z*Gd#d$�d$e+�Z,Gd%d&�d&e,�Z-Gd'd(�d(e,�Z.e/d)�Z0d*Z1e-d�Z2e-d�Z3e2Z4e.dddd�Z5e.dddd�Z6e.dddd�Z7e.dddd�Z8e5Z9d+d,�Z:d-d.�Z;d/d0�Z<Gd1d2�d2e+�Z=e=d3g�Z>e=g�Z?e>dfd4d5�Z@e>dfd6d7�ZAd8d9�ZBdS):z�DNS Names.

@var root: The DNS root name.
@type root: dns.name.Name object
@var empty: The empty DNS name.
@type empty: dns.name.Name object
�)�BytesIONTF�)�long�binary_type�	text_type�unichr�maybe_decode��P���c@seZdZdZdS)�
EmptyLabelzA DNS label is empty.N)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/name.pyr4src@seZdZdZdS)�	BadEscapez8An escaped code in a text format of DNS name is invalid.N)rrrrrrrrr9src@seZdZdZdS)�
BadPointerz=A DNS compression pointer points forward instead of backward.N)rrrrrrrrr>src@seZdZdZdS)�BadLabelTypez2The label type in DNS name wire format is unknown.N)rrrrrrrrrCsrc@seZdZdZdS)�NeedAbsoluteNameOrOriginzvAn attempt was made to convert a non-absolute name to
    wire when there was also a non-absolute (or missing) origin.N)rrrrrrrrrHsrc@seZdZdZdS)�NameTooLongz A DNS name is > 255 octets long.N)rrrrrrrrrNsrc@seZdZdZdS)�LabelTooLongz A DNS label is > 63 octets long.N)rrrrrrrrrSsrc@seZdZdZdS)�AbsoluteConcatenationz]An attempt was made to append anything other than the
    empty name to an absolute DNS name.N)rrrrrrrrrXsrc@seZdZdZdS)�NoParentzMAn attempt was made to get the parent of the root name
    or the empty name.N)rrrrrrrrr^src@seZdZdZdS)�
NoIDNA2008zLIDNA 2008 processing was requested but the idna module is not
    available.N)rrrrrrrrrcsrc@seZdZdZedg�ZdZdS)�
IDNAExceptionz$IDNA processing raised an exception.�idna_exceptionz+IDNA processing exception: {idna_exception}N)rrrr�setZsupp_kwargsZfmtrrrrris
rc@s8eZdZdZdd�Zdd�Zdd�Zdd	�Zd
d�ZdS)
�	IDNACodecz.Abstract base class for IDNA encoder/decoders.cCsdS)Nr)�selfrrr�__init__tszIDNACodec.__init__cCs|j�jd�S)Nsxn--)�lower�
startswith)r"�labelrrr�is_idnawszIDNACodec.is_idnacCs"x|D]}t|�dkrdSqWdS)N�FT)�ord)r"r&�crrr�is_all_asciizs
zIDNACodec.is_all_asciicCst�dS)N)�NotImplementedError)r"r&rrr�encode�szIDNACodec.encodecCs`|j|�rPy|dd�jd�}WqXtk
rL}zt|d��WYdd}~XqXXnt|�}t|�S)Nr
Zpunycode)r)r'�decode�	Exceptionrr�	_escapify)r"r&�errrr.�s
zIDNACodec.decodeN)	rrrrr#r'r+r-r.rrrrr!psr!cs6eZdZdZd	�fdd�	Zdd�Z�fdd�Z�ZS)
�
IDNA2003CodeczIDNA 2003 encoder/decoder.Fcstt|�j�||_dS)aInitialize the IDNA 2003 encoder/decoder.
        @param strict_decode: If True, then IDNA2003 checking is done when
        decoding.  This can cause failures if the name was encoded with
        IDNA2008.  The default is False.
        @type strict_decode: bool
        N)�superr2r#�
strict_decode)r"r4)�	__class__rrr#�szIDNA2003Codec.__init__cCs6|dkrdSytjj|�Stk
r0t�YnXdS)N��)�	encodings�idnaZToASCII�UnicodeErrorr)r"r&rrrr-�szIDNA2003Codec.encodecsd|jstt|�j|�S|dkr"dSyttjj|��Stk
r^}zt	|d��WYdd}~XnXdS)Nr7r6)r)
r4r3r2r.r0r8r9Z	ToUnicoder/r)r"r&r1)r5rrr.�szIDNA2003Codec.decode)F)rrrrr#r-r.�
__classcell__rr)r5rr2�s
r2cs6eZdZdZd	�fdd�	Zdd�Z�fdd�Z�ZS)
�
IDNA2008CodeczIDNA 2008 encoder/decoder.Fcs*tt|�j�||_||_||_||_dS)a�Initialize the IDNA 2008 encoder/decoder.
        @param uts_46: If True, apply Unicode IDNA compatibility processing
        as described in Unicode Technical Standard #46
        (U{http://unicode.org/reports/tr46/}).  This parameter is only
        meaningful if IDNA 2008 is in use.  If False, do not apply
        the mapping.  The default is False
        @type uts_46: bool
        @param transitional: If True, use the "transitional" mode described
        in Unicode Technical Standard #46.  This parameter is only
        meaningful if IDNA 2008 is in use.  The default is False.
        @type transitional: bool
        @param allow_pure_ascii: If True, then a label which
        consists of only ASCII characters is allowed.  This is less strict
        than regular IDNA 2008, but is also necessary for mixed names,
        e.g. a name with starting with "_sip._tcp." and ending in an IDN
        suffixm which would otherwise be disallowed.  The default is False
        @type allow_pure_ascii: bool
        @param strict_decode: If True, then IDNA2008 checking is done when
        decoding.  This can cause failures if the name was encoded with
        IDNA2003.  The default is False.
        @type strict_decode: bool
        N)r3r<r#�uts_46�transitional�allow_pure_asciir4)r"r=r>r?r4)r5rrr#�s
zIDNA2008Codec.__init__cCs�|dkrdS|jr&|j|�r&|jd�Sts.t�y |jrFtj|d|j�}tj	|�Stj
k
r|}zt|d��WYdd}~XnXdS)Nr6r7�asciiF)r)r?r+r-�have_idna_2008rr=r9�uts46_remapr>Zalabel�	IDNAErrorr)r"r&r1rrrr-�s

zIDNA2008Codec.encodecs�|jstt|�j|�S|dkr"dSts*t�y"|jr@tj|dd�}t	tj
|��Stjk
rz}zt|d��WYdd}~XnXdS)Nr7r6F)r)
r4r3r<r.rArr=r9rBr0ZulabelrCr)r"r&r1)r5rrr.�szIDNA2008Codec.decode)FFFF)rrrrr#r-r.r;rr)r5rr<�s
r<s"().;\@$z"().;\@$cCs�t|t�rzd}t|t�r |j�}xTt|�D]H}|tkrH|dt|�7}q*|dkrf|dkrf|t|�7}q*|d|7}q*W|Sd}xD|D]<}|tkr�|d|7}q�|dkr�|dt|�7}q�||7}q�W|S)zaEscape the characters in label which need it.
    @returns: the escaped string
    @rtype: stringr6�\� r(z\%03d� )	�
isinstance�bytesrr-�	bytearray�_escaped�chr�
_escaped_textr))r&�textr*rrrr0�s&


r0cCs�t|�}d}d}d}xH|D]@}t|�}||d7}|dkr>t�|dkrR|dkrR|}|d7}qW|dkrjt�|dkr�||dkr�t�dS)a/Check for empty labels in the middle of a label sequence,
    labels that are too long, and for too many labels.
    @raises NameTooLong: the name as a whole is too long
    @raises EmptyLabel: a label is empty (i.e. the root label) and appears
    in a position other than the end of the label sequencerr�?r7�N���)�lenrrr)�labels�l�total�i�jr&Zllrrr�_validate_labelss 
rWcCs(t|t�r|St|t�r |j�St�dS)N)rGrrr-�
ValueError)r&rrr�
_ensure_bytes/s


rYcsDeZdZdZdgZ�fdd�Zdd�Zdd�Zd	d
�Zdd�Z	�fd
d�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zdd�Zdd �Zd!d"�Zd#d$�Zd%d&�Zd'd(�Zd)d*�Zd+d,�ZdLd.d/�ZdMd1d2�ZdNd3d4�ZdOd5d6�Zd7d8�Zd9d:�Zd;d<�Z d=d>�Z!d?d@�Z"dAdB�Z#dCdD�Z$dEdF�Z%dPdHdI�Z&dJdK�Z'�Z(S)Q�Namez�A DNS name.

    The dns.name.Name class represents a DNS name as a tuple of labels.
    Instances of the class are immutable.

    @ivar labels: The tuple of labels in the name. Each label is a string of
    up to 63 octets.rRcs2dd�|D�}tt|�jdt|��t|j�dS)z�Initialize a domain name from a list of labels.
        @param labels: the labels
        @type labels: any iterable whose values are strings
        cSsg|]}t|��qSr)rY)�.0�xrrr�
<listcomp>Hsz!Name.__init__.<locals>.<listcomp>rRN)r3rZ�__setattr__�tuplerWrR)r"rR)r5rrr#Csz
Name.__init__cCstd��dS)Nz+object doesn't support attribute assignment)�	TypeError)r"�name�valuerrrr^LszName.__setattr__cCs
t|j�S)N)rZrR)r"rrr�__copy__Osz
Name.__copy__cCsttj|j|��S)N)rZ�copy�deepcopyrR)r"�memorrr�__deepcopy__RszName.__deepcopy__cCs
d|jiS)NrR)rR)r"rrr�__getstate__UszName.__getstate__cs$tt|�jd|d�t|j�dS)NrR)r3rZr^rWrR)r"�state)r5rr�__setstate__XszName.__setstate__cCst|j�dko|jddkS)zXIs the most significant label of this name the root label?
        @rtype: bool
        rrr7rP)rQrR)r"rrr�is_absolute\szName.is_absolutecCst|j�dko|jddkS)z\Is this name wild?  (I.e. Is the least significant label '*'?)
        @rtype: bool
        r�*)rQrR)r"rrr�is_wildcszName.is_wildcCsJtd�}x4|jD]*}x$t|j��D]}||d>|7}q"WqWt|t�S)zHReturn a case-insensitive hash of the name.
        @rtype: int
        rr)rrRrIr$�int�maxint)r"�hr&r*rrr�__hash__js
z
Name.__hash__c
Cs*|j�}|j�}||kr0|r&tddfStddfSt|j�}t|j�}||}|dkrZ|}n|}d}d}	t}
x�|dkr�|d8}|d8}|d8}|j|j�}|j|j�}||kr�d}|	dkr�t}
|
||	fS||kr�d}|	dkr�t}
|
||	fS|	d7}	qlW|}|dk�rt}
n|dk�rt}
nt}
|
||	fS)a�Compare two names, returning a 3-tuple (relation, order, nlabels).

        I{relation} describes the relation ship between the names,
        and is one of: dns.name.NAMERELN_NONE,
        dns.name.NAMERELN_SUPERDOMAIN, dns.name.NAMERELN_SUBDOMAIN,
        dns.name.NAMERELN_EQUAL, or dns.name.NAMERELN_COMMONANCESTOR

        I{order} is < 0 if self < other, > 0 if self > other, and ==
        0 if self == other.  A relative name is always less than an
        absolute name.  If both names have the same relativity, then
        the DNSSEC order relation is used to order them.

        I{nlabels} is the number of significant labels that the two names
        have in common.
        rrrPrP)	rk�
NAMERELN_NONErQrRr$�NAMERELN_COMMONANCESTOR�NAMERELN_SUPERDOMAIN�NAMERELN_SUBDOMAIN�NAMERELN_EQUAL)
r"�otherZsabsZoabs�l1�l2ZldiffrS�orderZnlabelsZnamerelnZlabel1Zlabel2rrr�fullcompareusN








zName.fullcomparecCs(|j|�\}}}|tks |tkr$dSdS)zoIs self a subdomain of other?

        The notion of subdomain includes equality.
        @rtype: bool
        TF)r{rurv)r"rw�nr�o�nlrrr�is_subdomain�szName.is_subdomaincCs(|j|�\}}}|tks |tkr$dSdS)zqIs self a superdomain of other?

        The notion of subdomain includes equality.
        @rtype: bool
        TF)r{rtrv)r"rwr|r}r~rrr�is_superdomain�szName.is_superdomaincCstdd�|jD��S)z�Return a name which is equal to the current name, but is in
        DNSSEC canonical form.
        @rtype: dns.name.Name object
        cSsg|]}|j��qSr)r$)r[r\rrrr]�sz%Name.canonicalize.<locals>.<listcomp>)rZrR)r"rrr�canonicalize�szName.canonicalizecCs$t|t�r|j|�ddkSdSdS)NrrF)rGrZr{)r"rwrrr�__eq__�s
zName.__eq__cCs$t|t�r|j|�ddkSdSdS)NrrT)rGrZr{)r"rwrrr�__ne__�s
zName.__ne__cCs$t|t�r|j|�ddkStSdS)Nrr)rGrZr{�NotImplemented)r"rwrrr�__lt__�s
zName.__lt__cCs$t|t�r|j|�ddkStSdS)Nrr)rGrZr{r�)r"rwrrr�__le__�s
zName.__le__cCs$t|t�r|j|�ddkStSdS)Nrr)rGrZr{r�)r"rwrrr�__ge__�s
zName.__ge__cCs$t|t�r|j|�ddkStSdS)Nrr)rGrZr{r�)r"rwrrr�__gt__�s
zName.__gt__cCsd|j�dS)Nz
<DNS name �>)�__str__)r"rrr�__repr__�sz
Name.__repr__cCs
|jd�S)NF)�to_text)r"rrrr��szName.__str__FcCspt|j�dkrtd�St|j�dkr:|jddkr:td�S|rV|j�rV|jdd�}n|j}djtt|��}|S)	z�Convert name to text format.
        @param omit_final_dot: If True, don't emit the final dot (denoting the
        root label) for absolute names.  The default is False.
        @rtype: string
        r�@rr7�.N�.rP)rQrRrrk�join�mapr0)r"�omit_final_dotrS�srrrr��szName.to_textNcsxt|j�dkrdSt|j�dkr2|jddkr2dS|rN|j�rN|jdd	�}n|j}�dkr`t�dj�fdd�|D��S)
a�Convert name to Unicode text format.

        IDN ACE labels are converted to Unicode.

        @param omit_final_dot: If True, don't emit the final dot (denoting the
        root label) for absolute names.  The default is False.
        @type omit_final_dot: bool
        @param idna_codec: IDNA encoder/decoder.  If None, the
        IDNA_2003_Practical encoder/decoder is used.  The IDNA_2003_Practical
        decoder does not impose any policy, it just decodes punycode, so if
        you don't want checking for compliance, you can use this decoder for
        IDNA2008 as well.
        @type idna_codec: dns.name.IDNA
        @rtype: string
        r�@rr7r�Ncsg|]}�j|��qSr)r.)r[r\)�
idna_codecrrr])sz#Name.to_unicode.<locals>.<listcomp>rP)rQrRrk�IDNA_2003_Practicalr�)r"r�r�rSr)r�r�
to_unicodeszName.to_unicodecCsX|j�s:|dks|j�rt�t|j�}|jt|j��n|j}dd�|D�}dj|�S)aConvert name to a format suitable for digesting in hashes.

        The name is canonicalized and converted to uncompressed wire format.

        @param origin: If the name is relative and origin is not None, then
        origin will be appended to it.
        @type origin: dns.name.Name object
        @raises NeedAbsoluteNameOrOrigin: All names in wire format are
        absolute.  If self is a relative name, then an origin must be supplied;
        if it is missing, then this exception is raised
        @rtype: string
        NcSs*g|]"}tjdt|�t|�|j���qS)z!B%ds)�struct�packrQr$)r[r\rrrr]@sz&Name.to_digestable.<locals>.<listcomp>r7)rkr�listrR�extendr�)r"�originrRZdlabelsrrr�
to_digestable+s
zName.to_digestablec
Cs.|dkrt�}d}nd}|j�sR|dks2|j�r6t�t|j�}|jt|j��n|j}d}x�|D]�}t||d��}|d7}|dk	r�|j|�}	nd}	|	dk	r�d|	}
tj	d|
�}|j
|�Pqb|dk	r�t|�dkr�|j�}	|	dkr�|	||<t|�}|j
tj	d	|��|dkrb|j
|�qbW|�r*|j
�SdS)
a�Convert name to wire format, possibly compressing it.

        @param file: the file where the name is emitted (typically
        a BytesIO file).  If None, a string containing the wire name
        will be returned.
        @type file: file or None
        @param compress: The compression table.  If None (the default) names
        will not be compressed.
        @type compress: dict
        @param origin: If the name is relative and origin is not None, then
        origin will be appended to it.
        @type origin: dns.name.Name object
        @raises NeedAbsoluteNameOrOrigin: All names in wire format are
        absolute.  If self is a relative name, then an origin must be supplied;
        if it is missing, then this exception is raised
        NTFrri�z!Hi�?z!B)rrkrr�rRr�rZ�getr�r��writerQ�tell�getvalue)
r"�file�compressr�Zwant_returnrRrUr&�n�posrbr�rSrrr�to_wireDs@


zName.to_wirecCs
t|j�S)z@The length of the name (in labels).
        @rtype: int
        )rQrR)r"rrr�__len__|szName.__len__cCs
|j|S)N)rR)r"�indexrrr�__getitem__�szName.__getitem__cCs
|j|�S)N)�concatenate)r"rwrrr�__add__�szName.__add__cCs
|j|�S)N)�
relativize)r"rwrrr�__sub__�szName.__sub__cCsnt|j�}|dkr|tjjfS||kr2tjj|fS|dksB||krJtd��t|d|��t||d��fS)a(Split a name into a prefix and suffix at depth.

        @param depth: the number of labels in the suffix
        @type depth: int
        @raises ValueError: the depth was not >= 0 and <= the length of the
        name.
        @returns: the tuple (prefix, suffix)
        @rtype: tuple
        rz0depth must be >= 0 and <= the length of the nameN)rQrR�dnsra�emptyrXrZ)r"�depthrSrrr�split�s
z
Name.splitcCs:|j�rt|�dkrt�t|j�}|jt|j��t|�S)z�Return a new name which is the concatenation of self and other.
        @rtype: dns.name.Name object
        @raises AbsoluteConcatenation: self is absolute and other is
        not the empty name
        r)rkrQrr�rRr�rZ)r"rwrRrrrr��s

zName.concatenatecCs0|dk	r(|j|�r(t|dt|���S|SdS)z�If self is a subdomain of origin, return a new name which is self
        relative to origin.  Otherwise return self.
        @rtype: dns.name.Name object
        N)rrZrQ)r"r�rrrr��szName.relativizecCs|j�s|j|�S|SdS)z�If self is a relative name, return a new name which is the
        concatenation of self and origin.  Otherwise return self.
        @rtype: dns.name.Name object
        N)rkr�)r"r�rrr�derelativize�s
zName.derelativizeTcCs&|r|r|j|�S|j|�Sn|SdS)aReturn a name with the relativity desired by the caller.  If
        origin is None, then self is returned.  Otherwise, if
        relativize is true the name is relativized, and if relativize is
        false the name is derelativized.
        @rtype: dns.name.Name object
        N)r�r�)r"r�r�rrr�choose_relativity�s

zName.choose_relativitycCs&|tks|tkrt�t|jdd��S)z�Return the parent of the name.
        @rtype: dns.name.Name object
        @raises NoParent: the name is either the root name or the empty name,
        and thus has no parent.
        rN)�rootr�rrZrR)r"rrr�parent�szName.parent)F)FN)N)NNN)NT))rrrr�	__slots__r#r^rcrgrhrjrkrmrqr{rr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r;rr)r5rrZ7sJ	=



8

rZr7c	Cs�t|t�std��|dkp"t|t�s,td��g}d}d}d}d}|dkrLt}|dkrXd}|�rz|dkrptd	g�Sx�|D]�}|r�|dkr�|j�r�t|�}|d
7}q�||7}d}n@|j�s�t�|d9}|t|�7}|d
7}|dkr�d}|t|�7}qv|dk�r"t	|�dk�rt
�|j|j|��d}qv|dk�r:d}d}d}qv||7}qvW|�rPt�t	|�dk�rp|j|j|��n
|jd	�t	|�dk�s�|dd	k�r�|dk	�r�|j
t|j��t|�S)a�Convert unicode text into a Name object.

    Labels are encoded in IDN ACE form.

    @param text: The text to convert into a name.
    @type text: Unicode string
    @param origin: The origin to append to non-absolute names.
    @type origin: dns.name.Name
    @param idna_codec: IDNA encoder/decoder.  If None, the default IDNA 2003
    encoder/decoder is used.
    @type idna_codec: dns.name.IDNA
    @rtype: dns.name.Name object
    z0input to from_unicode() must be a unicode stringNzorigin must be a Name or Noner6Frr�r�r7r�
r�。�.�。rDT)r�r�r�r�rP)rGrrXrZ�	IDNA_2003�isdigitrnrrrQr�appendr-r�r�rR)	rMr�r�rRr&�escaping�edigitsrTr*rrr�from_unicode�sd






&r�c
Cs�t|t�rt|||�St|t�s(td��|dkp8t|t�sBtd��g}d}d}d}d}|dkrbd}|�r�|dkrztdg�Sx�t|�D]�}tjd	|�}	|�r|dkr�|	j	�r�t
|	�}|d
7}n||	7}d}nF|	j	�s�t�|d9}|t
|	�7}|d
7}|dk�r^d}|tjd	|�7}q�|	dk�r>t|�dk�r.t
�|j|�d}q�|	d
k�rVd}d}d}q�||	7}q�W|�rlt�t|�dk�r�|j|�n
|jd�t|�dk�s�|ddk�r�|dk	�r�|jt|j��t|�S)a}Convert text into a Name object.

    @param text: The text to convert into a name.
    @type text: string
    @param origin: The origin to append to non-absolute names.
    @type origin: dns.name.Name
    @param idna_codec: IDNA encoder/decoder.  If None, the default IDNA 2003
    encoder/decoder is used.
    @type idna_codec: dns.name.IDNA
    @rtype: dns.name.Name object
    z%input to from_text() must be a stringNzorigin must be a Name or Noner7Frr�r�z!Brr�r�\TrP)rGrr�rrXrZrIr�r�r�rnrrQrr�r�r�rR)
rMr�r�rRr&r�r�rTr*Zbyte_rrr�	from_text*sf








&r�cCst|t�std��tjj|�}g}|}d}||}|d7}d}x�|dkr�|dkr�|j||||�j��||7}|dkr�||7}nJ|dkr�|d@d||}|dkr�|d7}||kr�t�|}|d7}nt	�||}|d7}|dkr@|d7}q@W|jd�t
|�|fS)	a^Convert possibly compressed wire format into a Name.
    @param message: the entire DNS message
    @type message: string
    @param current: the offset of the beginning of the name from the start
    of the message
    @type current: int
    @raises dns.name.BadPointer: a compression pointer did not point backwards
    in the message
    @raises dns.name.BadLabelType: an invalid label type was encountered.
    @returns: a tuple consisting of the name that was read and the number
    of bytes of the wire format message which were consumed reading it
    @rtype: (dns.name.Name object, int) tuple
    z*input to from_wire() must be a byte stringrr�@�rN�r6)rGrrXr�ZwiredataZ
maybe_wrapr�ZunwraprrrZ)�messageZcurrentrRZbiggest_pointerZhops�countZcusedrrr�	from_wireps<




r�)Cr�iorr��sysrdZencodings.idnar8r9rA�ImportErrorZ
dns.exceptionr�Zdns.wiredataZ_compatrrrrrro�AttributeError�calcsizerrrtrurvrsZ	exception�SyntaxErrorrrZ	FormErrorrrZDNSExceptionrrrrrrr�objectr!r2r<rIrJrLr�ZIDNA_2003_Strictr�ZIDNA_2008_PracticalZIDNA_2008_UTS_46ZIDNA_2008_StrictZIDNA_2008_TransitionalZ	IDNA_2008r0rWrYrZr�r�r�r�r�rrrr�<module>st

  >*
HF__pycache__/tokenizer.cpython-36.opt-1.pyc000064400000034253150351404330014360 0ustar003

�b�W�G�@s�dZddlmZddlZddlZddlZddlZddlm	Z	m
Z
mZdddddddd�ZddiZ
dZdZd	Zd
ZdZdZd
ZGdd�dejj�ZGdd�de�ZGdd�de�ZdS)zTokenize DNS master file format�)�StringION�)�long�	text_type�binary_typeT)� �	�
�;�(�)�"r
�����c@seZdZdZdS)�UngetBufferFullzDAn attempt was made to unget a token when the unget buffer was full.N)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/tokenizer.pyr.src@s�eZdZdZd%dd�Zdd�Zdd	�Zd
d�Zdd
�Zdd�Z	dd�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�Zd$S)&�Tokenz�A DNS master file format token.

    @ivar ttype: The token type
    @type ttype: int
    @ivar value: The token value
    @type value: string
    @ivar has_escape: Does the token value contain escapes?
    @type has_escape: bool
    �FcCs||_||_||_dS)aInitialize a token instance.

        @param ttype: The token type
        @type ttype: int
        @param value: The token value
        @type value: string
        @param has_escape: Does the token value contain escapes?
        @type has_escape: bool
        N)�ttype�value�
has_escape)�selfrrrrrr�__init__?s
zToken.__init__cCs
|jtkS)N)r�EOF)rrrr�is_eofMszToken.is_eofcCs
|jtkS)N)r�EOL)rrrr�is_eolPszToken.is_eolcCs
|jtkS)N)r�
WHITESPACE)rrrr�
is_whitespaceSszToken.is_whitespacecCs
|jtkS)N)r�
IDENTIFIER)rrrr�
is_identifierVszToken.is_identifiercCs
|jtkS)N)r�
QUOTED_STRING)rrrr�is_quoted_stringYszToken.is_quoted_stringcCs
|jtkS)N)r�COMMENT)rrrr�
is_comment\szToken.is_commentcCs
|jtkS)N)r�	DELIMITER)rrrr�is_delimiter_szToken.is_delimitercCs|jtkp|jtkS)N)rr#r!)rrrr�
is_eol_or_eofbszToken.is_eol_or_eofcCs&t|t�sdS|j|jko$|j|jkS)NF)�
isinstancerrr)r�otherrrr�__eq__es
zToken.__eq__cCs&t|t�sdS|j|jkp$|j|jkS)NT)r0rrr)rr1rrr�__ne__ks
zToken.__ne__cCsd|j|jfS)Nz%d "%s")rr)rrrr�__str__qsz
Token.__str__cCs|js
|Sd}t|j�}d}x�||kr�|j|}|d7}|dkr�||krPtjj�|j|}|d7}|j�r�||krztjj�|j|}|d7}||kr�tjj�|j|}|d7}|j�o�|j�s�tjj�tt	|�dt	|�dt	|��}||7}qWt
|j|�S)Nrrr�\�d�
)r�lenr�dns�	exception�
UnexpectedEnd�isdigit�SyntaxError�chr�intrr)rZ	unescaped�l�i�c�c2�c3rrr�unescapets6





$zToken.unescapecCsdS)Nrr)rrrr�__len__�sz
Token.__len__cCst|j|jf�S)N)�iterrr)rrrr�__iter__�szToken.__iter__cCs$|dkr|jS|dkr|jSt�dS)Nrr)rr�
IndexError)rrArrr�__getitem__�s
zToken.__getitem__N)rF)rrrrr r"r$r&r(r*r,r.r/r2r3r4rErFrHrJrrrrr3s"

rc@s�eZdZdZejdfdd�Zdd�Zdd�Zd	d
�Z	dd�Z
d(dd�Zdd�Zdd�Z
e
Zdd�Zdd�Zdd�Zdd�Zdd�Zd)dd�Zd*d d!�Zd+d"d#�Zd$d%�Zd&d'�ZdS),�	Tokenizera�A DNS master file format tokenizer.

    A token is a (type, value) tuple, where I{type} is an int, and
    I{value} is a string.  The valid types are EOF, EOL, WHITESPACE,
    IDENTIFIER, QUOTED_STRING, COMMENT, and DELIMITER.

    @ivar file: The file to tokenize
    @type file: file
    @ivar ungotten_char: The most recently ungotten character, or None.
    @type ungotten_char: string
    @ivar ungotten_token: The most recently ungotten token, or None.
    @type ungotten_token: (int, string) token tuple
    @ivar multiline: The current multiline level.  This value is increased
    by one every time a '(' delimiter is read, and decreased by one every time
    a ')' delimiter is read.
    @type multiline: int
    @ivar quoting: This variable is true if the tokenizer is currently
    reading a quoted string.
    @type quoting: bool
    @ivar eof: This variable is true if the tokenizer has encountered EOF.
    @type eof: bool
    @ivar delimiters: The current delimiter dictionary.
    @type delimiters: dict
    @ivar line_number: The current line number
    @type line_number: int
    @ivar filename: A filename that will be returned by the L{where} method.
    @type filename: string
    NcCs�t|t�r t|�}|dkr`d}n@t|t�rDt|j��}|dkr`d}n|dkr`|tjkr\d}nd}||_d|_d|_	d|_
d|_d|_t
|_d|_||_dS)a�Initialize a tokenizer instance.

        @param f: The file to tokenize.  The default is sys.stdin.
        This parameter may also be a string, in which case the tokenizer
        will take its input from the contents of the string.
        @type f: file or string
        @param filename: the name of the filename that the L{where} method
        will return.
        @type filename: string
        Nz<string>z<stdin>z<file>rFr)r0rrr�decode�sys�stdin�file�
ungotten_char�ungotten_token�	multiline�quoting�eof�_DELIMITERS�
delimiters�line_number�filename)r�frXrrrr �s*


zTokenizer.__init__cCsZ|jdkrJ|jrd}qV|jjd�}|dkr2d|_qV|dkrV|jd7_n|j}d|_|S)z<Read a character from input.
        @rtype: string
        NrrTr	)rPrTrO�readrW)rrBrrr�	_get_char�s
zTokenizer._get_charcCs|j|jfS)z�Return the current location in the input.

        @rtype: (string, int) tuple.  The first item is the filename of
        the input, the second is the current line number.
        )rXrW)rrrr�where�szTokenizer.wherecCs|jdk	rt�||_dS)aEUnget a character.

        The unget buffer for characters is only one character large; it is
        an error to try to unget a character when the unget buffer is not
        empty.

        @param c: the character to unget
        @type c: string
        @raises UngetBufferFull: there is already an ungotten char
        N)rPr)rrBrrr�_unget_chars
zTokenizer._unget_charcCsLd}xB|j�}|dkr<|dkr<|dks.|jr<|j|�|S|d7}qWdS)a(Consume input until a non-whitespace character is encountered.

        The non-whitespace character is then ungotten, and the number of
        whitespace characters consumed is returned.

        If the tokenizer is in multiline mode, then newlines are whitespace.

        @rtype: int
        rrrr	rN)r[rRr])r�skippedrBrrr�skip_whitespaces
zTokenizer.skip_whitespaceFc
CsT|jdk	r>|j}d|_|j�r(|r>|Sn|j�r:|r>|Sn|S|j�}|r\|dkr\ttd�Sd}t}d}�x�|j�}|dks�||jk�r|dkr�|j	r�t
jj�|dko�|t
k�r|dkr�|jd7_|j�ql�q|dk�r
|jdkr�t
jj�|jd8_|j�qln�|d	k�rH|j	�s0d
|_	t|_t
}qlnd|_	t|_|j�qln�|dk�r\ttd�S|dk�r�x,|j�}|dk�s�|dk�r�P||7}�qhW|�r�|j|�tt|�S|dk�r�|j�r�t
jjd
��tt�S|j�r�|j�d}qln
ttd�Sn|}t}n
|j|�P�n�|j	�r�|dk�r�|j�}|dk�r>t
jj�|j��r�|j�}|dk�rbt
jj�|j�}	|dk�r|t
jj�|j��o�|	j��s�t
jj�tt|�dt|�dt|	��}n|dk�rt
jjd��n:|dk�r||7}d
}|j�}|dk�s|dk�rt
jj�||7}qlW|dk�rH|t
k�rH|j�rDt
jjd
��t}t|||�S)aGet the next token.

        @param want_leading: If True, return a WHITESPACE token if the
        first character read is whitespace.  The default is False.
        @type want_leading: bool
        @param want_comment: If True, return a COMMENT token if the
        first token read is a comment.  The default is False.
        @type want_comment: bool
        @rtype: Token object
        @raises dns.exception.UnexpectedEnd: input ended prematurely
        @raises dns.exception.SyntaxError: input was badly formed
        NrrrFrrrr
Tr	r
zunbalanced parenthesesr5r6r7znewline in quoted string)rQr&r,r_rr%r'r[rVrSr9r:r;r)rRr=�_QUOTING_DELIMITERSrUr#r]r+r!r-r<r>r?)
rZwant_leadingZwant_comment�tokenr^rrrBrCrDrrr�get%s�
















&

z
Tokenizer.getcCs|jdk	rt�||_dS)a@Unget a token.

        The unget buffer for tokens is only one token large; it is
        an error to try to unget a token when the unget buffer is not
        empty.

        @param token: the token to unget
        @type token: Token object
        @raises UngetBufferFull: there is already an ungotten token
        N)rQr)rrarrr�unget�s
zTokenizer.ungetcCs|j�}|j�rt�|S)zLReturn the next item in an iteration.
        @rtype: (int, string)
        )rbr"�
StopIteration)rrarrr�next�szTokenizer.nextcCs|S)Nr)rrrrrH�szTokenizer.__iter__cCs@|j�j�}|j�s tjjd��|jj�s6tjjd��t|j�S)z|Read the next token and interpret it as an integer.

        @raises dns.exception.SyntaxError:
        @rtype: int
        zexpecting an identifierzexpecting an integer)	rbrEr(r9r:r=rr<r?)rrarrr�get_int�s
zTokenizer.get_intcCs,|j�}|dks|dkr(tjjd|��|S)z�Read the next token and interpret it as an 8-bit unsigned
        integer.

        @raises dns.exception.SyntaxError:
        @rtype: int
        r�z#%d is not an unsigned 8-bit integer)rfr9r:r=)rrrrr�	get_uint8�s

zTokenizer.get_uint8cCs,|j�}|dks|dkr(tjjd|��|S)z�Read the next token and interpret it as a 16-bit unsigned
        integer.

        @raises dns.exception.SyntaxError:
        @rtype: int
        ri��z$%d is not an unsigned 16-bit integer)rfr9r:r=)rrrrr�
get_uint16�s

zTokenizer.get_uint16cCsh|j�j�}|j�s tjjd��|jj�s6tjjd��t|j�}|dksT|td�krdtjjd|��|S)z�Read the next token and interpret it as a 32-bit unsigned
        integer.

        @raises dns.exception.SyntaxError:
        @rtype: int
        zexpecting an identifierzexpecting an integerrlz$%d is not an unsigned 32-bit integer)	rbrEr(r9r:r=rr<r)rrarrrr�
get_uint32�s


zTokenizer.get_uint32cCs.|j�j�}|j�p|j�s(tjjd��|jS)z}Read the next token and interpret it as a string.

        @raises dns.exception.SyntaxError:
        @rtype: string
        zexpecting a string)rbrEr(r*r9r:r=r)r�originrarrr�
get_string�szTokenizer.get_stringcCs&|j�j�}|j�s tjjd��|jS)z�Read the next token and raise an exception if it is not an identifier.

        @raises dns.exception.SyntaxError:
        @rtype: string
        zexpecting an identifier)rbrEr(r9r:r=r)rrkrarrr�get_identifier
szTokenizer.get_identifiercCs,|j�}|j�stjjd��tjj|j|�S)z�Read the next token and interpret it as a DNS name.

        @raises dns.exception.SyntaxError:
        @rtype: dns.name.Name objectzexpecting an identifier)rbr(r9r:r=�name�	from_textr)rrkrarrr�get_nameszTokenizer.get_namecCs.|j�}|j�s(tjjd|j|jf��|jS)z�Read the next token and raise an exception if it isn't EOL or
        EOF.

        @raises dns.exception.SyntaxError:
        @rtype: string
        z expected EOL or EOF, got %d "%s")rbr/r9r:r=rr)rrarrr�get_eol!szTokenizer.get_eolcCs.|j�j�}|j�s tjjd��tjj|j�S)Nzexpecting an identifier)	rbrEr(r9r:r=Zttlror)rrarrr�get_ttl0szTokenizer.get_ttl)FF)N)N)N)rrrrrMrNr r[r\r]r_rbrcre�__next__rHrfrhrirjrlrmrprqrrrrrrrK�s($	
{



rK)r�iorrMZ
dns.exceptionr9Zdns.nameZdns.ttlZ_compatrrrrUr`r!r#r%r'r)r+r-r:ZDNSExceptionr�objectrrKrrrr�<module>s0o__pycache__/resolver.cpython-36.opt-1.pyc000064400000105700150351404330014203 0ustar003

>D�W���@s�dZddlZddlZddlZddlZyddlZWnek
rLddlZYnXddl	Z
ddlZ
ddlZ
ddl
Z
ddlZ
ddlZ
ddlZ
ddlZ
ddlZ
ddlZ
ddlZ
ddlZ
ddlmZmZejdkr�yddlZWnek
r�ddlZYnXGdd�de
jj�ZGdd	�d	e
jj�Ze
jj Z Gd
d�de
jj�Z!Gdd
�d
e
jj�Z"Gdd�de
jj�Z#Gdd�de
jj�Z$Gdd�de
jj�Z%Gdd�de&�Z'Gdd�de&�Z(Gdd�de&�Z)Gdd�de&�Z*Gdd�de&�Z+da,dd�Z-d d!�Z.e
j/j0e
j1j2d"dd#dfd$d%�Z3e
j1j2d"dfd&d'�Z4ej5ej6gej7ej8giZ9da:ej;Z<ej=Z>ej?Z@ejAZBejCZDejEZFddejGdddfd(d)�ZHd8d*d+�ZId9d,d-�ZJd.d/�ZKd0d1�ZLd2d3�ZMd:d4d5�ZNd6d7�ZOdS);z{DNS stub resolver.

@var default_resolver: The default resolver object
@type default_resolver: dns.resolver.Resolver object�N�)�xrange�string_types�win32csVeZdZdZeddg�ZdZddd�Z�fdd�Zd	d
�Z	e
e	dd�Z	d
d�Z�ZS)�NXDOMAINz"The DNS query name does not exist.�qnames�	responsesNcCs\t|tttf�std��t|�dkr,td��|dkr:i}nt|t�sLtd��t||d�}|S)Nz#qnames must be a list, tuple or setrz(qnames must contain at least one elementz(responses must be a dict(qname=response))rr)�
isinstance�list�tuple�set�AttributeError�len�dict)�selfrr�kwargs�r�/usr/lib/python3.6/resolver.py�
_check_kwargs9s
zNXDOMAIN._check_kwargscs^d|jkrtt|�j�S|jd}t|�dkr4d}n|jdd�}djtt|��}d||fS)NrrzNone of DNS query names existz, z%s: %s���)	r�superr�__str__r�__doc__�join�map�str)rr�msg)�	__class__rrrEs

zNXDOMAIN.__str__cCs�d|jkrtd��tjj}tjj}d}xj|jdD]\}|jd|}x4|jD]*}|j|ksL|j	|krfqL|j
djj�}qLW|dk	r2tj
j|�Sq2W|jddS)Nrzparametrized exception requiredrr)r�	TypeError�dns�
rdataclass�IN�	rdatatype�CNAME�answer�rdtype�rdclass�items�target�to_text�name�	from_text)rr!r#�cname�qname�responser$rrr�canonical_namePs
zNXDOMAIN.canonical_namez%Return the unresolved canonical name.)�doccCs|t|jjdg��}t|jjdi��}|jjdi�}x<|jjdg�D]*}||krX|j|�||krB||||<qBWt||d�S)z3Augment by results from another NXDOMAIN exception.rr)rr)r
r�getr�appendr)rZe_nxZqnames0Z
responses0Z
responses1Zqname1rrr�__add__bs
zNXDOMAIN.__add__)N)
�__name__�
__module__�__qualname__rr�supp_kwargs�fmtrrr/�propertyr3�
__classcell__rr)rrr3s
rc@seZdZdZdS)�YXDOMAINz8The DNS query name is too long after DNAME substitution.N)r4r5r6rrrrrr;osr;cs.eZdZdZdZedg�Z�fdd�Z�ZS)�NoAnswerz<The DNS response does not contain an answer to the question.z,The DNS response does not contain an answer zto the question: {query}r.cstt|�j|djd�S)Nr.)�query)rr<�_fmt_kwargs�question)rr)rrrr>�s
zNoAnswer._fmt_kwargszDThe DNS response does not contain an answer to the question: {query})	r4r5r6rr8rr7r>r:rr)rrr<zs

r<cs@eZdZdZdZdedd
�Zeddg�Z�fdd	�Z�Z	S)�
NoNameserversz�All nameservers failed to answer the query.

    errors: list of servers and respective errors
    The type of errors is
    [(server ip address, any object convertible to string)].
    Non-empty errors list will add explanatory message ()
    z+All nameservers failed to answer the query.z%s {query}: {errors}Nr�request�errorscsdg}x>|dD]2}|jd|d|dr*dnd|d|df�qWtt|�j|d	jd
j|�d�S)NrBz Server %s %s port %s answered %srrZTCPZUDP��rAz; )r=rB)r2rr@r>r?r)rrZsrv_msgs�err)rrrr>�s&
zNoNameservers._fmt_kwargsr)
r4r5r6rrr8rr7r>r:rr)rrr@�s
r@c@seZdZdZdS)�NotAbsolutezEAn absolute domain name is required but a relative name was provided.N)r4r5r6rrrrrrF�srFc@seZdZdZdS)�	NoRootSOAzBThere is no SOA RR at the DNS root name. This should never happen!N)r4r5r6rrrrrrG�srGc@seZdZdZdS)�
NoMetaqueriesz DNS metaqueries are not allowed.N)r4r5r6rrrrrrH�srHc@sBeZdZdZddd�Zdd�Zdd�Zd	d
�Zdd�Zd
d�Z	dS)�Answera9DNS stub resolver answer

    Instances of this class bundle up the result of a successful DNS
    resolution.

    For convenience, the answer object implements much of the sequence
    protocol, forwarding to its rrset.  E.g. "for a in answer" is
    equivalent to "for a in answer.rrset", "answer[i]" is equivalent
    to "answer.rrset[i]", and "answer[i:j]" is equivalent to
    "answer.rrset[i:j]".

    Note that CNAMEs or DNAMEs in the response may mean that answer
    node's name might not be the query name.

    @ivar qname: The query name
    @type qname: dns.name.Name object
    @ivar rdtype: The query type
    @type rdtype: int
    @ivar rdclass: The query class
    @type rdclass: int
    @ivar response: The response message
    @type response: dns.message.Message object
    @ivar rrset: The answer
    @type rrset: dns.rrset.RRset object
    @ivar expiration: The time when the answer expires
    @type expiration: float (seconds since the epoch)
    @ivar canonical_name: The canonical name of the query name
    @type canonical_name: dns.name.Name object
    TcCs�||_||_||_||_d}d}x�tdd�D]�}y0|j|j|||�}|dksV|j|kr\|j}PWq,tk
�r|t	j
jkr�yJ|j|j||t	j
j�}	|dks�|	j|kr�|	j}x|	D]}
|
j}Pq�Ww,Wn"tk
r�|r�t
|d��YnX|�r�t
|d��Yq,Xq,W|dk�r |�r t
|d��||_||_|dk�r�x�yR|j|j||t	j
j�}|dk�sf|j|k�rl|j}|dj|k�r�|dj}PWn@tk
�r�y|j�}Wnt	jjk
�r�PYnXYnX�q8Wtj�||_dS)	Nrr�)r.rrrr)r-r%r&r.rZ
find_rrsetr$�ttl�KeyErrorrr"r#r(r<r/�rrsetZ	authority�SOAZminimum�parentr*�NoParent�time�
expiration)rr-r%r&r.�raise_on_no_answerZmin_ttlrM�countZcrrsetZrdZsrrsetrrr�__init__�sf






zAnswer.__init__cCs\|dkr|jjS|dkr |jjS|dkr0|jjS|dkr@|jjS|dkrP|jjSt|��dS)Nr*rK�coversr&r%)rMr*rKrVr&r%r
)r�attrrrr�__getattr__szAnswer.__getattr__cCs|jrt|j�pdS)Nr)rMr)rrrr�__len__szAnswer.__len__cCs|jrt|j�ptt��S)N)rM�iterr)rrrr�__iter__szAnswer.__iter__cCs
|j|S)N)rM)r�irrr�__getitem__szAnswer.__getitem__cCs|j|=dS)N)rM)rr\rrr�__delitem__szAnswer.__delitem__N)T)
r4r5r6rrUrXrYr[r]r^rrrrrI�s
7rIc@s<eZdZdZddd�Zdd�Zdd�Zd	d
�Zddd
�ZdS)�CacheaqSimple DNS answer cache.

    @ivar data: A dictionary of cached data
    @type data: dict
    @ivar cleaning_interval: The number of seconds between cleanings.  The
    default is 300 (5 minutes).
    @type cleaning_interval: float
    @ivar next_cleaning: The time the cache should next be cleaned (in seconds
    since the epoch.)
    @type next_cleaning: float
    ��r@cCs*i|_||_tj�|j|_tj�|_dS)z�Initialize a DNS cache.

        @param cleaning_interval: the number of seconds between periodic
        cleanings.  The default is 300.0
        @type cleaning_interval: float.
        N)�data�cleaning_intervalrQ�
next_cleaning�
_threading�Lock�lock)rrbrrrrU-szCache.__init__cCsptj�}|j|krlg}x*|jj�D]\}}|j|kr"|j|�q"Wx|D]}|j|=qHWtj�}||j|_dS)z&Clean the cache if it's time to do so.N)rQrcrar'rRr2rb)r�nowZkeys_to_delete�k�vrrr�_maybe_clean:s


zCache._maybe_cleanc
CsNz<|jj�|j�|jj|�}|dks6|jtj�kr:dS|S|jj�XdS)a)Get the answer associated with I{key}.  Returns None if
        no answer is cached for the key.
        @param key: the key
        @type key: (dns.name.Name, int, int) tuple whose values are the
        query name, rdtype, and rdclass.
        @rtype: dns.resolver.Answer object or None
        N)rf�acquirerjrar1rRrQ�release)r�keyrirrrr1Hs	
z	Cache.getc
Cs2z |jj�|j�||j|<Wd|jj�XdS)aAssociate key and value in the cache.
        @param key: the key
        @type key: (dns.name.Name, int, int) tuple whose values are the
        query name, rdtype, and rdclass.
        @param value: The answer being cached
        @type value: dns.resolver.Answer object
        N)rfrkrjrarl)rrm�valuerrr�put[s
	
z	Cache.putNc
CsRz@|jj�|dk	r(||jkr>|j|=ni|_tj�|j|_Wd|jj�XdS)z�Flush the cache.

        If I{key} is specified, only that item is flushed.  Otherwise
        the entire cache is flushed.

        @param key: the key to flush
        @type key: (dns.name.Name, int, int) tuple or None
        N)rfrkrarQrbrcrl)rrmrrr�flushks



zCache.flush)r`)N)	r4r5r6rrUrjr1rorprrrrr_s

r_c@s0eZdZdZdd�Zdd�Zdd�Zdd	�Zd
S)�LRUCacheNodezLRUCache node.
    cCs||_||_||_||_dS)N)rmrn�prev�next)rrmrnrrrrU�szLRUCacheNode.__init__cCs |j|_||_||j_||_dS)N)rrrs)r�noderrr�link_before�szLRUCacheNode.link_beforecCs ||_|j|_||j_||_dS)N)rrrs)rrtrrr�
link_after�szLRUCacheNode.link_aftercCs|j|j_|j|j_dS)N)rrrs)rrrr�unlink�s
zLRUCacheNode.unlinkN)r4r5r6rrUrurvrwrrrrrq�s
rqc@s<eZdZdZddd�Zdd�Zdd�Zd	d
�Zddd
�ZdS)�LRUCacheaOBounded least-recently-used DNS answer cache.

    This cache is better than the simple cache (above) if you're
    running a web crawler or other process that does a lot of
    resolutions.  The LRUCache has a maximum number of nodes, and when
    it is full, the least-recently used node is removed to make space
    for a new one.

    @ivar data: A dictionary of cached data
    @type data: dict
    @ivar sentinel: sentinel node for circular doubly linked list of nodes
    @type sentinel: LRUCacheNode object
    @ivar max_size: The maximum number of nodes
    @type max_size: int
    順cCs*i|_|j|�tdd�|_tj�|_dS)z�Initialize a DNS cache.

        @param max_size: The maximum number of nodes to cache; the default is
        100,000. Must be greater than 1.
        @type max_size: int
        N)ra�set_max_sizerq�sentinelrdrerf)r�max_sizerrrrU�s
zLRUCache.__init__cCs|dkrd}||_dS)Nr)r|)rr|rrrrz�szLRUCache.set_max_sizec
CslzZ|jj�|jj|�}|dkr$dS|j�|jjtj�krJ|j|j=dS|j	|j
�|jS|jj�XdS)a)Get the answer associated with I{key}.  Returns None if
        no answer is cached for the key.
        @param key: the key
        @type key: (dns.name.Name, int, int) tuple whose values are the
        query name, rdtype, and rdclass.
        @rtype: dns.resolver.Answer object or None
        N)rfrkrar1rwrnrRrQrmrvr{rl)rrmrtrrrr1�s

zLRUCache.getc
Cs�z�|jj�|jj|�}|dk	r2|j�|j|j=x.t|j�|jkr`|jj	}|j�|j|j=q4Wt
||�}|j|j�||j|<Wd|jj�XdS)aAssociate key and value in the cache.
        @param key: the key
        @type key: (dns.name.Name, int, int) tuple whose values are the
        query name, rdtype, and rdclass.
        @param value: The answer being cached
        @type value: dns.resolver.Answer object
        N)
rfrkrar1rwrmrr|r{rrrqrvrl)rrmrnrtrrrro�s


zLRUCache.putNc
Cs�zr|jj�|dk	r<|jj|�}|dk	rp|j�|j|j=n4|jj}x$||jkrh|j}d|_d|_|}qFWi|_Wd|jj	�XdS)z�Flush the cache.

        If I{key} is specified, only that item is flushed.  Otherwise
        the entire cache is flushed.

        @param key: the key to flush
        @type key: (dns.name.Name, int, int) tuple or None
        N)
rfrkrar1rwrmr{rsrrrl)rrmrtrsrrrrp�s	

zLRUCache.flush)ry)N)	r4r5r6rrUrzr1rorprrrrrx�s
rxc@s�eZdZdZd%dd�Zdd�Zdd	�Zd
d�Zdd
�Zdd�Z	dd�Z
dd�Zdd�Zdd�Z
dd�Zejjejjddddfdd�Zdejjfdd �Zd!d"�Zd#d$�ZdS)&�Resolvera-DNS stub resolver

    @ivar domain: The domain of this host
    @type domain: dns.name.Name object
    @ivar nameservers: A list of nameservers to query.  Each nameserver is
    a string which contains the IP address of a nameserver.
    @type nameservers: list of strings
    @ivar search: The search list.  If the query name is a relative name,
    the resolver will construct an absolute query name by appending the search
    names one by one to the query name.
    @type search: list of dns.name.Name objects
    @ivar port: The port to which to send queries.  The default is 53.
    @type port: int
    @ivar timeout: The number of seconds to wait for a response from a
    server, before timing out.
    @type timeout: float
    @ivar lifetime: The total number of seconds to spend trying to get an
    answer to the question.  If the lifetime expires, a Timeout exception
    will occur.
    @type lifetime: float
    @ivar keyring: The TSIG keyring to use.  The default is None.
    @type keyring: dict
    @ivar keyname: The TSIG keyname to use.  The default is None.
    @type keyname: dns.name.Name object
    @ivar keyalgorithm: The TSIG key algorithm to use.  The default is
    dns.tsig.default_algorithm.
    @type keyalgorithm: string
    @ivar edns: The EDNS level to use.  The default is -1, no Edns.
    @type edns: int
    @ivar ednsflags: The EDNS flags
    @type ednsflags: int
    @ivar payload: The EDNS payload size.  The default is 0.
    @type payload: int
    @ivar flags: The message flags to use.  The default is None (i.e. not
    overwritten)
    @type flags: int
    @ivar cache: The cache to use.  The default is None.
    @type cache: dns.resolver.Cache object
    @ivar retry_servfail: should we retry a nameserver if it says SERVFAIL?
    The default is 'false'.
    @type retry_servfail: bool
    �/etc/resolv.confTcCs�d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_	d|_
d|_d|_d|_
d|_d|_d|_|j�|r�tjdkr�|j�n|r�|j|�dS)aJInitialize a resolver instance.

        @param filename: The filename of a configuration file in
        standard /etc/resolv.conf format.  This parameter is meaningful
        only when I{configure} is true and the platform is POSIX.
        @type filename: string or file object
        @param configure: If True (the default), the resolver instance
        is configured in the normal fashion for the operating system
        the resolver is running on.  (I.e. a /etc/resolv.conf file on
        POSIX systems and from the registry on Windows systems.)
        @type configure: boolNFr)�domain�nameservers�nameserver_ports�port�search�timeout�lifetime�keyring�keyname�keyalgorithm�edns�	ednsflags�payload�cache�flags�retry_servfail�rotate�reset�sys�platform�
read_registry�read_resolv_conf)r�filenameZ	configurerrrrU9s.


zResolver.__init__cCs�tjjtjjtj��dd��|_t|j�dkr:tjj|_g|_	i|_
d|_g|_d|_
d|_d|_d|_tjj|_d|_d|_d|_d|_d|_d|_d|_dS)	z1Reset all resolver configuration to the defaults.rNr�5g@g>@Fr)rr*�Namer+�socket�gethostnamerr�rootr�r�r�r�r�r�r�r��tsig�default_algorithmr�r�r�r�r�r�r�r�)rrrrr�_s&"

zResolver.resetcCsZt|t�r<yt|d�}Wntk
r4dg|_dSXd}nd}z�x�|D]�}t|�dksH|ddksH|ddkrrqH|j�}t|�d	kr�qH|dd
kr�|jj|d�qH|ddkr�tj	j
|d�|_qH|dd
k�rxL|dd�D]}|jjtj	j
|��q�WqH|ddkrHd|dd�krHd|_
qHWWd|�r8|j�Xt|j�dk�rV|jjd�dS)z�Process f as a file in the /etc/resolv.conf format.  If f is
        a string, it is used as the name of the file to open; otherwise it
        is treated as the file itself.�rz	127.0.0.1NTFr�#�;rC�
nameserverrrr�Zoptionsr�)r	r�open�IOErrorr�r�splitr2rr*r+rr�r��close)r�fZ
want_close�l�tokens�suffixrrrr�vs:

$
zResolver.read_resolv_confcCs0|jd�dkrd}n|jd�dkr(d}nd}|S)N� r�,)�find)r�entry�
split_charrrr�_determine_split_char�szResolver._determine_split_charcCsDt|�}|j|�}|j|�}x"|D]}||jkr"|jj|�q"WdS)z&Configure a NameServer registry entry.N)rr�r�r�r2)rr�r�Zns_list�nsrrr�_config_win32_nameservers�s



z"Resolver._config_win32_nameserverscCstjjt|��|_dS)z"Configure a Domain registry entry.N)rr*r+rr)rrrrr�_config_win32_domain�szResolver._config_win32_domaincCsLt|�}|j|�}|j|�}x*|D]"}||jkr"|jjtjj|��q"WdS)z"Configure a Search registry entry.N)rr�r�r�r2rr*r+)rr�r�Zsearch_list�srrr�_config_win32_search�s



zResolver._config_win32_searchc#Cs.ytj|d�\}}Wntk
r,d}YnX|rv|j|�y"tj|d�\}}|r\|j|�Wq�tk
rrYq�Xntytj|d�\}}Wntk
r�d}YnX|r�|j|�y"tj|d�\}}|r�|j|�Wntk
r�YnXytj|d�\}}Wntk
�rd}YnX|�r*|j|�dS)z%Extract DNS info from a registry key.Z
NameServerNZDomainZDhcpNameServerZ
DhcpDomainZ
SearchList)�_winreg�QueryValueEx�WindowsErrorr�r�r�)rrmZserversZrtypeZdomr�rrr�_config_win32_fromkey�s<




zResolver._config_win32_fromkeyc,Cstjdtj�}d}z�ytj|d�}d}Wn tk
rHtj|d�}YnXz|j|�Wd|j�X|r�tj|d�}ztd}xjyNtj||�}|d7}tj||�}|j|||�s�w|z|j|�Wd|j�XWq|tk
r�PYq|Xq|WWd|j�XWd|j�XdS)	z9Extract resolver configuration from the Windows registry.NFz2SYSTEM\CurrentControlSet\Services\Tcpip\ParametersTz+SYSTEM\CurrentControlSet\Services\VxD\MSTCPz=SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfacesrr)	r�ZConnectRegistry�HKEY_LOCAL_MACHINE�OpenKey�EnvironmentErrorr��CloseZEnumKey�_win32_is_nic_enabled)r�lmZ	want_scanZ
tcp_paramsZ
interfacesr\�guidrmrrrr��s@
zResolver.read_registryc
Cs�y�tj|d|�}zftj|d�\}}|tjkr2t�tj|d|�}z(tj|d�\}}|tjkrbt�|d@S|j�XWd|j�XWnFttfk
r�ytj|d�\}	}|	dk	Stk
r�dSXYnXdS)Nz]SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\%s\ConnectionZ
PnpInstanceIDz SYSTEM\CurrentControlSet\Enum\%sZConfigFlagsrZNTEContextListF)	r�r�r�ZREG_SZ�
ValueErrorZ	REG_DWORDr�r�r�)
rr�r�Z
interface_keyZconnection_keyZpnp_idZttypeZ
device_keyr�Znterrrr�s6



zResolver._win32_is_nic_enabledcCsVtj�}||}|dkr0|dkr,t|d��n|}||jkrDt|d��t|j||j�S)Nrr)r�r)rQ�Timeoutr��minr�)r�startrgZdurationrrr�_compute_timeoutMs

zResolver._compute_timeoutFNrcCst|t�rtjj|d�}t|t�r.tjj|�}tjj|�r>t�t|t�rTtjj|�}tjj	|�rdt�g}|j
�r||j|�nZt|�dkr�|j|j
tjj��|jr�x2|jD]}	|j|j
|	��q�Wn|j|j
|j��d}
i}tj�}d}
�x�|D�]�}
|j�r@|jj|
||f�}|dk	�r@|jdk�r<|�r<t|jd��n|Stjj|
||�}|jdk	�rr|j|j|j|jd�|j|j|j|j �|j!dk	�r�|j!|_!d}|j"dd�}g}|j#�r�t$j%|�d}�x�|dk�r�t|�dk�r�t&||d���x`|dd�D�]N}|j'|�}|j(j||j)�}yx|}|�rDtj*j+||||||d	�}nNtj*j,||||||d	�}|j!tj!j-@�r�d}|j'|�}tj*j+||||||d	�}W�n t.j/tj0j1fk
�r�}z"|j|||||f�d}�w�WYdd}~Xn�tj*j2k
�r"}z"|j|||||f�d}�w�WYdd}~Xn�tj0j3k
�rn}z,|j4|�|j|||||f�d}�w�WYdd}~XnJt5k
�r�}z,|j4|�|j|||||f�d}�w�WYdd}~XnX|j6�}|tj6j7k�r�t7�}|j|||||f�|�|tj6j8k�s|tj6j9k�r
P|tj6j:k�s"|j;�r,|j4|�|j|||tj6j<|�|f�d}�q�W|dk	�r^Pt|�dk�r�|j'|�}t=||�}|d
9}tj>|��q�W|j6�tj6j9k�r�|||
<q�d}
Pq�W|
�r�t9||d��t?|
||||�}|j�r�|jj@|
||f|�|S)
aQuery nameservers to find the answer to the question.

        The I{qname}, I{rdtype}, and I{rdclass} parameters may be objects
        of the appropriate type, or strings that can be converted into objects
        of the appropriate type.  E.g. For I{rdtype} the integer 2 and the
        the string 'NS' both mean to query for records with DNS rdata type NS.

        @param qname: the query name
        @type qname: dns.name.Name object or string
        @param rdtype: the query type
        @type rdtype: int or string
        @param rdclass: the query class
        @type rdclass: int or string
        @param tcp: use TCP to make the query (default is False).
        @type tcp: bool
        @param source: bind to this IP address (defaults to machine default
        IP).
        @type source: IP address in dotted quad notation
        @param raise_on_no_answer: raise NoAnswer if there's no answer
        (defaults is True).
        @type raise_on_no_answer: bool
        @param source_port: The port from which to send the message.
        The default is 0.
        @type source_port: int
        @rtype: dns.resolver.Answer instance
        @raises Timeout: no answers could be found in the specified lifetime
        @raises NXDOMAIN: the query name does not exist
        @raises YXDOMAIN: the query name is too long after DNAME substitution
        @raises NoAnswer: the response did not contain an answer and
        raise_on_no_answer is True.
        @raises NoNameservers: no non-broken nameservers are available to
        answer the question.NrT)r.)�	algorithmg�������?r)rArB)�source�source_portrCF)rr)Ar	rrr*r+r"Zis_metatyperHr Zis_metaclass�is_absoluter2rZconcatenater�r�rrQr�r1rMr<r.�messageZ
make_queryr��use_tsigr�r��use_ednsr�r�r�r�r�r��randomZshuffler@r�r�r�r=�tcp�udpZTCr��error�	exceptionr�ZUnexpectedSourceZ	FormError�remove�EOFError�rcoder;ZNOERRORrZSERVFAILr�r)r�ZsleeprIro)rr-r%r&r�r�rSr�Z
qnames_to_tryr�Zall_nxdomainZnxdomain_responsesr�Z_qnamer$rAr.r�rBZbackoffr�r�r�Ztcp_attemptZexr�Z
sleep_timerrrr=]s�#




















zResolver.querycCs4||_|dkr$t|jj��d|_n||_||_dS)a�Add a TSIG signature to the query.

        @param keyring: The TSIG keyring to use; defaults to None.
        @type keyring: dict
        @param keyname: The name of the TSIG key to use; defaults to None.
        The key must be defined in the keyring.  If a keyring is specified
        but a keyname is not, then the key used will be the first key in the
        keyring.  Note that the order of keys in a dictionary is not defined,
        so applications should supply a keyname when a keyring is used, unless
        they know the keyring contains only one key.
        @param algorithm: The TSIG key algorithm to use.  The default
        is dns.tsig.default_algorithm.
        @type algorithm: stringNr)r�r
�keysr�r�)rr�r�r�rrrr�"s
zResolver.use_tsigcCs"|dkrd}||_||_||_dS)aConfigure Edns.

        @param edns: The EDNS level to use.  The default is -1, no Edns.
        @type edns: int
        @param ednsflags: The EDNS flags
        @type ednsflags: int
        @param payload: The EDNS payload size.  The default is 0.
        @type payload: intNrr)r�r�r�)rr�r�r�rrrr�8s

zResolver.use_ednscCs
||_dS)z�Overrides the default flags with your own

        @param flags: The flags to overwrite the default with
        @type flags: intN)r�)rr�rrr�	set_flagsHszResolver.set_flags)r~T)r4r5r6rrUr�r�r�r�r�r�r�r�r�r�rr"�Ar r!r=r�r�r�r�r�rrrrr}s&+
&)

"-7Er}cCstdkrt�tS)z7Get the default resolver, initializing it if necessary.N)�default_resolver�reset_default_resolverrrrr�get_default_resolverRsr�cCs
t�adS)zSRe-initialize default resolver.

    resolv.conf will be re-read immediatelly.
    N)r}r�rrrrr�Ysr�FTcCst�j|||||||�S)z�Query nameservers to find the answer to the question.

    This is a convenience function that uses the default resolver
    object to make the query.
    @see: L{dns.resolver.Resolver.query} for more information on the
    parameters.)r�r=)r-r%r&r�r�rSr�rrrr=bs	r=cCs�t|t�rtjj|tjj�}|dkr*t�}|j�s:t|��xxy(|j	|tj
j||�}|jj|krb|SWn tj
jtj
jfk
r�YnXy|j�}Wq<tjjk
r�t�Yq<Xq<WdS)a�Find the name of the zone which contains the specified name.

    @param name: the query name
    @type name: absolute dns.name.Name object or string
    @param rdclass: The query class
    @type rdclass: int
    @param tcp: use TCP to make the query (default is False).
    @type tcp: bool
    @param resolver: the resolver to use
    @type resolver: dns.resolver.Resolver object or None
    @rtype: dns.name.NameN)r	rrr*r+r�r�r�rFr=r"rNrM�resolverrr<rOrPrG)r*r&r�r�r$rrr�
zone_for_nameos"
r�c,Cs�|tjtjB@dkrt�|dkr4|dkr4tjtj��g}g}d}y�|dkr�d}|tj@dkrr|jd�|jd�q�|jd�|jd�n>|jd�}	t	|	�dkr�|	d}
n|}
t
jj|
�}|j|�|}W�npt
k
�r:y t
jj|�}|j|�|}W�n8t
k
�r4|tj@dk�r0y�|tjk�s8|tjk�r�tj|t
jjd	d
�}|j}|jjd�}|jdk	�r�x|jD]}
|j|
j��qrW|tjk�s�|tjk�r�tj|t
jjd	d
�}|j}|jjd�}|jdk	�r�x|jD]}
|j|
j��q�WWn<t
jjk
�rtjtj��Yntjtj��YnXYnXYnXd}y|dk�rRd}nt |�}WnLt
k
�r�|tj!@dk�r�ytj"|�}Wnt
k
�r�YnXYnX|dk�r�tjtj��g}|dk�r�tj#tj$g}n|g}|tj%@dk�r�|}nd}|tjk�s|tjk�rfxP|D]H}x@|D]8}x0t&|D]$}|jtj|||||ddff��q2W�q$W�qW|tjk�s~|tjk�r�xL|D]D}x<|D]4}x,t&|D] }|jtj|||||ff��q�W�q�W�q�Wt	|�dk�r�tjtj��|S)
NrZ	localhostz::z0.0.0.0z::1z	127.0.0.1�%rCF)rST�)'r�Z
AI_ADDRCONFIGZAI_V4MAPPED�NotImplementedError�gaierror�
EAI_NONAMEZ
AI_PASSIVEr2r�rr�ipv6�	inet_aton�	ExceptionZipv4ZAI_NUMERICHOST�AF_INET6�	AF_UNSPEC�	_resolverr=r"ZAAAAr-r/r)rMZaddress�AF_INETr�r�rZ
EAI_SYSTEM�intZAI_NUMERICSERVZ
getservbyname�
SOCK_DGRAM�SOCK_STREAM�AI_CANONNAME�_protocols_for_socktype)�host�service�familyZsocktype�protor�Zv6addrsZv4addrsr/�partsZahost�addrZv6ZrdataZv4r��tuplesZ	socktypesr,rrr�_getaddrinfo�s�












$

 r�c
Csf|d}|d}t|�dkr,|d}tj}n
d}tj}t|||tjtjd�}t|�dkrbtjd��|ddd}|tj@r�d}nd}t	j
j|�}	|tj@dk�ry"t
j|	d�}
|
jdjjd	�}WnVt	jjt	jjfk
�r|tj@r�tjtj��|}|dk	�r|d
t|�7}YnXn|}|dk	�r<|d
t|�7}|tj@�rRt|�}ntj||�}||fS)Nrr�rDz'sockaddr resolved to multiple addressesr�r�ZPTRTr�)rr�r�r�r�r��SOL_TCPr�ZNI_DGRAMrZreversenameZfrom_addressZNI_NUMERICHOSTr�r=rMr(r)r�rr<�NI_NAMEREQDr�r�rZNI_NUMERICSERVZ
getservbyport)
�sockaddrr�r�r�Zscoper�r�r�Zpnamer-r$Zhostnamer�rrr�_getnameinfosB






r�cCsD|dkrtj�}ytt|d�dd�dStk
r>|SXdS)N�Prr�)r�r�r�r�r�)r*rrr�_getfqdn.sr�cCst|�ddS)NrCr)�_gethostbyname_ex)r*rrr�_gethostbyname7sr�cCsXg}g}t|dtjtjtjtj�}|dd}x|D]}|j|dd�q4W|||fS)NrrDr�)r�r�r�r�r�r�r2)r*�aliases�	addressesr��	canonical�itemrrrr�;s
r�c
Cs�y"tjj|�|dddf}tj}Wn"tk
rD|df}tj}YnXt|tj�\}}g}g}t	|d|tj
tjtj�}|dd}x|D]}	|j
|	dd�q�W|||fS)Nr�rrDr�)rr�r�r�r�r�r�r�r�r�r�r�r�r2)
Zipr�r�r*r�r�r�r�r�rrrr�_gethostbyaddrGs 

rcCs:|dkrt�}|att_tt_tt_t	t_
tt_t
t_dS)a�Override the system resolver routines in the socket module with
    versions which use dnspython's resolver.

    This can be useful in testing situations where you want to control
    the resolution behavior of python code without having to change
    the system's resolver settings (e.g. /etc/resolv.conf).

    The resolver to use may be specified; if it's not, the default
    resolver will be used.

    @param resolver: the resolver to use
    @type resolver: dns.resolver.Resolver object or None
    N)r�r�r�r��getaddrinfor��getnameinfor��getfqdnr��
gethostbynamer��gethostbyname_exr�
gethostbyaddr)r�rrr�override_system_resolver[srcCs,datt_tt_tt_tt_	t
t_tt_
dS)z4Undo the effects of override_system_resolver().
    N)r��_original_getaddrinfor�r�_original_getnameinfor�_original_getfqdnr�_original_gethostbynamer�_original_gethostbyname_exr�_original_gethostbyaddrrrrrr�restore_system_resolverusr)r)N)N)Prr�r�rQr�Z	threadingrd�ImportErrorZdummy_threadingZ
dns.exceptionrZ	dns.flagsZdns.ipv4Zdns.ipv6Zdns.messageZdns.nameZ	dns.queryZ	dns.rcodeZdns.rdataclassZ
dns.rdatatypeZdns.reversenameZdns.tsigZ_compatrrr��winregr�r�ZDNSExceptionrr;r�r<r@rFrGrH�objectrIr_rqrxr}r�r�r�r"r�r r!r=r�r�ZSOL_UDPr�r�r�r�rr	rr
rrrrrr
rrr�r�r�r�r�r�rrrrrrr�<module>s�
<sboG	&

c
(
	
__pycache__/grange.cpython-36.pyc000064400000001702150351404330012643 0ustar003

�b�W��@sdZddlZdd�ZdS)zDNS GENERATE range conversion.�NcCs�d}d}d}|r(|ddkr(tjjd��xj|D]b}|dkrT|dkrTt|�}d}d}q.|dkrnt|�}d}d}q.|j�r�||7}q.tjjd	|��q.W|dkr�tjj��|dkr�t|�}|dkr�t|�}|dks�t�|dks�t�||ks�t�|||fS)z�Convert the text form of a range in a GENERATE statement to an
    integer.

    @param text: the textual range
    @type text: string
    @return: The start, stop and step values.
    @rtype: tuple
    ��r�-z!Start cannot be a negative number��/�zCould not parse %s�)rr)�dnsZ	exception�SyntaxError�int�isdigit�AssertionError)�text�stepZcur�state�c�start�stop�r�/usr/lib/python3.6/grange.py�	from_texts6


r)�__doc__r	rrrrr�<module>s__pycache__/reversename.cpython-36.opt-1.pyc000064400000005041150351404330014653 0ustar003

�b�W��@sXdZddlZddlZddlZddlZddlZejjd�Z	ejjd�Z
dd�Zdd�ZdS)	aDNS Reverse Map Names.

@var ipv4_reverse_domain: The DNS IPv4 reverse-map domain, in-addr.arpa.
@type ipv4_reverse_domain: dns.name.Name object
@var ipv6_reverse_domain: The DNS IPv6 reverse-map domain, ip6.arpa.
@type ipv6_reverse_domain: dns.name.Name object
�Nz
in-addr.arpa.z	ip6.arpa.cCs�yztjj|�}tjj|�rXtjdkr<dd�|dd�D�}ndd�|dd�D�}t}n dd�ttj	|�j
��D�}t}Wn2tk
r�dd�t
tjj|��D�}t}YnX|j�tjjd	j|�|d
�S)aConvert an IPv4 or IPv6 address in textual form into a Name object whose
    value is the reverse-map domain name of the address.
    @param text: an IPv4 or IPv6 address in textual form (e.g. '127.0.0.1',
    '::1')
    @type text: str
    @rtype: dns.name.Name object
    �cSsg|]}d|�qS)z%d�)�.0�byterr�!/usr/lib/python3.6/reversename.py�
<listcomp>/sz from_address.<locals>.<listcomp>�NcSsg|]}dt|��qS)z%d)�ord)rrrrrr1scSsg|]}|�qSrr)r�xrrrr4scSsg|]}d|�qS)z%dr)rrrrrr7s�.)�origin)r)�dns�ipv6�	inet_atonZ	is_mapped�sys�version_info�ipv4_reverse_domain�str�binasciiZhexlify�decode�ipv6_reverse_domain�	Exception�	bytearray�ipv4�reverse�name�	from_text�join)�textZv6�partsrrrr�from_address#s

r cCs�|jt�rD|jt�}t|j�}|j�dj|�}tjj	tjj
|��S|jt�r�|jt�}t|j�}|j�g}d}t|�}x0||kr�|j
dj|||d���|d7}q|Wdj|�}tjj	tjj
|��Stjjd��dS)z�Convert a reverse map domain name into textual address form.
    @param name: an IPv4 or IPv6 address in reverse-map form.
    @type name: dns.name.Name object
    @rtype: str
    �.r���:z"unknown reverse-map address familyN)Zis_subdomainrZ
relativize�list�labelsrrr
rZ	inet_ntoarr�len�appendrZ	exception�SyntaxError)rr&rr�i�lrrr�
to_address>s&








r,)
�__doc__rrZdns.namer
Zdns.ipv6Zdns.ipv4rrrrr r,rrrr�<module>s__pycache__/tsig.cpython-36.pyc000064400000014101150351404330012343 0ustar003

�b�W&�@s~dZddlZddlZddlZddlZddlZddlZddlm	Z	m
Z
mZGdd�dejj
�ZGdd�dejj
�ZGd	d
�d
ejj
�ZGdd�de�ZGd
d�de�ZGdd�de�ZGdd�de�Zejjd�Zejjd�Zejjd�Zejjd�Zejjd�Zejjd�ZedededededediZeZdZd Z d!Z!d"Z"dd#d$efd%d&�Z#dd#d$efd'd(�Z$d/d)d*�Z%d+d,�Z&d-d.�Z'dS)0zDNS TSIG support.�N�)�long�string_types�	text_typec@seZdZdZdS)�BadTimez8The current time is not within the TSIG's validity time.N)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/tsig.pyrsrc@seZdZdZdS)�BadSignaturez#The TSIG signature fails to verify.N)rrr	r
rrrrr
 sr
c@seZdZdZdS)�	PeerErrorz;Base class for all TSIG errors generated by the remote peerN)rrr	r
rrrrr%src@seZdZdZdS)�
PeerBadKeyz$The peer didn't know the key we usedN)rrr	r
rrrrr*src@seZdZdZdS)�PeerBadSignaturez*The peer didn't like the signature we sentN)rrr	r
rrrrr/src@seZdZdZdS)�PeerBadTimez%The peer didn't like the time we sentN)rrr	r
rrrrr4src@seZdZdZdS)�PeerBadTruncationz=The peer didn't like amount of truncation in the TSIG we sentN)rrr	r
rrrrr9srzHMAC-MD5.SIG-ALG.REG.INTz	hmac-sha1zhmac-sha224zhmac-sha256zhmac-sha384zhmac-sha512ZSHA224ZSHA256ZSHA384ZSHA512ZSHA1ZMD5����FTc
Cs�t|t�r|j�}t|�\}
}|r\tj||d�}	t|�}|dkr\|	jtj	d|��|	j|�tj	d|�}|	j|�|	j|dd��|r�|	j|j
��|	jtj	dtjj
��|	jtj	dd��|td�}|d?td�@}|td	�@}tj	d
|||�}|
|}t|�}|dk�rtd��tj	d||�|}|�rF|	j|�|	j|�n
|	j|�|	j�}tj	dt|��}|||||}|
�r�tj||d�}	t|�}|	jtj	d|��|	j|�nd}	|||	fS)
ajReturn a (tsig_rdata, mac, ctx) tuple containing the HMAC TSIG rdata
    for the input parameters, the HMAC MAC calculated by applying the
    TSIG signature algorithm, and the TSIG digest context.
    @rtype: (string, string, hmac.HMAC object)
    @raises ValueError: I{other_data} is too long
    @raises NotImplementedError: I{algorithm} is not supported
    )�	digestmodrz!H�Nz!I� i��l��z!HIHz TSIG Other Data is > 65535 bytesz!HH)�
isinstancer�encode�
get_algorithm�hmac�new�len�update�struct�pack�
to_digestable�dnsZ
rdataclass�ANYr�
ValueErrorZdigest)�wire�keyname�secret�time�fudge�original_id�error�
other_data�request_mac�ctx�multi�first�	algorithmZalgorithm_namerZml�idZ	long_time�
upper_time�
lower_timeZtime_macZpre_macZolZpost_mac�macZmpack�
tsig_rdatarrr�signWsN





r9c

Cs t||||||||||	|
||�
S)N)r9)
r'r(r)r*r+r,r-r.r/r0r1r2r3rrr�hmac_md5�sr:cCs�tjd|dd��\}|dkr&tjj�|d8}|dd�tjd|�|d|�}|}
tjj||
�\}}|
|}
tjd||
|
d��\}}}}|td�d>|td�}|
d7}
||
|
|�}|
|7}
tjd||
|
d	��\}}}|
d	7}
||
|
|�}|
|7}
|
||k�r tjj�|dk�rv|t	k�r:t
�n<|tk�rJt�n,|t
k�rZt�n|tk�rjt�ntd
|��||}||}||k�s�||k�r�t�t|||||||||||	|
|�
\}}}||k�r�t�|S)a*Validate the specified TSIG rdata against the other input parameters.

    @raises FormError: The TSIG is badly formed.
    @raises BadTime: There is too much time skew between the client and the
    server.
    @raises BadSignature: The TSIG signature did not validate
    @rtype: hmac.HMAC objectz!H�
�rrz!HIHHrz!HHH�zunknown TSIG error code %d)r!�unpackr$�	exception�	FormErrorr"�name�	from_wirer�BADSIGr�BADKEYr�BADTIMEr�BADTRUNCrrrr9r
)r'r(r)Znowr/Z
tsig_startr8�
tsig_rdlenr0r1r2ZadcountZnew_wire�current�aname�usedr5r6r+�mac_sizer*r7r,r-Z
other_sizer.Ztime_lowZ	time_highZjunkZour_macrrr�validate�sN
$ 





rLcCs\t|t�rtjj|�}y|j�tjjt|fSt	k
rVt
dt|�d��YnXdS)z�Returns the wire format string and the hash module to use for the
    specified TSIG algorithm

    @rtype: (string, hash constructor)
    @raises NotImplementedError: I{algorithm} is not supported
    zTSIG algorithm z is not supportedN)rrr$rA�	from_textr#�hashZhashes�_hashes�KeyError�NotImplementedError�str)r3rrrr�s
rcCsz|}tjj||�\}}||}tjd|||d��\}}}}	|d7}||||	�}
||	7}|||krrtjj�||
fS)zlReturn the tsig algorithm for the specified tsig_rdata
    @raises FormError: The TSIG is badly formed.
    z!HIHHr;)r$rArBr!r>r?r@)r'r8rGrHrIrJr5r6r+rKr7rrr�get_algorithm_and_mac�s rS)NFT)(r
rr!Z
dns.exceptionr$Zdns.hashZdns.rdataclassZdns.nameZ_compatrrrr?ZDNSExceptionrr
rrrrrrArMZHMAC_MD5Z	HMAC_SHA1ZHMAC_SHA224ZHMAC_SHA256ZHMAC_SHA384ZHMAC_SHA512rOZdefault_algorithmrCrDrErFr9r:rLrrSrrrr�<module>sL5
5__pycache__/rcode.cpython-36.pyc000064400000004667150351404330012511 0ustar003

�b�W �
@s�dZddlZddlmZdZdZdZdZdZ	dZ
d	Zd
ZdZ
dZd
ZdZeeeee	e
eee
eeed�Zedd�ej�D��ZGdd�dejj�Zdd�Zdd�Zdd�Zdd�ZdS)zDNS Result Codes.�N�)�long��������	�
�)�NOERROR�FORMERR�SERVFAIL�NXDOMAIN�NOTIMP�REFUSED�YXDOMAIN�YXRRSET�NXRRSET�NOTAUTH�NOTZONE�BADVERSccs|]\}}||fVqdS)N�)�.0�x�yrr�/usr/lib/python3.6/rcode.py�	<genexpr>6src@seZdZdZdS)�UnknownRcodezA DNS rcode is unknown.N)�__name__�
__module__�__qualname__�__doc__rrrrr 9sr cCsB|j�r$t|�}|dkr$|dkr$|Stj|j��}|dkr>t�|S)z�Convert text into an rcode.

    @param text: the textual rcode
    @type text: string
    @raises UnknownRcode: the rcode is unknown
    @rtype: int
    ri�N)�isdigit�int�_by_text�get�upperr )�text�vrrr�	from_text>s	r,cCs0|d@|d?d@B}|dks$|dkr,td��|S)z�Return the rcode value encoded by flags and ednsflags.

    @param flags: the DNS flags
    @type flags: int
    @param ednsflags: the EDNS flags
    @type ednsflags: int
    @raises ValueError: rcode is < 0 or > 4095
    @rtype: int
    ��i�ri�zrcode must be >= 0 and <= 4095)�
ValueError)�flagsZ	ednsflags�valuerrr�
from_flagsQsr2cCs8|dks|dkrtd��|d@}t|d@�d>}||fS)z�Return a (flags, ednsflags) tuple which encodes the rcode.

    @param value: the rcode
    @type value: int
    @raises ValueError: rcode is < 0 or > 4095
    @rtype: (int, int) tuple
    ri�zrcode must be >= 0 and <= 4095r-i�r.)r/r)r1r+Zevrrr�to_flagsbs
	r3cCstj|�}|dkrt|�}|S)zbConvert rcode into text.

    @param value: the rcode
    @type value: int
    @rtype: string
    N)�	_by_valuer(�str)r1r*rrr�to_textrs
r6)r$Z
dns.exceptionZdnsZ_compatrrrrrrrrrrrrrr'�dict�itemsr4Z	exceptionZDNSExceptionr r,r2r3r6rrrr�<module>s@__pycache__/ipv6.cpython-36.opt-1.pyc000064400000005654150351404330013235 0ustar003

�b�W��@s�dZddlZddlZddlZddlZddlmZmZm	Z	ej
d�Zdd�Zej
d�Z
ej
d	�Zej
d
�Zdd�ZdZdd�ZdS)zIPv6 helper functions.�N�)�xrange�binary_type�maybe_decodes
0+([0-9a-f]+)cCs�t|�dkrtd��tj|�}g}d}t|�}xJ||krx|||d�}tj|�}|dk	rd|jd�}|j|�|d7}q0Wd}d}d}	d}
xNtd�D]B}||d	kr�|
r�|}||	}||kr�|	}|}d}
q�|
s�|}	d
}
q�W|
�r�d}||	}||k�r�|	}|}|dk�r�|dk�rb|dk�s4|dk�rb|dd
k�rb|dk�rDd}
nd}
|
t	j
j|dd��}n,dj|d|��ddj|||d��}n
dj|�}t
|�S)z�Convert a network format IPv6 address into text.

    @param address: the binary address
    @type address: string
    @rtype: string
    @raises ValueError: the address isn't 16 bytes long
    �z IPv6 addresses are 16 bytes longr�NrF��0T��sffffs::s::ffff:��:���)�len�
ValueError�binasciiZhexlify�
_leading_zero�match�group�appendr�dns�ipv4�	inet_ntoa�joinr)�address�hex�chunks�i�l�chunk�mZ
best_startZbest_len�startZ
last_was_zero�endZcurrent_len�prefix�r$�/usr/lib/python3.6/ipv6.pyrs^	










rs(.*):(\d+\.\d+\.\d+\.\d+)$s::.*s.*::$c
Cs�t|t�s|j�}|dkrd}tj|�}|dk	rvttjj|j	d���}d|j	d�j
�|d|d|d|dfj�}tj|�}|dk	r�|dd�}ntj|�}|dk	r�|dd�}|j
d	�}t|�}|d
kr�tjj�d}g}x�|D]�}|dk�r.|�rtjj�d
}xftdd
|d�D]}|jd��qWq�t|�}	|	dk�rHtjj�|	dk�rbdd|	|}|j|�q�W|d
k�r�|�r�tjj�dj|�}y
tj|�Stjtfk
�r�tjj�YnXdS)z�Convert a text format IPv6 address into network format.

    @param text: the textual address
    @type text: string
    @rtype: string
    @raises dns.exception.SyntaxError: the text was not properly formatted
    s::s0::N�z%s:%02x%02x:%02x%02xrr�r
rF�Ts0000rr	r)�
isinstancer�encode�
_v4_endingr�	bytearrayrr�	inet_atonr�decode�_colon_colon_start�_colon_colon_end�splitrZ	exception�SyntaxErrorrrrrZ	unhexlify�Error�	TypeError)
�textr �brrZ
seen_emptyZ	canonical�crZlcr$r$r%r-bsR










r-��
s��cCs
|jt�S)N)�
startswith�_mapped_prefix)rr$r$r%�	is_mapped�sr<s
s��)�__doc__�rerZ
dns.exceptionrZdns.ipv4Z_compatrrr�compilerrr+r/r0r-r;r<r$r$r$r%�<module>s
C


G__pycache__/edns.cpython-36.opt-1.pyc000064400000010467150351404330013300 0ustar003

�b�W �@s@dZdZGdd�de�ZGdd�de�ZiZdd�Zdd	�Zd
S)zEDNS Options�c@sdeZdZdZdd�Zdd�Zedd��Zdd	�Zd
d�Z	dd
�Z
dd�Zdd�Zdd�Z
dd�ZdS)�Optionz*Base class for all EDNS option types.
    cCs
||_dS)z\Initialize an option.
        @param otype: The rdata type
        @type otype: int
        N)�otype)�selfr�r�/usr/lib/python3.6/edns.py�__init__szOption.__init__cCst�dS)z*Convert an option to wire format.
        N)�NotImplementedError)r�filerrr�to_wire!szOption.to_wirecCst�dS)a�Build an EDNS option object from wire format

        @param otype: The option type
        @type otype: int
        @param wire: The wire-format message
        @type wire: string
        @param current: The offset in wire of the beginning of the rdata.
        @type current: int
        @param olen: The length of the wire-format option data
        @type olen: int
        @rtype: dns.edns.Option instanceN)r)�clsr�wire�current�olenrrr�	from_wire&s
zOption.from_wirecCst�dS)z�Compare an EDNS option with another option of the same type.
        Return < 0 if self < other, 0 if self == other,
        and > 0 if self > other.
        N)r)r�otherrrr�_cmp5szOption._cmpcCs,t|t�sdS|j|jkrdS|j|�dkS)NF�)�
isinstancerrr)rrrrr�__eq__<s

z
Option.__eq__cCs,t|t�sdS|j|jkrdS|j|�dkS)NFr)rrrr)rrrrr�__ne__Cs

z
Option.__ne__cCs*t|t�s|j|jkrtS|j|�dkS)Nr)rrr�NotImplementedr)rrrrr�__lt__Jsz
Option.__lt__cCs*t|t�s|j|jkrtS|j|�dkS)Nr)rrrrr)rrrrr�__le__Psz
Option.__le__cCs*t|t�s|j|jkrtS|j|�dkS)Nr)rrrrr)rrrrr�__ge__Vsz
Option.__ge__cCs*t|t�s|j|jkrtS|j|�dkS)Nr)rrrrr)rrrrr�__gt__\sz
Option.__gt__N)�__name__�
__module__�__qualname__�__doc__rr
�classmethodrrrrrrrrrrrrrsrcs<eZdZdZ�fdd�Zdd�Zedd��Zdd	�Z�Z	S)
�
GenericOptionzwGenerate Rdata Class

    This class is used for EDNS option types for which we have no better
    implementation.
    cstt|�j|�||_dS)N)�superr r�data)rrr")�	__class__rrrkszGenericOption.__init__cCs|j|j�dS)N)�writer")rr	rrrr
oszGenericOption.to_wirecCs||||||��S)Nr)rrrr
rrrrrrszGenericOption.from_wirecCs$|j|jkrdS|j|jkr dSdS)Nr����)r")rrrrrrvs
zGenericOption._cmp)
rrrrrr
rrr�
__classcell__rr)r#rr cs
r cCstj|�}|dkrt}|S)N)�_type_to_class�getr )rrrrr�get_option_class�s
r*cCst|�}|j||||�S)auBuild an EDNS option object from wire format

    @param otype: The option type
    @type otype: int
    @param wire: The wire-format message
    @type wire: string
    @param current: The offset in wire of the beginning of the rdata.
    @type current: int
    @param olen: The length of the wire-format option data
    @type olen: int
    @rtype: dns.edns.Option instance)r*r)rrr
rrrrr�option_from_wire�s
r+N)rZNSID�objectrr r(r*r+rrrr�<module>sN__pycache__/message.cpython-36.opt-1.pyc000064400000077556150351404330014007 0ustar003

�@�Wy��
@s�dZddlmZddlmZddlZddlZddlZddl	Zddl
ZddlZddlZddl
ZddlZddlZddlZddlZddlZddlZddlZddlZddlmZmZmZGdd�dejj�ZGd	d
�d
ejj�ZGdd�dejj�ZGd
d�dejj�Z Gdd�dejj�Z!Gdd�dejj�Z"Gdd�de#�Z$Gdd�de#�Z%d(dd�Z&Gdd�de#�Z'dd�Z(d d!�Z)ej*j+ddddddfd"d#�Z,d)d&d'�Z-dS)*zDNS Messages�)�absolute_import)�StringION�)�long�xrange�string_typesc@seZdZdZdS)�ShortHeaderz2The DNS packet passed to from_wire() is too short.N)�__name__�
__module__�__qualname__�__doc__�r
r
�/usr/lib/python3.6/message.pyr*src@seZdZdZdS)�TrailingJunkzEThe DNS packet passed to from_wire() has extra junk at the end of it.N)r	r
rrr
r
r
rr/src@seZdZdZdS)�UnknownHeaderFieldzVThe header field name was not recognized when converting from text
    into a message.N)r	r
rrr
r
r
rr4src@seZdZdZdS)�BadEDNSzVOPT record occurred somewhere other than the start of
    the additional data section.N)r	r
rrr
r
r
rr:src@seZdZdZdS)�BadTSIGzWA TSIG record occurred somewhere other than the end of
    the additional data section.N)r	r
rrr
r
r
rr@src@seZdZdZdS)�UnknownTSIGKeyz(A TSIG with an unknown key was received.N)r	r
rrr
r
r
rrFsrc@s�eZdZdZd-dd�Zdd�Zdd�Zd.d
d�Zdd
�Zdd�Z	dd�Z
dd�Zej
jdddfdd�Zej
jdddfdd�Zd/dd�Zdddddejjfdd�Zd0d!d"�Zd1d#d$�Zd%d&�Zd'd(�Zd)d*�Zd+d,�ZdS)2�Messagea,
A DNS message.

    @ivar id: The query id; the default is a randomly chosen id.
    @type id: int
    @ivar flags: The DNS flags of the message.  @see: RFC 1035 for an
    explanation of these flags.
    @type flags: int
    @ivar question: The question section.
    @type question: list of dns.rrset.RRset objects
    @ivar answer: The answer section.
    @type answer: list of dns.rrset.RRset objects
    @ivar authority: The authority section.
    @type authority: list of dns.rrset.RRset objects
    @ivar additional: The additional data section.
    @type additional: list of dns.rrset.RRset objects
    @ivar edns: The EDNS level to use.  The default is -1, no Edns.
    @type edns: int
    @ivar ednsflags: The EDNS flags
    @type ednsflags: long
    @ivar payload: The EDNS payload size.  The default is 0.
    @type payload: int
    @ivar options: The EDNS options
    @type options: list of dns.edns.Option objects
    @ivar request_payload: The associated request's EDNS payload size.
    @type request_payload: int
    @ivar keyring: The TSIG keyring to use.  The default is None.
    @type keyring: dict
    @ivar keyname: The TSIG keyname to use.  The default is None.
    @type keyname: dns.name.Name object
    @ivar keyalgorithm: The TSIG algorithm to use; defaults to
    dns.tsig.default_algorithm.  Constants for TSIG algorithms are defined
    in dns.tsig, and the currently implemented algorithms are
    HMAC_MD5, HMAC_SHA1, HMAC_SHA224, HMAC_SHA256, HMAC_SHA384, and
    HMAC_SHA512.
    @type keyalgorithm: string
    @ivar request_mac: The TSIG MAC of the request message associated with
    this message; used when validating TSIG signatures.   @see: RFC 2845 for
    more information on TSIG fields.
    @type request_mac: string
    @ivar fudge: TSIG time fudge; default is 300 seconds.
    @type fudge: int
    @ivar original_id: TSIG original id; defaults to the message's id
    @type original_id: int
    @ivar tsig_error: TSIG error code; default is 0.
    @type tsig_error: int
    @ivar other_data: TSIG other data.
    @type other_data: string
    @ivar mac: The TSIG MAC for this message.
    @type mac: string
    @ivar xfr: Is the message being used to contain the results of a DNS
    zone transfer?  The default is False.
    @type xfr: bool
    @ivar origin: The origin of the zone in messages which are used for
    zone transfers or for DNS dynamic updates.  The default is None.
    @type origin: dns.name.Name object
    @ivar tsig_ctx: The TSIG signature context associated with this
    message.  The default is None.
    @type tsig_ctx: hmac.HMAC object
    @ivar had_tsig: Did the message decoded from wire format have a TSIG
    signature?
    @type had_tsig: bool
    @ivar multi: Is this message part of a multi-message sequence?  The
    default is false.  This variable is used when validating TSIG signatures
    on messages which are part of a zone transfer.
    @type multi: bool
    @ivar first: Is this message standalone, or the first of a multi
    message sequence?  This variable is used when validating TSIG signatures
    on messages which are part of a zone transfer.
    @type first: bool
    @ivar index: An index of rrsets in the message.  The index key is
    (section, name, rdclass, rdtype, covers, deleting).  Indexing can be
    disabled by setting the index to None.
    @type index: dict
    NcCs�|dkrtjj�|_n||_d|_g|_g|_g|_g|_d|_	d|_
d|_g|_d|_
d|_d|_tjj|_d|_d|_d|_d|_|j|_d|_d|_d|_d|_d|_d|_d|_i|_dS)Nrr�i,FT���) �dnsZentropyZ	random_16�id�flags�question�answer�	authority�
additional�edns�	ednsflags�payload�options�request_payload�keyring�keyname�tsig�default_algorithm�keyalgorithm�request_mac�
other_data�
tsig_error�fudge�original_id�mac�xfr�origin�tsig_ctx�had_tsig�multi�first�index)�selfrr
r
r�__init__�s:
zMessage.__init__cCsdt|j�dS)Nz<DNS message, ID �>)�reprr)r5r
r
r�__repr__�szMessage.__repr__cCs|j�S)N)�to_text)r5r
r
r�__str__�szMessage.__str__TcKst�}|jd|j�|jdtjjtjj|j���tjj|j|j	�}|jdtjj|��|jdtjj|j��|j
dkr�|jd|j
�|j	dkr�|jdtjj|j	��|jd|j�tjj
|j�}|r�|jd	�n
|jd
�x.|jD]$}|j|j||f|��|jd�q�W|�r,|jd�n
|jd
�x0|jD]&}|j|j||f|��|jd��q>W|�rz|jd�n
|jd�x0|jD]&}|j|j||f|��|jd��q�W|jd�x0|jD]&}|j|j||f|��|jd��q�W|j�dd�S)z�Convert the message to text.

        The I{origin}, I{relativize}, and any other keyword
        arguments are passed to the rrset to_wire() method.

        @rtype: string
        zid %d
z
opcode %s
z	rcode %s
z	flags %s
rzedns %s
z
eflags %s
zpayload %d
z;ZONE
z
;QUESTION
�
z;PREREQ
z;ANSWER
z;UPDATE
z;AUTHORITY
z;ADDITIONAL
Nrr)r�writerr�opcoder:�
from_flagsr�rcoderrZedns_to_textr �	is_updaterrrr�getvalue)r5r/�
relativize�kw�sZrcrA�rrsetr
r
rr:�sJ	





zMessage.to_textcCs�t|t�sdS|j|jkrdS|j|jkr.dSx|jD]}||jkr6dSq6Wx|jD]}||jkrTdSqTWx|jD]}||jkrrdSqrWx|jD]}||jkr�dSq�Wx|jD]}||jkr�dSq�Wx|jD]}||jkr�dSq�WdS)z�Two messages are equal if they have the same content in the
        header, question, answer, and authority sections.
        @rtype: boolFT)�
isinstancerrrrrr)r5�other�nr
r
r�__eq__�s2






zMessage.__eq__cCs|j|�S)z0Are two messages not equal?
        @rtype: bool)rJ)r5rHr
r
r�__ne__szMessage.__ne__cCs�|jtjj@dks:|j|jks:tjj|j�tjj|j�kr>dStjj|j|j�tjjkr\dStjj	|j�rndSx|j
D]}||j
krvdSqvWx|j
D]}||j
kr�dSq�WdS)z1Is other a response to self?
        @rtype: boolrFT)rr�QRrr>r?r@rZNOERRORrAr)r5rHrIr
r
r�is_responses"


zMessage.is_responsecCsD||jkrdS||jkrdS||jkr*dS||jkr8dStd��dS)Nrr��zunknown section)rrrr�
ValueError)r5�sectionr
r
r�section_number-s



zMessage.section_numberFc	Cs�|j|�|||||f}	|sb|jdk	r>|jj|	�}
|
dk	rb|
Sn$x"|D]}
|
j|||||�rD|
SqDW|sjt�tjj|||||�}
|j|
�|jdk	r�|
|j|	<|
S)aFind the RRset with the given attributes in the specified section.

        @param section: the section of the message to look in, e.g.
        self.answer.
        @type section: list of dns.rrset.RRset objects
        @param name: the name of the RRset
        @type name: dns.name.Name object
        @param rdclass: the class of the RRset
        @type rdclass: int
        @param rdtype: the type of the RRset
        @type rdtype: int
        @param covers: the covers value of the RRset
        @type covers: int
        @param deleting: the deleting value of the RRset
        @type deleting: int
        @param create: If True, create the RRset if it is not found.
        The created RRset is appended to I{section}.
        @type create: bool
        @param force_unique: If True and create is also True, create a
        new RRset regardless of whether a matching RRset exists already.
        @type force_unique: bool
        @raises KeyError: the RRset was not found and create was False
        @rtype: dns.rrset.RRset objectN)	rRr4�get�match�KeyErrorrrFZRRset�append)r5rQ�name�rdclass�rdtype�covers�deleting�create�force_unique�keyrFr
r
r�
find_rrset9s"




zMessage.find_rrsetc	
Cs:y|j||||||||�}	Wntk
r4d}	YnX|	S)aGet the RRset with the given attributes in the specified section.

        If the RRset is not found, None is returned.

        @param section: the section of the message to look in, e.g.
        self.answer.
        @type section: list of dns.rrset.RRset objects
        @param name: the name of the RRset
        @type name: dns.name.Name object
        @param rdclass: the class of the RRset
        @type rdclass: int
        @param rdtype: the type of the RRset
        @type rdtype: int
        @param covers: the covers value of the RRset
        @type covers: int
        @param deleting: the deleting value of the RRset
        @type deleting: int
        @param create: If True, create the RRset if it is not found.
        The created RRset is appended to I{section}.
        @type create: bool
        @param force_unique: If True and create is also True, create a
        new RRset regardless of whether a matching RRset exists already.
        @type force_unique: bool
        @rtype: dns.rrset.RRset object or NoneN)r_rU)
r5rQrWrXrYrZr[r\r]rFr
r
r�	get_rrsetgs
zMessage.get_rrsetrc	KsR|dkr|jdkr|j}nd}|dkr,d}n|dkr8d}tjj|j|j||�}x"|jD]}|j|j|j	|j
�qVWx"|jD]}|jtjj
|f|�qzWx"|jD]}|jtjj|f|�q�W|jdkr�|j|j|j|j|j�x"|jD]}|jtjj|f|�q�W|j�|jdk	�rJ|j|j|j|j|j|j|j|j|j|j �|j!|_!|j"�S)a7Return a string containing the message in DNS compressed wire
        format.

        Additional keyword arguments are passed to the rrset to_wire()
        method.

        @param origin: The origin to be appended to any relative names.
        @type origin: dns.name.Name object
        @param max_size: The maximum size of the wire format output; default
        is 0, which means 'the message's request payload, if nonzero, or
        65536'.
        @type max_size: int
        @raises dns.exception.TooBig: max_size was exceeded
        @rtype: string
        ri��iN)#r"rZrendererZRendererrrrZadd_questionrWrYrXrZ	add_rrset�ANSWERr�	AUTHORITYrZadd_ednsrr r!r�
ADDITIONALZwrite_headerr$Zadd_tsigr#r+r,r*r)r(r'r-Zget_wire)r5r/Zmax_sizerD�rrFr
r
r�to_wire�s6

zMessage.to_wirei,rcCst||_|dkr$t|jj��d|_nt|t�r:tjj|�}||_||_	||_
|dkr^|j|_n||_||_
||_dS)awWhen sending, a TSIG signature using the specified keyring
        and keyname should be added.

        @param keyring: The TSIG keyring to use; defaults to None.
        @type keyring: dict
        @param keyname: The name of the TSIG key to use; defaults to None.
        The key must be defined in the keyring.  If a keyring is specified
        but a keyname is not, then the key used will be the first key in the
        keyring.  Note that the order of keys in a dictionary is not defined,
        so applications should supply a keyname when a keyring is used, unless
        they know the keyring contains only one key.
        @type keyname: dns.name.Name or string
        @param fudge: TSIG time fudge; default is 300 seconds.
        @type fudge: int
        @param original_id: TSIG original id; defaults to the message's id
        @type original_id: int
        @param tsig_error: TSIG error code; default is 0.
        @type tsig_error: int
        @param other_data: TSIG other data.
        @type other_data: string
        @param algorithm: The TSIG algorithm to use; defaults to
        dns.tsig.default_algorithm
        Nr)r#�list�keysr$rGrrrW�	from_textr'r+rr,r*r))r5r#r$r+r,r*r)�	algorithmr
r
r�use_tsig�s

zMessage.use_tsig�cCs�|dks|dkrd}|dkr d}|dkr,|}|dkrFd}d}d}g}n$|td�M}||d>O}|dkrjg}||_||_||_||_||_dS)	a_Configure EDNS behavior.
        @param edns: The EDNS level to use.  Specifying None, False, or -1
        means 'do not use EDNS', and in this case the other parameters are
        ignored.  Specifying True is equivalent to specifying 0, i.e. 'use
        EDNS0'.
        @type edns: int or bool or None
        @param ednsflags: EDNS flag values.
        @type ednsflags: int
        @param payload: The EDNS sender's payload field, which is the maximum
        size of UDP datagram the sender can handle.
        @type payload: int
        @param request_payload: The EDNS payload size to use when sending
        this message.  If not specified, defaults to the value of payload.
        @type request_payload: int or None
        @param options: The EDNS options
        @type options: None or list of dns.edns.Option objects
        @see: RFC 2671
        NFrTrl�~�r)rrrr r!r")r5rrr r"r!r
r
r�use_edns�s(zMessage.use_ednscCsL|r*|jdkr|j�|jtjjO_n|jdkrH|jtjjM_dS)a
Enable or disable 'DNSSEC desired' flag in requests.
        @param wanted: Is DNSSEC desired?  If True, EDNS is enabled if
        required, and then the DO bit is set.  If False, the DO bit is
        cleared if EDNS is enabled.
        @type wanted: bool
        rN)rrmrrrZDO)r5Zwantedr
r
r�want_dnssecs

zMessage.want_dnsseccCstjj|j|j�S)z.Return the rcode.
        @rtype: int
        )rr@r?rr)r5r
r
rr@sz
Message.rcodecCsjtjj|�\}}|jdM_|j|O_|jtd�M_|j|O_|jdkrf|jdkrfd|_dS)zPSet the rcode.
        @param rcode: the rcode
        @type rcode: int
        i�i���rN)rr@�to_flagsrrrr)r5r@�valueZevaluer
r
r�	set_rcode"szMessage.set_rcodecCstjj|j�S)z/Return the opcode.
        @rtype: int
        )rr>r?r)r5r
r
rr>/szMessage.opcodecCs(|jdM_|jtjj|�O_dS)zTSet the opcode.
        @param opcode: the opcode
        @type opcode: int
        i��N)rrr>ro)r5r>r
r
r�
set_opcode5szMessage.set_opcode)N)NT)Nr)rrrkNN)T)r	r
rrr6r9r;r:rJrKrMrRr�	rdatatype�NONEr_r`rer%r&rjrmrnr@rqr>rrr
r
r
rrKs0K
 
7
-
!
.)
*

rc@s2eZdZdZddd�Zdd�Zdd�Zd	d
�ZdS)
�_WireReadera�Wire format reader.

    @ivar wire: the wire-format message.
    @type wire: string
    @ivar message: The message object being built
    @type message: dns.message.Message object
    @ivar current: When building a message object from wire format, this
    variable contains the offset from the beginning of wire of the next octet
    to be read.
    @type current: int
    @ivar updating: Is the message a dynamic update?
    @type updating: bool
    @ivar one_rr_per_rrset: Put each RR into its own RRset?
    @type one_rr_per_rrset: bool
    @ivar ignore_trailing: Ignore trailing junk at end of request?
    @type ignore_trailing: bool
    @ivar zone_rdclass: The class of the zone in messages which are
    DNS dynamic updates.
    @type zone_rdclass: int
    FcCs@tjj|�|_||_d|_d|_tjj|_	||_
||_||_dS)NrF)
rZwiredataZ
maybe_wrap�wire�message�current�updating�
rdataclass�IN�zone_rdclass�
question_only�one_rr_per_rrset�ignore_trailing)r5rvrwr}r~rr
r
rr6Us
z_WireReader.__init__c	Cs�|jr|dkrtjj�x�td|�D]�}tjj|j|j�\}}|j	j
dk	rV|j|j	j
�}|j||_tj
d|j|j|jd��\}}|jd|_|j	j|j	j|||ddd�|jr"||_q"WdS)z�Read the next I{qcount} records from the wire data and add them to
        the question section.
        @param qcount: the number of questions in the message
        @type qcount: intrrNz!HH�T)r\r])ryr�	exception�	FormErrorrrW�	from_wirervrxrwr/rC�struct�unpackr_rr|)r5�qcount�i�qname�usedrYrXr
r
r�
_get_question`sz_WireReader._get_questionc
CsH|js|jrd}nd}d}�x&td|�D�]}|j}tjj|j|j�\}}|}	|jj	dk	rh|j
|jj	�}|j||_tjd|j|j|jd��\}
}}}
|jd|_|
tj
jk�rn||jjk	s�|r�t�||j_||j_|d@d?|j_g|j_|j}|
}xj|dk�rdtjd	|j||d
��\}}|d
}tjj||j||�}|jjj|�||}|d
|}q�Wd}�n�|
tj
jk�rH||jjk�o�||dk�s�t�|jjdk�r�td��|jjj|	�}|dk�r�td
|��|	|j_tjj|j|j|
�\|j_|j_ tjj!|j|	|t"t#j#��|jj$||j|
|jj%|jj&|jj'�|j_%d|j_(n�|dk�rVd}|j�r�|tj)j*k�sz|tj)j+k�r�|}|j,}nd}|tj)j*k�s�|tj)j+k�r�||jj-k�r�tj
j+}d}n&tj.j||
|j|j|
|jj	�}|j/�}|jj0�r|
tj
j1k�rd}|jj2||||
||d|�}|dk	�r4|j3||�|j|
|_q(WdS)a/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 dns.rrset.RRset objects
        @param count: the number of records to read
        @type count: intTFrNz!HHIH�
i�rlz!HHr�rz"got signed message without keyringzkey '%s' unknown)4ryr~rrxrrWr�rvrwr/rCr�r�rs�OPTrrr rrr!Zoption_from_wirerVZTSIGrr#rrSr$r%Zget_algorithm_and_macr'r-Zvalidate�int�timer(r0r2r3r1rz�ANYrtr|r�rdatarZr.ZSOAr_�add)r5rQ�countr]Zseen_optr�Zrr_startrWr�Z
absolute_namerYrX�ttlZrdlenrxZoptslenZotypeZolen�optZsecretr[rZ�rdrFr
r
r�_get_sectionxs� 








z_WireReader._get_sectioncCs�t|j�}|dkrt�tjd|jdd��\|j_|j_}}}}d|_t	j
j|jj�r\d|_|j
|�|jrpdS|j|jj|�|j|jj|�|j|jj|�|jr�|j|kr�t�|jjr�|jjr�|jjr�|jjj|j�dS)zNRead a wire format DNS message and build a dns.message.Message
        object.�z!HHHHHHNT)�lenrvrr�r�rwrrrxrr>rAryr�r}r�rrrrrr2r0r1�update)r5�lr�ZancountZaucountZadcountr
r
r�read�s$
*

z_WireReader.readN)FFF)r	r
rrr6r�r�r�r
r
r
rru>s

crurFTc
CsPtdd�}||_||_||_||_||_||_||_t||||	|
�}|j	�|S)a)Convert a DNS wire format message into a message
    object.

    @param keyring: The keyring to use if the message is signed.
    @type keyring: dict
    @param request_mac: If the message is a response to a TSIG-signed request,
    I{request_mac} should be set to the MAC of that request.
    @type request_mac: string
    @param xfr: Is this message part of a zone transfer?
    @type xfr: bool
    @param origin: If the message is part of a zone transfer, I{origin}
    should be the origin name of the zone.
    @type origin: dns.name.Name object
    @param tsig_ctx: The ongoing TSIG context, used when validating zone
    transfers.
    @type tsig_ctx: hmac.HMAC object
    @param multi: Is this message part of a multiple message sequence?
    @type multi: bool
    @param first: Is this message standalone, or the first of a multi
    message sequence?
    @type first: bool
    @param question_only: Read only up to the end of the question section?
    @type question_only: bool
    @param one_rr_per_rrset: Put each RR into its own RRset
    @type one_rr_per_rrset: bool
    @param ignore_trailing: Ignore trailing junk at end of request?
    @type ignore_trailing: bool
    @raises ShortHeader: The message is less than 12 octets long.
    @raises TrailingJunk: There were octets in the message past the end
    of the proper DNS message.
    @raises BadEDNS: An OPT record was in the wrong section, or occurred more
    than once.
    @raises BadTSIG: A TSIG record was not the last record of the additional
    data section.
    @rtype: dns.message.Message objectr)r)
rr#r(r.r/r0r2r3rur�)
rvr#r(r.r/r0r2r3r}r~r�m�readerr
r
rr��s(

r�c@s8eZdZdZdd�Zdd�Zdd�Zdd	�Zd
d�ZdS)
�_TextReaderaText format reader.

    @ivar tok: the tokenizer
    @type tok: dns.tokenizer.Tokenizer object
    @ivar message: The message object being built
    @type message: dns.message.Message object
    @ivar updating: Is the message a dynamic update?
    @type updating: bool
    @ivar zone_rdclass: The class of the zone in messages which are
    DNS dynamic updates.
    @type zone_rdclass: int
    @ivar last_name: The most recently read name when building a message object
    from text format.
    @type last_name: dns.name.Name object
    cCs.||_tjj|�|_d|_tjj|_d|_	dS)NF)
rwrZ	tokenizer�	Tokenizer�tok�	last_namerzr{r|ry)r5�textrwr
r
rr6>s

z_TextReader.__init__cCs�|jj�}|j}|dkr*|jj�|j_�n�|dkr�x>|jj�}|j�sT|jj|�P|jjt	jj
|j�B|j_q4Wt	jj|jj�r�d|_
�n&|dkr�|jj�|j_|jj|jjd>B|j_n�|dk�r|jjdkr�d|j_x�|jj�}|j��s�|jj|�P|jjt	jj|j�B|j_q�Wn�|dk�rN|jj�|j_|jjdk�r�d|j_nd|d	k�r�|jj�}|jjt	jjt	jj
|��B|j_n.|d
k�r�|jj�}|jjt	jj
|��nt�|jj�dS)z5Process one line from the text format header section.rrTrrlZeflagsrr r>r@N)r�rSrpZget_intrwr�
is_identifier�ungetrrrhr>rAryrrZedns_from_textr Z
get_stringrorqr@r�get_eol)r5rQ�tokenZwhatr�r
r
r�_header_lineEsR











z_TextReader._header_linecCs�|jjdd�}|j�s(tjj|jd�|_|j}|jj�}|j�sHtj	j
�y,tjj|j�}|jj�}|j�srtj	j
�Wn:tj	j
k
r�tj	j
�Yntk
r�tjj
}YnXtjj|j�}|jj|jj|||ddd�|jr�||_|jj�dS)z7Process one line from the text format question section.T)�want_leadingN)r\r])r�rS�
is_whitespacerrWrhrpr�r�r��SyntaxErrorrz�	Exceptionr{rsrwr_rryr|r�)r5rQr�rWrXrYr
r
r�_question_liness.

z_TextReader._question_linecCs�d}|jjdd�}|j�s,tjj|jd�|_|j}|jj�}|j�sLtj	j
�y*t|jd�}|jj�}|j�sttj	j
�Wn6tj	j
k
r�tj	j
�Yntk
r�d}YnXyPtj
j|j�}|jj�}|j�s�tj	j
�|tj
jks�|tj
jk�r�|}|j}Wn>tj	j
k
�r tj	j
�Yntk
�r<tj
j}YnXtjj|j�}|jj�}|j��s�|jj|�tjj|||jd�}|j�}	nd}tjj}	|jj|||||	|d|j�}
|dk	�r�|
j||�dS)zfProcess one line from the text format answer, authority, or
        additional data sections.
        NT)r�r)r�rSr�rrWrhrpr�r�r�r�r�r�rzr�rtr|r{rs�
is_eol_or_eofr�r�rZrwr_ryr�)r5rQr[r�rWr�rXrYr�rZrFr
r
r�_rr_line�sT









z_TextReader._rr_linecCs�|j}d}x�|jjdd�}|j�r$P|j�r�|jj�}|dkrF|j}nv|dksV|dkrf|j}|jj	}nV|dksv|dkr�|j
}|jj}n6|dks�|d	kr�|j
}|jj}n|d
kr�|j
}|jj
}|jj�q|jj|�||�qWdS)zNRead a text format DNS message and build a dns.message.Message
        object.NTZHEADERZQUESTIONZZONEraZPREREQrbZUPDATErc)r�r�rSr�Z
is_commentrp�upperr�rwrr�rrrr�r�)r5Zline_methodrQr��ur
r
rr��s4




z_TextReader.readN)	r	r
rrr6r�r�r�r�r
r
r
rr�,s.5r�cCst�}t||�}|j�|S)z�Convert the text format message into a message object.

    @param text: The text format message.
    @type text: string
    @raises UnknownHeaderField:
    @raises dns.exception.SyntaxError:
    @rtype: dns.message.Message object)rr�r�)r�r�r�r
r
rrh�s

rhc
CsFt}d}t||�r"t||�}d}nd}zt|�}Wd|r@|j�X|S)aRead the next text format message from the specified file.

    @param f: file or string.  If I{f} is a string, it is treated
    as the name of a file to open.
    @raises UnknownHeaderField:
    @raises dns.exception.SyntaxError:
    @rtype: dns.message.Message objectZrUTFN)rrG�openrh�close)�fZstr_typeZoptsZ
want_closer�r
r
r�	from_file�s	


r�c	Cst|t�rtjj|�}t|t�r,tjj|�}t|t�rBtjj|�}t�}	|	jtjj	O_|	j
|	j|||ddd�i}
|dk	r�||
d<|dkr�d}|dk	r�||
d<|dkr�d}|dk	r�||
d<|dkr�d}|dk	r�||
d<|dkr�d}||
d	<|	jf|
�|	j
|�|	S)
aVMake a query message.

    The query name, type, and class may all be specified either
    as objects of the appropriate type, or as strings.

    The query will have a randomly chosen query id, and its DNS flags
    will be set to dns.flags.RD.

    @param qname: The query name.
    @type qname: dns.name.Name object or string
    @param rdtype: The desired rdata type.
    @type rdtype: int
    @param rdclass: The desired rdata class; the default is class IN.
    @type rdclass: int
    @param use_edns: The EDNS level to use; the default is None (no EDNS).
    See the description of dns.message.Message.use_edns() for the possible
    values for use_edns and their meanings.
    @type use_edns: int or bool or None
    @param want_dnssec: Should the query indicate that DNSSEC is desired?
    @type want_dnssec: bool
    @param ednsflags: EDNS flag values.
    @type ednsflags: int
    @param payload: The EDNS sender's payload field, which is the maximum
    size of UDP datagram the sender can handle.
    @type payload: int
    @param request_payload: The EDNS payload size to use when sending
    this message.  If not specified, defaults to the value of payload.
    @type request_payload: int or None
    @param options: The EDNS options
    @type options: None or list of dns.edns.Option objects
    @see: RFC 2671
    @rtype: dns.message.Message objectT)r\r]Nrrr r"r!r)rGrrrWrhrsrzrr�RDr_rrmrn)r�rYrXrmrnrr r"r!r��kwargsr
r
r�
make_querys>$



r�� �,cCs�|jtjj@rtjjd��tjj|j�}tjj|jtjj@B|_|rV|jtjj	O_|j
|j��t|j
�|_
|jdkr�|jdd||j�|jr�|j|j|j|ddd|j�|j|_|S)aMake a message which is a response for the specified query.
    The message returned is really a response skeleton; it has all
    of the infrastructure required of a response, but none of the
    content.

    The response's question section is a shallow copy of the query's
    question section, so the query's question RRsets should not be
    changed.

    @param query: the query to respond to
    @type query: dns.message.Message object
    @param recursion_available: should RA be set in the response?
    @type recursion_available: bool
    @param our_payload: payload size to advertise in EDNS responses; default
    is 8192.
    @type our_payload: int
    @param fudge: TSIG time fudge; default is 300 seconds.
    @type fudge: int
    @rtype: dns.message.Message objectz&specified query message is not a queryrNr)rrrLr�r�rwrrr�ZRArrr>rfrrrmr r1rjr#r$r'r-r()ZqueryZrecursion_availableZour_payloadr+Zresponser
r
r�
make_response\s
r�)
NrFNNFTFFF)Fr�r�).rZ
__future__r�iorr�r�Zdns.ednsrZ
dns.exceptionZ	dns.flagsZdns.nameZ
dns.opcodeZdns.entropyZ	dns.rcodeZ	dns.rdataZdns.rdataclassZ
dns.rdatatypeZ	dns.rrsetZdns.rendererZdns.tsigZdns.wiredataZ_compatrrrr�r�rrZDNSExceptionrrrr�objectrrur�r�rhr�rzr{r�r�r
r
r
r�<module>sXv7
5:F__pycache__/rdataclass.cpython-36.opt-1.pyc000064400000004714150351404330014466 0ustar003

�b�W��@s�dZddlZddlZdZdZdZdZdZdZ	eeeeee	d�Z
ed	d
�e
j�D��Z
e
jeeed��ede	diZejd
ej�ZGdd�dejj�Zdd�Zdd�Zdd�ZdS)akDNS Rdata Classes.

@var _by_text: The rdata class textual name to value mapping
@type _by_text: dict
@var _by_value: The rdata class value to textual name mapping
@type _by_value: dict
@var _metaclasses: If an rdataclass is a metaclass, there will be a mapping
whose key is the rdatatype value and whose value is True in this dictionary.
@type _metaclasses: dict�N�����)�	RESERVED0�IN�CH�HS�NONE�ANYccs|]\}}||fVqdS)N�)�.0�x�yr
r
� /usr/lib/python3.6/rdataclass.py�	<genexpr>2sr)ZINTERNETZCHAOSZHESIODTzCLASS([0-9]+)$c@seZdZdZdS)�UnknownRdataclasszA DNS class is unknown.N)�__name__�
__module__�__qualname__�__doc__r
r
r
rrEsrcCsVtj|j��}|dkrRtj|�}|dkr,t�t|jd��}|dksJ|dkrRtd��|S)z�Convert text into a DNS rdata class value.
    @param text: the text
    @type text: string
    @rtype: int
    @raises dns.rdataclass.UnknownRdataclass: the class is unknown
    @raises ValueError: the rdata class value is not >= 0 and <= 65535
    Nrri��z'class must be between >= 0 and <= 65535)	�_by_text�get�upper�_unknown_class_pattern�matchr�int�group�
ValueError)�text�valuerr
r
r�	from_textJs	
r"cCs:|dks|dkrtd��tj|�}|dkr6dt|�}|S)z�Convert a DNS rdata class to text.
    @param value: the rdata class value
    @type value: int
    @rtype: string
    @raises ValueError: the rdata class value is not >= 0 and <= 65535
    ri��z'class must be between >= 0 and <= 65535NZCLASS)r�	_by_valuer�repr)r!r r
r
r�to_text^s
r%cCs|tkrdSdS)zmTrue if the class is a metaclass.
    @param rdclass: the rdata class
    @type rdclass: int
    @rtype: boolTF)�_metaclasses)Zrdclassr
r
r�is_metaclassnsr')r�reZ
dns.exceptionZdnsrrr	r
rrr�dict�itemsr#�updater&�compile�IrZ	exceptionZDNSExceptionrr"r%r'r
r
r
r�<module>s4
__pycache__/resolver.cpython-36.pyc000064400000105700150351404330013244 0ustar003

>D�W���@s�dZddlZddlZddlZddlZyddlZWnek
rLddlZYnXddl	Z
ddlZ
ddlZ
ddl
Z
ddlZ
ddlZ
ddlZ
ddlZ
ddlZ
ddlZ
ddlZ
ddlZ
ddlmZmZejdkr�yddlZWnek
r�ddlZYnXGdd�de
jj�ZGdd	�d	e
jj�Ze
jj Z Gd
d�de
jj�Z!Gdd
�d
e
jj�Z"Gdd�de
jj�Z#Gdd�de
jj�Z$Gdd�de
jj�Z%Gdd�de&�Z'Gdd�de&�Z(Gdd�de&�Z)Gdd�de&�Z*Gdd�de&�Z+da,dd�Z-d d!�Z.e
j/j0e
j1j2d"dd#dfd$d%�Z3e
j1j2d"dfd&d'�Z4ej5ej6gej7ej8giZ9da:ej;Z<ej=Z>ej?Z@ejAZBejCZDejEZFddejGdddfd(d)�ZHd8d*d+�ZId9d,d-�ZJd.d/�ZKd0d1�ZLd2d3�ZMd:d4d5�ZNd6d7�ZOdS);z{DNS stub resolver.

@var default_resolver: The default resolver object
@type default_resolver: dns.resolver.Resolver object�N�)�xrange�string_types�win32csVeZdZdZeddg�ZdZddd�Z�fdd�Zd	d
�Z	e
e	dd�Z	d
d�Z�ZS)�NXDOMAINz"The DNS query name does not exist.�qnames�	responsesNcCs\t|tttf�std��t|�dkr,td��|dkr:i}nt|t�sLtd��t||d�}|S)Nz#qnames must be a list, tuple or setrz(qnames must contain at least one elementz(responses must be a dict(qname=response))rr)�
isinstance�list�tuple�set�AttributeError�len�dict)�selfrr�kwargs�r�/usr/lib/python3.6/resolver.py�
_check_kwargs9s
zNXDOMAIN._check_kwargscs^d|jkrtt|�j�S|jd}t|�dkr4d}n|jdd�}djtt|��}d||fS)NrrzNone of DNS query names existz, z%s: %s���)	r�superr�__str__r�__doc__�join�map�str)rr�msg)�	__class__rrrEs

zNXDOMAIN.__str__cCs�d|jkrtd��tjj}tjj}d}xj|jdD]\}|jd|}x4|jD]*}|j|ksL|j	|krfqL|j
djj�}qLW|dk	r2tj
j|�Sq2W|jddS)Nrzparametrized exception requiredrr)r�	TypeError�dns�
rdataclass�IN�	rdatatype�CNAME�answer�rdtype�rdclass�items�target�to_text�name�	from_text)rr!r#�cname�qname�responser$rrr�canonical_namePs
zNXDOMAIN.canonical_namez%Return the unresolved canonical name.)�doccCs|t|jjdg��}t|jjdi��}|jjdi�}x<|jjdg�D]*}||krX|j|�||krB||||<qBWt||d�S)z3Augment by results from another NXDOMAIN exception.rr)rr)r
r�getr�appendr)rZe_nxZqnames0Z
responses0Z
responses1Zqname1rrr�__add__bs
zNXDOMAIN.__add__)N)
�__name__�
__module__�__qualname__rr�supp_kwargs�fmtrrr/�propertyr3�
__classcell__rr)rrr3s
rc@seZdZdZdS)�YXDOMAINz8The DNS query name is too long after DNAME substitution.N)r4r5r6rrrrrr;osr;cs.eZdZdZdZedg�Z�fdd�Z�ZS)�NoAnswerz<The DNS response does not contain an answer to the question.z,The DNS response does not contain an answer zto the question: {query}r.cstt|�j|djd�S)Nr.)�query)rr<�_fmt_kwargs�question)rr)rrrr>�s
zNoAnswer._fmt_kwargszDThe DNS response does not contain an answer to the question: {query})	r4r5r6rr8rr7r>r:rr)rrr<zs

r<cs@eZdZdZdZdedd
�Zeddg�Z�fdd	�Z�Z	S)�
NoNameserversz�All nameservers failed to answer the query.

    errors: list of servers and respective errors
    The type of errors is
    [(server ip address, any object convertible to string)].
    Non-empty errors list will add explanatory message ()
    z+All nameservers failed to answer the query.z%s {query}: {errors}Nr�request�errorscsdg}x>|dD]2}|jd|d|dr*dnd|d|df�qWtt|�j|d	jd
j|�d�S)NrBz Server %s %s port %s answered %srrZTCPZUDP��rAz; )r=rB)r2rr@r>r?r)rrZsrv_msgs�err)rrrr>�s&
zNoNameservers._fmt_kwargsr)
r4r5r6rrr8rr7r>r:rr)rrr@�s
r@c@seZdZdZdS)�NotAbsolutezEAn absolute domain name is required but a relative name was provided.N)r4r5r6rrrrrrF�srFc@seZdZdZdS)�	NoRootSOAzBThere is no SOA RR at the DNS root name. This should never happen!N)r4r5r6rrrrrrG�srGc@seZdZdZdS)�
NoMetaqueriesz DNS metaqueries are not allowed.N)r4r5r6rrrrrrH�srHc@sBeZdZdZddd�Zdd�Zdd�Zd	d
�Zdd�Zd
d�Z	dS)�Answera9DNS stub resolver answer

    Instances of this class bundle up the result of a successful DNS
    resolution.

    For convenience, the answer object implements much of the sequence
    protocol, forwarding to its rrset.  E.g. "for a in answer" is
    equivalent to "for a in answer.rrset", "answer[i]" is equivalent
    to "answer.rrset[i]", and "answer[i:j]" is equivalent to
    "answer.rrset[i:j]".

    Note that CNAMEs or DNAMEs in the response may mean that answer
    node's name might not be the query name.

    @ivar qname: The query name
    @type qname: dns.name.Name object
    @ivar rdtype: The query type
    @type rdtype: int
    @ivar rdclass: The query class
    @type rdclass: int
    @ivar response: The response message
    @type response: dns.message.Message object
    @ivar rrset: The answer
    @type rrset: dns.rrset.RRset object
    @ivar expiration: The time when the answer expires
    @type expiration: float (seconds since the epoch)
    @ivar canonical_name: The canonical name of the query name
    @type canonical_name: dns.name.Name object
    TcCs�||_||_||_||_d}d}x�tdd�D]�}y0|j|j|||�}|dksV|j|kr\|j}PWq,tk
�r|t	j
jkr�yJ|j|j||t	j
j�}	|dks�|	j|kr�|	j}x|	D]}
|
j}Pq�Ww,Wn"tk
r�|r�t
|d��YnX|�r�t
|d��Yq,Xq,W|dk�r |�r t
|d��||_||_|dk�r�x�yR|j|j||t	j
j�}|dk�sf|j|k�rl|j}|dj|k�r�|dj}PWn@tk
�r�y|j�}Wnt	jjk
�r�PYnXYnX�q8Wtj�||_dS)	Nrr�)r.rrrr)r-r%r&r.rZ
find_rrsetr$�ttl�KeyErrorrr"r#r(r<r/�rrsetZ	authority�SOAZminimum�parentr*�NoParent�time�
expiration)rr-r%r&r.�raise_on_no_answerZmin_ttlrM�countZcrrsetZrdZsrrsetrrr�__init__�sf






zAnswer.__init__cCs\|dkr|jjS|dkr |jjS|dkr0|jjS|dkr@|jjS|dkrP|jjSt|��dS)Nr*rK�coversr&r%)rMr*rKrVr&r%r
)r�attrrrr�__getattr__szAnswer.__getattr__cCs|jrt|j�pdS)Nr)rMr)rrrr�__len__szAnswer.__len__cCs|jrt|j�ptt��S)N)rM�iterr)rrrr�__iter__szAnswer.__iter__cCs
|j|S)N)rM)r�irrr�__getitem__szAnswer.__getitem__cCs|j|=dS)N)rM)rr\rrr�__delitem__szAnswer.__delitem__N)T)
r4r5r6rrUrXrYr[r]r^rrrrrI�s
7rIc@s<eZdZdZddd�Zdd�Zdd�Zd	d
�Zddd
�ZdS)�CacheaqSimple DNS answer cache.

    @ivar data: A dictionary of cached data
    @type data: dict
    @ivar cleaning_interval: The number of seconds between cleanings.  The
    default is 300 (5 minutes).
    @type cleaning_interval: float
    @ivar next_cleaning: The time the cache should next be cleaned (in seconds
    since the epoch.)
    @type next_cleaning: float
    ��r@cCs*i|_||_tj�|j|_tj�|_dS)z�Initialize a DNS cache.

        @param cleaning_interval: the number of seconds between periodic
        cleanings.  The default is 300.0
        @type cleaning_interval: float.
        N)�data�cleaning_intervalrQ�
next_cleaning�
_threading�Lock�lock)rrbrrrrU-szCache.__init__cCsptj�}|j|krlg}x*|jj�D]\}}|j|kr"|j|�q"Wx|D]}|j|=qHWtj�}||j|_dS)z&Clean the cache if it's time to do so.N)rQrcrar'rRr2rb)r�nowZkeys_to_delete�k�vrrr�_maybe_clean:s


zCache._maybe_cleanc
CsNz<|jj�|j�|jj|�}|dks6|jtj�kr:dS|S|jj�XdS)a)Get the answer associated with I{key}.  Returns None if
        no answer is cached for the key.
        @param key: the key
        @type key: (dns.name.Name, int, int) tuple whose values are the
        query name, rdtype, and rdclass.
        @rtype: dns.resolver.Answer object or None
        N)rf�acquirerjrar1rRrQ�release)r�keyrirrrr1Hs	
z	Cache.getc
Cs2z |jj�|j�||j|<Wd|jj�XdS)aAssociate key and value in the cache.
        @param key: the key
        @type key: (dns.name.Name, int, int) tuple whose values are the
        query name, rdtype, and rdclass.
        @param value: The answer being cached
        @type value: dns.resolver.Answer object
        N)rfrkrjrarl)rrm�valuerrr�put[s
	
z	Cache.putNc
CsRz@|jj�|dk	r(||jkr>|j|=ni|_tj�|j|_Wd|jj�XdS)z�Flush the cache.

        If I{key} is specified, only that item is flushed.  Otherwise
        the entire cache is flushed.

        @param key: the key to flush
        @type key: (dns.name.Name, int, int) tuple or None
        N)rfrkrarQrbrcrl)rrmrrr�flushks



zCache.flush)r`)N)	r4r5r6rrUrjr1rorprrrrr_s

r_c@s0eZdZdZdd�Zdd�Zdd�Zdd	�Zd
S)�LRUCacheNodezLRUCache node.
    cCs||_||_||_||_dS)N)rmrn�prev�next)rrmrnrrrrU�szLRUCacheNode.__init__cCs |j|_||_||j_||_dS)N)rrrs)r�noderrr�link_before�szLRUCacheNode.link_beforecCs ||_|j|_||j_||_dS)N)rrrs)rrtrrr�
link_after�szLRUCacheNode.link_aftercCs|j|j_|j|j_dS)N)rrrs)rrrr�unlink�s
zLRUCacheNode.unlinkN)r4r5r6rrUrurvrwrrrrrq�s
rqc@s<eZdZdZddd�Zdd�Zdd�Zd	d
�Zddd
�ZdS)�LRUCacheaOBounded least-recently-used DNS answer cache.

    This cache is better than the simple cache (above) if you're
    running a web crawler or other process that does a lot of
    resolutions.  The LRUCache has a maximum number of nodes, and when
    it is full, the least-recently used node is removed to make space
    for a new one.

    @ivar data: A dictionary of cached data
    @type data: dict
    @ivar sentinel: sentinel node for circular doubly linked list of nodes
    @type sentinel: LRUCacheNode object
    @ivar max_size: The maximum number of nodes
    @type max_size: int
    順cCs*i|_|j|�tdd�|_tj�|_dS)z�Initialize a DNS cache.

        @param max_size: The maximum number of nodes to cache; the default is
        100,000. Must be greater than 1.
        @type max_size: int
        N)ra�set_max_sizerq�sentinelrdrerf)r�max_sizerrrrU�s
zLRUCache.__init__cCs|dkrd}||_dS)Nr)r|)rr|rrrrz�szLRUCache.set_max_sizec
CslzZ|jj�|jj|�}|dkr$dS|j�|jjtj�krJ|j|j=dS|j	|j
�|jS|jj�XdS)a)Get the answer associated with I{key}.  Returns None if
        no answer is cached for the key.
        @param key: the key
        @type key: (dns.name.Name, int, int) tuple whose values are the
        query name, rdtype, and rdclass.
        @rtype: dns.resolver.Answer object or None
        N)rfrkrar1rwrnrRrQrmrvr{rl)rrmrtrrrr1�s

zLRUCache.getc
Cs�z�|jj�|jj|�}|dk	r2|j�|j|j=x.t|j�|jkr`|jj	}|j�|j|j=q4Wt
||�}|j|j�||j|<Wd|jj�XdS)aAssociate key and value in the cache.
        @param key: the key
        @type key: (dns.name.Name, int, int) tuple whose values are the
        query name, rdtype, and rdclass.
        @param value: The answer being cached
        @type value: dns.resolver.Answer object
        N)
rfrkrar1rwrmrr|r{rrrqrvrl)rrmrnrtrrrro�s


zLRUCache.putNc
Cs�zr|jj�|dk	r<|jj|�}|dk	rp|j�|j|j=n4|jj}x$||jkrh|j}d|_d|_|}qFWi|_Wd|jj	�XdS)z�Flush the cache.

        If I{key} is specified, only that item is flushed.  Otherwise
        the entire cache is flushed.

        @param key: the key to flush
        @type key: (dns.name.Name, int, int) tuple or None
        N)
rfrkrar1rwrmr{rsrrrl)rrmrtrsrrrrp�s	

zLRUCache.flush)ry)N)	r4r5r6rrUrzr1rorprrrrrx�s
rxc@s�eZdZdZd%dd�Zdd�Zdd	�Zd
d�Zdd
�Zdd�Z	dd�Z
dd�Zdd�Zdd�Z
dd�Zejjejjddddfdd�Zdejjfdd �Zd!d"�Zd#d$�ZdS)&�Resolvera-DNS stub resolver

    @ivar domain: The domain of this host
    @type domain: dns.name.Name object
    @ivar nameservers: A list of nameservers to query.  Each nameserver is
    a string which contains the IP address of a nameserver.
    @type nameservers: list of strings
    @ivar search: The search list.  If the query name is a relative name,
    the resolver will construct an absolute query name by appending the search
    names one by one to the query name.
    @type search: list of dns.name.Name objects
    @ivar port: The port to which to send queries.  The default is 53.
    @type port: int
    @ivar timeout: The number of seconds to wait for a response from a
    server, before timing out.
    @type timeout: float
    @ivar lifetime: The total number of seconds to spend trying to get an
    answer to the question.  If the lifetime expires, a Timeout exception
    will occur.
    @type lifetime: float
    @ivar keyring: The TSIG keyring to use.  The default is None.
    @type keyring: dict
    @ivar keyname: The TSIG keyname to use.  The default is None.
    @type keyname: dns.name.Name object
    @ivar keyalgorithm: The TSIG key algorithm to use.  The default is
    dns.tsig.default_algorithm.
    @type keyalgorithm: string
    @ivar edns: The EDNS level to use.  The default is -1, no Edns.
    @type edns: int
    @ivar ednsflags: The EDNS flags
    @type ednsflags: int
    @ivar payload: The EDNS payload size.  The default is 0.
    @type payload: int
    @ivar flags: The message flags to use.  The default is None (i.e. not
    overwritten)
    @type flags: int
    @ivar cache: The cache to use.  The default is None.
    @type cache: dns.resolver.Cache object
    @ivar retry_servfail: should we retry a nameserver if it says SERVFAIL?
    The default is 'false'.
    @type retry_servfail: bool
    �/etc/resolv.confTcCs�d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_	d|_
d|_d|_d|_
d|_d|_d|_|j�|r�tjdkr�|j�n|r�|j|�dS)aJInitialize a resolver instance.

        @param filename: The filename of a configuration file in
        standard /etc/resolv.conf format.  This parameter is meaningful
        only when I{configure} is true and the platform is POSIX.
        @type filename: string or file object
        @param configure: If True (the default), the resolver instance
        is configured in the normal fashion for the operating system
        the resolver is running on.  (I.e. a /etc/resolv.conf file on
        POSIX systems and from the registry on Windows systems.)
        @type configure: boolNFr)�domain�nameservers�nameserver_ports�port�search�timeout�lifetime�keyring�keyname�keyalgorithm�edns�	ednsflags�payload�cache�flags�retry_servfail�rotate�reset�sys�platform�
read_registry�read_resolv_conf)r�filenameZ	configurerrrrU9s.


zResolver.__init__cCs�tjjtjjtj��dd��|_t|j�dkr:tjj|_g|_	i|_
d|_g|_d|_
d|_d|_d|_tjj|_d|_d|_d|_d|_d|_d|_d|_dS)	z1Reset all resolver configuration to the defaults.rNr�5g@g>@Fr)rr*�Namer+�socket�gethostnamerr�rootr�r�r�r�r�r�r�r��tsig�default_algorithmr�r�r�r�r�r�r�r�)rrrrr�_s&"

zResolver.resetcCsZt|t�r<yt|d�}Wntk
r4dg|_dSXd}nd}z�x�|D]�}t|�dksH|ddksH|ddkrrqH|j�}t|�d	kr�qH|dd
kr�|jj|d�qH|ddkr�tj	j
|d�|_qH|dd
k�rxL|dd�D]}|jjtj	j
|��q�WqH|ddkrHd|dd�krHd|_
qHWWd|�r8|j�Xt|j�dk�rV|jjd�dS)z�Process f as a file in the /etc/resolv.conf format.  If f is
        a string, it is used as the name of the file to open; otherwise it
        is treated as the file itself.�rz	127.0.0.1NTFr�#�;rC�
nameserverrrr�Zoptionsr�)r	r�open�IOErrorr�r�splitr2rr*r+rr�r��close)r�fZ
want_close�l�tokens�suffixrrrr�vs:

$
zResolver.read_resolv_confcCs0|jd�dkrd}n|jd�dkr(d}nd}|S)N� r�,)�find)r�entry�
split_charrrr�_determine_split_char�szResolver._determine_split_charcCsDt|�}|j|�}|j|�}x"|D]}||jkr"|jj|�q"WdS)z&Configure a NameServer registry entry.N)rr�r�r�r2)rr�r�Zns_list�nsrrr�_config_win32_nameservers�s



z"Resolver._config_win32_nameserverscCstjjt|��|_dS)z"Configure a Domain registry entry.N)rr*r+rr)rrrrr�_config_win32_domain�szResolver._config_win32_domaincCsLt|�}|j|�}|j|�}x*|D]"}||jkr"|jjtjj|��q"WdS)z"Configure a Search registry entry.N)rr�r�r�r2rr*r+)rr�r�Zsearch_list�srrr�_config_win32_search�s



zResolver._config_win32_searchc#Cs.ytj|d�\}}Wntk
r,d}YnX|rv|j|�y"tj|d�\}}|r\|j|�Wq�tk
rrYq�Xntytj|d�\}}Wntk
r�d}YnX|r�|j|�y"tj|d�\}}|r�|j|�Wntk
r�YnXytj|d�\}}Wntk
�rd}YnX|�r*|j|�dS)z%Extract DNS info from a registry key.Z
NameServerNZDomainZDhcpNameServerZ
DhcpDomainZ
SearchList)�_winreg�QueryValueEx�WindowsErrorr�r�r�)rrmZserversZrtypeZdomr�rrr�_config_win32_fromkey�s<




zResolver._config_win32_fromkeyc,Cstjdtj�}d}z�ytj|d�}d}Wn tk
rHtj|d�}YnXz|j|�Wd|j�X|r�tj|d�}ztd}xjyNtj||�}|d7}tj||�}|j|||�s�w|z|j|�Wd|j�XWq|tk
r�PYq|Xq|WWd|j�XWd|j�XdS)	z9Extract resolver configuration from the Windows registry.NFz2SYSTEM\CurrentControlSet\Services\Tcpip\ParametersTz+SYSTEM\CurrentControlSet\Services\VxD\MSTCPz=SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfacesrr)	r�ZConnectRegistry�HKEY_LOCAL_MACHINE�OpenKey�EnvironmentErrorr��CloseZEnumKey�_win32_is_nic_enabled)r�lmZ	want_scanZ
tcp_paramsZ
interfacesr\�guidrmrrrr��s@
zResolver.read_registryc
Cs�y�tj|d|�}zftj|d�\}}|tjkr2t�tj|d|�}z(tj|d�\}}|tjkrbt�|d@S|j�XWd|j�XWnFttfk
r�ytj|d�\}	}|	dk	Stk
r�dSXYnXdS)Nz]SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\%s\ConnectionZ
PnpInstanceIDz SYSTEM\CurrentControlSet\Enum\%sZConfigFlagsrZNTEContextListF)	r�r�r�ZREG_SZ�
ValueErrorZ	REG_DWORDr�r�r�)
rr�r�Z
interface_keyZconnection_keyZpnp_idZttypeZ
device_keyr�Znterrrr�s6



zResolver._win32_is_nic_enabledcCsVtj�}||}|dkr0|dkr,t|d��n|}||jkrDt|d��t|j||j�S)Nrr)r�r)rQ�Timeoutr��minr�)r�startrgZdurationrrr�_compute_timeoutMs

zResolver._compute_timeoutFNrcCst|t�rtjj|d�}t|t�r.tjj|�}tjj|�r>t�t|t�rTtjj|�}tjj	|�rdt�g}|j
�r||j|�nZt|�dkr�|j|j
tjj��|jr�x2|jD]}	|j|j
|	��q�Wn|j|j
|j��d}
i}tj�}d}
�x�|D�]�}
|j�r@|jj|
||f�}|dk	�r@|jdk�r<|�r<t|jd��n|Stjj|
||�}|jdk	�rr|j|j|j|jd�|j|j|j|j �|j!dk	�r�|j!|_!d}|j"dd�}g}|j#�r�t$j%|�d}�x�|dk�r�t|�dk�r�t&||d���x`|dd�D�]N}|j'|�}|j(j||j)�}yx|}|�rDtj*j+||||||d	�}nNtj*j,||||||d	�}|j!tj!j-@�r�d}|j'|�}tj*j+||||||d	�}W�n t.j/tj0j1fk
�r�}z"|j|||||f�d}�w�WYdd}~Xn�tj*j2k
�r"}z"|j|||||f�d}�w�WYdd}~Xn�tj0j3k
�rn}z,|j4|�|j|||||f�d}�w�WYdd}~XnJt5k
�r�}z,|j4|�|j|||||f�d}�w�WYdd}~XnX|j6�}|tj6j7k�r�t7�}|j|||||f�|�|tj6j8k�s|tj6j9k�r
P|tj6j:k�s"|j;�r,|j4|�|j|||tj6j<|�|f�d}�q�W|dk	�r^Pt|�dk�r�|j'|�}t=||�}|d
9}tj>|��q�W|j6�tj6j9k�r�|||
<q�d}
Pq�W|
�r�t9||d��t?|
||||�}|j�r�|jj@|
||f|�|S)
aQuery nameservers to find the answer to the question.

        The I{qname}, I{rdtype}, and I{rdclass} parameters may be objects
        of the appropriate type, or strings that can be converted into objects
        of the appropriate type.  E.g. For I{rdtype} the integer 2 and the
        the string 'NS' both mean to query for records with DNS rdata type NS.

        @param qname: the query name
        @type qname: dns.name.Name object or string
        @param rdtype: the query type
        @type rdtype: int or string
        @param rdclass: the query class
        @type rdclass: int or string
        @param tcp: use TCP to make the query (default is False).
        @type tcp: bool
        @param source: bind to this IP address (defaults to machine default
        IP).
        @type source: IP address in dotted quad notation
        @param raise_on_no_answer: raise NoAnswer if there's no answer
        (defaults is True).
        @type raise_on_no_answer: bool
        @param source_port: The port from which to send the message.
        The default is 0.
        @type source_port: int
        @rtype: dns.resolver.Answer instance
        @raises Timeout: no answers could be found in the specified lifetime
        @raises NXDOMAIN: the query name does not exist
        @raises YXDOMAIN: the query name is too long after DNAME substitution
        @raises NoAnswer: the response did not contain an answer and
        raise_on_no_answer is True.
        @raises NoNameservers: no non-broken nameservers are available to
        answer the question.NrT)r.)�	algorithmg�������?r)rArB)�source�source_portrCF)rr)Ar	rrr*r+r"Zis_metatyperHr Zis_metaclass�is_absoluter2rZconcatenater�r�rrQr�r1rMr<r.�messageZ
make_queryr��use_tsigr�r��use_ednsr�r�r�r�r�r��randomZshuffler@r�r�r�r=�tcp�udpZTCr��error�	exceptionr�ZUnexpectedSourceZ	FormError�remove�EOFError�rcoder;ZNOERRORrZSERVFAILr�r)r�ZsleeprIro)rr-r%r&r�r�rSr�Z
qnames_to_tryr�Zall_nxdomainZnxdomain_responsesr�Z_qnamer$rAr.r�rBZbackoffr�r�r�Ztcp_attemptZexr�Z
sleep_timerrrr=]s�#




















zResolver.querycCs4||_|dkr$t|jj��d|_n||_||_dS)a�Add a TSIG signature to the query.

        @param keyring: The TSIG keyring to use; defaults to None.
        @type keyring: dict
        @param keyname: The name of the TSIG key to use; defaults to None.
        The key must be defined in the keyring.  If a keyring is specified
        but a keyname is not, then the key used will be the first key in the
        keyring.  Note that the order of keys in a dictionary is not defined,
        so applications should supply a keyname when a keyring is used, unless
        they know the keyring contains only one key.
        @param algorithm: The TSIG key algorithm to use.  The default
        is dns.tsig.default_algorithm.
        @type algorithm: stringNr)r�r
�keysr�r�)rr�r�r�rrrr�"s
zResolver.use_tsigcCs"|dkrd}||_||_||_dS)aConfigure Edns.

        @param edns: The EDNS level to use.  The default is -1, no Edns.
        @type edns: int
        @param ednsflags: The EDNS flags
        @type ednsflags: int
        @param payload: The EDNS payload size.  The default is 0.
        @type payload: intNrr)r�r�r�)rr�r�r�rrrr�8s

zResolver.use_ednscCs
||_dS)z�Overrides the default flags with your own

        @param flags: The flags to overwrite the default with
        @type flags: intN)r�)rr�rrr�	set_flagsHszResolver.set_flags)r~T)r4r5r6rrUr�r�r�r�r�r�r�r�r�r�rr"�Ar r!r=r�r�r�r�r�rrrrr}s&+
&)

"-7Er}cCstdkrt�tS)z7Get the default resolver, initializing it if necessary.N)�default_resolver�reset_default_resolverrrrr�get_default_resolverRsr�cCs
t�adS)zSRe-initialize default resolver.

    resolv.conf will be re-read immediatelly.
    N)r}r�rrrrr�Ysr�FTcCst�j|||||||�S)z�Query nameservers to find the answer to the question.

    This is a convenience function that uses the default resolver
    object to make the query.
    @see: L{dns.resolver.Resolver.query} for more information on the
    parameters.)r�r=)r-r%r&r�r�rSr�rrrr=bs	r=cCs�t|t�rtjj|tjj�}|dkr*t�}|j�s:t|��xxy(|j	|tj
j||�}|jj|krb|SWn tj
jtj
jfk
r�YnXy|j�}Wq<tjjk
r�t�Yq<Xq<WdS)a�Find the name of the zone which contains the specified name.

    @param name: the query name
    @type name: absolute dns.name.Name object or string
    @param rdclass: The query class
    @type rdclass: int
    @param tcp: use TCP to make the query (default is False).
    @type tcp: bool
    @param resolver: the resolver to use
    @type resolver: dns.resolver.Resolver object or None
    @rtype: dns.name.NameN)r	rrr*r+r�r�r�rFr=r"rNrM�resolverrr<rOrPrG)r*r&r�r�r$rrr�
zone_for_nameos"
r�c,Cs�|tjtjB@dkrt�|dkr4|dkr4tjtj��g}g}d}y�|dkr�d}|tj@dkrr|jd�|jd�q�|jd�|jd�n>|jd�}	t	|	�dkr�|	d}
n|}
t
jj|
�}|j|�|}W�npt
k
�r:y t
jj|�}|j|�|}W�n8t
k
�r4|tj@dk�r0y�|tjk�s8|tjk�r�tj|t
jjd	d
�}|j}|jjd�}|jdk	�r�x|jD]}
|j|
j��qrW|tjk�s�|tjk�r�tj|t
jjd	d
�}|j}|jjd�}|jdk	�r�x|jD]}
|j|
j��q�WWn<t
jjk
�rtjtj��Yntjtj��YnXYnXYnXd}y|dk�rRd}nt |�}WnLt
k
�r�|tj!@dk�r�ytj"|�}Wnt
k
�r�YnXYnX|dk�r�tjtj��g}|dk�r�tj#tj$g}n|g}|tj%@dk�r�|}nd}|tjk�s|tjk�rfxP|D]H}x@|D]8}x0t&|D]$}|jtj|||||ddff��q2W�q$W�qW|tjk�s~|tjk�r�xL|D]D}x<|D]4}x,t&|D] }|jtj|||||ff��q�W�q�W�q�Wt	|�dk�r�tjtj��|S)
NrZ	localhostz::z0.0.0.0z::1z	127.0.0.1�%rCF)rST�)'r�Z
AI_ADDRCONFIGZAI_V4MAPPED�NotImplementedError�gaierror�
EAI_NONAMEZ
AI_PASSIVEr2r�rr�ipv6�	inet_aton�	ExceptionZipv4ZAI_NUMERICHOST�AF_INET6�	AF_UNSPEC�	_resolverr=r"ZAAAAr-r/r)rMZaddress�AF_INETr�r�rZ
EAI_SYSTEM�intZAI_NUMERICSERVZ
getservbyname�
SOCK_DGRAM�SOCK_STREAM�AI_CANONNAME�_protocols_for_socktype)�host�service�familyZsocktype�protor�Zv6addrsZv4addrsr/�partsZahost�addrZv6ZrdataZv4r��tuplesZ	socktypesr,rrr�_getaddrinfo�s�












$

 r�c
Csf|d}|d}t|�dkr,|d}tj}n
d}tj}t|||tjtjd�}t|�dkrbtjd��|ddd}|tj@r�d}nd}t	j
j|�}	|tj@dk�ry"t
j|	d�}
|
jdjjd	�}WnVt	jjt	jjfk
�r|tj@r�tjtj��|}|dk	�r|d
t|�7}YnXn|}|dk	�r<|d
t|�7}|tj@�rRt|�}ntj||�}||fS)Nrr�rDz'sockaddr resolved to multiple addressesr�r�ZPTRTr�)rr�r�r�r�r��SOL_TCPr�ZNI_DGRAMrZreversenameZfrom_addressZNI_NUMERICHOSTr�r=rMr(r)r�rr<�NI_NAMEREQDr�r�rZNI_NUMERICSERVZ
getservbyport)
�sockaddrr�r�r�Zscoper�r�r�Zpnamer-r$Zhostnamer�rrr�_getnameinfosB






r�cCsD|dkrtj�}ytt|d�dd�dStk
r>|SXdS)N�Prr�)r�r�r�r�r�)r*rrr�_getfqdn.sr�cCst|�ddS)NrCr)�_gethostbyname_ex)r*rrr�_gethostbyname7sr�cCsXg}g}t|dtjtjtjtj�}|dd}x|D]}|j|dd�q4W|||fS)NrrDr�)r�r�r�r�r�r�r2)r*�aliases�	addressesr��	canonical�itemrrrr�;s
r�c
Cs�y"tjj|�|dddf}tj}Wn"tk
rD|df}tj}YnXt|tj�\}}g}g}t	|d|tj
tjtj�}|dd}x|D]}	|j
|	dd�q�W|||fS)Nr�rrDr�)rr�r�r�r�r�r�r�r�r�r�r�r�r2)
Zipr�r�r*r�r�r�r�r�rrrr�_gethostbyaddrGs 

rcCs:|dkrt�}|att_tt_tt_t	t_
tt_t
t_dS)a�Override the system resolver routines in the socket module with
    versions which use dnspython's resolver.

    This can be useful in testing situations where you want to control
    the resolution behavior of python code without having to change
    the system's resolver settings (e.g. /etc/resolv.conf).

    The resolver to use may be specified; if it's not, the default
    resolver will be used.

    @param resolver: the resolver to use
    @type resolver: dns.resolver.Resolver object or None
    N)r�r�r�r��getaddrinfor��getnameinfor��getfqdnr��
gethostbynamer��gethostbyname_exr�
gethostbyaddr)r�rrr�override_system_resolver[srcCs,datt_tt_tt_tt_	t
t_tt_
dS)z4Undo the effects of override_system_resolver().
    N)r��_original_getaddrinfor�r�_original_getnameinfor�_original_getfqdnr�_original_gethostbynamer�_original_gethostbyname_exr�_original_gethostbyaddrrrrrr�restore_system_resolverusr)r)N)N)Prr�r�rQr�Z	threadingrd�ImportErrorZdummy_threadingZ
dns.exceptionrZ	dns.flagsZdns.ipv4Zdns.ipv6Zdns.messageZdns.nameZ	dns.queryZ	dns.rcodeZdns.rdataclassZ
dns.rdatatypeZdns.reversenameZdns.tsigZ_compatrrr��winregr�r�ZDNSExceptionrr;r�r<r@rFrGrH�objectrIr_rqrxr}r�r�r�r"r�r r!r=r�r�ZSOL_UDPr�r�r�r�rr	rr
rrrrrr
rrr�r�r�r�r�r�rrrrrrr�<module>s�
<sboG	&

c
(
	
__pycache__/set.cpython-36.opt-1.pyc000064400000017337150351404330013145 0ustar003

�b�W#�@sdZGdd�de�ZdS)zA simple Set class.c@seZdZdZdgZdDdd�Zdd�Zdd	�Zd
d�Zdd
�Z	dd�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�Zd$d%�Zd&d'�Zd(d)�Zd*d+�Zd,d-�Zd.d/�Zd0d1�Zd2d3�Zd4d5�Zd6d7�Zd8d9�Zd:d;�Z d<d=�Z!d>d?�Z"d@dA�Z#dBdC�Z$dS)E�Seta'A simple set class.

    Sets are not in Python until 2.3, and rdata are not immutable so
    we cannot use sets.Set anyway.  This class implements subset of
    the 2.3 Set interface using a list as the container.

    @ivar items: A list of the items which are in the set
    @type items: list�itemsNcCs*g|_|dk	r&x|D]}|j|�qWdS)zvInitialize the set.

        @param items: the initial set of items
        @type items: any iterable or None
        N)r�add)�selfr�item�r�/usr/lib/python3.6/set.py�__init__ s
zSet.__init__cCsdt|j�S)Nzdns.simpleset.Set(%s))�reprr)rrrr�__repr__,szSet.__repr__cCs||jkr|jj|�dS)zAdd an item to the set.N)r�append)rrrrrr/s
zSet.addcCs|jj|�dS)zRemove an item from the set.N)r�remove)rrrrrr4sz
Set.removecCs*y|jj|�Wntk
r$YnXdS)z'Remove an item from the set if present.N)rr�
ValueError)rrrrr�discard8szSet.discardcCs |j}|j|�}t|j�|_|S)a�Make a (shallow) copy of the set.

        There is a 'clone protocol' that subclasses of this class
        should use.  To make a copy, first call your super's _clone()
        method, and use the object returned as the new instance.  Then
        make shallow copies of the attributes defined in the subclass.

        This protocol allows us to write the set algorithms that
        return new instances (e.g. union) once, and keep using them in
        subclasses.
        )�	__class__�__new__�listr)r�cls�objrrr�_clone?s

z
Set._clonecCs|j�S)z!Make a (shallow) copy of the set.)r)rrrr�__copy__QszSet.__copy__cCs|j�S)z!Make a (shallow) copy of the set.)r)rrrr�copyUszSet.copycCs<t|t�std��||krdSx|jD]}|j|�q&WdS)z�Update the set, adding any elements from other which are not
        already in the set.
        @param other: the collection of items with which to update the set
        @type other: Set object
        zother must be a Set instanceN)�
isinstancerr
rr)r�otherrrrr�union_updateYs
zSet.union_updatecCsLt|t�std��||krdSx(t|j�D]}||jkr*|jj|�q*WdS)z�Update the set, removing any elements from other which are not
        in both sets.
        @param other: the collection of items with which to update the set
        @type other: Set object
        zother must be a Set instanceN)rrr
rrr)rrrrrr�intersection_updatefs

zSet.intersection_updatecCs@t|t�std��||kr"g|_nx|jD]}|j|�q*WdS)z�Update the set, removing any elements from other which are in
        the set.
        @param other: the collection of items with which to update the set
        @type other: Set object
        zother must be a Set instanceN)rrr
rr)rrrrrr�difference_updatevs
zSet.difference_updatecCs|j�}|j|�|S)z�Return a new set which is the union of I{self} and I{other}.

        @param other: the other set
        @type other: Set object
        @rtype: the same type as I{self}
        )rr)rrrrrr�union�s
z	Set.unioncCs|j�}|j|�|S)z�Return a new set which is the intersection of I{self} and I{other}.

        @param other: the other set
        @type other: Set object
        @rtype: the same type as I{self}
        )rr)rrrrrr�intersection�s
zSet.intersectioncCs|j�}|j|�|S)z�Return a new set which I{self} - I{other}, i.e. the items
        in I{self} which are not also in I{other}.

        @param other: the other set
        @type other: Set object
        @rtype: the same type as I{self}
        )rr)rrrrrr�
difference�s	
zSet.differencecCs
|j|�S)N)r)rrrrr�__or__�sz
Set.__or__cCs
|j|�S)N)r)rrrrr�__and__�szSet.__and__cCs
|j|�S)N)r)rrrrr�__add__�szSet.__add__cCs
|j|�S)N)r)rrrrr�__sub__�szSet.__sub__cCs|j|�|S)N)r)rrrrr�__ior__�s
zSet.__ior__cCs|j|�|S)N)r)rrrrr�__iand__�s
zSet.__iand__cCs|j|�|S)N)r)rrrrr�__iadd__�s
zSet.__iadd__cCs|j|�|S)N)r)rrrrr�__isub__�s
zSet.__isub__cCsx|D]}|j|�qWdS)z�Update the set, adding any elements from other which are not
        already in the set.
        @param other: the collection of items with which to update the set
        @type other: any iterable typeN)r)rrrrrr�update�s
z
Set.updatecCs
g|_dS)zMake the set empty.N)r)rrrr�clear�sz	Set.clearcCs@x|jD]}||jkrdSqWx|jD]}||jkr&dSq&WdS)NFT)r)rrrrrr�__eq__�s

z
Set.__eq__cCs|j|�S)N)r))rrrrr�__ne__�sz
Set.__ne__cCs
t|j�S)N)�lenr)rrrr�__len__�szSet.__len__cCs
t|j�S)N)�iterr)rrrr�__iter__�szSet.__iter__cCs
|j|S)N)r)r�irrr�__getitem__�szSet.__getitem__cCs|j|=dS)N)r)rr/rrr�__delitem__�szSet.__delitem__cCs4t|t�std��x|jD]}||jkrdSqWdS)z?Is I{self} a subset of I{other}?

        @rtype: bool
        zother must be a Set instanceFT)rrr
r)rrrrrr�issubset�s

zSet.issubsetcCs4t|t�std��x|jD]}||jkrdSqWdS)zAIs I{self} a superset of I{other}?

        @rtype: bool
        zother must be a Set instanceFT)rrr
r)rrrrrr�
issuperset�s

zSet.issuperset)N)%�__name__�
__module__�__qualname__�__doc__�	__slots__rr
rrrrrrrrrrrrrr r!r"r#r$r%r&r'r(r)r*r,r.r0r1r2r3rrrrrsD	



rN)r7�objectrrrrr�<module>s__pycache__/version.cpython-36.pyc000064400000000702150351404330013064 0ustar003

�b�W��@s�dZdZdZdZdZdZedkr0deeefZn,edkrJdeeeefZndeeeeefZed>ed>Bed	>Bed
>BeBZdS)z&dnspython release version information.���z%d.%d.%dz%d.%d.%dx%dz%d.%d.%d%x%d����N)�__doc__ZMAJORZMINORZMICROZRELEASELEVELZSERIAL�version�
hexversion�rr�/usr/lib/python3.6/version.py�<module>s__pycache__/rdataset.cpython-36.pyc000064400000022516150351404330013215 0ustar003

�b�W$-�@s�dZddlZddlmZddlZddlZddlZddlZddl	Zddl
ZddlmZej
jZGdd�dejj�ZGdd	�d	ejj�ZGd
d�dej
j�Zdd
�Zdd�Zdd�Zdd�ZdS)zHDNS rdatasets (an rdataset is a set of rdatas of a given type and class)�N)�StringIO�)�string_typesc@seZdZdZdS)�DifferingCoversz~An attempt was made to add a DNS SIG/RRSIG whose covered type
    is not the same as that of the other rdatas in the rdataset.N)�__name__�
__module__�__qualname__�__doc__�r
r
�/usr/lib/python3.6/rdataset.pyr!src@seZdZdZdS)�IncompatibleTypesz?An attempt was made to add DNS RR data of an incompatible type.N)rrrr	r
r
r
rr'srcs�eZdZdZddddgZejjf�fdd�	Z�fdd	�Z	d
d�Z
d$�fd
d�	Z�fdd�Z�fdd�Z
�fdd�Zdd�Zdd�Z�fdd�Zdd�Zd%dd�Zd&d d!�Zd"d#�Z�ZS)'�Rdataseta�A DNS rdataset.

    @ivar rdclass: The class of the rdataset
    @type rdclass: int
    @ivar rdtype: The type of the rdataset
    @type rdtype: int
    @ivar covers: The covered type.  Usually this value is
    dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or
    dns.rdatatype.RRSIG, then the covers value will be the rdata
    type the SIG/RRSIG covers.  The library treats the SIG and RRSIG
    types as if they were a family of
    types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA).  This makes RRSIGs much
    easier to work with than if RRSIGs covering different rdata
    types were aggregated into a single RRSIG rdataset.
    @type covers: int
    @ivar ttl: The DNS TTL (Time To Live) value
    @type ttl: int
    �rdclass�rdtype�covers�ttlcs*tt|�j�||_||_||_d|_dS)z�Create a new rdataset of the specified class and type.

        @see: the description of the class instance variables for the
        meaning of I{rdclass} and I{rdtype}rN)�superr
�__init__rrrr)�selfrrr)�	__class__r
rrCs
zRdataset.__init__cs2tt|�j�}|j|_|j|_|j|_|j|_|S)N)rr
�_clonerrrr)r�obj)rr
rrOszRdataset._clonecCs(t|�dkr||_n||jkr$||_dS)z�Set the TTL of the rdataset to be the lesser of the set's current
        TTL or the specified TTL.  If the set contains no rdatas, set the TTL
        to the specified TTL.
        @param ttl: The TTL
        @type ttl: intrN)�lenr)rrr
r
r�
update_ttlWs
zRdataset.update_ttlNcs�|j|jks|j|jkrt�|dk	r.|j|�|jtjjksJ|jtjjkr�|j�}t	|�dkrt|jtjj
krt||_n|j|kr�t�tjj|j�r�t	|�dkr�|j
�tt|�j|�dS)a%Add the specified rdata to the rdataset.

        If the optional I{ttl} parameter is supplied, then
        self.update_ttl(ttl) will be called prior to adding the rdata.

        @param rd: The rdata
        @type rd: dns.rdata.Rdata object
        @param ttl: The TTL
        @type ttl: intNr)rrrr�dns�	rdatatypeZRRSIGZSIGrr�NONErZis_singleton�clearrr
�add)r�rdrr)rr
rrcs

zRdataset.addcs |j|j�tt|�j|�dS)N)rrrr
�union_update)r�other)rr
rr �szRdataset.union_updatecs |j|j�tt|�j|�dS)N)rrrr
�intersection_update)rr!)rr
rr"�szRdataset.intersection_updatecs |j|j�tt|�j|�dS)z�Add all rdatas in other to self.

        @param other: The rdataset from which to update
        @type other: dns.rdataset.Rdataset objectN)rrrr
�update)rr!)rr
rr#�szRdataset.updatecCsR|jdkrd}ndtjj|j�d}dtjj|j�dtjj|j�|dS)Nr��(�)z<DNS � z
 rdataset>)rrr�to_text�
rdataclassrr)rZctextr
r
r�__repr__�s
zRdataset.__repr__cCs|j�S)N)r()rr
r
r�__str__�szRdataset.__str__csFt|t�sdS|j|jks2|j|jks2|j|jkr6dStt|�j|�S)zTwo rdatasets are equal if they have the same class, type, and
        covers, and contain the same rdata.
        @rtype: boolF)�
isinstancer
rrrr�__eq__)rr!)rr
rr-�s
zRdataset.__eq__cCs|j|�S)N)r-)rr!r
r
r�__ne__�szRdataset.__ne__Tc
Ks�|dk	r"|j||�}t|�}d}nd}d}t�}|dk	r>|}	n|j}	t|�dkrz|jd||tjj|	�tj	j|j
�f�nNxL|D]D}
|jd|||jtjj|	�tj	j|j
�|
jf||d�|��f�q�W|j�dd	�S)
a�Convert the rdataset into DNS master file format.

        @see: L{dns.name.Name.choose_relativity} for more information
        on how I{origin} and I{relativize} determine the way names
        are emitted.

        Any additional keyword arguments are passed on to the rdata
        to_text() method.

        @param name: If name is not None, emit a RRs with I{name} as
        the owner name.
        @type name: dns.name.Name object
        @param origin: The origin for relative names, or None.
        @type origin: dns.name.Name object
        @param relativize: True if names should names be relativized
        @type relativize: boolNr'r$rz
%s%s%s %s
z%s%s%d %s %s %s
)�origin�
relativizer���)
Zchoose_relativity�strrrr�writerr)r(rrr�getvalue)r�namer/r0�override_rdclass�kwZntextZpad�srrr
r
rr(�s*


zRdataset.to_textc
Cs&|dk	r|}d}n|j}|jdd�t|�dkr`|j|||�tjd|j|dd�}|j|�dS|rxt|�}	t	j
|	�n|}	x�|	D]�}
|j|||�tjd|j||jd�}|j|�|j�}|
j|||�|j�}||dks�t
�|j|d�tjd||�}|j|�|jdd�q�Wt|�SdS)	a,Convert the rdataset to wire format.

        @param name: The owner name of the RRset that will be emitted
        @type name: dns.name.Name object
        @param file: The file to which the wire format data will be appended
        @type file: file
        @param compress: The compression table to use; the default is None.
        @type compress: dict
        @param origin: The origin to be appended to any relative names when
        they are emitted.  The default is None.
        @returns: the number of records emitted
        @rtype: int
        NFr�z!HHIHriz!H)r�seekr�to_wire�struct�packrr3�list�randomZshuffler�tell�AssertionError)
rr5�file�compressr/r6Zwant_shufflerZstuff�lr�start�endr
r
rr;�s8




zRdataset.to_wirecCs&|j|kr"|j|kr"|j|kr"dSdS)zSReturns True if this rdataset matches the specified class, type,
        and coversTF)rrr)rrrrr
r
r�matchs



zRdataset.match)N)NNTN)NNNT)rrrr	�	__slots__rrrrrrrr r"r#r*r+r-r.r(r;rG�
__classcell__r
r
)rrr
,s$ 	

2
/r
cCspt|t�rtjj|�}t|t�r,tjj|�}t||�}|j|�x*|D]"}tjj|j	|j
|�}|j|�qFW|S)z�Create an rdataset with the specified class, type, and TTL, and with
    the specified list of rdatas in text format.

    @rtype: dns.rdataset.Rdataset object
    )r,rrr)�	from_textrr
rZrdatarrr)rrr�text_rdatas�r�trr
r
r�from_text_lists




rNcGst||||�S)z�Create an rdataset with the specified class, type, and TTL, and with
    the specified rdatas in text format.

    @rtype: dns.rdataset.Rdataset object
    )rN)rrrrKr
r
rrJ/srJcCsTt|�dkrtd��d}x6|D].}|dkrBt|j|j�}|j|�|j|�qW|S)z�Create an rdataset with the specified TTL, and with
    the specified list of rdata objects.

    @rtype: dns.rdataset.Rdataset object
    rzrdata list must not be emptyN)r�
ValueErrorr
rrrr)r�rdatasrLrr
r
r�from_rdata_list9s

rQcGs
t||�S)z�Create an rdataset with the specified TTL, and with
    the specified rdata objects.

    @rtype: dns.rdataset.Rdataset object
    )rQ)rrPr
r
r�
from_rdataKsrR)r	r?�iorr<Z
dns.exceptionrZ
dns.rdatatypeZdns.rdataclassZ	dns.rdataZdns.setZ_compatr�set�SetZ	SimpleSetZ	exceptionZDNSExceptionrrr
rNrJrQrRr
r
r
r�<module>s$q
__pycache__/hash.cpython-36.pyc000064400000000733150351404330012326 0ustar003

�b�WL�@sXdZddlZiZejed<ejed<ejed<ejed<ejed<ejed<d	d
�Z	dS)z'Hashing backwards compatibility wrapper�NZMD5ZSHA1ZSHA224ZSHA256ZSHA384ZSHA512cCst|j�S)N)�hashes�upper)�	algorithm�r�/usr/lib/python3.6/hash.py�getsr)
�__doc__ZhashlibrZmd5Zsha1Zsha224Zsha256Zsha384Zsha512rrrrr�<module>s





__pycache__/set.cpython-36.pyc000064400000017337150351404330012206 0ustar003

�b�W#�@sdZGdd�de�ZdS)zA simple Set class.c@seZdZdZdgZdDdd�Zdd�Zdd	�Zd
d�Zdd
�Z	dd�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�Zd$d%�Zd&d'�Zd(d)�Zd*d+�Zd,d-�Zd.d/�Zd0d1�Zd2d3�Zd4d5�Zd6d7�Zd8d9�Zd:d;�Z d<d=�Z!d>d?�Z"d@dA�Z#dBdC�Z$dS)E�Seta'A simple set class.

    Sets are not in Python until 2.3, and rdata are not immutable so
    we cannot use sets.Set anyway.  This class implements subset of
    the 2.3 Set interface using a list as the container.

    @ivar items: A list of the items which are in the set
    @type items: list�itemsNcCs*g|_|dk	r&x|D]}|j|�qWdS)zvInitialize the set.

        @param items: the initial set of items
        @type items: any iterable or None
        N)r�add)�selfr�item�r�/usr/lib/python3.6/set.py�__init__ s
zSet.__init__cCsdt|j�S)Nzdns.simpleset.Set(%s))�reprr)rrrr�__repr__,szSet.__repr__cCs||jkr|jj|�dS)zAdd an item to the set.N)r�append)rrrrrr/s
zSet.addcCs|jj|�dS)zRemove an item from the set.N)r�remove)rrrrrr4sz
Set.removecCs*y|jj|�Wntk
r$YnXdS)z'Remove an item from the set if present.N)rr�
ValueError)rrrrr�discard8szSet.discardcCs |j}|j|�}t|j�|_|S)a�Make a (shallow) copy of the set.

        There is a 'clone protocol' that subclasses of this class
        should use.  To make a copy, first call your super's _clone()
        method, and use the object returned as the new instance.  Then
        make shallow copies of the attributes defined in the subclass.

        This protocol allows us to write the set algorithms that
        return new instances (e.g. union) once, and keep using them in
        subclasses.
        )�	__class__�__new__�listr)r�cls�objrrr�_clone?s

z
Set._clonecCs|j�S)z!Make a (shallow) copy of the set.)r)rrrr�__copy__QszSet.__copy__cCs|j�S)z!Make a (shallow) copy of the set.)r)rrrr�copyUszSet.copycCs<t|t�std��||krdSx|jD]}|j|�q&WdS)z�Update the set, adding any elements from other which are not
        already in the set.
        @param other: the collection of items with which to update the set
        @type other: Set object
        zother must be a Set instanceN)�
isinstancerr
rr)r�otherrrrr�union_updateYs
zSet.union_updatecCsLt|t�std��||krdSx(t|j�D]}||jkr*|jj|�q*WdS)z�Update the set, removing any elements from other which are not
        in both sets.
        @param other: the collection of items with which to update the set
        @type other: Set object
        zother must be a Set instanceN)rrr
rrr)rrrrrr�intersection_updatefs

zSet.intersection_updatecCs@t|t�std��||kr"g|_nx|jD]}|j|�q*WdS)z�Update the set, removing any elements from other which are in
        the set.
        @param other: the collection of items with which to update the set
        @type other: Set object
        zother must be a Set instanceN)rrr
rr)rrrrrr�difference_updatevs
zSet.difference_updatecCs|j�}|j|�|S)z�Return a new set which is the union of I{self} and I{other}.

        @param other: the other set
        @type other: Set object
        @rtype: the same type as I{self}
        )rr)rrrrrr�union�s
z	Set.unioncCs|j�}|j|�|S)z�Return a new set which is the intersection of I{self} and I{other}.

        @param other: the other set
        @type other: Set object
        @rtype: the same type as I{self}
        )rr)rrrrrr�intersection�s
zSet.intersectioncCs|j�}|j|�|S)z�Return a new set which I{self} - I{other}, i.e. the items
        in I{self} which are not also in I{other}.

        @param other: the other set
        @type other: Set object
        @rtype: the same type as I{self}
        )rr)rrrrrr�
difference�s	
zSet.differencecCs
|j|�S)N)r)rrrrr�__or__�sz
Set.__or__cCs
|j|�S)N)r)rrrrr�__and__�szSet.__and__cCs
|j|�S)N)r)rrrrr�__add__�szSet.__add__cCs
|j|�S)N)r)rrrrr�__sub__�szSet.__sub__cCs|j|�|S)N)r)rrrrr�__ior__�s
zSet.__ior__cCs|j|�|S)N)r)rrrrr�__iand__�s
zSet.__iand__cCs|j|�|S)N)r)rrrrr�__iadd__�s
zSet.__iadd__cCs|j|�|S)N)r)rrrrr�__isub__�s
zSet.__isub__cCsx|D]}|j|�qWdS)z�Update the set, adding any elements from other which are not
        already in the set.
        @param other: the collection of items with which to update the set
        @type other: any iterable typeN)r)rrrrrr�update�s
z
Set.updatecCs
g|_dS)zMake the set empty.N)r)rrrr�clear�sz	Set.clearcCs@x|jD]}||jkrdSqWx|jD]}||jkr&dSq&WdS)NFT)r)rrrrrr�__eq__�s

z
Set.__eq__cCs|j|�S)N)r))rrrrr�__ne__�sz
Set.__ne__cCs
t|j�S)N)�lenr)rrrr�__len__�szSet.__len__cCs
t|j�S)N)�iterr)rrrr�__iter__�szSet.__iter__cCs
|j|S)N)r)r�irrr�__getitem__�szSet.__getitem__cCs|j|=dS)N)r)rr/rrr�__delitem__�szSet.__delitem__cCs4t|t�std��x|jD]}||jkrdSqWdS)z?Is I{self} a subset of I{other}?

        @rtype: bool
        zother must be a Set instanceFT)rrr
r)rrrrrr�issubset�s

zSet.issubsetcCs4t|t�std��x|jD]}||jkrdSqWdS)zAIs I{self} a superset of I{other}?

        @rtype: bool
        zother must be a Set instanceFT)rrr
r)rrrrrr�
issuperset�s

zSet.issuperset)N)%�__name__�
__module__�__qualname__�__doc__�	__slots__rr
rrrrrrrrrrrrrr r!r"r#r$r%r&r'r(r)r*r,r.r0r1r2r3rrrrrsD	



rN)r7�objectrrrrr�<module>s__pycache__/message.cpython-36.pyc000064400000077556150351404330013050 0ustar003

�@�Wy��
@s�dZddlmZddlmZddlZddlZddlZddl	Zddl
ZddlZddlZddl
ZddlZddlZddlZddlZddlZddlZddlZddlZddlmZmZmZGdd�dejj�ZGd	d
�d
ejj�ZGdd�dejj�ZGd
d�dejj�Z Gdd�dejj�Z!Gdd�dejj�Z"Gdd�de#�Z$Gdd�de#�Z%d(dd�Z&Gdd�de#�Z'dd�Z(d d!�Z)ej*j+ddddddfd"d#�Z,d)d&d'�Z-dS)*zDNS Messages�)�absolute_import)�StringION�)�long�xrange�string_typesc@seZdZdZdS)�ShortHeaderz2The DNS packet passed to from_wire() is too short.N)�__name__�
__module__�__qualname__�__doc__�r
r
�/usr/lib/python3.6/message.pyr*src@seZdZdZdS)�TrailingJunkzEThe DNS packet passed to from_wire() has extra junk at the end of it.N)r	r
rrr
r
r
rr/src@seZdZdZdS)�UnknownHeaderFieldzVThe header field name was not recognized when converting from text
    into a message.N)r	r
rrr
r
r
rr4src@seZdZdZdS)�BadEDNSzVOPT record occurred somewhere other than the start of
    the additional data section.N)r	r
rrr
r
r
rr:src@seZdZdZdS)�BadTSIGzWA TSIG record occurred somewhere other than the end of
    the additional data section.N)r	r
rrr
r
r
rr@src@seZdZdZdS)�UnknownTSIGKeyz(A TSIG with an unknown key was received.N)r	r
rrr
r
r
rrFsrc@s�eZdZdZd-dd�Zdd�Zdd�Zd.d
d�Zdd
�Zdd�Z	dd�Z
dd�Zej
jdddfdd�Zej
jdddfdd�Zd/dd�Zdddddejjfdd�Zd0d!d"�Zd1d#d$�Zd%d&�Zd'd(�Zd)d*�Zd+d,�ZdS)2�Messagea,
A DNS message.

    @ivar id: The query id; the default is a randomly chosen id.
    @type id: int
    @ivar flags: The DNS flags of the message.  @see: RFC 1035 for an
    explanation of these flags.
    @type flags: int
    @ivar question: The question section.
    @type question: list of dns.rrset.RRset objects
    @ivar answer: The answer section.
    @type answer: list of dns.rrset.RRset objects
    @ivar authority: The authority section.
    @type authority: list of dns.rrset.RRset objects
    @ivar additional: The additional data section.
    @type additional: list of dns.rrset.RRset objects
    @ivar edns: The EDNS level to use.  The default is -1, no Edns.
    @type edns: int
    @ivar ednsflags: The EDNS flags
    @type ednsflags: long
    @ivar payload: The EDNS payload size.  The default is 0.
    @type payload: int
    @ivar options: The EDNS options
    @type options: list of dns.edns.Option objects
    @ivar request_payload: The associated request's EDNS payload size.
    @type request_payload: int
    @ivar keyring: The TSIG keyring to use.  The default is None.
    @type keyring: dict
    @ivar keyname: The TSIG keyname to use.  The default is None.
    @type keyname: dns.name.Name object
    @ivar keyalgorithm: The TSIG algorithm to use; defaults to
    dns.tsig.default_algorithm.  Constants for TSIG algorithms are defined
    in dns.tsig, and the currently implemented algorithms are
    HMAC_MD5, HMAC_SHA1, HMAC_SHA224, HMAC_SHA256, HMAC_SHA384, and
    HMAC_SHA512.
    @type keyalgorithm: string
    @ivar request_mac: The TSIG MAC of the request message associated with
    this message; used when validating TSIG signatures.   @see: RFC 2845 for
    more information on TSIG fields.
    @type request_mac: string
    @ivar fudge: TSIG time fudge; default is 300 seconds.
    @type fudge: int
    @ivar original_id: TSIG original id; defaults to the message's id
    @type original_id: int
    @ivar tsig_error: TSIG error code; default is 0.
    @type tsig_error: int
    @ivar other_data: TSIG other data.
    @type other_data: string
    @ivar mac: The TSIG MAC for this message.
    @type mac: string
    @ivar xfr: Is the message being used to contain the results of a DNS
    zone transfer?  The default is False.
    @type xfr: bool
    @ivar origin: The origin of the zone in messages which are used for
    zone transfers or for DNS dynamic updates.  The default is None.
    @type origin: dns.name.Name object
    @ivar tsig_ctx: The TSIG signature context associated with this
    message.  The default is None.
    @type tsig_ctx: hmac.HMAC object
    @ivar had_tsig: Did the message decoded from wire format have a TSIG
    signature?
    @type had_tsig: bool
    @ivar multi: Is this message part of a multi-message sequence?  The
    default is false.  This variable is used when validating TSIG signatures
    on messages which are part of a zone transfer.
    @type multi: bool
    @ivar first: Is this message standalone, or the first of a multi
    message sequence?  This variable is used when validating TSIG signatures
    on messages which are part of a zone transfer.
    @type first: bool
    @ivar index: An index of rrsets in the message.  The index key is
    (section, name, rdclass, rdtype, covers, deleting).  Indexing can be
    disabled by setting the index to None.
    @type index: dict
    NcCs�|dkrtjj�|_n||_d|_g|_g|_g|_g|_d|_	d|_
d|_g|_d|_
d|_d|_tjj|_d|_d|_d|_d|_|j|_d|_d|_d|_d|_d|_d|_d|_i|_dS)Nrr�i,FT���) �dnsZentropyZ	random_16�id�flags�question�answer�	authority�
additional�edns�	ednsflags�payload�options�request_payload�keyring�keyname�tsig�default_algorithm�keyalgorithm�request_mac�
other_data�
tsig_error�fudge�original_id�mac�xfr�origin�tsig_ctx�had_tsig�multi�first�index)�selfrr
r
r�__init__�s:
zMessage.__init__cCsdt|j�dS)Nz<DNS message, ID �>)�reprr)r5r
r
r�__repr__�szMessage.__repr__cCs|j�S)N)�to_text)r5r
r
r�__str__�szMessage.__str__TcKst�}|jd|j�|jdtjjtjj|j���tjj|j|j	�}|jdtjj|��|jdtjj|j��|j
dkr�|jd|j
�|j	dkr�|jdtjj|j	��|jd|j�tjj
|j�}|r�|jd	�n
|jd
�x.|jD]$}|j|j||f|��|jd�q�W|�r,|jd�n
|jd
�x0|jD]&}|j|j||f|��|jd��q>W|�rz|jd�n
|jd�x0|jD]&}|j|j||f|��|jd��q�W|jd�x0|jD]&}|j|j||f|��|jd��q�W|j�dd�S)z�Convert the message to text.

        The I{origin}, I{relativize}, and any other keyword
        arguments are passed to the rrset to_wire() method.

        @rtype: string
        zid %d
z
opcode %s
z	rcode %s
z	flags %s
rzedns %s
z
eflags %s
zpayload %d
z;ZONE
z
;QUESTION
�
z;PREREQ
z;ANSWER
z;UPDATE
z;AUTHORITY
z;ADDITIONAL
Nrr)r�writerr�opcoder:�
from_flagsr�rcoderrZedns_to_textr �	is_updaterrrr�getvalue)r5r/�
relativize�kw�sZrcrA�rrsetr
r
rr:�sJ	





zMessage.to_textcCs�t|t�sdS|j|jkrdS|j|jkr.dSx|jD]}||jkr6dSq6Wx|jD]}||jkrTdSqTWx|jD]}||jkrrdSqrWx|jD]}||jkr�dSq�Wx|jD]}||jkr�dSq�Wx|jD]}||jkr�dSq�WdS)z�Two messages are equal if they have the same content in the
        header, question, answer, and authority sections.
        @rtype: boolFT)�
isinstancerrrrrr)r5�other�nr
r
r�__eq__�s2






zMessage.__eq__cCs|j|�S)z0Are two messages not equal?
        @rtype: bool)rJ)r5rHr
r
r�__ne__szMessage.__ne__cCs�|jtjj@dks:|j|jks:tjj|j�tjj|j�kr>dStjj|j|j�tjjkr\dStjj	|j�rndSx|j
D]}||j
krvdSqvWx|j
D]}||j
kr�dSq�WdS)z1Is other a response to self?
        @rtype: boolrFT)rr�QRrr>r?r@rZNOERRORrAr)r5rHrIr
r
r�is_responses"


zMessage.is_responsecCsD||jkrdS||jkrdS||jkr*dS||jkr8dStd��dS)Nrr��zunknown section)rrrr�
ValueError)r5�sectionr
r
r�section_number-s



zMessage.section_numberFc	Cs�|j|�|||||f}	|sb|jdk	r>|jj|	�}
|
dk	rb|
Sn$x"|D]}
|
j|||||�rD|
SqDW|sjt�tjj|||||�}
|j|
�|jdk	r�|
|j|	<|
S)aFind the RRset with the given attributes in the specified section.

        @param section: the section of the message to look in, e.g.
        self.answer.
        @type section: list of dns.rrset.RRset objects
        @param name: the name of the RRset
        @type name: dns.name.Name object
        @param rdclass: the class of the RRset
        @type rdclass: int
        @param rdtype: the type of the RRset
        @type rdtype: int
        @param covers: the covers value of the RRset
        @type covers: int
        @param deleting: the deleting value of the RRset
        @type deleting: int
        @param create: If True, create the RRset if it is not found.
        The created RRset is appended to I{section}.
        @type create: bool
        @param force_unique: If True and create is also True, create a
        new RRset regardless of whether a matching RRset exists already.
        @type force_unique: bool
        @raises KeyError: the RRset was not found and create was False
        @rtype: dns.rrset.RRset objectN)	rRr4�get�match�KeyErrorrrFZRRset�append)r5rQ�name�rdclass�rdtype�covers�deleting�create�force_unique�keyrFr
r
r�
find_rrset9s"




zMessage.find_rrsetc	
Cs:y|j||||||||�}	Wntk
r4d}	YnX|	S)aGet the RRset with the given attributes in the specified section.

        If the RRset is not found, None is returned.

        @param section: the section of the message to look in, e.g.
        self.answer.
        @type section: list of dns.rrset.RRset objects
        @param name: the name of the RRset
        @type name: dns.name.Name object
        @param rdclass: the class of the RRset
        @type rdclass: int
        @param rdtype: the type of the RRset
        @type rdtype: int
        @param covers: the covers value of the RRset
        @type covers: int
        @param deleting: the deleting value of the RRset
        @type deleting: int
        @param create: If True, create the RRset if it is not found.
        The created RRset is appended to I{section}.
        @type create: bool
        @param force_unique: If True and create is also True, create a
        new RRset regardless of whether a matching RRset exists already.
        @type force_unique: bool
        @rtype: dns.rrset.RRset object or NoneN)r_rU)
r5rQrWrXrYrZr[r\r]rFr
r
r�	get_rrsetgs
zMessage.get_rrsetrc	KsR|dkr|jdkr|j}nd}|dkr,d}n|dkr8d}tjj|j|j||�}x"|jD]}|j|j|j	|j
�qVWx"|jD]}|jtjj
|f|�qzWx"|jD]}|jtjj|f|�q�W|jdkr�|j|j|j|j|j�x"|jD]}|jtjj|f|�q�W|j�|jdk	�rJ|j|j|j|j|j|j|j|j|j|j �|j!|_!|j"�S)a7Return a string containing the message in DNS compressed wire
        format.

        Additional keyword arguments are passed to the rrset to_wire()
        method.

        @param origin: The origin to be appended to any relative names.
        @type origin: dns.name.Name object
        @param max_size: The maximum size of the wire format output; default
        is 0, which means 'the message's request payload, if nonzero, or
        65536'.
        @type max_size: int
        @raises dns.exception.TooBig: max_size was exceeded
        @rtype: string
        ri��iN)#r"rZrendererZRendererrrrZadd_questionrWrYrXrZ	add_rrset�ANSWERr�	AUTHORITYrZadd_ednsrr r!r�
ADDITIONALZwrite_headerr$Zadd_tsigr#r+r,r*r)r(r'r-Zget_wire)r5r/Zmax_sizerD�rrFr
r
r�to_wire�s6

zMessage.to_wirei,rcCst||_|dkr$t|jj��d|_nt|t�r:tjj|�}||_||_	||_
|dkr^|j|_n||_||_
||_dS)awWhen sending, a TSIG signature using the specified keyring
        and keyname should be added.

        @param keyring: The TSIG keyring to use; defaults to None.
        @type keyring: dict
        @param keyname: The name of the TSIG key to use; defaults to None.
        The key must be defined in the keyring.  If a keyring is specified
        but a keyname is not, then the key used will be the first key in the
        keyring.  Note that the order of keys in a dictionary is not defined,
        so applications should supply a keyname when a keyring is used, unless
        they know the keyring contains only one key.
        @type keyname: dns.name.Name or string
        @param fudge: TSIG time fudge; default is 300 seconds.
        @type fudge: int
        @param original_id: TSIG original id; defaults to the message's id
        @type original_id: int
        @param tsig_error: TSIG error code; default is 0.
        @type tsig_error: int
        @param other_data: TSIG other data.
        @type other_data: string
        @param algorithm: The TSIG algorithm to use; defaults to
        dns.tsig.default_algorithm
        Nr)r#�list�keysr$rGrrrW�	from_textr'r+rr,r*r))r5r#r$r+r,r*r)�	algorithmr
r
r�use_tsig�s

zMessage.use_tsig�cCs�|dks|dkrd}|dkr d}|dkr,|}|dkrFd}d}d}g}n$|td�M}||d>O}|dkrjg}||_||_||_||_||_dS)	a_Configure EDNS behavior.
        @param edns: The EDNS level to use.  Specifying None, False, or -1
        means 'do not use EDNS', and in this case the other parameters are
        ignored.  Specifying True is equivalent to specifying 0, i.e. 'use
        EDNS0'.
        @type edns: int or bool or None
        @param ednsflags: EDNS flag values.
        @type ednsflags: int
        @param payload: The EDNS sender's payload field, which is the maximum
        size of UDP datagram the sender can handle.
        @type payload: int
        @param request_payload: The EDNS payload size to use when sending
        this message.  If not specified, defaults to the value of payload.
        @type request_payload: int or None
        @param options: The EDNS options
        @type options: None or list of dns.edns.Option objects
        @see: RFC 2671
        NFrTrl�~�r)rrrr r!r")r5rrr r"r!r
r
r�use_edns�s(zMessage.use_ednscCsL|r*|jdkr|j�|jtjjO_n|jdkrH|jtjjM_dS)a
Enable or disable 'DNSSEC desired' flag in requests.
        @param wanted: Is DNSSEC desired?  If True, EDNS is enabled if
        required, and then the DO bit is set.  If False, the DO bit is
        cleared if EDNS is enabled.
        @type wanted: bool
        rN)rrmrrrZDO)r5Zwantedr
r
r�want_dnssecs

zMessage.want_dnsseccCstjj|j|j�S)z.Return the rcode.
        @rtype: int
        )rr@r?rr)r5r
r
rr@sz
Message.rcodecCsjtjj|�\}}|jdM_|j|O_|jtd�M_|j|O_|jdkrf|jdkrfd|_dS)zPSet the rcode.
        @param rcode: the rcode
        @type rcode: int
        i�i���rN)rr@�to_flagsrrrr)r5r@�valueZevaluer
r
r�	set_rcode"szMessage.set_rcodecCstjj|j�S)z/Return the opcode.
        @rtype: int
        )rr>r?r)r5r
r
rr>/szMessage.opcodecCs(|jdM_|jtjj|�O_dS)zTSet the opcode.
        @param opcode: the opcode
        @type opcode: int
        i��N)rrr>ro)r5r>r
r
r�
set_opcode5szMessage.set_opcode)N)NT)Nr)rrrkNN)T)r	r
rrr6r9r;r:rJrKrMrRr�	rdatatype�NONEr_r`rer%r&rjrmrnr@rqr>rrr
r
r
rrKs0K
 
7
-
!
.)
*

rc@s2eZdZdZddd�Zdd�Zdd�Zd	d
�ZdS)
�_WireReadera�Wire format reader.

    @ivar wire: the wire-format message.
    @type wire: string
    @ivar message: The message object being built
    @type message: dns.message.Message object
    @ivar current: When building a message object from wire format, this
    variable contains the offset from the beginning of wire of the next octet
    to be read.
    @type current: int
    @ivar updating: Is the message a dynamic update?
    @type updating: bool
    @ivar one_rr_per_rrset: Put each RR into its own RRset?
    @type one_rr_per_rrset: bool
    @ivar ignore_trailing: Ignore trailing junk at end of request?
    @type ignore_trailing: bool
    @ivar zone_rdclass: The class of the zone in messages which are
    DNS dynamic updates.
    @type zone_rdclass: int
    FcCs@tjj|�|_||_d|_d|_tjj|_	||_
||_||_dS)NrF)
rZwiredataZ
maybe_wrap�wire�message�current�updating�
rdataclass�IN�zone_rdclass�
question_only�one_rr_per_rrset�ignore_trailing)r5rvrwr}r~rr
r
rr6Us
z_WireReader.__init__c	Cs�|jr|dkrtjj�x�td|�D]�}tjj|j|j�\}}|j	j
dk	rV|j|j	j
�}|j||_tj
d|j|j|jd��\}}|jd|_|j	j|j	j|||ddd�|jr"||_q"WdS)z�Read the next I{qcount} records from the wire data and add them to
        the question section.
        @param qcount: the number of questions in the message
        @type qcount: intrrNz!HH�T)r\r])ryr�	exception�	FormErrorrrW�	from_wirervrxrwr/rC�struct�unpackr_rr|)r5�qcount�i�qname�usedrYrXr
r
r�
_get_question`sz_WireReader._get_questionc
CsH|js|jrd}nd}d}�x&td|�D�]}|j}tjj|j|j�\}}|}	|jj	dk	rh|j
|jj	�}|j||_tjd|j|j|jd��\}
}}}
|jd|_|
tj
jk�rn||jjk	s�|r�t�||j_||j_|d@d?|j_g|j_|j}|
}xj|dk�rdtjd	|j||d
��\}}|d
}tjj||j||�}|jjj|�||}|d
|}q�Wd}�n�|
tj
jk�rH||jjk�o�||dk�s�t�|jjdk�r�td��|jjj|	�}|dk�r�td
|��|	|j_tjj|j|j|
�\|j_|j_ tjj!|j|	|t"t#j#��|jj$||j|
|jj%|jj&|jj'�|j_%d|j_(n�|dk�rVd}|j�r�|tj)j*k�sz|tj)j+k�r�|}|j,}nd}|tj)j*k�s�|tj)j+k�r�||jj-k�r�tj
j+}d}n&tj.j||
|j|j|
|jj	�}|j/�}|jj0�r|
tj
j1k�rd}|jj2||||
||d|�}|dk	�r4|j3||�|j|
|_q(WdS)a/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 dns.rrset.RRset objects
        @param count: the number of records to read
        @type count: intTFrNz!HHIH�
i�rlz!HHr�rz"got signed message without keyringzkey '%s' unknown)4ryr~rrxrrWr�rvrwr/rCr�r�rs�OPTrrr rrr!Zoption_from_wirerVZTSIGrr#rrSr$r%Zget_algorithm_and_macr'r-Zvalidate�int�timer(r0r2r3r1rz�ANYrtr|r�rdatarZr.ZSOAr_�add)r5rQ�countr]Zseen_optr�Zrr_startrWr�Z
absolute_namerYrX�ttlZrdlenrxZoptslenZotypeZolen�optZsecretr[rZ�rdrFr
r
r�_get_sectionxs� 








z_WireReader._get_sectioncCs�t|j�}|dkrt�tjd|jdd��\|j_|j_}}}}d|_t	j
j|jj�r\d|_|j
|�|jrpdS|j|jj|�|j|jj|�|j|jj|�|jr�|j|kr�t�|jjr�|jjr�|jjr�|jjj|j�dS)zNRead a wire format DNS message and build a dns.message.Message
        object.�z!HHHHHHNT)�lenrvrr�r�rwrrrxrr>rAryr�r}r�rrrrrr2r0r1�update)r5�lr�ZancountZaucountZadcountr
r
r�read�s$
*

z_WireReader.readN)FFF)r	r
rrr6r�r�r�r
r
r
rru>s

crurFTc
CsPtdd�}||_||_||_||_||_||_||_t||||	|
�}|j	�|S)a)Convert a DNS wire format message into a message
    object.

    @param keyring: The keyring to use if the message is signed.
    @type keyring: dict
    @param request_mac: If the message is a response to a TSIG-signed request,
    I{request_mac} should be set to the MAC of that request.
    @type request_mac: string
    @param xfr: Is this message part of a zone transfer?
    @type xfr: bool
    @param origin: If the message is part of a zone transfer, I{origin}
    should be the origin name of the zone.
    @type origin: dns.name.Name object
    @param tsig_ctx: The ongoing TSIG context, used when validating zone
    transfers.
    @type tsig_ctx: hmac.HMAC object
    @param multi: Is this message part of a multiple message sequence?
    @type multi: bool
    @param first: Is this message standalone, or the first of a multi
    message sequence?
    @type first: bool
    @param question_only: Read only up to the end of the question section?
    @type question_only: bool
    @param one_rr_per_rrset: Put each RR into its own RRset
    @type one_rr_per_rrset: bool
    @param ignore_trailing: Ignore trailing junk at end of request?
    @type ignore_trailing: bool
    @raises ShortHeader: The message is less than 12 octets long.
    @raises TrailingJunk: There were octets in the message past the end
    of the proper DNS message.
    @raises BadEDNS: An OPT record was in the wrong section, or occurred more
    than once.
    @raises BadTSIG: A TSIG record was not the last record of the additional
    data section.
    @rtype: dns.message.Message objectr)r)
rr#r(r.r/r0r2r3rur�)
rvr#r(r.r/r0r2r3r}r~r�m�readerr
r
rr��s(

r�c@s8eZdZdZdd�Zdd�Zdd�Zdd	�Zd
d�ZdS)
�_TextReaderaText format reader.

    @ivar tok: the tokenizer
    @type tok: dns.tokenizer.Tokenizer object
    @ivar message: The message object being built
    @type message: dns.message.Message object
    @ivar updating: Is the message a dynamic update?
    @type updating: bool
    @ivar zone_rdclass: The class of the zone in messages which are
    DNS dynamic updates.
    @type zone_rdclass: int
    @ivar last_name: The most recently read name when building a message object
    from text format.
    @type last_name: dns.name.Name object
    cCs.||_tjj|�|_d|_tjj|_d|_	dS)NF)
rwrZ	tokenizer�	Tokenizer�tok�	last_namerzr{r|ry)r5�textrwr
r
rr6>s

z_TextReader.__init__cCs�|jj�}|j}|dkr*|jj�|j_�n�|dkr�x>|jj�}|j�sT|jj|�P|jjt	jj
|j�B|j_q4Wt	jj|jj�r�d|_
�n&|dkr�|jj�|j_|jj|jjd>B|j_n�|dk�r|jjdkr�d|j_x�|jj�}|j��s�|jj|�P|jjt	jj|j�B|j_q�Wn�|dk�rN|jj�|j_|jjdk�r�d|j_nd|d	k�r�|jj�}|jjt	jjt	jj
|��B|j_n.|d
k�r�|jj�}|jjt	jj
|��nt�|jj�dS)z5Process one line from the text format header section.rrTrrlZeflagsrr r>r@N)r�rSrpZget_intrwr�
is_identifier�ungetrrrhr>rAryrrZedns_from_textr Z
get_stringrorqr@r�get_eol)r5rQ�tokenZwhatr�r
r
r�_header_lineEsR











z_TextReader._header_linecCs�|jjdd�}|j�s(tjj|jd�|_|j}|jj�}|j�sHtj	j
�y,tjj|j�}|jj�}|j�srtj	j
�Wn:tj	j
k
r�tj	j
�Yntk
r�tjj
}YnXtjj|j�}|jj|jj|||ddd�|jr�||_|jj�dS)z7Process one line from the text format question section.T)�want_leadingN)r\r])r�rS�
is_whitespacerrWrhrpr�r�r��SyntaxErrorrz�	Exceptionr{rsrwr_rryr|r�)r5rQr�rWrXrYr
r
r�_question_liness.

z_TextReader._question_linecCs�d}|jjdd�}|j�s,tjj|jd�|_|j}|jj�}|j�sLtj	j
�y*t|jd�}|jj�}|j�sttj	j
�Wn6tj	j
k
r�tj	j
�Yntk
r�d}YnXyPtj
j|j�}|jj�}|j�s�tj	j
�|tj
jks�|tj
jk�r�|}|j}Wn>tj	j
k
�r tj	j
�Yntk
�r<tj
j}YnXtjj|j�}|jj�}|j��s�|jj|�tjj|||jd�}|j�}	nd}tjj}	|jj|||||	|d|j�}
|dk	�r�|
j||�dS)zfProcess one line from the text format answer, authority, or
        additional data sections.
        NT)r�r)r�rSr�rrWrhrpr�r�r�r�r�r�rzr�rtr|r{rs�
is_eol_or_eofr�r�rZrwr_ryr�)r5rQr[r�rWr�rXrYr�rZrFr
r
r�_rr_line�sT









z_TextReader._rr_linecCs�|j}d}x�|jjdd�}|j�r$P|j�r�|jj�}|dkrF|j}nv|dksV|dkrf|j}|jj	}nV|dksv|dkr�|j
}|jj}n6|dks�|d	kr�|j
}|jj}n|d
kr�|j
}|jj
}|jj�q|jj|�||�qWdS)zNRead a text format DNS message and build a dns.message.Message
        object.NTZHEADERZQUESTIONZZONEraZPREREQrbZUPDATErc)r�r�rSr�Z
is_commentrp�upperr�rwrr�rrrr�r�)r5Zline_methodrQr��ur
r
rr��s4




z_TextReader.readN)	r	r
rrr6r�r�r�r�r
r
r
rr�,s.5r�cCst�}t||�}|j�|S)z�Convert the text format message into a message object.

    @param text: The text format message.
    @type text: string
    @raises UnknownHeaderField:
    @raises dns.exception.SyntaxError:
    @rtype: dns.message.Message object)rr�r�)r�r�r�r
r
rrh�s

rhc
CsFt}d}t||�r"t||�}d}nd}zt|�}Wd|r@|j�X|S)aRead the next text format message from the specified file.

    @param f: file or string.  If I{f} is a string, it is treated
    as the name of a file to open.
    @raises UnknownHeaderField:
    @raises dns.exception.SyntaxError:
    @rtype: dns.message.Message objectZrUTFN)rrG�openrh�close)�fZstr_typeZoptsZ
want_closer�r
r
r�	from_file�s	


r�c	Cst|t�rtjj|�}t|t�r,tjj|�}t|t�rBtjj|�}t�}	|	jtjj	O_|	j
|	j|||ddd�i}
|dk	r�||
d<|dkr�d}|dk	r�||
d<|dkr�d}|dk	r�||
d<|dkr�d}|dk	r�||
d<|dkr�d}||
d	<|	jf|
�|	j
|�|	S)
aVMake a query message.

    The query name, type, and class may all be specified either
    as objects of the appropriate type, or as strings.

    The query will have a randomly chosen query id, and its DNS flags
    will be set to dns.flags.RD.

    @param qname: The query name.
    @type qname: dns.name.Name object or string
    @param rdtype: The desired rdata type.
    @type rdtype: int
    @param rdclass: The desired rdata class; the default is class IN.
    @type rdclass: int
    @param use_edns: The EDNS level to use; the default is None (no EDNS).
    See the description of dns.message.Message.use_edns() for the possible
    values for use_edns and their meanings.
    @type use_edns: int or bool or None
    @param want_dnssec: Should the query indicate that DNSSEC is desired?
    @type want_dnssec: bool
    @param ednsflags: EDNS flag values.
    @type ednsflags: int
    @param payload: The EDNS sender's payload field, which is the maximum
    size of UDP datagram the sender can handle.
    @type payload: int
    @param request_payload: The EDNS payload size to use when sending
    this message.  If not specified, defaults to the value of payload.
    @type request_payload: int or None
    @param options: The EDNS options
    @type options: None or list of dns.edns.Option objects
    @see: RFC 2671
    @rtype: dns.message.Message objectT)r\r]Nrrr r"r!r)rGrrrWrhrsrzrr�RDr_rrmrn)r�rYrXrmrnrr r"r!r��kwargsr
r
r�
make_querys>$



r�� �,cCs�|jtjj@rtjjd��tjj|j�}tjj|jtjj@B|_|rV|jtjj	O_|j
|j��t|j
�|_
|jdkr�|jdd||j�|jr�|j|j|j|ddd|j�|j|_|S)aMake a message which is a response for the specified query.
    The message returned is really a response skeleton; it has all
    of the infrastructure required of a response, but none of the
    content.

    The response's question section is a shallow copy of the query's
    question section, so the query's question RRsets should not be
    changed.

    @param query: the query to respond to
    @type query: dns.message.Message object
    @param recursion_available: should RA be set in the response?
    @type recursion_available: bool
    @param our_payload: payload size to advertise in EDNS responses; default
    is 8192.
    @type our_payload: int
    @param fudge: TSIG time fudge; default is 300 seconds.
    @type fudge: int
    @rtype: dns.message.Message objectz&specified query message is not a queryrNr)rrrLr�r�rwrrr�ZRArrr>rfrrrmr r1rjr#r$r'r-r()ZqueryZrecursion_availableZour_payloadr+Zresponser
r
r�
make_response\s
r�)
NrFNNFTFFF)Fr�r�).rZ
__future__r�iorr�r�Zdns.ednsrZ
dns.exceptionZ	dns.flagsZdns.nameZ
dns.opcodeZdns.entropyZ	dns.rcodeZ	dns.rdataZdns.rdataclassZ
dns.rdatatypeZ	dns.rrsetZdns.rendererZdns.tsigZdns.wiredataZ_compatrrrr�r�rrZDNSExceptionrrrr�objectrrur�r�rhr�rzr{r�r�r
r
r
r�<module>sXv7
5:F__pycache__/exception.cpython-36.pyc000064400000007504150351404330013404 0ustar003

d��W�@shdZGdd�de�ZGdd�de�ZGdd�de�ZGdd�de�ZGd	d
�d
e�ZGdd�de�Zd
S)zCommon DNS Exceptions.csReZdZdZdZe�ZdZ�fdd�Zdd�Z	dd�Z
d	d
�Z�fdd�Z�Z
S)
�DNSExceptiona�Abstract base class shared by all dnspython exceptions.

    It supports two basic modes of operation:

    a) Old/compatible mode is used if __init__ was called with
    empty **kwargs.
    In compatible mode all *args are passed to standard Python Exception class
    as before and all *args are printed by standard __str__ implementation.
    Class variable msg (or doc string if msg is None) is returned from str()
    if *args is empty.

    b) New/parametrized mode is used if __init__ was called with
    non-empty **kwargs.
    In the new mode *args has to be empty and all kwargs has to exactly match
    set in class variable self.supp_kwargs. All kwargs are stored inside
    self.kwargs and used in new __str__ implementation to construct
    formatted message based on self.fmt string.

    In the simplest case it is enough to override supp_kwargs and fmt
    class variables to get nice parametrized messages.
    Ncsp|j||�|r*|jf|�|_t|�|_nt�|_|jdkrD|j|_|rZtt|�j	|�ntt|�j	|j�dS)N)
�
_check_params�
_check_kwargs�kwargs�str�msg�dict�__doc__�superr�__init__)�self�argsr)�	__class__��/usr/lib/python3.6/exception.pyr
.s
zDNSException.__init__cOs$|s|r t|�t|�ks td��dS)zsOld exceptions supported only args and not kwargs.

        For sanity we do not allow to mix old and new behavior.z=keyword arguments are mutually exclusive with positional argsN)�bool�AssertionError)rrrrrrr=szDNSException._check_paramscKs(|r$t|j��|jks$td|j��|S)Nz-following set of keyword args is required: %s)�set�keys�supp_kwargsr)rrrrrrEs

zDNSException._check_kwargscKshi}x^|j�D]R\}}t|ttf�rXttt|��||<t||�dkr`||j�||<q|||<qW|S)z�Format kwargs before printing them.

        Resulting dictionary has to have keys necessary for str.format call
        on fmt class variable.
        �)�items�
isinstance�listr�mapr�len�pop)rr�fmtargs�kw�datarrr�_fmt_kwargsLszDNSException._fmt_kwargscs:|jr(|jr(|jf|j�}|jjf|�Stt|�j�SdS)N)r�fmtr�formatr	r�__str__)rr)r
rrr"^szDNSException.__str__)�__name__�
__module__�__qualname__rrrrr r
rrrr"�
__classcell__rr)r
rrsrc@seZdZdZdS)�	FormErrorzDNS message is malformed.N)r#r$r%rrrrrr'hsr'c@seZdZdZdS)�SyntaxErrorzText input is malformed.N)r#r$r%rrrrrr(msr(c@seZdZdZdS)�
UnexpectedEndzText input ended unexpectedly.N)r#r$r%rrrrrr)rsr)c@seZdZdZdS)�TooBigzThe DNS message is too big.N)r#r$r%rrrrrr*wsr*c@seZdZdZedg�ZdZdS)�TimeoutzThe DNS operation timed out.Ztimeoutz3The DNS operation timed out after {timeout} secondsN)r#r$r%rrrr rrrrr+|s
r+N)r�	Exceptionrr'r(r)r*r+rrrr�<module>sU__pycache__/rdata.cpython-36.opt-1.pyc000064400000034023150351404330013434 0ustar003

�b�W�:�@s�dZddlmZddlZddlZddlZddlZddlZddl	Zddl
ZddlZddlm
Z
mZmZdZefdd�ZdZefd	d
�Zed�Zdd
�Zdd�ZGdd�de�ZGdd�de�ZiZdZdd�Zddd�Zddd�ZdS)a�DNS rdata.

@var _rdata_modules: A dictionary mapping a (rdclass, rdtype) tuple to
the module which implements that type.
@type _rdata_modules: dict
@var _module_prefix: The prefix to use when forming modules names.  The
default is 'dns.rdtypes'.  Changing this value will break the library.
@type _module_prefix: string
@var _hex_chunk: At most this many octets that will be represented in each
chunk of hexstring that _hexify() produces before whitespace occurs.
@type _hex_chunk: int�)�BytesION�)�xrange�string_types�	text_type� cs4tj|��dj��fdd�tdt����D��j�S)aConvert a binary string into its hex encoding, broken up into chunks
    of I{chunksize} characters separated by a space.

    @param data: the binary string
    @type data: string
    @param chunksize: the chunk size.  Default is L{dns.rdata._hex_chunksize}
    @rtype: string
    � csg|]}�||���qS�r	)�.0�i)�	chunksize�liner	�/usr/lib/python3.6/rdata.py�
<listcomp>6sz_hexify.<locals>.<listcomp>r)�binasciiZhexlify�join�range�len�decode)�datarr	)rr
r�_hexify+s

rcs4tj|��dj��fdd�tdt����D��j�S)a$Convert a binary string into its base64 encoding, broken up into chunks
    of I{chunksize} characters separated by a space.

    @param data: the binary string
    @type data: string
    @param chunksize: the chunk size.  Default is
    L{dns.rdata._base64_chunksize}
    @rtype: string
    rcsg|]}�||���qSr	r	)r
r)rr
r	rrIsz_base64ify.<locals>.<listcomp>r)�base64Z	b64encoderrrr)rrr	)rr
r�
_base64ify=s
rs"\cCs~t|t�r|j�}t|t�s$t|�}d}xP|D]H}|tkrL|dt|�7}q.|dkrj|dkrj|t|�7}q.|d|7}q.W|S)z�Escape the characters in a quoted string which need it.

    @param qstring: the string
    @type qstring: string
    @returns: the escaped string
    @rtype: string
    ��\r�z\%03d)�
isinstancer�encode�	bytearray�	__escaped�chr)Zqstring�text�cr	r	r�	_escapifyOs	


r#cCsFx8tt|�ddd�D] }||dkr|d|d�SqW|dd�S)z�Determine the index of greatest byte that isn't all zeros, and
    return the bitmap that contains all the bytes less than that index.

    @param what: a string of octets representing a bitmap.
    @type what: string
    @rtype: string
    rr���r$)rr)Zwhatrr	r	r�_truncate_bitmaphs	r%c@s�eZdZdZddgZdd�Zdd�Zdd	�Zd.dd
�Zd/dd�Z	d0dd�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�Zd$d%�Zd&d'�Zed1d(d)��Zed2d*d+��Zd3d,d-�Zd
S)4�Rdataz(Base class for all DNS rdata types.
    �rdclass�rdtypecCs||_||_dS)z�Initialize an rdata.
        @param rdclass: The rdata class
        @type rdclass: int
        @param rdtype: The rdata type
        @type rdtype: int
        N)r'r()�selfr'r(r	r	r�__init__~szRdata.__init__cCstjjS)a_DNS SIG/RRSIG rdatas apply to a specific type; this type is
        returned by the covers() function.  If the rdata type is not
        SIG or RRSIG, dns.rdatatype.NONE is returned.  This is useful when
        creating rdatasets, allowing the rdataset to contain only RRSIGs
        of a particular type, e.g. RRSIG(NS).
        @rtype: int
        )�dns�	rdatatype�NONE)r)r	r	r�covers�s	zRdata.coverscCs|j�d>|jBS)z�Return a 32-bit type value, the least significant 16 bits of
        which are the ordinary DNS type, and the upper 16 bits of which are
        the "covered" type, if any.
        @rtype: int
        �)r.r()r)r	r	r�extended_rdatatype�szRdata.extended_rdatatypeNTcKst�dS)z@Convert an rdata to text format.
        @rtype: string
        N)�NotImplementedError)r)�origin�
relativize�kwr	r	r�to_text�sz
Rdata.to_textcCst�dS)z@Convert an rdata to wire format.
        @rtype: string
        N)r1)r)�file�compressr2r	r	r�to_wire�sz
Rdata.to_wirecCst�}|j|d|�|j�S)zlConvert rdata to a format suitable for digesting in hashes.  This
        is also the DNSSEC canonical form.N)rr8�getvalue)r)r2�fr	r	r�
to_digestable�szRdata.to_digestablecCstjj|j|j|j��dS)z�Check that the current contents of the rdata's fields are
        valid.  If you change an rdata by assigning to its fields,
        it is a good idea to call validate() when you are done making
        changes.
        N)r+�rdata�	from_textr'r(r5)r)r	r	r�validate�szRdata.validatecCsf|j�}|tjjkrd}ndtjj|�d}dtjj|j�dtjj|j�|dt|�dS)Nr�(�)z<DNS � z rdata: �>)	r.r+r,r-r5�
rdataclassr'r(�str)r)r.Zctextr	r	r�__repr__�s
zRdata.__repr__cCs|j�S)N)r5)r)r	r	r�__str__�sz
Rdata.__str__cCs8|jtjj�}|jtjj�}||kr(dS||kr4dSdS)z�Compare an rdata with another rdata of the same rdtype and
        rdclass.  Return < 0 if self < other in the DNSSEC ordering,
        0 if self == other, and > 0 if self > other.
        rrr$)r;r+�name�root)r)�otherZourZtheirr	r	r�_cmp�sz
Rdata._cmpcCs8t|t�sdS|j|jks&|j|jkr*dS|j|�dkS)NFr)rr&r'r(rJ)r)rIr	r	r�__eq__�s

zRdata.__eq__cCs8t|t�sdS|j|jks&|j|jkr*dS|j|�dkS)NTr)rr&r'r(rJ)r)rIr	r	r�__ne__�s

zRdata.__ne__cCs6t|t�s$|j|jks$|j|jkr(tS|j|�dkS)Nr)rr&r'r(�NotImplementedrJ)r)rIr	r	r�__lt__�szRdata.__lt__cCs6t|t�s$|j|jks$|j|jkr(tS|j|�dkS)Nr)rr&r'r(rMrJ)r)rIr	r	r�__le__�szRdata.__le__cCs6t|t�s$|j|jks$|j|jkr(tS|j|�dkS)Nr)rr&r'r(rMrJ)r)rIr	r	r�__ge__�szRdata.__ge__cCs6t|t�s$|j|jks$|j|jkr(tS|j|�dkS)Nr)rr&r'r(rMrJ)r)rIr	r	r�__gt__�szRdata.__gt__cCst|jtjj��S)N)�hashr;r+rGrH)r)r	r	r�__hash__�szRdata.__hash__cCst�dS)a�Build an rdata object from text format.

        @param rdclass: The rdata class
        @type rdclass: int
        @param rdtype: The rdata type
        @type rdtype: int
        @param tok: The tokenizer
        @type tok: dns.tokenizer.Tokenizer
        @param origin: The origin to use for relative names
        @type origin: dns.name.Name
        @param relativize: should names be relativized?
        @type relativize: bool
        @rtype: dns.rdata.Rdata instance
        N)r1)�clsr'r(�tokr2r3r	r	rr=�szRdata.from_textcCst�dS)a<Build an rdata object from wire format

        @param rdclass: The rdata class
        @type rdclass: int
        @param rdtype: The rdata type
        @type rdtype: int
        @param wire: The wire-format message
        @type wire: string
        @param current: The offset in wire of the beginning of the rdata.
        @type current: int
        @param rdlen: The length of the wire-format rdata
        @type rdlen: int
        @param origin: The origin to use for relative names
        @type origin: dns.name.Name
        @rtype: dns.rdata.Rdata instance
        N)r1)rTr'r(�wire�current�rdlenr2r	r	r�	from_wireszRdata.from_wirecCsdS)zWConvert any domain names in the rdata to the specified
        relativization.
        Nr	)r)r2r3r	r	r�choose_relativity&szRdata.choose_relativity)NT)NN)N)NT)N)NT)�__name__�
__module__�__qualname__�__doc__�	__slots__r*r.r0r5r8r;r>rErFrJrKrLrNrOrPrQrS�classmethodr=rYrZr	r	r	rr&ws0	



r&csVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�GenericRdataz�Generate Rdata Class

    This class is used for rdata types for which we have no better
    implementation.  It implements the DNS "unknown RRs" scheme.
    rcstt|�j||�||_dS)N)�superrar*r)r)r'r(r)�	__class__r	rr*8szGenericRdata.__init__NTcKsdt|j�t|j�S)Nz\# %d )rrr)r)r2r3r4r	r	rr5<szGenericRdata.to_textcCs�|j�}|j�s|jdkr(tjjd��|j�}g}x&|j�}|j�rHP|j|jj	��q6Wdj
|�}	tj|	�}
t
|
�|kr�tjjd��||||
�S)Nz\#z$generic rdata does not start with \#�z'generic rdata hex data has wrong length)�get�
is_identifier�valuer+Z	exception�SyntaxErrorZget_intZ
is_eol_or_eof�appendrrrZ	unhexlifyr)rTr'r(rUr2r3�tokenZlengthZchunks�hexrr	r	rr=?s"

zGenericRdata.from_textcCs|j|j�dS)N)�writer)r)r6r7r2r	r	rr8SszGenericRdata.to_wirecCs|||||||��S)Nr	)rTr'r(rVrWrXr2r	r	rrYVszGenericRdata.from_wire)NT)NT)NN)N)r[r\r]r^r_r*r5r`r=r8rY�
__classcell__r	r	)rcrra.s

razdns.rdtypescCs�dd�}tj||f�}tjj|�}tjj|�}|jdd�}|s�tjtjj|f�}|s�y$|djt	||g��}|t||f<WnVt
k
r�y(|djt	d|g��}|ttjj|f<Wnt
k
r�d}YnXYnX|r�t||�}nt}|S)NcSs6t|�}|jd�}x|dd�D]}t||�}q W|S)N�.r)�
__import__�split�getattr)rG�modZ
components�compr	r	r�
import_module`s

z&get_rdata_class.<locals>.import_module�-�_rn�ANY)
�_rdata_modulesrer+rCr5r,�replacerwr�_module_prefix�ImportErrorrqra)r'r(rtrrZrdclass_textZrdtype_textrTr	r	r�get_rdata_class^s.r|TcCs�t|t�rtjj|�}t||�}|tkrx|j�}|j|�|j	�rx|j
dkrxtj|||||�}t|||j
dt|j
�|�S|j|||||�S)adBuild an rdata object from text format.

    This function attempts to dynamically load a class which
    implements the specified rdata class and type.  If there is no
    class-and-type-specific implementation, the GenericRdata class
    is used.

    Once a class is chosen, its from_text() class method is called
    with the parameters to this function.

    If I{tok} is a string, then a tokenizer is created and the string
    is used as its input.

    @param rdclass: The rdata class
    @type rdclass: int
    @param rdtype: The rdata type
    @type rdtype: int
    @param tok: The tokenizer or input text
    @type tok: dns.tokenizer.Tokenizer or string
    @param origin: The origin to use for relative names
    @type origin: dns.name.Name
    @param relativize: Should names be relativized?
    @type relativize: bool
    @rtype: dns.rdata.Rdata instancez\#r)rrr+Z	tokenizer�	Tokenizerr|rareZungetrfrgr=rYrr)r'r(rUr2r3rTrjr<r	r	rr=�s



r=cCs*tjj|�}t||�}|j||||||�S)a>Build an rdata object from wire format

    This function attempts to dynamically load a class which
    implements the specified rdata class and type.  If there is no
    class-and-type-specific implementation, the GenericRdata class
    is used.

    Once a class is chosen, its from_wire() class method is called
    with the parameters to this function.

    @param rdclass: The rdata class
    @type rdclass: int
    @param rdtype: The rdata type
    @type rdtype: int
    @param wire: The wire-format message
    @type wire: string
    @param current: The offset in wire of the beginning of the rdata.
    @type current: int
    @param rdlen: The length of the wire-format rdata
    @type rdlen: int
    @param origin: The origin to use for relative names
    @type origin: dns.name.Name
    @rtype: dns.rdata.Rdata instance)r+ZwiredataZ
maybe_wrapr|rY)r'r(rVrWrXr2rTr	r	rrY�s
rY)NT)N) r^�iorrrZ
dns.exceptionr+Zdns.nameZdns.rdataclassZ
dns.rdatatypeZ
dns.tokenizerZdns.wiredataZ_compatrrrZ_hex_chunksizerZ_base64_chunksizerrrr#r%�objectr&rarxrzr|r=rYr	r	r	r�<module>s28,"
/__pycache__/wiredata.cpython-36.opt-1.pyc000064400000004421150351404330014140 0ustar003

�b�W��@s^dZddlZddlZddlmZmZGdd�de�Ze�dd�ZGdd�de�Z	d	d
�Z
dS)zDNS Wire Data Helper�N�)�binary_type�string_typesc@s&eZdZdd�Zejdkr"dd�ZdS)�_SliceUnspecifiedBoundcCs|jS)N)�stop)�self�key�r	�/usr/lib/python3.6/wiredata.py�__getitem__ sz"_SliceUnspecifiedBound.__getitem__�cCs|jt||��S)N)r�slice)r�i�jr	r	r
�__getslice__$sz#_SliceUnspecifiedBound.__getslice__N)r)�__name__�
__module__�__qualname__r�sys�version_inforr	r	r	r
rs
rcs>eZdZ�fdd�Zejd
kr&dd�Zdd�Zdd	�Z�Z	S)�WireDatacs�y�t|t�r�|j}|j}tjdkrx|tkr2t|�}|dksB|dkrJtj	j
�||kr�tt|�j
|�tt|�j
|d�n6x4||fD](}|dkr�q�q�t|�t|�kr�tj	j
�q�Wttt|�j
t||���St|j��|Stk
r�tj	j
�YnXdS)Nrrr)r)�
isinstancer
�startrrr�_unspecified_bound�len�dns�	exception�	FormError�superrr�abs�	bytearray�unwrap�
IndexError)rrrr�index)�	__class__r	r
r-s,

zWireData.__getitem__rcCs|jt||��S)N)rr
)rrrr	r	r
rPszWireData.__getslice__ccsBd}x8y||V|d7}Wqtjjk
r8t�YqXqWdS)Nrr)rrr�
StopIteration)rrr	r	r
�__iter__Ss
zWireData.__iter__cCst|�S)N)r)rr	r	r
r!\szWireData.unwrap)r)
rrrrrrrr&r!�
__classcell__r	r	)r$r
r*s
"
	rcCsJt|t�r|St|t�r t|�St|t�r6t|j��Stdt|���dS)Nzunhandled type %s)rrrr�encode�
ValueError�type)Zwirer	r	r
�
maybe_wrap`s


r+)�__doc__rZ
dns.exceptionrZ_compatrrrrrr+r	r	r	r
�<module>s		6__pycache__/grange.cpython-36.opt-1.pyc000064400000001610150351404330013600 0ustar003

�b�W��@sdZddlZdd�ZdS)zDNS GENERATE range conversion.�NcCs�d}d}d}|r(|ddkr(tjjd��xj|D]b}|dkrT|dkrTt|�}d}d}q.|dkrnt|�}d}d}q.|j�r�||7}q.tjjd	|��q.W|dkr�tjj��|dkr�t|�}|dkr�t|�}|||fS)z�Convert the text form of a range in a GENERATE statement to an
    integer.

    @param text: the textual range
    @type text: string
    @return: The start, stop and step values.
    @rtype: tuple
    ��r�-z!Start cannot be a negative number��/�zCould not parse %s�)rr)�dnsZ	exception�SyntaxError�int�isdigit)�text�stepZcur�state�c�start�stop�r�/usr/lib/python3.6/grange.py�	from_texts0


r)�__doc__r	rrrrr�<module>s__pycache__/dnssec.cpython-36.opt-1.pyc000064400000025134150351404330013623 0ustar003

�b�W�9�@sHdZddlmZddlZddlZddlZddlZddlZddl	Zddl
ZddlZddlZddl
ZddlmZGdd�dejj�ZGdd	�d	ejj�ZdZd
ZdZdZd
ZdZdZdZdZdZdZdZdZ dZ!eeeeeeeeeeeee e!d�Z"e#dd�e"j$�D��Z%dd�Z&dd�Z'dd�Z(dDd d!�Z)dEd"d#�Z*d$d%�Z+d&d'�Z,d(d)�Z-d*d+�Z.d,d-�Z/d.d/�Z0d0d1�Z1d2d3�Z2d4d5�Z3d6d7�Z4d8d9�Z5dFd:d;�Z6dGd<d=�Z7d>d?�Z8y(ddl9Z:ddl;Z:ddl<Z:e7Z=e6Z>d@Z?Wn"e@k
�r�e8Z=e8Z>dAZ?YnXy8ddlAZAddlBZAddlCZAddlDZAd@ZEGdBdC�dCeF�ZGWne@k
�rBdAZEYnXdS)Hz.Common DNSSEC-related functions and constants.�)�BytesION�)�string_typesc@seZdZdZdS)�UnsupportedAlgorithmz&The DNSSEC algorithm is not supported.N)�__name__�
__module__�__qualname__�__doc__�r
r
�/usr/lib/python3.6/dnssec.pyr!src@seZdZdZdS)�ValidationFailurez The DNSSEC signature is invalid.N)rrrr	r
r
r
rr&sr��������
�
����)�RSAMD5�DH�DSA�ECC�RSASHA1�DSANSEC3SHA1�RSASHA1NSEC3SHA1�	RSASHA256�	RSASHA512�INDIRECT�ECDSAP256SHA256�ECDSAP384SHA384�
PRIVATEDNS�
PRIVATEOIDccs|]\}}||fVqdS)Nr
)�.0�x�yr
r
r�	<genexpr>Nsr+cCs"tj|j��}|dkrt|�}|S)z:Convert text into a DNSSEC algorithm value
    @rtype: intN)�_algorithm_by_text�get�upper�int)�text�valuer
r
r�algorithm_from_textQsr2cCstj|�}|dkrt|�}|S)z;Convert a DNSSEC algorithm value to text
    @rtype: stringN)�_algorithm_by_valuer-�str)r1r0r
r
r�algorithm_to_text[s
r5cCst�}|j||d�|j�S)N)�origin)r�to_wire�getvalue)�recordr6�sr
r
r�	_to_rdataesr;cCs�t||�}t|�}|jtkr0|dd>|d	Sd}x<tt|�d�D](}||d|d>|d|d7}qFWt|�ddkr�||t|�dd>7}||d?d@7}|d@SdS)
Nrrr
rr�i��������)r;�	bytearray�	algorithmr�range�len)�keyr6�rdataZtotal�ir
r
r�key_idks

rFcCs�|j�dkr d}tjjd�}n,|j�dkr@d}tjjd�}ntd|��t|t�rdtjj||�}|j	|j
�j��|j	t||��|j
�}tjdt|�|j|�|}tjjtjjtjj|dt|��S)N�SHA1r�SHA256r
zunsupported algorithm "%s"z!HBBr)r.�dns�hash�hashesr�
isinstancer�name�	from_text�updateZcanonicalizer7r;�digest�struct�packrFr@rDZ	from_wire�
rdataclass�IN�	rdatatypeZDSrB)rMrCr@r6ZdsalgrJrPZdsrdatar
r
r�make_ds{s
rVcCs�g}|j|j�}|dkrdSt|tjj�rZy|jtjjtj	j
�}Wq^tk
rVdSXn|}x0|D](}|j|jkrdt
|�|jkrd|j|�qdW|S)N)r-�signerrLrIZnodeZNodeZ
find_rdatasetrSrTrUZDNSKEY�KeyErrorr@rFZkey_tag�append)�keys�rrsigZcandidate_keysr1�rdatasetrDr
r
r�_find_candidate_keys�s 

r]cCs|tttttfkS)N)rrr r!r")r@r
r
r�_is_rsa�sr^cCs|ttfkS)N)rr)r@r
r
r�_is_dsa�sr_cCsto|ttfkS)N)�_have_ecdsar$r%)r@r
r
r�	_is_ecdsa�sracCs|tkS)N)r)r@r
r
r�_is_md5�srbcCs|ttttfkS)N)rrrr )r@r
r
r�_is_sha1�srccCs|ttfkS)N)r!r$)r@r
r
r�
_is_sha256�srdcCs|tkS)N)r%)r@r
r
r�
_is_sha384�srecCs|tkS)N)r")r@r
r
r�
_is_sha512�srfcCs~t|�rtjjd�St|�r,tjjd�St|�rBtjjd�St|�rXtjjd�St|�rntjjd�Std|��dS)NZMD5rGrHZSHA384ZSHA512zunknown hash for algorithm %u)	rbrIrJrKrcrdrerfr)r@r
r
r�
_make_hash�srgc	Cs�t|�rddddddddg}ndt|�r6dd	d
ddg}nLt|�rVdddd
dd
ddd
g	}n,t|�rvdddd
dd
ddd
g	}ntd|��t|�}t|�j}dgd||gd|dgd|g|ddgd|g}tj	dt|�f|��S)N�*��H�rr
r�+rr��`r�erzunknown algorithm %u�0rrrz!%dB)
rbrcrdrfrrBrgZdigest_sizerQrR)r@ZoidZolenZdlenZidbytesr
r
r�_make_algorithm_id�s
<rqc)Cs�t|t�rtjj|tjj�}�x�t||�D�]�}|s<td��t|t�rX|d}|d}n
|j}|}|dkrrt	j	�}|j
|kr�td��|j|kr�td��t|j
�}t|j
��r`|j}	tjd|	dd��\}
|	dd�}	|
dk�rtjd|	dd	��\}
|	d	d�}	|	d|
�}|	|
d�}t|�d
}
tjjjtjjj|�tjjj|�f�}tjjj|j�f}�nt|j
��rj|j}	tjd|	dd��\}|	dd�}	d|d
}|	dd�}|	dd�}	|	d|�}|	|d�}	|	d|�}|	|d�}	|	d|�}tjjjtjjj|�tjjj|�tjjj|�tjjj|�f�}tjd
|jdd��\}}tjjj|�tjjj|�f}n�t|j
��rX|j
tk�r�tj j!}d}n"|j
t"k�r�tj j#}d}ntd��|j}	tjjj|	d|��}tjjj|	||d	��}tj$j%|j&|||j'�}tj(j)j*||�}t+||�}|jd|�}|j|d�}tjj,tjjj|�tjjj|��}ntd|j
��|j-t.||�dd��|j-|j/j0|��|j1t|�dk�r�|j2|j1d�d} tjjd| �}|j0|�}!tj3d|j4|j5|j6�}"t7|�}#xP|#D]H}$|j-|!�|j-|"�|$j0|�}%tj3dt|%��}&|j-|&�|j-|%��q�W|j8�}'t|j
��r�t9|j
�|'}'|
d
t|'�d}(tj3dd	|(dfddgdg|(dg��|'}'n(t|j
��s�t|j
��r�ntd|j
��|j:|'|�r*dSq*Wtd��dS)a�Validate an RRset against a single signature rdata

    The owner name of the rrsig is assumed to be the same as the owner name
    of the rrset.

    @param rrset: The RRset to validate
    @type rrset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset)
    tuple
    @param rrsig: The signature rdata
    @type rrsig: dns.rrset.Rdata
    @param keys: The key dictionary.
    @type keys: a dictionary keyed by dns.name.Name with node or rdataset
    values
    @param origin: The origin to use for relative names
    @type origin: dns.name.Name or None
    @param now: The time to use when validating the signatures.  The default
    is the current time.
    @type now: int
    zunknown keyrrNZexpiredz
not yet validz!Bz!Hr
r�@�z!20s20s� rpzunknown ECDSA curvezunknown algorithm %u��*z!HHIrz!%dB�zverify failure);rLrrIrMrN�rootr]r�tuple�timeZ
expirationZ	inceptionrgr@r^rCrQ�unpackrB�CryptoZ	PublicKeyZRSAZ	construct�Util�number�
bytes_to_longZ	signaturer_rrar$�ecdsaZcurvesZNIST256pr%ZNIST384pZ
ellipticcurveZPoint�curve�orderrZZVerifyingKeyZfrom_public_point�ECKeyWrapperZ	SignaturerOr;rWZ
to_digestableZlabels�splitrRZrdtypeZrdclassZoriginal_ttl�sortedrPrq�verify))�rrsetr[rZr6�nowZ
candidate_key�rrnamer\rJZkeyptrZbytes_Zrsa_eZrsa_nZkeylen�pubkey�sig�tZoctetsZdsa_qZdsa_pZdsa_gZdsa_yZdsa_rZdsa_sr��key_lenr)r*ZpointZ
verifying_key�rr:�suffixZ	rrnamebufZrrfixedZrrlistZrrZrrdataZrrlenrPZpadlenr
r
r�_validate_rrsig�s�














"r�c	
Cs�t|t�rtjj|tjj�}t|t�r0|d}n|j}t|t�rR|d}|d}n
|j}|}|j|�}|j|�}||kr�td��x6|D].}yt	|||||�dStk
r�Yq�Xq�Wtd��dS)ahValidate an RRset

    @param rrset: The RRset to validate
    @type rrset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset)
    tuple
    @param rrsigset: The signature RRset
    @type rrsigset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset)
    tuple
    @param keys: The key dictionary.
    @type keys: a dictionary keyed by dns.name.Name with node or rdataset
    values
    @param origin: The origin to use for relative names
    @type origin: dns.name.Name or None
    @param now: The time to use when validating the signatures.  The default
    is the current time.
    @type now: int
    rrzowner names do not matchNzno RRSIGs validated)
rLrrIrMrNrxryZchoose_relativityrr�)	r�ZrrsigsetrZr6r�r�Z	rrsignameZ
rrsigrdatasetr[r
r
r�	_validatexs*








r�cOstd��dS)Nz#DNSSEC validation requires pycrypto)�NotImplementedError)�args�kwargsr
r
r�_need_pycrypto�sr�TFc@seZdZdd�Zdd�ZdS)r�cCs||_||_dS)N)rCr�)�selfrCr�r
r
r�__init__�szECKeyWrapper.__init__cCstjjj|�}|jjj||�S)N)r|r}r~rrCr�Zverifies)r�rPr�Zdiglongr
r
rr��szECKeyWrapper.verifyN)rrrr�r�r
r
r
rr��sr�)N)N)NN)NN)Hr	�iorrQrzZ
dns.exceptionrIZdns.hashZdns.nameZdns.nodeZdns.rdatasetZ	dns.rdataZ
dns.rdatatypeZdns.rdataclassZ_compatrZ	exceptionZDNSExceptionrrrrrrrrr r!r"r$r%r#r&r'r,�dict�itemsr3r2r5r;rFrVr]r^r_rarbrcrdrerfrgrqr�r�r�ZCrypto.PublicKey.RSAr|ZCrypto.PublicKey.DSAZCrypto.Util.numberZvalidateZvalidate_rrsigZ_have_pycrypto�ImportErrorr�Zecdsa.ecdsaZecdsa.ellipticcurveZ
ecdsa.keysr`�objectr�r
r
r
r�<module>s�





0

__pycache__/flags.cpython-36.opt-1.pyc000064400000004172150351404330013437 0ustar003

�b�Wh
�@s�dZdZdZdZdZdZdZdZdZeeeeeeed�Z	d	eiZ
ed
d�e	j�D��Z
edd�e
j�D��Zd
d�Zee
�Zee�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�ZdS)zDNS Message Flags.i�ii��� �)�QR�AA�TC�RD�RA�AD�CD�DOccs|]\}}||fVqdS)N�)�.0�x�yr
r
�/usr/lib/python3.6/flags.py�	<genexpr>3srccs|]\}}||fVqdS)Nr
)rrrr
r
rr5scCs t|j��}|j�|j�|S)N)�list�items�sort�reverse)�table�orderr
r
r�_order_flags8srcCs.d}|j�}x|D]}|||j�B}qW|S)N�)�split�upper)�textr�flags�tokens�tr
r
r�
_from_textCs

r!cCs6g}x&|D]\}}||@dkr
|j|�q
Wdj|�S)Nr� )�append�join)rrrZ
text_flags�k�vr
r
r�_to_textKs
r'cCs
t|t�S)zZConvert a space-separated list of flag text values into a flags
    value.
    @rtype: int)r!�_by_text)rr
r
r�	from_textSsr)cCst|tt�S)z]Convert a flags value into a space-separated list of flag text
    values.
    @rtype: string)r'�	_by_value�_flags_order)rr
r
r�to_text[sr,cCs
t|t�S)zdConvert a space-separated list of EDNS flag text values into a EDNS
    flags value.
    @rtype: int)r!�
_edns_by_text)rr
r
r�edns_from_textcsr.cCst|tt�S)zhConvert an EDNS flags value into a space-separated list of EDNS flag
    text values.
    @rtype: string)r'�_edns_by_value�_edns_flags_order)rr
r
r�edns_to_textksr1N)�__doc__rrrrr	r
rrr(r-�dictrr*r/rr+r0r!r'r)r,r.r1r
r
r
r�<module>s6__pycache__/ttl.cpython-36.opt-1.pyc000064400000002450150351404330013143 0ustar003

�b�W��@s8dZddlZddlmZGdd�dejj�Zdd�ZdS)	zDNS TTL conversion.�N�)�longc@seZdZdZdS)�BadTTLz!DNS TTL value is not well-formed.N)�__name__�
__module__�__qualname__�__doc__�r	r	�/usr/lib/python3.6/ttl.pyrsrcCs*|j�rt|�}n�|dj�s"t�td�}td�}x�|D]�}|j�rZ|d9}|t|�7}q8|j�}|dkr|||td�7}nl|dkr�||td�7}nR|dkr�||td�7}n8|d	kr�||td
�7}n|dkr�||7}ntd|��d}q8W|dk�std
��|td�k�s|td�k�r&td��|S)z�Convert the text form of a TTL to an integer.

    The BIND 8 units syntax for TTLs (e.g. '1w6d4h3m10s') is supported.

    @param text: the textual TTL
    @type text: string
    @raises dns.ttl.BadTTL: the TTL is not well-formed
    @rtype: int
    r�
�wi�:	�di�Q�hi�m�<�szunknown unit '%s'ztrailing integeri���z0TTL should be between 0 and 2^31 - 1 (inclusive))�isdigitrr�lower)�textZtotalZcurrent�cr	r	r
�	from_texts8



r)	rZ
dns.exceptionZdnsZ_compatrZ	exception�SyntaxErrorrrr	r	r	r
�<module>s__pycache__/rdataclass.cpython-36.pyc000064400000004714150351404330013527 0ustar003

�b�W��@s�dZddlZddlZdZdZdZdZdZdZ	eeeeee	d�Z
ed	d
�e
j�D��Z
e
jeeed��ede	diZejd
ej�ZGdd�dejj�Zdd�Zdd�Zdd�ZdS)akDNS Rdata Classes.

@var _by_text: The rdata class textual name to value mapping
@type _by_text: dict
@var _by_value: The rdata class value to textual name mapping
@type _by_value: dict
@var _metaclasses: If an rdataclass is a metaclass, there will be a mapping
whose key is the rdatatype value and whose value is True in this dictionary.
@type _metaclasses: dict�N�����)�	RESERVED0�IN�CH�HS�NONE�ANYccs|]\}}||fVqdS)N�)�.0�x�yr
r
� /usr/lib/python3.6/rdataclass.py�	<genexpr>2sr)ZINTERNETZCHAOSZHESIODTzCLASS([0-9]+)$c@seZdZdZdS)�UnknownRdataclasszA DNS class is unknown.N)�__name__�
__module__�__qualname__�__doc__r
r
r
rrEsrcCsVtj|j��}|dkrRtj|�}|dkr,t�t|jd��}|dksJ|dkrRtd��|S)z�Convert text into a DNS rdata class value.
    @param text: the text
    @type text: string
    @rtype: int
    @raises dns.rdataclass.UnknownRdataclass: the class is unknown
    @raises ValueError: the rdata class value is not >= 0 and <= 65535
    Nrri��z'class must be between >= 0 and <= 65535)	�_by_text�get�upper�_unknown_class_pattern�matchr�int�group�
ValueError)�text�valuerr
r
r�	from_textJs	
r"cCs:|dks|dkrtd��tj|�}|dkr6dt|�}|S)z�Convert a DNS rdata class to text.
    @param value: the rdata class value
    @type value: int
    @rtype: string
    @raises ValueError: the rdata class value is not >= 0 and <= 65535
    ri��z'class must be between >= 0 and <= 65535NZCLASS)r�	_by_valuer�repr)r!r r
r
r�to_text^s
r%cCs|tkrdSdS)zmTrue if the class is a metaclass.
    @param rdclass: the rdata class
    @type rdclass: int
    @rtype: boolTF)�_metaclasses)Zrdclassr
r
r�is_metaclassnsr')r�reZ
dns.exceptionZdnsrrr	r
rrr�dict�itemsr#�updater&�compile�IrZ	exceptionZDNSExceptionrr"r%r'r
r
r
r�<module>s4
__pycache__/rcode.cpython-36.opt-1.pyc000064400000004667150351404330013450 0ustar003

�b�W �
@s�dZddlZddlmZdZdZdZdZdZ	dZ
d	Zd
ZdZ
dZd
ZdZeeeee	e
eee
eeed�Zedd�ej�D��ZGdd�dejj�Zdd�Zdd�Zdd�Zdd�ZdS)zDNS Result Codes.�N�)�long��������	�
�)�NOERROR�FORMERR�SERVFAIL�NXDOMAIN�NOTIMP�REFUSED�YXDOMAIN�YXRRSET�NXRRSET�NOTAUTH�NOTZONE�BADVERSccs|]\}}||fVqdS)N�)�.0�x�yrr�/usr/lib/python3.6/rcode.py�	<genexpr>6src@seZdZdZdS)�UnknownRcodezA DNS rcode is unknown.N)�__name__�
__module__�__qualname__�__doc__rrrrr 9sr cCsB|j�r$t|�}|dkr$|dkr$|Stj|j��}|dkr>t�|S)z�Convert text into an rcode.

    @param text: the textual rcode
    @type text: string
    @raises UnknownRcode: the rcode is unknown
    @rtype: int
    ri�N)�isdigit�int�_by_text�get�upperr )�text�vrrr�	from_text>s	r,cCs0|d@|d?d@B}|dks$|dkr,td��|S)z�Return the rcode value encoded by flags and ednsflags.

    @param flags: the DNS flags
    @type flags: int
    @param ednsflags: the EDNS flags
    @type ednsflags: int
    @raises ValueError: rcode is < 0 or > 4095
    @rtype: int
    ��i�ri�zrcode must be >= 0 and <= 4095)�
ValueError)�flagsZ	ednsflags�valuerrr�
from_flagsQsr2cCs8|dks|dkrtd��|d@}t|d@�d>}||fS)z�Return a (flags, ednsflags) tuple which encodes the rcode.

    @param value: the rcode
    @type value: int
    @raises ValueError: rcode is < 0 or > 4095
    @rtype: (int, int) tuple
    ri�zrcode must be >= 0 and <= 4095r-i�r.)r/r)r1r+Zevrrr�to_flagsbs
	r3cCstj|�}|dkrt|�}|S)zbConvert rcode into text.

    @param value: the rcode
    @type value: int
    @rtype: string
    N)�	_by_valuer(�str)r1r*rrr�to_textrs
r6)r$Z
dns.exceptionZdnsZ_compatrrrrrrrrrrrrrr'�dict�itemsr4Z	exceptionZDNSExceptionr r,r2r3r6rrrr�<module>s@__pycache__/namedict.cpython-36.pyc000064400000005447150351404330013176 0ustar003

�b�W]�@s6dZddlZddlZddlmZGdd�dej�ZdS)zDNS name dictionary�N�)�xrangec@sbeZdZdZdddgZdd�Zdd�Zd	d
�Zdd�Zd
d�Z	dd�Z
dd�Zdd�Zdd�Z
dS)�NameDictaA dictionary whose keys are dns.name.Name objects.
    @ivar max_depth: the maximum depth of the keys that have ever been
    added to the dictionary.
    @type max_depth: int
    @ivar max_depth_items: the number of items of maximum depth
    @type max_depth_items: int
    �	max_depth�max_depth_itemsZ__storecOs(t�|_d|_d|_|jt||��dS)Nr)�dict�_NameDict__storerr�update)�self�args�kwargs�r
�/usr/lib/python3.6/namedict.py�__init__-szNameDict.__init__cCs>t|�|jkr|jd|_nt|�|jkr:t|�|_d|_dS)Nr)�lenrr)r
�keyr
r
rZ__update_max_depth3s

zNameDict.__update_max_depthcCs
|j|S)N)r)r
rr
r
r�__getitem__:szNameDict.__getitem__cCs.t|tjj�std��||j|<|j|�dS)NzNameDict key must be a name)�
isinstance�dns�name�Name�
ValueErrorr�_NameDict__update_max_depth)r
r�valuer
r
r�__setitem__=s
zNameDict.__setitem__cCsT|jj|�}t|�|jkr&|jd|_|jdkrPd|_x|jD]}|j|�q>WdS)Nrr)r�poprrrr)r
rr�kr
r
r�__delitem__Cs
zNameDict.__delitem__cCs
t|j�S)N)�iterr)r
r
r
r�__iter__LszNameDict.__iter__cCs
t|j�S)N)rr)r
r
r
r�__len__OszNameDict.__len__cCs
||jkS)N)r)r
rr
r
r�has_keyRszNameDict.has_keycCsnt|�}||jkr|j}x<t|d�D],}tjj||d��}||kr&|||fSq&W|tjj}tjj|fS)aFind the deepest match to I{name} in the dictionary.

        The deepest match is the longest name in the dictionary which is
        a superdomain of I{name}.

        @param name: the name
        @type name: dns.name.Name object
        @rtype: (key, value) tuple
        rN)rrrrrr�empty)r
r�depth�i�n�vr
r
r�get_deepest_matchUs
zNameDict.get_deepest_matchN)�__name__�
__module__�__qualname__�__doc__�	__slots__rrrrrrr r!r'r
r
r
rr!s
	r)r+�collectionsZdns.namerZ_compatr�MutableMappingrr
r
r
r�<module>s__pycache__/tsigkeyring.cpython-36.pyc000064400000002037150351404330013741 0ustar003

�b�W��@s8dZddlmZmZddlZddlZdd�Zdd�ZdS)zA place to store TSIG keys.�)�maybe_decode�maybe_encodeNcCs<i}x2|D]*}tjj|�}tjt||��}|||<q
W|S)z�Convert a dictionary containing (textual DNS name, base64 secret) pairs
    into a binary keyring which has (dns.name.Name, binary secret) pairs.
    @rtype: dict)�dns�name�	from_text�base64Zdecodestringr)�textring�keyring�keytext�keyname�secret�r
�!/usr/lib/python3.6/tsigkeyring.pyrs
rcCs<i}x2|D]*}t|j��}ttj||��}|||<q
W|S)z�Convert a dictionary containing (dns.name.Name, binary secret) pairs
    into a text keyring which has (textual DNS name, base64 secret) pairs.
    @rtype: dict)r�to_textrZencodestring)r	rrr
rr
r
rr&s
r)	�__doc__Zdns._compatrrrZdns.namerrrr
r
r
r�<module>s

__pycache__/node.cpython-36.pyc000064400000012636150351404330012335 0ustar003

�b�W��@s<dZddlmZddlZddlZddlZGdd�de�ZdS)z)DNS nodes.  A node is a set of rdatasets.�)�StringIONc@s�eZdZdZdgZdd�Zdd�Zdd�Zd	d
�Zdd�Z	d
d�Z
dd�Zej
jdfdd�Zej
jdfdd�Zej
jfdd�Zdd�ZdS)�Nodez�A DNS node.

    A node is a set of rdatasets

    @ivar rdatasets: the node's rdatasets
    @type rdatasets: list of dns.rdataset.Rdataset objects�	rdatasetscCs
g|_dS)zInitialize a DNS node.
        N)r)�self�r�/usr/lib/python3.6/node.py�__init__$sz
Node.__init__cKsPt�}x8|jD].}t|�dkr|j|j|f|��|jd�qW|j�dd�S)a+Convert a node to text format.

        Each rdataset at the node is printed.  Any keyword arguments
        to this method are passed on to the rdataset's to_text() method.
        @param name: the owner name of the rdatasets
        @type name: dns.name.Name object
        @rtype: string
        r�
N����)rr�len�write�to_text�getvalue)r�name�kw�s�rdsrrrr*s
zNode.to_textcCsdtt|��dS)Nz
<DNS node �>)�str�id)rrrr�__repr__;sz
Node.__repr__cCs@x|jD]}||jkrdSqWx|jD]}||jkr&dSq&WdS)zSTwo nodes are equal if they have the same rdatasets.

        @rtype: bool
        FT)r)r�otherZrdrrr�__eq__>s

zNode.__eq__cCs|j|�S)N)r)rrrrr�__ne__NszNode.__ne__cCs
t|j�S)N)rr)rrrr�__len__QszNode.__len__cCs
t|j�S)N)�iterr)rrrr�__iter__Tsz
Node.__iter__FcCsHx |jD]}|j|||�r|SqW|s*t�tjj||�}|jj|�|S)aFind an rdataset matching the specified properties in the
        current node.

        @param rdclass: The class of the rdataset
        @type rdclass: int
        @param rdtype: The type of the rdataset
        @type rdtype: int
        @param covers: The covered type.  Usually this value is
        dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or
        dns.rdatatype.RRSIG, then the covers value will be the rdata
        type the SIG/RRSIG covers.  The library treats the SIG and RRSIG
        types as if they were a family of
        types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA).  This makes RRSIGs much
        easier to work with than if RRSIGs covering different rdata
        types were aggregated into a single RRSIG rdataset.
        @type covers: int
        @param create: If True, create the rdataset if it is not found.
        @type create: bool
        @raises KeyError: An rdataset of the desired type and class does
        not exist and I{create} is not True.
        @rtype: dns.rdataset.Rdataset object
        )r�match�KeyError�dns�rdataset�Rdataset�append)r�rdclass�rdtype�covers�createrrrr�
find_rdatasetWszNode.find_rdatasetcCs2y|j||||�}Wntk
r,d}YnX|S)aEGet an rdataset matching the specified properties in the
        current node.

        None is returned if an rdataset of the specified type and
        class does not exist and I{create} is not True.

        @param rdclass: The class of the rdataset
        @type rdclass: int
        @param rdtype: The type of the rdataset
        @type rdtype: int
        @param covers: The covered type.
        @type covers: int
        @param create: If True, create the rdataset if it is not found.
        @type create: bool
        @rtype: dns.rdataset.Rdataset object or None
        N)r(r)rr$r%r&r'rrrr�get_rdatasetys

zNode.get_rdatasetcCs&|j|||�}|dk	r"|jj|�dS)azDelete the rdataset matching the specified properties in the
        current node.

        If a matching rdataset does not exist, it is not an error.

        @param rdclass: The class of the rdataset
        @type rdclass: int
        @param rdtype: The type of the rdataset
        @type rdtype: int
        @param covers: The covered type.
        @type covers: int
        N)r)r�remove)rr$r%r&rrrr�delete_rdataset�szNode.delete_rdatasetcCs:t|tjj�std��|j|j|j|j�|j	j
|�dS)a8Replace an rdataset.

        It is not an error if there is no rdataset matching I{replacement}.

        Ownership of the I{replacement} object is transferred to the node;
        in other words, this method does not store a copy of I{replacement}
        at the node, it stores I{replacement} itself.
        zreplacement is not an rdatasetN)�
isinstancer r!r"�
ValueErrorr+r$r%r&rr#)rZreplacementrrr�replace_rdataset�s

zNode.replace_rdatasetN)�__name__�
__module__�__qualname__�__doc__�	__slots__rrrrrrrr Z	rdatatypeZNONEr(r)r+r.rrrrrs!r)	r2�iorZdns.rdatasetr Z
dns.rdatatypeZdns.renderer�objectrrrrr�<module>s
__pycache__/rdatatype.cpython-36.pyc000064400000010625150351404330013401 0ustar003

��W��F@s0dZddlZddlZdZdZdZdZdZdZ	dZ
d	Zd
ZdZ
dZd
ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!d Z"d!Z#d"Z$d#Z%d$Z&d%Z'd&Z(d'Z)d(Z*d)Z+d*Z,d+Z-d,Z.d-Z/d.Z0d/Z1d0Z2d1Z3d2Z4d3Z5d4Z6d5Z7d6Z8d7Z9d8Z:d9Z;d:Z<d;Z=d<Z>d=Z?d>Z@d?ZAd@ZBdAZCdBZDdCZEdDZFdEZGdFZHeeeeee	e
eee
eeeeeeeeeeeeeeeeeee e!e"e#e$e%e&e'e(e)e*e+e,e-e.e/e0e1e2e3e4e5e6e7e8e9e:e;e<e=e>e?e@eAeBeCeDeEeFeGeHdG�EZIeJdHdI�eIjK�D��ZLe)dJiZMe
dJe"dJe(dJe/dJiZNejOdKejP�ZQGdLdM�dMejRjS�ZTdNdO�ZUdPdQ�ZVdRdS�ZWdTdU�ZXdS)VaDNS Rdata Types.

@var _by_text: The rdata type textual name to value mapping
@type _by_text: dict
@var _by_value: The rdata type value to textual name mapping
@type _by_value: dict
@var _metatypes: If an rdatatype is a metatype, there will be a mapping
whose key is the rdatatype value and whose value is True in this dictionary.
@type _metatypes: dict
@var _singletons: If an rdatatype is a singleton, there will be a mapping
whose key is the rdatatype value and whose value is True in this dictionary.
@type _singletons: dict�N���������	�
���
������������������!�#�$�%�&�'�)�*�+�,�-�.�/�0�1�2�3�4�7�;�<�>�c�g�l�m��������iii�i�)E�NONE�A�NS�MD�MF�CNAME�SOA�MB�MG�MR�NULL�WKS�PTR�HINFO�MINFO�MX�TXT�RP�AFSDB�X25�ISDN�RT�NSAPzNSAP-PTR�SIG�KEY�PX�GPOS�AAAA�LOC�NXT�SRV�NAPTR�KX�CERT�A6�DNAME�OPT�APL�DS�SSHFP�IPSECKEY�RRSIG�NSEC�DNSKEY�DHCID�NSEC3�
NSEC3PARAM�TLSA�HIP�CDS�CDNSKEY�CSYNC�SPF�UNSPEC�EUI48�EUI64�TKEY�TSIG�IXFR�AXFR�MAILB�MAILA�ANY�URI�CAA�AVC�TA�DLVccs|]\}}||fVqdS)N�)�.0�x�yr�r��/usr/lib/python3.6/rdatatype.py�	<genexpr>�sr�Tz
TYPE([0-9]+)$c@seZdZdZdS)�UnknownRdatatypez$DNS resource record type is unknown.N)�__name__�
__module__�__qualname__�__doc__r�r�r�r�r��sr�cCsVtj|j��}|dkrRtj|�}|dkr,t�t|jd��}|dksJ|dkrRtd��|S)z�Convert text into a DNS rdata type value.
    @param text: the text
    @type text: string
    @raises dns.rdatatype.UnknownRdatatype: the type is unknown
    @raises ValueError: the rdata type value is not >= 0 and <= 65535
    @rtype: intNrri��z&type must be between >= 0 and <= 65535)	�_by_text�get�upper�_unknown_type_pattern�matchr��int�group�
ValueError)�text�valuer�r�r�r��	from_text�s
r�cCs:|dks|dkrtd��tj|�}|dkr6dt|�}|S)z�Convert a DNS rdata type to text.
    @param value: the rdata type value
    @type value: int
    @raises ValueError: the rdata type value is not >= 0 and <= 65535
    @rtype: stringri��z&type must be between >= 0 and <= 65535NZTYPE)r��	_by_valuer��repr)r�r�r�r�r��to_text�s
r�cCs |tkr|tks|tkrdSdS)zbTrue if the type is a metatype.
    @param rdtype: the type
    @type rdtype: int
    @rtype: boolTF)rzr��
_metatypes)�rdtyper�r�r��is_metatype�sr�cCs|tkrdSdS)zcTrue if the type is a singleton.
    @param rdtype: the type
    @type rdtype: int
    @rtype: boolTF)�_singletons)r�r�r�r��is_singleton�sr�)Yr��reZ
dns.exceptionZdnsrBrCrDrErFrGrHrIrJrKrLrMrNrOrPrQrRrSrTrUrVrWrXZNSAP_PTRrYrZr[r\r]r^r_r`rarbrcrdrerfrgrhrirjrkrlrmrnrorprqrrrsrtrurvrwrxryrzr{r|r}r~rr�r�r�r�r�r�r��dict�itemsr�r�r��compile�Ir�Z	exceptionZDNSExceptionr�r�r�r�r�r�r�r�r��<module>s0__pycache__/e164.cpython-36.opt-1.pyc000064400000005147150351404330013025 0ustar003

�b�WK�@s\dZddlZddlZddlZddlmZejjd�Z	e	fdd�Z
e	dfd	d
�Zd
dd�ZdS)z�DNS E.164 helpers

@var public_enum_domain: The DNS public ENUM domain, e164.arpa.
@type public_enum_domain: dns.name.Name object
�N�)�string_typesz
e164.arpa.cCs,dd�|D�}|j�tjjdj|�|d�S)auConvert an E.164 number in textual form into a Name object whose
    value is the ENUM domain name for that number.
    @param text: an E.164 number in textual form.
    @type text: str
    @param origin: The domain in which the number should be constructed.
    The default is e164.arpa.
    @type origin: dns.name.Name object or None
    @rtype: dns.name.Name object
    cSsg|]}|j�r|�qS�)�isdigit)�.0�drr�/usr/lib/python3.6/e164.py�
<listcomp>)szfrom_e164.<locals>.<listcomp>�.)�origin)�reverse�dns�name�	from_text�join)�textr�partsrrr�	from_e164s
rTcCsb|dk	r|j|�}dd�|jD�}t|�t|j�kr@tjjd��|j�dj|�}|r^d|}|S)a�Convert an ENUM domain name into an E.164 number.
    @param name: the ENUM domain name.
    @type name: dns.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 origin: dns.name.Name object or None
    @param want_plus_prefix: if True, add a '+' to the beginning of the
    returned number.
    @rtype: str
    NcSs$g|]}|j�rt|�dkr|�qS)r)r�len)rrrrrr	;szto_e164.<locals>.<listcomp>z$non-digit labels in ENUM domain name��+)Z
relativizeZlabelsrr
Z	exception�SyntaxErrorrr)rrZwant_plus_prefixZdlabelsrrrr�to_e164.s

rcCs�|dkrtjj�}tjj�}xl|D]d}t|t�r<tjj|�}tjj	||�}y|j
|d�Stjjk
r�}z||7}WYdd}~Xq"Xq"W|�dS)z�Look for NAPTR RRs for the specified number in the specified domains.

    e.g. lookup('16505551212', ['e164.dnspython.org.', 'e164.arpa.'])
    NZNAPTR)r
�resolverZget_default_resolverZNXDOMAIN�
isinstancerrrZe164r�query)ZnumberZdomainsrZe_nxZdomainZqname�errrrEs



r)N)
�__doc__Z
dns.exceptionr
Zdns.nameZdns.resolverZ_compatrrrZpublic_enum_domainrrrrrrr�<module>s__pycache__/reversename.cpython-36.pyc000064400000005041150351404330013714 0ustar003

�b�W��@sXdZddlZddlZddlZddlZddlZejjd�Z	ejjd�Z
dd�Zdd�ZdS)	aDNS Reverse Map Names.

@var ipv4_reverse_domain: The DNS IPv4 reverse-map domain, in-addr.arpa.
@type ipv4_reverse_domain: dns.name.Name object
@var ipv6_reverse_domain: The DNS IPv6 reverse-map domain, ip6.arpa.
@type ipv6_reverse_domain: dns.name.Name object
�Nz
in-addr.arpa.z	ip6.arpa.cCs�yztjj|�}tjj|�rXtjdkr<dd�|dd�D�}ndd�|dd�D�}t}n dd�ttj	|�j
��D�}t}Wn2tk
r�dd�t
tjj|��D�}t}YnX|j�tjjd	j|�|d
�S)aConvert an IPv4 or IPv6 address in textual form into a Name object whose
    value is the reverse-map domain name of the address.
    @param text: an IPv4 or IPv6 address in textual form (e.g. '127.0.0.1',
    '::1')
    @type text: str
    @rtype: dns.name.Name object
    �cSsg|]}d|�qS)z%d�)�.0�byterr�!/usr/lib/python3.6/reversename.py�
<listcomp>/sz from_address.<locals>.<listcomp>�NcSsg|]}dt|��qS)z%d)�ord)rrrrrr1scSsg|]}|�qSrr)r�xrrrr4scSsg|]}d|�qS)z%dr)rrrrrr7s�.)�origin)r)�dns�ipv6�	inet_atonZ	is_mapped�sys�version_info�ipv4_reverse_domain�str�binasciiZhexlify�decode�ipv6_reverse_domain�	Exception�	bytearray�ipv4�reverse�name�	from_text�join)�textZv6�partsrrrr�from_address#s

r cCs�|jt�rD|jt�}t|j�}|j�dj|�}tjj	tjj
|��S|jt�r�|jt�}t|j�}|j�g}d}t|�}x0||kr�|j
dj|||d���|d7}q|Wdj|�}tjj	tjj
|��Stjjd��dS)z�Convert a reverse map domain name into textual address form.
    @param name: an IPv4 or IPv6 address in reverse-map form.
    @type name: dns.name.Name object
    @rtype: str
    �.r���:z"unknown reverse-map address familyN)Zis_subdomainrZ
relativize�list�labelsrrr
rZ	inet_ntoarr�len�appendrZ	exception�SyntaxError)rr&rr�i�lrrr�
to_address>s&








r,)
�__doc__rrZdns.namer
Zdns.ipv6Zdns.ipv4rrrrr r,rrrr�<module>s__pycache__/tsig.cpython-36.opt-1.pyc000064400000014101150351404330013302 0ustar003

�b�W&�@s~dZddlZddlZddlZddlZddlZddlZddlm	Z	m
Z
mZGdd�dejj
�ZGdd�dejj
�ZGd	d
�d
ejj
�ZGdd�de�ZGd
d�de�ZGdd�de�ZGdd�de�Zejjd�Zejjd�Zejjd�Zejjd�Zejjd�Zejjd�ZedededededediZeZdZd Z d!Z!d"Z"dd#d$efd%d&�Z#dd#d$efd'd(�Z$d/d)d*�Z%d+d,�Z&d-d.�Z'dS)0zDNS TSIG support.�N�)�long�string_types�	text_typec@seZdZdZdS)�BadTimez8The current time is not within the TSIG's validity time.N)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/tsig.pyrsrc@seZdZdZdS)�BadSignaturez#The TSIG signature fails to verify.N)rrr	r
rrrrr
 sr
c@seZdZdZdS)�	PeerErrorz;Base class for all TSIG errors generated by the remote peerN)rrr	r
rrrrr%src@seZdZdZdS)�
PeerBadKeyz$The peer didn't know the key we usedN)rrr	r
rrrrr*src@seZdZdZdS)�PeerBadSignaturez*The peer didn't like the signature we sentN)rrr	r
rrrrr/src@seZdZdZdS)�PeerBadTimez%The peer didn't like the time we sentN)rrr	r
rrrrr4src@seZdZdZdS)�PeerBadTruncationz=The peer didn't like amount of truncation in the TSIG we sentN)rrr	r
rrrrr9srzHMAC-MD5.SIG-ALG.REG.INTz	hmac-sha1zhmac-sha224zhmac-sha256zhmac-sha384zhmac-sha512ZSHA224ZSHA256ZSHA384ZSHA512ZSHA1ZMD5����FTc
Cs�t|t�r|j�}t|�\}
}|r\tj||d�}	t|�}|dkr\|	jtj	d|��|	j|�tj	d|�}|	j|�|	j|dd��|r�|	j|j
��|	jtj	dtjj
��|	jtj	dd��|td�}|d?td�@}|td	�@}tj	d
|||�}|
|}t|�}|dk�rtd��tj	d||�|}|�rF|	j|�|	j|�n
|	j|�|	j�}tj	dt|��}|||||}|
�r�tj||d�}	t|�}|	jtj	d|��|	j|�nd}	|||	fS)
ajReturn a (tsig_rdata, mac, ctx) tuple containing the HMAC TSIG rdata
    for the input parameters, the HMAC MAC calculated by applying the
    TSIG signature algorithm, and the TSIG digest context.
    @rtype: (string, string, hmac.HMAC object)
    @raises ValueError: I{other_data} is too long
    @raises NotImplementedError: I{algorithm} is not supported
    )�	digestmodrz!H�Nz!I� i��l��z!HIHz TSIG Other Data is > 65535 bytesz!HH)�
isinstancer�encode�
get_algorithm�hmac�new�len�update�struct�pack�
to_digestable�dnsZ
rdataclass�ANYr�
ValueErrorZdigest)�wire�keyname�secret�time�fudge�original_id�error�
other_data�request_mac�ctx�multi�first�	algorithmZalgorithm_namerZml�idZ	long_time�
upper_time�
lower_timeZtime_macZpre_macZolZpost_mac�macZmpack�
tsig_rdatarrr�signWsN





r9c

Cs t||||||||||	|
||�
S)N)r9)
r'r(r)r*r+r,r-r.r/r0r1r2r3rrr�hmac_md5�sr:cCs�tjd|dd��\}|dkr&tjj�|d8}|dd�tjd|�|d|�}|}
tjj||
�\}}|
|}
tjd||
|
d��\}}}}|td�d>|td�}|
d7}
||
|
|�}|
|7}
tjd||
|
d	��\}}}|
d	7}
||
|
|�}|
|7}
|
||k�r tjj�|dk�rv|t	k�r:t
�n<|tk�rJt�n,|t
k�rZt�n|tk�rjt�ntd
|��||}||}||k�s�||k�r�t�t|||||||||||	|
|�
\}}}||k�r�t�|S)a*Validate the specified TSIG rdata against the other input parameters.

    @raises FormError: The TSIG is badly formed.
    @raises BadTime: There is too much time skew between the client and the
    server.
    @raises BadSignature: The TSIG signature did not validate
    @rtype: hmac.HMAC objectz!H�
�rrz!HIHHrz!HHH�zunknown TSIG error code %d)r!�unpackr$�	exception�	FormErrorr"�name�	from_wirer�BADSIGr�BADKEYr�BADTIMEr�BADTRUNCrrrr9r
)r'r(r)Znowr/Z
tsig_startr8�
tsig_rdlenr0r1r2ZadcountZnew_wire�current�aname�usedr5r6r+�mac_sizer*r7r,r-Z
other_sizer.Ztime_lowZ	time_highZjunkZour_macrrr�validate�sN
$ 





rLcCs\t|t�rtjj|�}y|j�tjjt|fSt	k
rVt
dt|�d��YnXdS)z�Returns the wire format string and the hash module to use for the
    specified TSIG algorithm

    @rtype: (string, hash constructor)
    @raises NotImplementedError: I{algorithm} is not supported
    zTSIG algorithm z is not supportedN)rrr$rA�	from_textr#�hashZhashes�_hashes�KeyError�NotImplementedError�str)r3rrrr�s
rcCsz|}tjj||�\}}||}tjd|||d��\}}}}	|d7}||||	�}
||	7}|||krrtjj�||
fS)zlReturn the tsig algorithm for the specified tsig_rdata
    @raises FormError: The TSIG is badly formed.
    z!HIHHr;)r$rArBr!r>r?r@)r'r8rGrHrIrJr5r6r+rKr7rrr�get_algorithm_and_mac�s rS)NFT)(r
rr!Z
dns.exceptionr$Zdns.hashZdns.rdataclassZdns.nameZ_compatrrrr?ZDNSExceptionrr
rrrrrrArMZHMAC_MD5Z	HMAC_SHA1ZHMAC_SHA224ZHMAC_SHA256ZHMAC_SHA384ZHMAC_SHA512rOZdefault_algorithmrCrDrErFr9r:rLrrSrrrr�<module>sL5
5__pycache__/flags.cpython-36.pyc000064400000004172150351404330012500 0ustar003

�b�Wh
�@s�dZdZdZdZdZdZdZdZdZeeeeeeed�Z	d	eiZ
ed
d�e	j�D��Z
edd�e
j�D��Zd
d�Zee
�Zee�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�ZdS)zDNS Message Flags.i�ii��� �)�QR�AA�TC�RD�RA�AD�CD�DOccs|]\}}||fVqdS)N�)�.0�x�yr
r
�/usr/lib/python3.6/flags.py�	<genexpr>3srccs|]\}}||fVqdS)Nr
)rrrr
r
rr5scCs t|j��}|j�|j�|S)N)�list�items�sort�reverse)�table�orderr
r
r�_order_flags8srcCs.d}|j�}x|D]}|||j�B}qW|S)N�)�split�upper)�textr�flags�tokens�tr
r
r�
_from_textCs

r!cCs6g}x&|D]\}}||@dkr
|j|�q
Wdj|�S)Nr� )�append�join)rrrZ
text_flags�k�vr
r
r�_to_textKs
r'cCs
t|t�S)zZConvert a space-separated list of flag text values into a flags
    value.
    @rtype: int)r!�_by_text)rr
r
r�	from_textSsr)cCst|tt�S)z]Convert a flags value into a space-separated list of flag text
    values.
    @rtype: string)r'�	_by_value�_flags_order)rr
r
r�to_text[sr,cCs
t|t�S)zdConvert a space-separated list of EDNS flag text values into a EDNS
    flags value.
    @rtype: int)r!�
_edns_by_text)rr
r
r�edns_from_textcsr.cCst|tt�S)zhConvert an EDNS flags value into a space-separated list of EDNS flag
    text values.
    @rtype: string)r'�_edns_by_value�_edns_flags_order)rr
r
r�edns_to_textksr1N)�__doc__rrrrr	r
rrr(r-�dictrr*r/rr+r0r!r'r)r,r.r1r
r
r
r�<module>s6__pycache__/e164.cpython-36.pyc000064400000005147150351404330012066 0ustar003

�b�WK�@s\dZddlZddlZddlZddlmZejjd�Z	e	fdd�Z
e	dfd	d
�Zd
dd�ZdS)z�DNS E.164 helpers

@var public_enum_domain: The DNS public ENUM domain, e164.arpa.
@type public_enum_domain: dns.name.Name object
�N�)�string_typesz
e164.arpa.cCs,dd�|D�}|j�tjjdj|�|d�S)auConvert an E.164 number in textual form into a Name object whose
    value is the ENUM domain name for that number.
    @param text: an E.164 number in textual form.
    @type text: str
    @param origin: The domain in which the number should be constructed.
    The default is e164.arpa.
    @type origin: dns.name.Name object or None
    @rtype: dns.name.Name object
    cSsg|]}|j�r|�qS�)�isdigit)�.0�drr�/usr/lib/python3.6/e164.py�
<listcomp>)szfrom_e164.<locals>.<listcomp>�.)�origin)�reverse�dns�name�	from_text�join)�textr�partsrrr�	from_e164s
rTcCsb|dk	r|j|�}dd�|jD�}t|�t|j�kr@tjjd��|j�dj|�}|r^d|}|S)a�Convert an ENUM domain name into an E.164 number.
    @param name: the ENUM domain name.
    @type name: dns.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 origin: dns.name.Name object or None
    @param want_plus_prefix: if True, add a '+' to the beginning of the
    returned number.
    @rtype: str
    NcSs$g|]}|j�rt|�dkr|�qS)r)r�len)rrrrrr	;szto_e164.<locals>.<listcomp>z$non-digit labels in ENUM domain name��+)Z
relativizeZlabelsrr
Z	exception�SyntaxErrorrr)rrZwant_plus_prefixZdlabelsrrrr�to_e164.s

rcCs�|dkrtjj�}tjj�}xl|D]d}t|t�r<tjj|�}tjj	||�}y|j
|d�Stjjk
r�}z||7}WYdd}~Xq"Xq"W|�dS)z�Look for NAPTR RRs for the specified number in the specified domains.

    e.g. lookup('16505551212', ['e164.dnspython.org.', 'e164.arpa.'])
    NZNAPTR)r
�resolverZget_default_resolverZNXDOMAIN�
isinstancerrrZe164r�query)ZnumberZdomainsrZe_nxZdomainZqname�errrrEs



r)N)
�__doc__Z
dns.exceptionr
Zdns.nameZdns.resolverZ_compatrrrZpublic_enum_domainrrrrrrr�<module>s__pycache__/entropy.cpython-36.opt-1.pyc000064400000006323150351404330014043 0ustar003

�b�Wq�@s�ddlZddlZddlZddlmZmZyddlZWnek
rPddl	ZYnXGdd�de
�Ze�Zyej
�ZWnek
r�dZYnXdd�Zdd	�ZdS)
�N�)�long�binary_typec@sHeZdZddd�Zddd�Zdd�Zd	d
�Zdd�Zd
d�Zdd�Z	dS)�EntropyPoolNcCs�d|_d|_d|_tj�|_yddl}|j�|_d|_	Wn^t
k
r�yddl}|j�|_d|_	Wn,t
k
r�ddl
}|j�|_d|_	YnXYnXtd|j	�|_|dk	r�|jt|��d|_tj�|_nd|_d|_dS)Nr���TF)�
pool_index�digest�	next_byte�
_threadingZLock�lock�hashlibZsha1�hash�hash_len�ImportError�sha�new�md5�	bytearray�pool�stir�seeded�os�getpid�seed_pid)�self�seedrrr�r�/usr/lib/python3.6/entropy.py�__init__s0





zEntropyPool.__init__FcCsr|s|jj�zNxH|D]@}|j|jkr,d|_|d@}|j|j|N<|jd7_qWWd|sl|jj�XdS)Nr�r)r
�acquirer	rr�release)rZentropyZalready_locked�c�brrrr7s

zEntropyPool.stircCs�|js|jtj�kr�ytjd�}Wn`tk
r�y*tddd�}z|jd�}Wd|j�XWn tk
r~t	t
j
��}YnXYnXd|_tj�|_d|_t|�}|j
|d�dS)Nrz/dev/urandom�rbrT)rrrr�urandom�	Exception�open�read�close�str�timer
rr)rr�rrrr�_maybe_seedEs 
zEntropyPool._maybe_seedc
Cs�|jj�zr|j�|jdks*|j|jkr`|jjt|j	��t
|jj��|_|j|jd�d|_|j|j}|jd7_Wd|jj�X|S)NTrr)
r
r"r/r
rrr�updaterrrrr#)r�valuerrr�random_8Xs
zEntropyPool.random_8cCs|j�d|j�S)N�)r2)rrrr�	random_16gszEntropyPool.random_16cCs|j�d|j�S)Ni)r4)rrrr�	random_32jszEntropyPool.random_32cCsl||d}|td�kr td��|dkr8|j}td�}n|dkrL|j}d}n
|j}d}|||�|dS)	Nrlztoo bigil��r3i��r!)r�
ValueErrorr5r4r2)r�first�last�sizeZrand�maxrrr�random_betweenms
zEntropyPool.random_between)N)F)
�__name__�
__module__�__qualname__r rr/r2r4r5r;rrrrrs

rcCs tdk	rtjdd�Stj�SdS)Nri)�
system_random�	randrangerr4rrrrr4�sr4cCs(tdk	rtj||d�Stj||�SdS)Nr)r?r@rr;)r7r8rrr�between�srA)rZrandomr-Z_compatrrZ	threadingrrZdummy_threading�objectrrZSystemRandomr?r(r4rArrrr�<module>sb
__pycache__/hash.cpython-36.opt-1.pyc000064400000000733150351404330013265 0ustar003

�b�WL�@sXdZddlZiZejed<ejed<ejed<ejed<ejed<ejed<d	d
�Z	dS)z'Hashing backwards compatibility wrapper�NZMD5ZSHA1ZSHA224ZSHA256ZSHA384ZSHA512cCst|j�S)N)�hashes�upper)�	algorithm�r�/usr/lib/python3.6/hash.py�getsr)
�__doc__ZhashlibrZmd5Zsha1Zsha224Zsha256Zsha384Zsha512rrrrr�<module>s





__pycache__/rdatatype.cpython-36.opt-1.pyc000064400000010625150351404330014340 0ustar003

��W��F@s0dZddlZddlZdZdZdZdZdZdZ	dZ
d	Zd
ZdZ
dZd
ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!d Z"d!Z#d"Z$d#Z%d$Z&d%Z'd&Z(d'Z)d(Z*d)Z+d*Z,d+Z-d,Z.d-Z/d.Z0d/Z1d0Z2d1Z3d2Z4d3Z5d4Z6d5Z7d6Z8d7Z9d8Z:d9Z;d:Z<d;Z=d<Z>d=Z?d>Z@d?ZAd@ZBdAZCdBZDdCZEdDZFdEZGdFZHeeeeee	e
eee
eeeeeeeeeeeeeeeeeee e!e"e#e$e%e&e'e(e)e*e+e,e-e.e/e0e1e2e3e4e5e6e7e8e9e:e;e<e=e>e?e@eAeBeCeDeEeFeGeHdG�EZIeJdHdI�eIjK�D��ZLe)dJiZMe
dJe"dJe(dJe/dJiZNejOdKejP�ZQGdLdM�dMejRjS�ZTdNdO�ZUdPdQ�ZVdRdS�ZWdTdU�ZXdS)VaDNS Rdata Types.

@var _by_text: The rdata type textual name to value mapping
@type _by_text: dict
@var _by_value: The rdata type value to textual name mapping
@type _by_value: dict
@var _metatypes: If an rdatatype is a metatype, there will be a mapping
whose key is the rdatatype value and whose value is True in this dictionary.
@type _metatypes: dict
@var _singletons: If an rdatatype is a singleton, there will be a mapping
whose key is the rdatatype value and whose value is True in this dictionary.
@type _singletons: dict�N���������	�
���
������������������!�#�$�%�&�'�)�*�+�,�-�.�/�0�1�2�3�4�7�;�<�>�c�g�l�m��������iii�i�)E�NONE�A�NS�MD�MF�CNAME�SOA�MB�MG�MR�NULL�WKS�PTR�HINFO�MINFO�MX�TXT�RP�AFSDB�X25�ISDN�RT�NSAPzNSAP-PTR�SIG�KEY�PX�GPOS�AAAA�LOC�NXT�SRV�NAPTR�KX�CERT�A6�DNAME�OPT�APL�DS�SSHFP�IPSECKEY�RRSIG�NSEC�DNSKEY�DHCID�NSEC3�
NSEC3PARAM�TLSA�HIP�CDS�CDNSKEY�CSYNC�SPF�UNSPEC�EUI48�EUI64�TKEY�TSIG�IXFR�AXFR�MAILB�MAILA�ANY�URI�CAA�AVC�TA�DLVccs|]\}}||fVqdS)N�)�.0�x�yr�r��/usr/lib/python3.6/rdatatype.py�	<genexpr>�sr�Tz
TYPE([0-9]+)$c@seZdZdZdS)�UnknownRdatatypez$DNS resource record type is unknown.N)�__name__�
__module__�__qualname__�__doc__r�r�r�r�r��sr�cCsVtj|j��}|dkrRtj|�}|dkr,t�t|jd��}|dksJ|dkrRtd��|S)z�Convert text into a DNS rdata type value.
    @param text: the text
    @type text: string
    @raises dns.rdatatype.UnknownRdatatype: the type is unknown
    @raises ValueError: the rdata type value is not >= 0 and <= 65535
    @rtype: intNrri��z&type must be between >= 0 and <= 65535)	�_by_text�get�upper�_unknown_type_pattern�matchr��int�group�
ValueError)�text�valuer�r�r�r��	from_text�s
r�cCs:|dks|dkrtd��tj|�}|dkr6dt|�}|S)z�Convert a DNS rdata type to text.
    @param value: the rdata type value
    @type value: int
    @raises ValueError: the rdata type value is not >= 0 and <= 65535
    @rtype: stringri��z&type must be between >= 0 and <= 65535NZTYPE)r��	_by_valuer��repr)r�r�r�r�r��to_text�s
r�cCs |tkr|tks|tkrdSdS)zbTrue if the type is a metatype.
    @param rdtype: the type
    @type rdtype: int
    @rtype: boolTF)rzr��
_metatypes)�rdtyper�r�r��is_metatype�sr�cCs|tkrdSdS)zcTrue if the type is a singleton.
    @param rdtype: the type
    @type rdtype: int
    @rtype: boolTF)�_singletons)r�r�r�r��is_singleton�sr�)Yr��reZ
dns.exceptionZdnsrBrCrDrErFrGrHrIrJrKrLrMrNrOrPrQrRrSrTrUrVrWrXZNSAP_PTRrYrZr[r\r]r^r_r`rarbrcrdrerfrgrhrirjrkrlrmrnrorprqrrrsrtrurvrwrxryrzr{r|r}r~rr�r�r�r�r�r�r��dict�itemsr�r�r��compile�Ir�Z	exceptionZDNSExceptionr�r�r�r�r�r�r�r�r��<module>s0__pycache__/edns.cpython-36.pyc000064400000010467150351404330012341 0ustar003

�b�W �@s@dZdZGdd�de�ZGdd�de�ZiZdd�Zdd	�Zd
S)zEDNS Options�c@sdeZdZdZdd�Zdd�Zedd��Zdd	�Zd
d�Z	dd
�Z
dd�Zdd�Zdd�Z
dd�ZdS)�Optionz*Base class for all EDNS option types.
    cCs
||_dS)z\Initialize an option.
        @param otype: The rdata type
        @type otype: int
        N)�otype)�selfr�r�/usr/lib/python3.6/edns.py�__init__szOption.__init__cCst�dS)z*Convert an option to wire format.
        N)�NotImplementedError)r�filerrr�to_wire!szOption.to_wirecCst�dS)a�Build an EDNS option object from wire format

        @param otype: The option type
        @type otype: int
        @param wire: The wire-format message
        @type wire: string
        @param current: The offset in wire of the beginning of the rdata.
        @type current: int
        @param olen: The length of the wire-format option data
        @type olen: int
        @rtype: dns.edns.Option instanceN)r)�clsr�wire�current�olenrrr�	from_wire&s
zOption.from_wirecCst�dS)z�Compare an EDNS option with another option of the same type.
        Return < 0 if self < other, 0 if self == other,
        and > 0 if self > other.
        N)r)r�otherrrr�_cmp5szOption._cmpcCs,t|t�sdS|j|jkrdS|j|�dkS)NF�)�
isinstancerrr)rrrrr�__eq__<s

z
Option.__eq__cCs,t|t�sdS|j|jkrdS|j|�dkS)NFr)rrrr)rrrrr�__ne__Cs

z
Option.__ne__cCs*t|t�s|j|jkrtS|j|�dkS)Nr)rrr�NotImplementedr)rrrrr�__lt__Jsz
Option.__lt__cCs*t|t�s|j|jkrtS|j|�dkS)Nr)rrrrr)rrrrr�__le__Psz
Option.__le__cCs*t|t�s|j|jkrtS|j|�dkS)Nr)rrrrr)rrrrr�__ge__Vsz
Option.__ge__cCs*t|t�s|j|jkrtS|j|�dkS)Nr)rrrrr)rrrrr�__gt__\sz
Option.__gt__N)�__name__�
__module__�__qualname__�__doc__rr
�classmethodrrrrrrrrrrrrrsrcs<eZdZdZ�fdd�Zdd�Zedd��Zdd	�Z�Z	S)
�
GenericOptionzwGenerate Rdata Class

    This class is used for EDNS option types for which we have no better
    implementation.
    cstt|�j|�||_dS)N)�superr r�data)rrr")�	__class__rrrkszGenericOption.__init__cCs|j|j�dS)N)�writer")rr	rrrr
oszGenericOption.to_wirecCs||||||��S)Nr)rrrr
rrrrrrszGenericOption.from_wirecCs$|j|jkrdS|j|jkr dSdS)Nr����)r")rrrrrrvs
zGenericOption._cmp)
rrrrrr
rrr�
__classcell__rr)r#rr cs
r cCstj|�}|dkrt}|S)N)�_type_to_class�getr )rrrrr�get_option_class�s
r*cCst|�}|j||||�S)auBuild an EDNS option object from wire format

    @param otype: The option type
    @type otype: int
    @param wire: The wire-format message
    @type wire: string
    @param current: The offset in wire of the beginning of the rdata.
    @type current: int
    @param olen: The length of the wire-format option data
    @type olen: int
    @rtype: dns.edns.Option instance)r*r)rrr
rrrrr�option_from_wire�s
r+N)rZNSID�objectrr r(r*r+rrrr�<module>sN__pycache__/tokenizer.cpython-36.pyc000064400000034253150351404330013421 0ustar003

�b�W�G�@s�dZddlmZddlZddlZddlZddlZddlm	Z	m
Z
mZdddddddd�ZddiZ
dZdZd	Zd
ZdZdZd
ZGdd�dejj�ZGdd�de�ZGdd�de�ZdS)zTokenize DNS master file format�)�StringION�)�long�	text_type�binary_typeT)� �	�
�;�(�)�"r
�����c@seZdZdZdS)�UngetBufferFullzDAn attempt was made to unget a token when the unget buffer was full.N)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/tokenizer.pyr.src@s�eZdZdZd%dd�Zdd�Zdd	�Zd
d�Zdd
�Zdd�Z	dd�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�Zd$S)&�Tokenz�A DNS master file format token.

    @ivar ttype: The token type
    @type ttype: int
    @ivar value: The token value
    @type value: string
    @ivar has_escape: Does the token value contain escapes?
    @type has_escape: bool
    �FcCs||_||_||_dS)aInitialize a token instance.

        @param ttype: The token type
        @type ttype: int
        @param value: The token value
        @type value: string
        @param has_escape: Does the token value contain escapes?
        @type has_escape: bool
        N)�ttype�value�
has_escape)�selfrrrrrr�__init__?s
zToken.__init__cCs
|jtkS)N)r�EOF)rrrr�is_eofMszToken.is_eofcCs
|jtkS)N)r�EOL)rrrr�is_eolPszToken.is_eolcCs
|jtkS)N)r�
WHITESPACE)rrrr�
is_whitespaceSszToken.is_whitespacecCs
|jtkS)N)r�
IDENTIFIER)rrrr�
is_identifierVszToken.is_identifiercCs
|jtkS)N)r�
QUOTED_STRING)rrrr�is_quoted_stringYszToken.is_quoted_stringcCs
|jtkS)N)r�COMMENT)rrrr�
is_comment\szToken.is_commentcCs
|jtkS)N)r�	DELIMITER)rrrr�is_delimiter_szToken.is_delimitercCs|jtkp|jtkS)N)rr#r!)rrrr�
is_eol_or_eofbszToken.is_eol_or_eofcCs&t|t�sdS|j|jko$|j|jkS)NF)�
isinstancerrr)r�otherrrr�__eq__es
zToken.__eq__cCs&t|t�sdS|j|jkp$|j|jkS)NT)r0rrr)rr1rrr�__ne__ks
zToken.__ne__cCsd|j|jfS)Nz%d "%s")rr)rrrr�__str__qsz
Token.__str__cCs|js
|Sd}t|j�}d}x�||kr�|j|}|d7}|dkr�||krPtjj�|j|}|d7}|j�r�||krztjj�|j|}|d7}||kr�tjj�|j|}|d7}|j�o�|j�s�tjj�tt	|�dt	|�dt	|��}||7}qWt
|j|�S)Nrrr�\�d�
)r�lenr�dns�	exception�
UnexpectedEnd�isdigit�SyntaxError�chr�intrr)rZ	unescaped�l�i�c�c2�c3rrr�unescapets6





$zToken.unescapecCsdS)Nrr)rrrr�__len__�sz
Token.__len__cCst|j|jf�S)N)�iterrr)rrrr�__iter__�szToken.__iter__cCs$|dkr|jS|dkr|jSt�dS)Nrr)rr�
IndexError)rrArrr�__getitem__�s
zToken.__getitem__N)rF)rrrrr r"r$r&r(r*r,r.r/r2r3r4rErFrHrJrrrrr3s"

rc@s�eZdZdZejdfdd�Zdd�Zdd�Zd	d
�Z	dd�Z
d(dd�Zdd�Zdd�Z
e
Zdd�Zdd�Zdd�Zdd�Zdd�Zd)dd�Zd*d d!�Zd+d"d#�Zd$d%�Zd&d'�ZdS),�	Tokenizera�A DNS master file format tokenizer.

    A token is a (type, value) tuple, where I{type} is an int, and
    I{value} is a string.  The valid types are EOF, EOL, WHITESPACE,
    IDENTIFIER, QUOTED_STRING, COMMENT, and DELIMITER.

    @ivar file: The file to tokenize
    @type file: file
    @ivar ungotten_char: The most recently ungotten character, or None.
    @type ungotten_char: string
    @ivar ungotten_token: The most recently ungotten token, or None.
    @type ungotten_token: (int, string) token tuple
    @ivar multiline: The current multiline level.  This value is increased
    by one every time a '(' delimiter is read, and decreased by one every time
    a ')' delimiter is read.
    @type multiline: int
    @ivar quoting: This variable is true if the tokenizer is currently
    reading a quoted string.
    @type quoting: bool
    @ivar eof: This variable is true if the tokenizer has encountered EOF.
    @type eof: bool
    @ivar delimiters: The current delimiter dictionary.
    @type delimiters: dict
    @ivar line_number: The current line number
    @type line_number: int
    @ivar filename: A filename that will be returned by the L{where} method.
    @type filename: string
    NcCs�t|t�r t|�}|dkr`d}n@t|t�rDt|j��}|dkr`d}n|dkr`|tjkr\d}nd}||_d|_d|_	d|_
d|_d|_t
|_d|_||_dS)a�Initialize a tokenizer instance.

        @param f: The file to tokenize.  The default is sys.stdin.
        This parameter may also be a string, in which case the tokenizer
        will take its input from the contents of the string.
        @type f: file or string
        @param filename: the name of the filename that the L{where} method
        will return.
        @type filename: string
        Nz<string>z<stdin>z<file>rFr)r0rrr�decode�sys�stdin�file�
ungotten_char�ungotten_token�	multiline�quoting�eof�_DELIMITERS�
delimiters�line_number�filename)r�frXrrrr �s*


zTokenizer.__init__cCsZ|jdkrJ|jrd}qV|jjd�}|dkr2d|_qV|dkrV|jd7_n|j}d|_|S)z<Read a character from input.
        @rtype: string
        NrrTr	)rPrTrO�readrW)rrBrrr�	_get_char�s
zTokenizer._get_charcCs|j|jfS)z�Return the current location in the input.

        @rtype: (string, int) tuple.  The first item is the filename of
        the input, the second is the current line number.
        )rXrW)rrrr�where�szTokenizer.wherecCs|jdk	rt�||_dS)aEUnget a character.

        The unget buffer for characters is only one character large; it is
        an error to try to unget a character when the unget buffer is not
        empty.

        @param c: the character to unget
        @type c: string
        @raises UngetBufferFull: there is already an ungotten char
        N)rPr)rrBrrr�_unget_chars
zTokenizer._unget_charcCsLd}xB|j�}|dkr<|dkr<|dks.|jr<|j|�|S|d7}qWdS)a(Consume input until a non-whitespace character is encountered.

        The non-whitespace character is then ungotten, and the number of
        whitespace characters consumed is returned.

        If the tokenizer is in multiline mode, then newlines are whitespace.

        @rtype: int
        rrrr	rN)r[rRr])r�skippedrBrrr�skip_whitespaces
zTokenizer.skip_whitespaceFc
CsT|jdk	r>|j}d|_|j�r(|r>|Sn|j�r:|r>|Sn|S|j�}|r\|dkr\ttd�Sd}t}d}�x�|j�}|dks�||jk�r|dkr�|j	r�t
jj�|dko�|t
k�r|dkr�|jd7_|j�ql�q|dk�r
|jdkr�t
jj�|jd8_|j�qln�|d	k�rH|j	�s0d
|_	t|_t
}qlnd|_	t|_|j�qln�|dk�r\ttd�S|dk�r�x,|j�}|dk�s�|dk�r�P||7}�qhW|�r�|j|�tt|�S|dk�r�|j�r�t
jjd
��tt�S|j�r�|j�d}qln
ttd�Sn|}t}n
|j|�P�n�|j	�r�|dk�r�|j�}|dk�r>t
jj�|j��r�|j�}|dk�rbt
jj�|j�}	|dk�r|t
jj�|j��o�|	j��s�t
jj�tt|�dt|�dt|	��}n|dk�rt
jjd��n:|dk�r||7}d
}|j�}|dk�s|dk�rt
jj�||7}qlW|dk�rH|t
k�rH|j�rDt
jjd
��t}t|||�S)aGet the next token.

        @param want_leading: If True, return a WHITESPACE token if the
        first character read is whitespace.  The default is False.
        @type want_leading: bool
        @param want_comment: If True, return a COMMENT token if the
        first token read is a comment.  The default is False.
        @type want_comment: bool
        @rtype: Token object
        @raises dns.exception.UnexpectedEnd: input ended prematurely
        @raises dns.exception.SyntaxError: input was badly formed
        NrrrFrrrr
Tr	r
zunbalanced parenthesesr5r6r7znewline in quoted string)rQr&r,r_rr%r'r[rVrSr9r:r;r)rRr=�_QUOTING_DELIMITERSrUr#r]r+r!r-r<r>r?)
rZwant_leadingZwant_comment�tokenr^rrrBrCrDrrr�get%s�
















&

z
Tokenizer.getcCs|jdk	rt�||_dS)a@Unget a token.

        The unget buffer for tokens is only one token large; it is
        an error to try to unget a token when the unget buffer is not
        empty.

        @param token: the token to unget
        @type token: Token object
        @raises UngetBufferFull: there is already an ungotten token
        N)rQr)rrarrr�unget�s
zTokenizer.ungetcCs|j�}|j�rt�|S)zLReturn the next item in an iteration.
        @rtype: (int, string)
        )rbr"�
StopIteration)rrarrr�next�szTokenizer.nextcCs|S)Nr)rrrrrH�szTokenizer.__iter__cCs@|j�j�}|j�s tjjd��|jj�s6tjjd��t|j�S)z|Read the next token and interpret it as an integer.

        @raises dns.exception.SyntaxError:
        @rtype: int
        zexpecting an identifierzexpecting an integer)	rbrEr(r9r:r=rr<r?)rrarrr�get_int�s
zTokenizer.get_intcCs,|j�}|dks|dkr(tjjd|��|S)z�Read the next token and interpret it as an 8-bit unsigned
        integer.

        @raises dns.exception.SyntaxError:
        @rtype: int
        r�z#%d is not an unsigned 8-bit integer)rfr9r:r=)rrrrr�	get_uint8�s

zTokenizer.get_uint8cCs,|j�}|dks|dkr(tjjd|��|S)z�Read the next token and interpret it as a 16-bit unsigned
        integer.

        @raises dns.exception.SyntaxError:
        @rtype: int
        ri��z$%d is not an unsigned 16-bit integer)rfr9r:r=)rrrrr�
get_uint16�s

zTokenizer.get_uint16cCsh|j�j�}|j�s tjjd��|jj�s6tjjd��t|j�}|dksT|td�krdtjjd|��|S)z�Read the next token and interpret it as a 32-bit unsigned
        integer.

        @raises dns.exception.SyntaxError:
        @rtype: int
        zexpecting an identifierzexpecting an integerrlz$%d is not an unsigned 32-bit integer)	rbrEr(r9r:r=rr<r)rrarrrr�
get_uint32�s


zTokenizer.get_uint32cCs.|j�j�}|j�p|j�s(tjjd��|jS)z}Read the next token and interpret it as a string.

        @raises dns.exception.SyntaxError:
        @rtype: string
        zexpecting a string)rbrEr(r*r9r:r=r)r�originrarrr�
get_string�szTokenizer.get_stringcCs&|j�j�}|j�s tjjd��|jS)z�Read the next token and raise an exception if it is not an identifier.

        @raises dns.exception.SyntaxError:
        @rtype: string
        zexpecting an identifier)rbrEr(r9r:r=r)rrkrarrr�get_identifier
szTokenizer.get_identifiercCs,|j�}|j�stjjd��tjj|j|�S)z�Read the next token and interpret it as a DNS name.

        @raises dns.exception.SyntaxError:
        @rtype: dns.name.Name objectzexpecting an identifier)rbr(r9r:r=�name�	from_textr)rrkrarrr�get_nameszTokenizer.get_namecCs.|j�}|j�s(tjjd|j|jf��|jS)z�Read the next token and raise an exception if it isn't EOL or
        EOF.

        @raises dns.exception.SyntaxError:
        @rtype: string
        z expected EOL or EOF, got %d "%s")rbr/r9r:r=rr)rrarrr�get_eol!szTokenizer.get_eolcCs.|j�j�}|j�s tjjd��tjj|j�S)Nzexpecting an identifier)	rbrEr(r9r:r=Zttlror)rrarrr�get_ttl0szTokenizer.get_ttl)FF)N)N)N)rrrrrMrNr r[r\r]r_rbrcre�__next__rHrfrhrirjrlrmrprqrrrrrrrK�s($	
{



rK)r�iorrMZ
dns.exceptionr9Zdns.nameZdns.ttlZ_compatrrrrUr`r!r#r%r'r)r+r-r:ZDNSExceptionr�objectrrKrrrr�<module>s0o__pycache__/opcode.cpython-36.pyc000064400000004002150351404330012645 0ustar003

�b�W�	�@s�dZddlZdZdZdZdZdZeeeeed�Ze	dd	�ej
�D��ZGd
d�dejj
�Zdd
�Zdd�Zdd�Zdd�Zdd�ZdS)zDNS Opcodes.�N����)�QUERY�IQUERY�STATUS�NOTIFY�UPDATEccs|]\}}||fVqdS)N�)�.0�x�yrr�/usr/lib/python3.6/opcode.py�	<genexpr>&src@seZdZdZdS)�
UnknownOpcodezAn DNS opcode is unknown.N)�__name__�
__module__�__qualname__�__doc__rrrrr)srcCsB|j�r$t|�}|dkr$|dkr$|Stj|j��}|dkr>t�|S)z�Convert text into an opcode.

    @param text: the textual opcode
    @type text: string
    @raises UnknownOpcode: the opcode is unknown
    @rtype: int
    r�N)�isdigit�int�_by_text�get�upperr)�text�valuerrr�	from_text.s	rcCs|d@d?S)zUExtract an opcode from DNS message flags.

    @param flags: int
    @rtype: int
    ix�r)�flagsrrr�
from_flagsAsr!cCs|d>d@S)z`Convert an opcode to a value suitable for ORing into DNS message
    flags.
    @rtype: int
    rixr)rrrr�to_flagsKsr"cCstj|�}|dkrt|�}|S)z�Convert an opcode to text.

    @param value: the opcdoe
    @type value: int
    @raises UnknownOpcode: the opcode is unknown
    @rtype: string
    N)�	_by_valuer�str)rrrrr�to_textTs	
r%cCst|�tkS)znTrue if the opcode in flags is UPDATE.

    @param flags: DNS flags
    @type flags: int
    @rtype: bool
    )r!r
)r rrr�	is_updatecsr&)rZ
dns.exceptionZdnsrrrr	r
r�dict�itemsr#Z	exceptionZDNSExceptionrrr!r"r%r&rrrr�<module>s$
	__pycache__/ttl.cpython-36.pyc000064400000002450150351404330012204 0ustar003

�b�W��@s8dZddlZddlmZGdd�dejj�Zdd�ZdS)	zDNS TTL conversion.�N�)�longc@seZdZdZdS)�BadTTLz!DNS TTL value is not well-formed.N)�__name__�
__module__�__qualname__�__doc__�r	r	�/usr/lib/python3.6/ttl.pyrsrcCs*|j�rt|�}n�|dj�s"t�td�}td�}x�|D]�}|j�rZ|d9}|t|�7}q8|j�}|dkr|||td�7}nl|dkr�||td�7}nR|dkr�||td�7}n8|d	kr�||td
�7}n|dkr�||7}ntd|��d}q8W|dk�std
��|td�k�s|td�k�r&td��|S)z�Convert the text form of a TTL to an integer.

    The BIND 8 units syntax for TTLs (e.g. '1w6d4h3m10s') is supported.

    @param text: the textual TTL
    @type text: string
    @raises dns.ttl.BadTTL: the TTL is not well-formed
    @rtype: int
    r�
�wi�:	�di�Q�hi�m�<�szunknown unit '%s'ztrailing integeri���z0TTL should be between 0 and 2^31 - 1 (inclusive))�isdigitrr�lower)�textZtotalZcurrent�cr	r	r
�	from_texts8



r)	rZ
dns.exceptionZdnsZ_compatrZ	exception�SyntaxErrorrrr	r	r	r
�<module>s__pycache__/name.cpython-36.opt-1.pyc000064400000064766150351404330013302 0ustar003

�Of�r�@s�dZddlmZddlZddlZddlZddlZyddlZdZ	Wne
k
rXdZ	YnXddlZddl
ZddlmZmZmZmZmZy
ejZWn.ek
r�ddejd	�>d
dZYnXdZdZd
ZdZdZGd
d�dejj�ZGdd�dejj�ZGdd�dejj �Z!Gdd�dejj �Z"Gdd�dejj#�Z$Gdd�dejj �Z%Gdd�dejj�Z&Gdd�dejj#�Z'Gdd�dejj#�Z(Gdd �d ejj#�Z)Gd!d"�d"ejj#�Z*Gd#d$�d$e+�Z,Gd%d&�d&e,�Z-Gd'd(�d(e,�Z.e/d)�Z0d*Z1e-d�Z2e-d�Z3e2Z4e.dddd�Z5e.dddd�Z6e.dddd�Z7e.dddd�Z8e5Z9d+d,�Z:d-d.�Z;d/d0�Z<Gd1d2�d2e+�Z=e=d3g�Z>e=g�Z?e>dfd4d5�Z@e>dfd6d7�ZAd8d9�ZBdS):z�DNS Names.

@var root: The DNS root name.
@type root: dns.name.Name object
@var empty: The empty DNS name.
@type empty: dns.name.Name object
�)�BytesIONTF�)�long�binary_type�	text_type�unichr�maybe_decode��P���c@seZdZdZdS)�
EmptyLabelzA DNS label is empty.N)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/name.pyr4src@seZdZdZdS)�	BadEscapez8An escaped code in a text format of DNS name is invalid.N)rrrrrrrrr9src@seZdZdZdS)�
BadPointerz=A DNS compression pointer points forward instead of backward.N)rrrrrrrrr>src@seZdZdZdS)�BadLabelTypez2The label type in DNS name wire format is unknown.N)rrrrrrrrrCsrc@seZdZdZdS)�NeedAbsoluteNameOrOriginzvAn attempt was made to convert a non-absolute name to
    wire when there was also a non-absolute (or missing) origin.N)rrrrrrrrrHsrc@seZdZdZdS)�NameTooLongz A DNS name is > 255 octets long.N)rrrrrrrrrNsrc@seZdZdZdS)�LabelTooLongz A DNS label is > 63 octets long.N)rrrrrrrrrSsrc@seZdZdZdS)�AbsoluteConcatenationz]An attempt was made to append anything other than the
    empty name to an absolute DNS name.N)rrrrrrrrrXsrc@seZdZdZdS)�NoParentzMAn attempt was made to get the parent of the root name
    or the empty name.N)rrrrrrrrr^src@seZdZdZdS)�
NoIDNA2008zLIDNA 2008 processing was requested but the idna module is not
    available.N)rrrrrrrrrcsrc@seZdZdZedg�ZdZdS)�
IDNAExceptionz$IDNA processing raised an exception.�idna_exceptionz+IDNA processing exception: {idna_exception}N)rrrr�setZsupp_kwargsZfmtrrrrris
rc@s8eZdZdZdd�Zdd�Zdd�Zdd	�Zd
d�ZdS)
�	IDNACodecz.Abstract base class for IDNA encoder/decoders.cCsdS)Nr)�selfrrr�__init__tszIDNACodec.__init__cCs|j�jd�S)Nsxn--)�lower�
startswith)r"�labelrrr�is_idnawszIDNACodec.is_idnacCs"x|D]}t|�dkrdSqWdS)N�FT)�ord)r"r&�crrr�is_all_asciizs
zIDNACodec.is_all_asciicCst�dS)N)�NotImplementedError)r"r&rrr�encode�szIDNACodec.encodecCs`|j|�rPy|dd�jd�}WqXtk
rL}zt|d��WYdd}~XqXXnt|�}t|�S)Nr
Zpunycode)r)r'�decode�	Exceptionrr�	_escapify)r"r&�errrr.�s
zIDNACodec.decodeN)	rrrrr#r'r+r-r.rrrrr!psr!cs6eZdZdZd	�fdd�	Zdd�Z�fdd�Z�ZS)
�
IDNA2003CodeczIDNA 2003 encoder/decoder.Fcstt|�j�||_dS)aInitialize the IDNA 2003 encoder/decoder.
        @param strict_decode: If True, then IDNA2003 checking is done when
        decoding.  This can cause failures if the name was encoded with
        IDNA2008.  The default is False.
        @type strict_decode: bool
        N)�superr2r#�
strict_decode)r"r4)�	__class__rrr#�szIDNA2003Codec.__init__cCs6|dkrdSytjj|�Stk
r0t�YnXdS)N��)�	encodings�idnaZToASCII�UnicodeErrorr)r"r&rrrr-�szIDNA2003Codec.encodecsd|jstt|�j|�S|dkr"dSyttjj|��Stk
r^}zt	|d��WYdd}~XnXdS)Nr7r6)r)
r4r3r2r.r0r8r9Z	ToUnicoder/r)r"r&r1)r5rrr.�szIDNA2003Codec.decode)F)rrrrr#r-r.�
__classcell__rr)r5rr2�s
r2cs6eZdZdZd	�fdd�	Zdd�Z�fdd�Z�ZS)
�
IDNA2008CodeczIDNA 2008 encoder/decoder.Fcs*tt|�j�||_||_||_||_dS)a�Initialize the IDNA 2008 encoder/decoder.
        @param uts_46: If True, apply Unicode IDNA compatibility processing
        as described in Unicode Technical Standard #46
        (U{http://unicode.org/reports/tr46/}).  This parameter is only
        meaningful if IDNA 2008 is in use.  If False, do not apply
        the mapping.  The default is False
        @type uts_46: bool
        @param transitional: If True, use the "transitional" mode described
        in Unicode Technical Standard #46.  This parameter is only
        meaningful if IDNA 2008 is in use.  The default is False.
        @type transitional: bool
        @param allow_pure_ascii: If True, then a label which
        consists of only ASCII characters is allowed.  This is less strict
        than regular IDNA 2008, but is also necessary for mixed names,
        e.g. a name with starting with "_sip._tcp." and ending in an IDN
        suffixm which would otherwise be disallowed.  The default is False
        @type allow_pure_ascii: bool
        @param strict_decode: If True, then IDNA2008 checking is done when
        decoding.  This can cause failures if the name was encoded with
        IDNA2003.  The default is False.
        @type strict_decode: bool
        N)r3r<r#�uts_46�transitional�allow_pure_asciir4)r"r=r>r?r4)r5rrr#�s
zIDNA2008Codec.__init__cCs�|dkrdS|jr&|j|�r&|jd�Sts.t�y |jrFtj|d|j�}tj	|�Stj
k
r|}zt|d��WYdd}~XnXdS)Nr6r7�asciiF)r)r?r+r-�have_idna_2008rr=r9�uts46_remapr>Zalabel�	IDNAErrorr)r"r&r1rrrr-�s

zIDNA2008Codec.encodecs�|jstt|�j|�S|dkr"dSts*t�y"|jr@tj|dd�}t	tj
|��Stjk
rz}zt|d��WYdd}~XnXdS)Nr7r6F)r)
r4r3r<r.rArr=r9rBr0ZulabelrCr)r"r&r1)r5rrr.�szIDNA2008Codec.decode)FFFF)rrrrr#r-r.r;rr)r5rr<�s
r<s"().;\@$z"().;\@$cCs�t|t�rzd}t|t�r |j�}xTt|�D]H}|tkrH|dt|�7}q*|dkrf|dkrf|t|�7}q*|d|7}q*W|Sd}xD|D]<}|tkr�|d|7}q�|dkr�|dt|�7}q�||7}q�W|S)zaEscape the characters in label which need it.
    @returns: the escaped string
    @rtype: stringr6�\� r(z\%03d� )	�
isinstance�bytesrr-�	bytearray�_escaped�chr�
_escaped_textr))r&�textr*rrrr0�s&


r0cCs�t|�}d}d}d}xH|D]@}t|�}||d7}|dkr>t�|dkrR|dkrR|}|d7}qW|dkrjt�|dkr�||dkr�t�dS)a/Check for empty labels in the middle of a label sequence,
    labels that are too long, and for too many labels.
    @raises NameTooLong: the name as a whole is too long
    @raises EmptyLabel: a label is empty (i.e. the root label) and appears
    in a position other than the end of the label sequencerr�?r7�N���)�lenrrr)�labels�l�total�i�jr&Zllrrr�_validate_labelss 
rWcCs(t|t�r|St|t�r |j�St�dS)N)rGrrr-�
ValueError)r&rrr�
_ensure_bytes/s


rYcsDeZdZdZdgZ�fdd�Zdd�Zdd�Zd	d
�Zdd�Z	�fd
d�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zdd�Zdd �Zd!d"�Zd#d$�Zd%d&�Zd'd(�Zd)d*�Zd+d,�ZdLd.d/�ZdMd1d2�ZdNd3d4�ZdOd5d6�Zd7d8�Zd9d:�Zd;d<�Z d=d>�Z!d?d@�Z"dAdB�Z#dCdD�Z$dEdF�Z%dPdHdI�Z&dJdK�Z'�Z(S)Q�Namez�A DNS name.

    The dns.name.Name class represents a DNS name as a tuple of labels.
    Instances of the class are immutable.

    @ivar labels: The tuple of labels in the name. Each label is a string of
    up to 63 octets.rRcs2dd�|D�}tt|�jdt|��t|j�dS)z�Initialize a domain name from a list of labels.
        @param labels: the labels
        @type labels: any iterable whose values are strings
        cSsg|]}t|��qSr)rY)�.0�xrrr�
<listcomp>Hsz!Name.__init__.<locals>.<listcomp>rRN)r3rZ�__setattr__�tuplerWrR)r"rR)r5rrr#Csz
Name.__init__cCstd��dS)Nz+object doesn't support attribute assignment)�	TypeError)r"�name�valuerrrr^LszName.__setattr__cCs
t|j�S)N)rZrR)r"rrr�__copy__Osz
Name.__copy__cCsttj|j|��S)N)rZ�copy�deepcopyrR)r"�memorrr�__deepcopy__RszName.__deepcopy__cCs
d|jiS)NrR)rR)r"rrr�__getstate__UszName.__getstate__cs$tt|�jd|d�t|j�dS)NrR)r3rZr^rWrR)r"�state)r5rr�__setstate__XszName.__setstate__cCst|j�dko|jddkS)zXIs the most significant label of this name the root label?
        @rtype: bool
        rrr7rP)rQrR)r"rrr�is_absolute\szName.is_absolutecCst|j�dko|jddkS)z\Is this name wild?  (I.e. Is the least significant label '*'?)
        @rtype: bool
        r�*)rQrR)r"rrr�is_wildcszName.is_wildcCsJtd�}x4|jD]*}x$t|j��D]}||d>|7}q"WqWt|t�S)zHReturn a case-insensitive hash of the name.
        @rtype: int
        rr)rrRrIr$�int�maxint)r"�hr&r*rrr�__hash__js
z
Name.__hash__c
Cs*|j�}|j�}||kr0|r&tddfStddfSt|j�}t|j�}||}|dkrZ|}n|}d}d}	t}
x�|dkr�|d8}|d8}|d8}|j|j�}|j|j�}||kr�d}|	dkr�t}
|
||	fS||kr�d}|	dkr�t}
|
||	fS|	d7}	qlW|}|dk�rt}
n|dk�rt}
nt}
|
||	fS)a�Compare two names, returning a 3-tuple (relation, order, nlabels).

        I{relation} describes the relation ship between the names,
        and is one of: dns.name.NAMERELN_NONE,
        dns.name.NAMERELN_SUPERDOMAIN, dns.name.NAMERELN_SUBDOMAIN,
        dns.name.NAMERELN_EQUAL, or dns.name.NAMERELN_COMMONANCESTOR

        I{order} is < 0 if self < other, > 0 if self > other, and ==
        0 if self == other.  A relative name is always less than an
        absolute name.  If both names have the same relativity, then
        the DNSSEC order relation is used to order them.

        I{nlabels} is the number of significant labels that the two names
        have in common.
        rrrPrP)	rk�
NAMERELN_NONErQrRr$�NAMERELN_COMMONANCESTOR�NAMERELN_SUPERDOMAIN�NAMERELN_SUBDOMAIN�NAMERELN_EQUAL)
r"�otherZsabsZoabs�l1�l2ZldiffrS�orderZnlabelsZnamerelnZlabel1Zlabel2rrr�fullcompareusN








zName.fullcomparecCs(|j|�\}}}|tks |tkr$dSdS)zoIs self a subdomain of other?

        The notion of subdomain includes equality.
        @rtype: bool
        TF)r{rurv)r"rw�nr�o�nlrrr�is_subdomain�szName.is_subdomaincCs(|j|�\}}}|tks |tkr$dSdS)zqIs self a superdomain of other?

        The notion of subdomain includes equality.
        @rtype: bool
        TF)r{rtrv)r"rwr|r}r~rrr�is_superdomain�szName.is_superdomaincCstdd�|jD��S)z�Return a name which is equal to the current name, but is in
        DNSSEC canonical form.
        @rtype: dns.name.Name object
        cSsg|]}|j��qSr)r$)r[r\rrrr]�sz%Name.canonicalize.<locals>.<listcomp>)rZrR)r"rrr�canonicalize�szName.canonicalizecCs$t|t�r|j|�ddkSdSdS)NrrF)rGrZr{)r"rwrrr�__eq__�s
zName.__eq__cCs$t|t�r|j|�ddkSdSdS)NrrT)rGrZr{)r"rwrrr�__ne__�s
zName.__ne__cCs$t|t�r|j|�ddkStSdS)Nrr)rGrZr{�NotImplemented)r"rwrrr�__lt__�s
zName.__lt__cCs$t|t�r|j|�ddkStSdS)Nrr)rGrZr{r�)r"rwrrr�__le__�s
zName.__le__cCs$t|t�r|j|�ddkStSdS)Nrr)rGrZr{r�)r"rwrrr�__ge__�s
zName.__ge__cCs$t|t�r|j|�ddkStSdS)Nrr)rGrZr{r�)r"rwrrr�__gt__�s
zName.__gt__cCsd|j�dS)Nz
<DNS name �>)�__str__)r"rrr�__repr__�sz
Name.__repr__cCs
|jd�S)NF)�to_text)r"rrrr��szName.__str__FcCspt|j�dkrtd�St|j�dkr:|jddkr:td�S|rV|j�rV|jdd�}n|j}djtt|��}|S)	z�Convert name to text format.
        @param omit_final_dot: If True, don't emit the final dot (denoting the
        root label) for absolute names.  The default is False.
        @rtype: string
        r�@rr7�.N�.rP)rQrRrrk�join�mapr0)r"�omit_final_dotrS�srrrr��szName.to_textNcsxt|j�dkrdSt|j�dkr2|jddkr2dS|rN|j�rN|jdd	�}n|j}�dkr`t�dj�fdd�|D��S)
a�Convert name to Unicode text format.

        IDN ACE labels are converted to Unicode.

        @param omit_final_dot: If True, don't emit the final dot (denoting the
        root label) for absolute names.  The default is False.
        @type omit_final_dot: bool
        @param idna_codec: IDNA encoder/decoder.  If None, the
        IDNA_2003_Practical encoder/decoder is used.  The IDNA_2003_Practical
        decoder does not impose any policy, it just decodes punycode, so if
        you don't want checking for compliance, you can use this decoder for
        IDNA2008 as well.
        @type idna_codec: dns.name.IDNA
        @rtype: string
        r�@rr7r�Ncsg|]}�j|��qSr)r.)r[r\)�
idna_codecrrr])sz#Name.to_unicode.<locals>.<listcomp>rP)rQrRrk�IDNA_2003_Practicalr�)r"r�r�rSr)r�r�
to_unicodeszName.to_unicodecCsX|j�s:|dks|j�rt�t|j�}|jt|j��n|j}dd�|D�}dj|�S)aConvert name to a format suitable for digesting in hashes.

        The name is canonicalized and converted to uncompressed wire format.

        @param origin: If the name is relative and origin is not None, then
        origin will be appended to it.
        @type origin: dns.name.Name object
        @raises NeedAbsoluteNameOrOrigin: All names in wire format are
        absolute.  If self is a relative name, then an origin must be supplied;
        if it is missing, then this exception is raised
        @rtype: string
        NcSs*g|]"}tjdt|�t|�|j���qS)z!B%ds)�struct�packrQr$)r[r\rrrr]@sz&Name.to_digestable.<locals>.<listcomp>r7)rkr�listrR�extendr�)r"�originrRZdlabelsrrr�
to_digestable+s
zName.to_digestablec
Cs.|dkrt�}d}nd}|j�sR|dks2|j�r6t�t|j�}|jt|j��n|j}d}x�|D]�}t||d��}|d7}|dk	r�|j|�}	nd}	|	dk	r�d|	}
tj	d|
�}|j
|�Pqb|dk	r�t|�dkr�|j�}	|	dkr�|	||<t|�}|j
tj	d	|��|dkrb|j
|�qbW|�r*|j
�SdS)
a�Convert name to wire format, possibly compressing it.

        @param file: the file where the name is emitted (typically
        a BytesIO file).  If None, a string containing the wire name
        will be returned.
        @type file: file or None
        @param compress: The compression table.  If None (the default) names
        will not be compressed.
        @type compress: dict
        @param origin: If the name is relative and origin is not None, then
        origin will be appended to it.
        @type origin: dns.name.Name object
        @raises NeedAbsoluteNameOrOrigin: All names in wire format are
        absolute.  If self is a relative name, then an origin must be supplied;
        if it is missing, then this exception is raised
        NTFrri�z!Hi�?z!B)rrkrr�rRr�rZ�getr�r��writerQ�tell�getvalue)
r"�file�compressr�Zwant_returnrRrUr&�n�posrbr�rSrrr�to_wireDs@


zName.to_wirecCs
t|j�S)z@The length of the name (in labels).
        @rtype: int
        )rQrR)r"rrr�__len__|szName.__len__cCs
|j|S)N)rR)r"�indexrrr�__getitem__�szName.__getitem__cCs
|j|�S)N)�concatenate)r"rwrrr�__add__�szName.__add__cCs
|j|�S)N)�
relativize)r"rwrrr�__sub__�szName.__sub__cCsnt|j�}|dkr|tjjfS||kr2tjj|fS|dksB||krJtd��t|d|��t||d��fS)a(Split a name into a prefix and suffix at depth.

        @param depth: the number of labels in the suffix
        @type depth: int
        @raises ValueError: the depth was not >= 0 and <= the length of the
        name.
        @returns: the tuple (prefix, suffix)
        @rtype: tuple
        rz0depth must be >= 0 and <= the length of the nameN)rQrR�dnsra�emptyrXrZ)r"�depthrSrrr�split�s
z
Name.splitcCs:|j�rt|�dkrt�t|j�}|jt|j��t|�S)z�Return a new name which is the concatenation of self and other.
        @rtype: dns.name.Name object
        @raises AbsoluteConcatenation: self is absolute and other is
        not the empty name
        r)rkrQrr�rRr�rZ)r"rwrRrrrr��s

zName.concatenatecCs0|dk	r(|j|�r(t|dt|���S|SdS)z�If self is a subdomain of origin, return a new name which is self
        relative to origin.  Otherwise return self.
        @rtype: dns.name.Name object
        N)rrZrQ)r"r�rrrr��szName.relativizecCs|j�s|j|�S|SdS)z�If self is a relative name, return a new name which is the
        concatenation of self and origin.  Otherwise return self.
        @rtype: dns.name.Name object
        N)rkr�)r"r�rrr�derelativize�s
zName.derelativizeTcCs&|r|r|j|�S|j|�Sn|SdS)aReturn a name with the relativity desired by the caller.  If
        origin is None, then self is returned.  Otherwise, if
        relativize is true the name is relativized, and if relativize is
        false the name is derelativized.
        @rtype: dns.name.Name object
        N)r�r�)r"r�r�rrr�choose_relativity�s

zName.choose_relativitycCs&|tks|tkrt�t|jdd��S)z�Return the parent of the name.
        @rtype: dns.name.Name object
        @raises NoParent: the name is either the root name or the empty name,
        and thus has no parent.
        rN)�rootr�rrZrR)r"rrr�parent�szName.parent)F)FN)N)NNN)NT))rrrr�	__slots__r#r^rcrgrhrjrkrmrqr{rr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r;rr)r5rrZ7sJ	=



8

rZr7c	Cs�t|t�std��|dkp"t|t�s,td��g}d}d}d}d}|dkrLt}|dkrXd}|�rz|dkrptd	g�Sx�|D]�}|r�|dkr�|j�r�t|�}|d
7}q�||7}d}n@|j�s�t�|d9}|t|�7}|d
7}|dkr�d}|t|�7}qv|dk�r"t	|�dk�rt
�|j|j|��d}qv|dk�r:d}d}d}qv||7}qvW|�rPt�t	|�dk�rp|j|j|��n
|jd	�t	|�dk�s�|dd	k�r�|dk	�r�|j
t|j��t|�S)a�Convert unicode text into a Name object.

    Labels are encoded in IDN ACE form.

    @param text: The text to convert into a name.
    @type text: Unicode string
    @param origin: The origin to append to non-absolute names.
    @type origin: dns.name.Name
    @param idna_codec: IDNA encoder/decoder.  If None, the default IDNA 2003
    encoder/decoder is used.
    @type idna_codec: dns.name.IDNA
    @rtype: dns.name.Name object
    z0input to from_unicode() must be a unicode stringNzorigin must be a Name or Noner6Frr�r�r7r�
r�。�.�。rDT)r�r�r�r�rP)rGrrXrZ�	IDNA_2003�isdigitrnrrrQr�appendr-r�r�rR)	rMr�r�rRr&�escaping�edigitsrTr*rrr�from_unicode�sd






&r�c
Cs�t|t�rt|||�St|t�s(td��|dkp8t|t�sBtd��g}d}d}d}d}|dkrbd}|�r�|dkrztdg�Sx�t|�D]�}tjd	|�}	|�r|dkr�|	j	�r�t
|	�}|d
7}n||	7}d}nF|	j	�s�t�|d9}|t
|	�7}|d
7}|dk�r^d}|tjd	|�7}q�|	dk�r>t|�dk�r.t
�|j|�d}q�|	d
k�rVd}d}d}q�||	7}q�W|�rlt�t|�dk�r�|j|�n
|jd�t|�dk�s�|ddk�r�|dk	�r�|jt|j��t|�S)a}Convert text into a Name object.

    @param text: The text to convert into a name.
    @type text: string
    @param origin: The origin to append to non-absolute names.
    @type origin: dns.name.Name
    @param idna_codec: IDNA encoder/decoder.  If None, the default IDNA 2003
    encoder/decoder is used.
    @type idna_codec: dns.name.IDNA
    @rtype: dns.name.Name object
    z%input to from_text() must be a stringNzorigin must be a Name or Noner7Frr�r�z!Brr�r�\TrP)rGrr�rrXrZrIr�r�r�rnrrQrr�r�r�rR)
rMr�r�rRr&r�r�rTr*Zbyte_rrr�	from_text*sf








&r�cCst|t�std��tjj|�}g}|}d}||}|d7}d}x�|dkr�|dkr�|j||||�j��||7}|dkr�||7}nJ|dkr�|d@d||}|dkr�|d7}||kr�t�|}|d7}nt	�||}|d7}|dkr@|d7}q@W|jd�t
|�|fS)	a^Convert possibly compressed wire format into a Name.
    @param message: the entire DNS message
    @type message: string
    @param current: the offset of the beginning of the name from the start
    of the message
    @type current: int
    @raises dns.name.BadPointer: a compression pointer did not point backwards
    in the message
    @raises dns.name.BadLabelType: an invalid label type was encountered.
    @returns: a tuple consisting of the name that was read and the number
    of bytes of the wire format message which were consumed reading it
    @rtype: (dns.name.Name object, int) tuple
    z*input to from_wire() must be a byte stringrr�@�rN�r6)rGrrXr�ZwiredataZ
maybe_wrapr�ZunwraprrrZ)�messageZcurrentrRZbiggest_pointerZhops�countZcusedrrr�	from_wireps<




r�)Cr�iorr��sysrdZencodings.idnar8r9rA�ImportErrorZ
dns.exceptionr�Zdns.wiredataZ_compatrrrrrro�AttributeError�calcsizerrrtrurvrsZ	exception�SyntaxErrorrrZ	FormErrorrrZDNSExceptionrrrrrrr�objectr!r2r<rIrJrLr�ZIDNA_2003_Strictr�ZIDNA_2008_PracticalZIDNA_2008_UTS_46ZIDNA_2008_StrictZIDNA_2008_TransitionalZ	IDNA_2008r0rWrYrZr�r�r�r�r�rrrr�<module>st

  >*
HF__pycache__/query.cpython-36.pyc000064400000032664150351404330012560 0ustar003

�Of�L�@s�dZddlmZddlZddlZddlZddlZddlZddlZddl	Z
ddlZ
ddlZ
ddl
Z
ddlZ
ddlZ
ddlmZmZejd/kr�eZnejZejZGdd�de
jj�ZGd	d
�d
e
jj�Zdd�Zd
d�Zdd�Zdd�Z dd�Z!e"ed�r�ea#nea#dd�Z$dd�Z%dd�Z&dd�Z'dd�Z(d0d"d#�Z)d$d%�Z*d&d'�Z+d(d)�Z,d1d*d+�Z-e
j.j/e
j0j1dd ddd,dddddd!e
j2j3fd-d.�Z4dS)2zTalk to a DNS server.�)�
generatorsN�)�long�string_types�c@seZdZdZdS)�UnexpectedSourcez=A DNS query response came from an unexpected address or port.N)�__name__�
__module__�__qualname__�__doc__�rr�/usr/lib/python3.6/query.pyr,src@seZdZdZdS)�BadResponsez<A DNS query response does not respond to the question asked.N)rr	r
rrrrr
r1srcCs|dkrdStj�|SdS)N)�time)�timeoutrrr
�_compute_expiration6srcCsjd}|r|tjO}|r |tjO}|r.|tjO}tj�}|j||�|rZ|jt|d��}n|j�}t|�S)aqPoll polling backend.
    @param fd: File descriptor
    @type fd: int
    @param readable: Whether to wait for readability
    @type readable: bool
    @param writable: Whether to wait for writability
    @type writable: bool
    @param timeout: Deadline timeout (expiration time, in seconds)
    @type timeout: float
    @return True on success, False on timeout
    ri�)�selectZPOLLINZPOLLOUTZPOLLERR�poll�registerr�bool)�fd�readable�writable�errorrZ
event_maskZpollableZ
event_listrrr
�	_poll_for=s


rcCsrggg}}}|r|g}|r$|g}|r.|g}|dkrLtj|||�\}}	}
ntj||||�\}}	}
t|pn|	pn|
�S)asSelect polling backend.
    @param fd: File descriptor
    @type fd: int
    @param readable: Whether to wait for readability
    @type readable: bool
    @param writable: Whether to wait for writability
    @type writable: bool
    @param timeout: Deadline timeout (expiration time, in seconds)
    @type timeout: float
    @return True on success, False on timeout
    N)rr)rrrrrZrsetZwsetZxsetZrcountZwcountZxcountrrr
�_select_for\srcCs�d}x�|s�|dkrd}n|tj�}|dkr4tjj�yt|||||�sNtjj�Wn6tk
r�}z|jdtjkrv|�WYdd}~XnXd}qWdS)NFgrT)	r�dns�	exceptionZTimeout�_polling_backend�select_error�args�errnoZEINTR)rrrr�
expiration�doner�errr
�	_wait_forysr%cCs|adS)z#
    Internal API. Do not use.
    N)r)�fnrrr
�_set_polling_backend�sr'rcCst|ddd|�dS)NTF)r%)�sr"rrr
�_wait_for_readable�sr)cCst|ddd|�dS)NFT)r%)r(r"rrr
�_wait_for_writable�sr*cCsDtjj||d�}tjj||d�}||koB|dd�|dd�kS)Nrr)r�inetZ	inet_pton)�afZa1Za2Zn1Zn2rrr
�_addresses_equal�sr-cCs`|sdSt|||�s<tjj|d�r@|dd�|dd�kr@dS|rHdStd|�d|����dS)NTrrFzgot a response from z instead of )r-rr+Zis_multicastr)r,�from_address�destination�ignore_unexpectedrrr
�_matches_destination�s(r1cCs�|dkr6ytjj|�}Wntk
r4tjj}YnX|tjjkrp||f}|dk	sZ|dkr�|dkrfd}||f}n@|tjjkr�||ddf}|dk	s�|dkr�|dkr�d}||ddf}|||fS)Nrz0.0.0.0z::)rr+Zaf_for_address�	ExceptionZAF_INETZAF_INET6)r,�where�port�source�source_portr/rrr
�_destination_and_source�s$
r7�5Fc
Cs"|j�}
t|||||�\}}}t|tjd�}d}
z�t|�}|jd�|dk	rV|j|�t||�t	j	�}
|j
|
|�x�t||�|jd�\}
}t
|j|||�s�qvt	j	�|
}y"tjj|
|j|j|d�}||_	Wntk
r�|	r�wvn�YnX|j|��r�|S|	�rqvqvt�qvWWd|j�XdS)a�Return the response obtained after sending a query via UDP.

    @param q: the query
    @type q: dns.message.Message
    @param where: where to send the message
    @type where: string containing an IPv4 or IPv6 address
    @param timeout: The number of seconds to wait before the query times out.
    If None, the default, wait forever.
    @type timeout: float
    @param port: The port to which to send the message.  The default is 53.
    @type port: int
    @param af: the address family to use.  The default is None, which
    causes the address family to use to be inferred from the form of where.
    If the inference attempt fails, AF_INET is used.
    @type af: int
    @rtype: dns.message.Message object
    @param source: source address.  The default is the wildcard address.
    @type source: string
    @param source_port: The port from which to send the message.
    The default is 0.
    @type source_port: int
    @param ignore_unexpected: If True, ignore responses from unexpected
    sources.  The default is False.
    @type ignore_unexpected: bool
    @param one_rr_per_rrset: Put each RR into its own RRset
    @type one_rr_per_rrset: bool
    rNi��)�keyring�request_mac�one_rr_per_rrset)�to_wirer7�socket_factory�socket�
SOCK_DGRAMr�setblocking�bindr*rZsendtor)�recvfromr1Zfamilyr�message�	from_wirer9�macr2�is_responser�close)�qr3rr4r,r5r6r0r;�
ignore_errors�wirer/r(�
begin_timer"r.�
response_time�rrrr
�udp�sD




rNcCsJd}x@|dkrDt||�|j|�}|dkr.t�|t|�}||}qW|S)z�Read the specified number of bytes from sock.  Keep trying until we
    either get the desired amount, or we hit EOF.
    A Timeout exception will be raised if the operation is not completed
    by the expiration time.
    �r)r)Zrecv�EOFError�len)�sock�countr"r(�nrrr
�	_net_reads


rUcCs>d}t|�}x,||kr8t||�||j||d��7}qWdS)z�Write the specified data to the socket.
    A Timeout exception will be raised if the operation is not completed
    by the expiration time.
    rN)rQr*�send)rR�datar"Zcurrent�lrrr
�
_net_write/s


rYcCspy|j|�Wn\tjk
rjtj�dd�\}}t|d�rF|j}n|d}|tjtjtj	gkrf|�YnXdS)N�r!r)
Zconnectr>r�sys�exc_info�hasattrr!ZEINPROGRESSZEWOULDBLOCKZEALREADY)r(ZaddressZty�vZv_errrrr
�_connect;s
r_cCs|j�}t|||||�\}}	}t|tjd�}
d}z�t|�}|
jd�tj�}|dk	r^|
j|�t	|
|	�t
|�}
tjd|
�|}t
|
||�t|
d|�}tjd|�\}
t|
|
|�}Wd|dkr�d}ntj�|}|
j�Xtjj||j|j|d�}||_|j|��st�|S)aReturn the response obtained after sending a query via TCP.

    @param q: the query
    @type q: dns.message.Message object
    @param where: where to send the message
    @type where: string containing an IPv4 or IPv6 address
    @param timeout: The number of seconds to wait before the query times out.
    If None, the default, wait forever.
    @type timeout: float
    @param port: The port to which to send the message.  The default is 53.
    @type port: int
    @param af: the address family to use.  The default is None, which
    causes the address family to use to be inferred from the form of where.
    If the inference attempt fails, AF_INET is used.
    @type af: int
    @rtype: dns.message.Message object
    @param source: source address.  The default is the wildcard address.
    @type source: string
    @param source_port: The port from which to send the message.
    The default is 0.
    @type source_port: int
    @param one_rr_per_rrset: Put each RR into its own RRset
    @type one_rr_per_rrset: bool
    rNz!HrZ)r9r:r;)r<r7r=r>�SOCK_STREAMrr@rrAr_rQ�struct�packrYrU�unpackrGrrCrDr9rErFr)rHr3rr4r,r5r6r;rJr/r(rKr"rX�tcpmsg�ldatarLrMrrr
�tcpIs8



rfTc&cs�t|t�rtjj|�}t|t�r,tjj|�}tjj|||�}|tjjkrltj	j|dddd|
�}|j
j|�|dk	r�|j|||d�|j
�}t|	||||�\}	}}|r�|tjjkr�td��t|	tjd�}nt|	tjd�}|jd�|dk	r�|j|�t|
�}t||�t|�}|�r*t||�|j|�ntjd|�|}t|||�d	}d
}d	}d}|�rj|}tjj}nd}|}d}d
}�x6|�s�t|�} | dk�s�|dk	�r�| |k�r�|} |�r�t||�|j d�\}}!n&t!|d| �}"tj"d|"�\}t!||| �}|tjjk}#tjj#||j$|j%d
||d
||#d
�	}$|$j&}d	}d}%|dk�r�|$j'�sV|$j'dj|k�rbtj(j)d��|$j'd}|j*tjj+k�r�tj(j)d��d}%|j,�}|tjjk�r�|dj-|
k�r�d
}nd
}x�|$j'|%d�D]�}|�r�tj(j)d��|j*tjj+k�rl|j|k�rl|�r&|dj-|
k�r tj(j)d��d	}n|tjjk�r:|}||k�r~|tjj.k�sf|tjjk�r~|�r~d
}n|�r�tjj.}d	}�q�W|�r�|j$�r�|$j/�r�tj(j)d��|$V�q~W|j0�dS)a�Return a generator for the responses to a zone transfer.

    @param where: where to send the message
    @type where: string containing an IPv4 or IPv6 address
    @param zone: The name of the zone to transfer
    @type zone: dns.name.Name object or string
    @param rdtype: The type of zone transfer.  The default is
    dns.rdatatype.AXFR.
    @type rdtype: int or string
    @param rdclass: The class of the zone transfer.  The default is
    dns.rdataclass.IN.
    @type rdclass: int or string
    @param timeout: The number of seconds to wait for each response message.
    If None, the default, wait forever.
    @type timeout: float
    @param port: The port to which to send the message.  The default is 53.
    @type port: int
    @param keyring: The TSIG keyring to use
    @type keyring: dict
    @param keyname: The name of the TSIG key to use
    @type keyname: dns.name.Name object or string
    @param relativize: If True, all names in the zone will be relativized to
    the zone origin.  It is essential that the relativize setting matches
    the one specified to dns.zone.from_xfr().
    @type relativize: bool
    @param af: the address family to use.  The default is None, which
    causes the address family to use to be inferred from the form of where.
    If the inference attempt fails, AF_INET is used.
    @type af: int
    @param lifetime: The total number of seconds to spend doing the transfer.
    If None, the default, then there is no limit on the time the transfer may
    take.
    @type lifetime: float
    @rtype: generator of dns.message.Message objects.
    @param source: source address.  The default is the wildcard address.
    @type source: string
    @param source_port: The port from which to send the message.
    The default is 0.
    @type source_port: int
    @param serial: The SOA serial number to use as the base for an IXFR diff
    sequence (only meaningful if rdtype == dns.rdatatype.IXFR).
    @type serial: int
    @param use_udp: Use UDP (only meaningful for IXFR)
    @type use_udp: bool
    @param keyalgorithm: The TSIG algorithm to use; defaults to
    dns.tsig.default_algorithm
    @type keyalgorithm: string
    r�IN�SOAz. . %u 0 0 0 0N)�	algorithmzcannot do a UDP AXFRz!HFTi��rZ)r9r:�xfr�origin�tsig_ctxZmulti�firstr;z No answer or RRset not for qnamezfirst RRset is not an SOArzanswers after final SOAzIXFR base serial mismatchzmissing TSIG)1�
isinstancerr�nameZ	from_text�	rdatatyperCZ
make_queryZIXFR�rrsetZ	authority�appendZuse_tsigr<r7�
ValueErrorr=r>r?r`r@rArr_rQr*rVrarbrY�emptyr)rBrUrcrDr9rErlZanswerr�	FormError�rdtyperh�copy�serial�AXFRZhad_tsigrG)&r3ZzonervZrdclassrr4r9ZkeynameZ
relativizer,Zlifetimer5r6rxZuse_udpZkeyalgorithmrHrqrJr/r(r"rXrdr#Zdelete_modeZ
expecting_SOAZ	soa_rrsetrkZonamerlrmZmexpirationr.reZis_ixfrrMZanswer_indexrrr
rj�s�5














rj)r)Nr8NNrFFF)Nr8NNrF)5rZ
__future__rr!rr>rar[rZ
dns.exceptionrZdns.inetZdns.nameZdns.messageZdns.rdataclassZ
dns.rdatatypeZ_compatrr�version_info�OSErrorrrr=rZDNSExceptionrrurrrrr%r'r]rr)r*r-r1r7rNrUrYr_rfrpryZ
rdataclassrgZtsigZdefault_algorithmrjrrrr
�<module>sX

	
I
?

__pycache__/rdata.cpython-36.pyc000064400000034023150351404330012475 0ustar003

�b�W�:�@s�dZddlmZddlZddlZddlZddlZddlZddl	Zddl
ZddlZddlm
Z
mZmZdZefdd�ZdZefd	d
�Zed�Zdd
�Zdd�ZGdd�de�ZGdd�de�ZiZdZdd�Zddd�Zddd�ZdS)a�DNS rdata.

@var _rdata_modules: A dictionary mapping a (rdclass, rdtype) tuple to
the module which implements that type.
@type _rdata_modules: dict
@var _module_prefix: The prefix to use when forming modules names.  The
default is 'dns.rdtypes'.  Changing this value will break the library.
@type _module_prefix: string
@var _hex_chunk: At most this many octets that will be represented in each
chunk of hexstring that _hexify() produces before whitespace occurs.
@type _hex_chunk: int�)�BytesION�)�xrange�string_types�	text_type� cs4tj|��dj��fdd�tdt����D��j�S)aConvert a binary string into its hex encoding, broken up into chunks
    of I{chunksize} characters separated by a space.

    @param data: the binary string
    @type data: string
    @param chunksize: the chunk size.  Default is L{dns.rdata._hex_chunksize}
    @rtype: string
    � csg|]}�||���qS�r	)�.0�i)�	chunksize�liner	�/usr/lib/python3.6/rdata.py�
<listcomp>6sz_hexify.<locals>.<listcomp>r)�binasciiZhexlify�join�range�len�decode)�datarr	)rr
r�_hexify+s

rcs4tj|��dj��fdd�tdt����D��j�S)a$Convert a binary string into its base64 encoding, broken up into chunks
    of I{chunksize} characters separated by a space.

    @param data: the binary string
    @type data: string
    @param chunksize: the chunk size.  Default is
    L{dns.rdata._base64_chunksize}
    @rtype: string
    rcsg|]}�||���qSr	r	)r
r)rr
r	rrIsz_base64ify.<locals>.<listcomp>r)�base64Z	b64encoderrrr)rrr	)rr
r�
_base64ify=s
rs"\cCs~t|t�r|j�}t|t�s$t|�}d}xP|D]H}|tkrL|dt|�7}q.|dkrj|dkrj|t|�7}q.|d|7}q.W|S)z�Escape the characters in a quoted string which need it.

    @param qstring: the string
    @type qstring: string
    @returns: the escaped string
    @rtype: string
    ��\r�z\%03d)�
isinstancer�encode�	bytearray�	__escaped�chr)Zqstring�text�cr	r	r�	_escapifyOs	


r#cCsFx8tt|�ddd�D] }||dkr|d|d�SqW|dd�S)z�Determine the index of greatest byte that isn't all zeros, and
    return the bitmap that contains all the bytes less than that index.

    @param what: a string of octets representing a bitmap.
    @type what: string
    @rtype: string
    rr���r$)rr)Zwhatrr	r	r�_truncate_bitmaphs	r%c@s�eZdZdZddgZdd�Zdd�Zdd	�Zd.dd
�Zd/dd�Z	d0dd�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�Zd$d%�Zd&d'�Zed1d(d)��Zed2d*d+��Zd3d,d-�Zd
S)4�Rdataz(Base class for all DNS rdata types.
    �rdclass�rdtypecCs||_||_dS)z�Initialize an rdata.
        @param rdclass: The rdata class
        @type rdclass: int
        @param rdtype: The rdata type
        @type rdtype: int
        N)r'r()�selfr'r(r	r	r�__init__~szRdata.__init__cCstjjS)a_DNS SIG/RRSIG rdatas apply to a specific type; this type is
        returned by the covers() function.  If the rdata type is not
        SIG or RRSIG, dns.rdatatype.NONE is returned.  This is useful when
        creating rdatasets, allowing the rdataset to contain only RRSIGs
        of a particular type, e.g. RRSIG(NS).
        @rtype: int
        )�dns�	rdatatype�NONE)r)r	r	r�covers�s	zRdata.coverscCs|j�d>|jBS)z�Return a 32-bit type value, the least significant 16 bits of
        which are the ordinary DNS type, and the upper 16 bits of which are
        the "covered" type, if any.
        @rtype: int
        �)r.r()r)r	r	r�extended_rdatatype�szRdata.extended_rdatatypeNTcKst�dS)z@Convert an rdata to text format.
        @rtype: string
        N)�NotImplementedError)r)�origin�
relativize�kwr	r	r�to_text�sz
Rdata.to_textcCst�dS)z@Convert an rdata to wire format.
        @rtype: string
        N)r1)r)�file�compressr2r	r	r�to_wire�sz
Rdata.to_wirecCst�}|j|d|�|j�S)zlConvert rdata to a format suitable for digesting in hashes.  This
        is also the DNSSEC canonical form.N)rr8�getvalue)r)r2�fr	r	r�
to_digestable�szRdata.to_digestablecCstjj|j|j|j��dS)z�Check that the current contents of the rdata's fields are
        valid.  If you change an rdata by assigning to its fields,
        it is a good idea to call validate() when you are done making
        changes.
        N)r+�rdata�	from_textr'r(r5)r)r	r	r�validate�szRdata.validatecCsf|j�}|tjjkrd}ndtjj|�d}dtjj|j�dtjj|j�|dt|�dS)Nr�(�)z<DNS � z rdata: �>)	r.r+r,r-r5�
rdataclassr'r(�str)r)r.Zctextr	r	r�__repr__�s
zRdata.__repr__cCs|j�S)N)r5)r)r	r	r�__str__�sz
Rdata.__str__cCs8|jtjj�}|jtjj�}||kr(dS||kr4dSdS)z�Compare an rdata with another rdata of the same rdtype and
        rdclass.  Return < 0 if self < other in the DNSSEC ordering,
        0 if self == other, and > 0 if self > other.
        rrr$)r;r+�name�root)r)�otherZourZtheirr	r	r�_cmp�sz
Rdata._cmpcCs8t|t�sdS|j|jks&|j|jkr*dS|j|�dkS)NFr)rr&r'r(rJ)r)rIr	r	r�__eq__�s

zRdata.__eq__cCs8t|t�sdS|j|jks&|j|jkr*dS|j|�dkS)NTr)rr&r'r(rJ)r)rIr	r	r�__ne__�s

zRdata.__ne__cCs6t|t�s$|j|jks$|j|jkr(tS|j|�dkS)Nr)rr&r'r(�NotImplementedrJ)r)rIr	r	r�__lt__�szRdata.__lt__cCs6t|t�s$|j|jks$|j|jkr(tS|j|�dkS)Nr)rr&r'r(rMrJ)r)rIr	r	r�__le__�szRdata.__le__cCs6t|t�s$|j|jks$|j|jkr(tS|j|�dkS)Nr)rr&r'r(rMrJ)r)rIr	r	r�__ge__�szRdata.__ge__cCs6t|t�s$|j|jks$|j|jkr(tS|j|�dkS)Nr)rr&r'r(rMrJ)r)rIr	r	r�__gt__�szRdata.__gt__cCst|jtjj��S)N)�hashr;r+rGrH)r)r	r	r�__hash__�szRdata.__hash__cCst�dS)a�Build an rdata object from text format.

        @param rdclass: The rdata class
        @type rdclass: int
        @param rdtype: The rdata type
        @type rdtype: int
        @param tok: The tokenizer
        @type tok: dns.tokenizer.Tokenizer
        @param origin: The origin to use for relative names
        @type origin: dns.name.Name
        @param relativize: should names be relativized?
        @type relativize: bool
        @rtype: dns.rdata.Rdata instance
        N)r1)�clsr'r(�tokr2r3r	r	rr=�szRdata.from_textcCst�dS)a<Build an rdata object from wire format

        @param rdclass: The rdata class
        @type rdclass: int
        @param rdtype: The rdata type
        @type rdtype: int
        @param wire: The wire-format message
        @type wire: string
        @param current: The offset in wire of the beginning of the rdata.
        @type current: int
        @param rdlen: The length of the wire-format rdata
        @type rdlen: int
        @param origin: The origin to use for relative names
        @type origin: dns.name.Name
        @rtype: dns.rdata.Rdata instance
        N)r1)rTr'r(�wire�current�rdlenr2r	r	r�	from_wireszRdata.from_wirecCsdS)zWConvert any domain names in the rdata to the specified
        relativization.
        Nr	)r)r2r3r	r	r�choose_relativity&szRdata.choose_relativity)NT)NN)N)NT)N)NT)�__name__�
__module__�__qualname__�__doc__�	__slots__r*r.r0r5r8r;r>rErFrJrKrLrNrOrPrQrS�classmethodr=rYrZr	r	r	rr&ws0	



r&csVeZdZdZdgZ�fdd�Zddd�Zedd	d
��Zddd�Z	edd
d��Z
�ZS)�GenericRdataz�Generate Rdata Class

    This class is used for rdata types for which we have no better
    implementation.  It implements the DNS "unknown RRs" scheme.
    rcstt|�j||�||_dS)N)�superrar*r)r)r'r(r)�	__class__r	rr*8szGenericRdata.__init__NTcKsdt|j�t|j�S)Nz\# %d )rrr)r)r2r3r4r	r	rr5<szGenericRdata.to_textcCs�|j�}|j�s|jdkr(tjjd��|j�}g}x&|j�}|j�rHP|j|jj	��q6Wdj
|�}	tj|	�}
t
|
�|kr�tjjd��||||
�S)Nz\#z$generic rdata does not start with \#�z'generic rdata hex data has wrong length)�get�
is_identifier�valuer+Z	exception�SyntaxErrorZget_intZ
is_eol_or_eof�appendrrrZ	unhexlifyr)rTr'r(rUr2r3�tokenZlengthZchunks�hexrr	r	rr=?s"

zGenericRdata.from_textcCs|j|j�dS)N)�writer)r)r6r7r2r	r	rr8SszGenericRdata.to_wirecCs|||||||��S)Nr	)rTr'r(rVrWrXr2r	r	rrYVszGenericRdata.from_wire)NT)NT)NN)N)r[r\r]r^r_r*r5r`r=r8rY�
__classcell__r	r	)rcrra.s

razdns.rdtypescCs�dd�}tj||f�}tjj|�}tjj|�}|jdd�}|s�tjtjj|f�}|s�y$|djt	||g��}|t||f<WnVt
k
r�y(|djt	d|g��}|ttjj|f<Wnt
k
r�d}YnXYnX|r�t||�}nt}|S)NcSs6t|�}|jd�}x|dd�D]}t||�}q W|S)N�.r)�
__import__�split�getattr)rG�modZ
components�compr	r	r�
import_module`s

z&get_rdata_class.<locals>.import_module�-�_rn�ANY)
�_rdata_modulesrer+rCr5r,�replacerwr�_module_prefix�ImportErrorrqra)r'r(rtrrZrdclass_textZrdtype_textrTr	r	r�get_rdata_class^s.r|TcCs�t|t�rtjj|�}t||�}|tkrx|j�}|j|�|j	�rx|j
dkrxtj|||||�}t|||j
dt|j
�|�S|j|||||�S)adBuild an rdata object from text format.

    This function attempts to dynamically load a class which
    implements the specified rdata class and type.  If there is no
    class-and-type-specific implementation, the GenericRdata class
    is used.

    Once a class is chosen, its from_text() class method is called
    with the parameters to this function.

    If I{tok} is a string, then a tokenizer is created and the string
    is used as its input.

    @param rdclass: The rdata class
    @type rdclass: int
    @param rdtype: The rdata type
    @type rdtype: int
    @param tok: The tokenizer or input text
    @type tok: dns.tokenizer.Tokenizer or string
    @param origin: The origin to use for relative names
    @type origin: dns.name.Name
    @param relativize: Should names be relativized?
    @type relativize: bool
    @rtype: dns.rdata.Rdata instancez\#r)rrr+Z	tokenizer�	Tokenizerr|rareZungetrfrgr=rYrr)r'r(rUr2r3rTrjr<r	r	rr=�s



r=cCs*tjj|�}t||�}|j||||||�S)a>Build an rdata object from wire format

    This function attempts to dynamically load a class which
    implements the specified rdata class and type.  If there is no
    class-and-type-specific implementation, the GenericRdata class
    is used.

    Once a class is chosen, its from_wire() class method is called
    with the parameters to this function.

    @param rdclass: The rdata class
    @type rdclass: int
    @param rdtype: The rdata type
    @type rdtype: int
    @param wire: The wire-format message
    @type wire: string
    @param current: The offset in wire of the beginning of the rdata.
    @type current: int
    @param rdlen: The length of the wire-format rdata
    @type rdlen: int
    @param origin: The origin to use for relative names
    @type origin: dns.name.Name
    @rtype: dns.rdata.Rdata instance)r+ZwiredataZ
maybe_wrapr|rY)r'r(rVrWrXr2rTr	r	rrY�s
rY)NT)N) r^�iorrrZ
dns.exceptionr+Zdns.nameZdns.rdataclassZ
dns.rdatatypeZ
dns.tokenizerZdns.wiredataZ_compatrrrZ_hex_chunksizerZ_base64_chunksizerrrr#r%�objectr&rarxrzr|r=rYr	r	r	r�<module>s28,"
/__pycache__/zone.cpython-36.pyc000064400000072671150351404330012370 0ustar003

ӕ�WZ��@sNdZddlmZddlZddlZddlZddlmZddlZ	ddl
Z	ddlZ	ddlZ	ddl
Z	ddlZ	ddlZ	ddlZ	ddlZ	ddlZ	ddlmZmZejdkZGdd	�d	e	jj�ZGd
d�de�ZGdd
�d
e�ZGdd�de�ZGdd�de�ZGdd�de�Z de	j!j"dedddfdd�Z#de	j!j"dedddfdd�Z$eddfdd�Z%dS)z
DNS Zones.�)�
generatorsN)�BytesIO�)�string_types�	text_type�c@seZdZdZdS)�BadZonezThe DNS zone is malformed.N)�__name__�
__module__�__qualname__�__doc__�r
r
�/usr/lib/python3.6/zone.pyr)src@seZdZdZdS)�NoSOAz)The DNS zone has no SOA RR at its origin.N)r	r
rrr
r
r
rr.src@seZdZdZdS)�NoNSz+The DNS zone has no NS RRset at its origin.N)r	r
rrr
r
r
rr3src@seZdZdZdS)�
UnknownOriginz!The DNS zone's origin is unknown.N)r	r
rrr
r
r
rr8src@sjeZdZdZejjZddddgZej	j
dfdd�Zd	d
�Zdd�Z
d
d�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd �ZeZd!d"�Zd#d$�ZdCd&d'�ZdDd(d)�Zd*d+�Zejjd%fd,d-�Z ejjd%fd.d/�Z!ejjfd0d1�Z"d2d3�Z#ejjfd4d5�Z$ejjfd6d7�Z%ejj&ejjfd8d9�Z'ejj&ejjfd:d;�Z(dEd=d>�Z)dFd?d@�Z*dAdB�Z+d<S)G�ZoneaZA DNS zone.

    A Zone is a mapping from names to nodes.  The zone object may be
    treated like a Python dictionary, e.g. zone[name] will retrieve
    the node associated with that name.  The I{name} may be a
    dns.name.Name object, or it may be a string.  In the either case,
    if the name is relative it is treated as relative to the origin of
    the zone.

    @ivar rdclass: The zone's rdata class; the default is class IN.
    @type rdclass: int
    @ivar origin: The origin of the zone.
    @type origin: dns.name.Name object
    @ivar nodes: A dictionary mapping the names of nodes in the zone to the
    nodes themselves.
    @type nodes: dict
    @ivar relativize: should names in the zone be relativized?
    @type relativize: bool
    @cvar node_factory: the factory used to create a new node
    @type node_factory: class or callable
    �rdclass�origin�nodes�
relativizeTcCsb|dk	rFt|t�r tjj|�}nt|tjj�s6td��|j�sFtd��||_||_	i|_
||_dS)z�Initialize a zone object.

        @param origin: The origin of the zone.
        @type origin: dns.name.Name object
        @param rdclass: The zone's rdata class; the default is class IN.
        @type rdclass: intNz2origin parameter must be convertible to a DNS namez)origin parameter must be an absolute name)�
isinstancer�dns�name�	from_text�Name�
ValueError�is_absoluterrrr)�selfrrrr
r
r�__init__Ys
z
Zone.__init__cCs:t|t�sdS|j|jks2|j|jks2|j|jkr6dSdS)ziTwo zones are equal if they have the same origin, class, and
        nodes.
        @rtype: bool
        FT)rrrrr)r�otherr
r
r�__eq__ns
zZone.__eq__cCs|j|�S)z6Are two zones not equal?
        @rtype: bool
        )r!)rr r
r
r�__ne__|szZone.__ne__cCsbt|t�rtjj|d�}nt|tjj�s0td��|j�r^|j|j	�sLtd��|j
r^|j
|j	�}|S)Nz0name parameter must be convertible to a DNS namez5name parameter must be a subdomain of the zone origin)rrrrrr�KeyErrorr�is_subdomainrr)rrr
r
r�_validate_name�s
zZone._validate_namecCs|j|�}|j|S)N)r%r)r�keyr
r
r�__getitem__�s
zZone.__getitem__cCs|j|�}||j|<dS)N)r%r)rr&�valuer
r
r�__setitem__�s
zZone.__setitem__cCs|j|�}|j|=dS)N)r%r)rr&r
r
r�__delitem__�s
zZone.__delitem__cCs
|jj�S)N)r�__iter__)rr
r
rr+�sz
Zone.__iter__cCstr|jj�S|jj�SdS)N)�_py3r�keys�iterkeys)rr
r
rr.�s
z
Zone.iterkeyscCs
|jj�S)N)rr-)rr
r
rr-�sz	Zone.keyscCstr|jj�S|jj�SdS)N)r,r�values�
itervalues)rr
r
rr0�s
zZone.itervaluescCs
|jj�S)N)rr/)rr
r
rr/�szZone.valuescCs
|jj�S)N)r�items)rr
r
rr1�sz
Zone.itemscCs|j|�}|jj|�S)N)r%r�get)rr&r
r
rr2�s
zZone.getcCs
||jkS)N)r)rr r
r
r�__contains__�szZone.__contains__FcCs<|j|�}|jj|�}|dkr8|s&t�|j�}||j|<|S)arFind a node in the zone, possibly creating it.

        @param name: the name of the node to find
        @type name: dns.name.Name object or string
        @param create: should the node be created if it doesn't exist?
        @type create: bool
        @raises KeyError: the name is not known and create was not specified.
        @rtype: dns.node.Node object
        N)r%rr2r#�node_factory)rr�create�noder
r
r�	find_node�s

zZone.find_nodecCs.y|j||�}Wntk
r(d}YnX|S)a�Get a node in the zone, possibly creating it.

        This method is like L{find_node}, except it returns None instead
        of raising an exception if the node does not exist and creation
        has not been requested.

        @param name: the name of the node to find
        @type name: dns.name.Name object or string
        @param create: should the node be created if it doesn't exist?
        @type create: bool
        @rtype: dns.node.Node object or None
        N)r7r#)rrr5r6r
r
r�get_node�s

z
Zone.get_nodecCs |j|�}||jkr|j|=dS)zhDelete the specified node if it exists.

        It is not an error if the node does not exist.
        N)r%r)rrr
r
r�delete_node�s

zZone.delete_nodecCsT|j|�}t|t�r tjj|�}t|t�r6tjj|�}|j||�}|j|j|||�S)a�Look for rdata with the specified name and type in the zone,
        and return an rdataset encapsulating it.

        The I{name}, I{rdtype}, and I{covers} parameters may be
        strings, in which case they will be converted to their proper
        type.

        The rdataset returned is not a copy; changes to it will change
        the zone.

        KeyError is raised if the name or type are not found.
        Use L{get_rdataset} if you want to have None returned instead.

        @param name: the owner name to look for
        @type name: DNS.name.Name object or string
        @param rdtype: the rdata type desired
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        @param create: should the node and rdataset be created if they do not
        exist?
        @type create: bool
        @raises KeyError: the node or rdata could not be found
        @rtype: dns.rrset.RRset object
        )	r%rrr�	rdatatyperr7�
find_rdatasetr)rr�rdtype�coversr5r6r
r
rr;�s


zZone.find_rdatasetcCs2y|j||||�}Wntk
r,d}YnX|S)a�Look for rdata with the specified name and type in the zone,
        and return an rdataset encapsulating it.

        The I{name}, I{rdtype}, and I{covers} parameters may be
        strings, in which case they will be converted to their proper
        type.

        The rdataset returned is not a copy; changes to it will change
        the zone.

        None is returned if the name or type are not found.
        Use L{find_rdataset} if you want to have KeyError raised instead.

        @param name: the owner name to look for
        @type name: DNS.name.Name object or string
        @param rdtype: the rdata type desired
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        @param create: should the node and rdataset be created if they do not
        exist?
        @type create: bool
        @rtype: dns.rrset.RRset object
        N)r;r#)rrr<r=r5�rdatasetr
r
r�get_rdatasets

zZone.get_rdatasetcCsr|j|�}t|t�r tjj|�}t|t�r6tjj|�}|j|�}|dk	rn|j|j||�t	|�dkrn|j
|�dS)a�Delete the rdataset matching I{rdtype} and I{covers}, if it
        exists at the node specified by I{name}.

        The I{name}, I{rdtype}, and I{covers} parameters may be
        strings, in which case they will be converted to their proper
        type.

        It is not an error if the node does not exist, or if there is no
        matching rdataset at the node.

        If the node has no rdatasets after the deletion, it will itself
        be deleted.

        @param name: the owner name to look for
        @type name: DNS.name.Name object or string
        @param rdtype: the rdata type desired
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        Nr)r%rrrr:rr8�delete_rdatasetr�lenr9)rrr<r=r6r
r
rr@4s



zZone.delete_rdatasetcCs.|j|jkrtd��|j|d�}|j|�dS)a:Replace an rdataset at name.

        It is not an error if there is no rdataset matching I{replacement}.

        Ownership of the I{replacement} object is transferred to the zone;
        in other words, this method does not store a copy of I{replacement}
        at the node, it stores I{replacement} itself.

        If the I{name} node does not exist, it is created.

        @param name: the owner name
        @type name: DNS.name.Name object or string
        @param replacement: the replacement rdataset
        @type replacement: dns.rdataset.Rdataset
        z#replacement.rdclass != zone.rdclassTN)rrr7�replace_rdataset)rrZreplacementr6r
r
rrBUszZone.replace_rdatasetcCsn|j|�}t|t�r tjj|�}t|t�r6tjj|�}|j|j|j||�}tj	j
||j||�}|j|�|S)a�Look for rdata with the specified name and type in the zone,
        and return an RRset encapsulating it.

        The I{name}, I{rdtype}, and I{covers} parameters may be
        strings, in which case they will be converted to their proper
        type.

        This method is less efficient than the similar
        L{find_rdataset} because it creates an RRset instead of
        returning the matching rdataset.  It may be more convenient
        for some uses since it returns an object which binds the owner
        name to the rdata.

        This method may not be used to create new nodes or rdatasets;
        use L{find_rdataset} instead.

        KeyError is raised if the name or type are not found.
        Use L{get_rrset} if you want to have None returned instead.

        @param name: the owner name to look for
        @type name: DNS.name.Name object or string
        @param rdtype: the rdata type desired
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        @raises KeyError: the node or rdata could not be found
        @rtype: dns.rrset.RRset object
        )r%rrrr:rrr;r�rrsetZRRset�update)rrr<r=r>rCr
r
r�
find_rrsetks



zZone.find_rrsetcCs0y|j|||�}Wntk
r*d}YnX|S)aJLook for rdata with the specified name and type in the zone,
        and return an RRset encapsulating it.

        The I{name}, I{rdtype}, and I{covers} parameters may be
        strings, in which case they will be converted to their proper
        type.

        This method is less efficient than the similar L{get_rdataset}
        because it creates an RRset instead of returning the matching
        rdataset.  It may be more convenient for some uses since it
        returns an object which binds the owner name to the rdata.

        This method may not be used to create new nodes or rdatasets;
        use L{find_rdataset} instead.

        None is returned if the name or type are not found.
        Use L{find_rrset} if you want to have KeyError raised instead.

        @param name: the owner name to look for
        @type name: DNS.name.Name object or string
        @param rdtype: the rdata type desired
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        @rtype: dns.rrset.RRset object
        N)rEr#)rrr<r=rCr
r
r�	get_rrset�s

zZone.get_rrsetccs~t|t�rtjj|�}t|t�r,tjj|�}xL|j�D]@\}}x6|D].}|tjjksh|j|krD|j|krD||fVqDWq6WdS)a�Return a generator which yields (name, rdataset) tuples for
        all rdatasets in the zone which have the specified I{rdtype}
        and I{covers}.  If I{rdtype} is dns.rdatatype.ANY, the default,
        then all rdatasets will be matched.

        @param rdtype: int or string
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        N)	rrrr:r�	iteritems�ANYr<r=)rr<r=rr6�rdsr
r
r�iterate_rdatasets�s


zZone.iterate_rdatasetsccs�t|t�rtjj|�}t|t�r,tjj|�}x^|j�D]R\}}xH|D]@}|tjjksh|j|krD|j|krDx|D]}||j	|fVqnWqDWq6WdS)a�Return a generator which yields (name, ttl, rdata) tuples for
        all rdatas in the zone which have the specified I{rdtype}
        and I{covers}.  If I{rdtype} is dns.rdatatype.ANY, the default,
        then all rdatas will be matched.

        @param rdtype: int or string
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        N)
rrrr:rrGrHr<r=�ttl)rr<r=rr6rI�rdatar
r
r�iterate_rdatas�s



zZone.iterate_rdatasNcCs8t|t�rt|d�}d}nd}t|dd�}|dkr6d}|dkrPtjj|�}d}n"t|t�rf|j|�}n|}|j�}z�|r�t|j	��}|j
�n|j�}x�|D]�}	||	j|	|j
|d�}
t|
t�r�|
j|�}n|
}|
j�}
y|j|�|j|�Wq�tk
�r|j|
�|j|�Yq�Xq�WWd|�r2|j�XdS)	aWrite a zone to a file.

        @param f: file or string.  If I{f} is a string, it is treated
        as the name of a file to open.
        @param sorted: if True, the file will be written with the
        names sorted in DNSSEC order from least to greatest.  Otherwise
        the names will be written in whatever order they happen to have
        in the zone's dictionary.
        @param relativize: if True, domain names in the output will be
        relativized to the zone's origin (if possible).
        @type relativize: bool
        @param nl: The end of line string.  If not specified, the
        output will use the platform's native end-of-line marker (i.e.
        LF on POSIX, CRLF on Windows, CR on Macintosh).
        @type nl: string or None
        �wbTF�encodingNzutf-8�
)rr)rr�open�getattr�os�linesep�encode�decode�listr-�sortr.�to_textrr�write�	TypeError�close)r�f�sortedr�nl�
want_closeZfile_encZnl_b�names�n�lZl_br
r
r�to_file�sD







zZone.to_filecCs*t�}|j||||�|j�}|j�|S)a�Return a zone's text as though it were written to a file.

        @param sorted: if True, the file will be written with the
        names sorted in DNSSEC order from least to greatest.  Otherwise
        the names will be written in whatever order they happen to have
        in the zone's dictionary.
        @param relativize: if True, domain names in the output will be
        relativized to the zone's origin (if possible).
        @type relativize: bool
        @param nl: The end of line string.  If not specified, the
        output will use the platform's native end-of-line marker (i.e.
        LF on POSIX, CRLF on Windows, CR on Macintosh).
        @type nl: string or None
        )rrd�getvaluer\)rr^rr_Ztemp_bufferZreturn_valuer
r
rrY$s
zZone.to_textcCsJ|jrtjj}n|j}|j|tjj�dkr.t�|j|tjj	�dkrFt
�dS)z�Do some simple checking of the zone's origin.

        @raises dns.zone.NoSOA: there is no SOA RR
        @raises dns.zone.NoNS: there is no NS RRset
        @raises KeyError: there is no origin node
        N)rrr�emptyrr?r:ZSOArZNSr)rrr
r
r�check_origin9s
zZone.check_origin)F)F)TTN)TTN),r	r
rrrr6ZNoder4�	__slots__�
rdataclass�INrr!r"r%r'r)r*r+r.r-r0r/r1rGr2r3r7r8r9r:ZNONEr;r?r@rBrErFrHrJrMrdrYrgr
r
r
rr=sJ



# !("
@
rc@sHeZdZdZeddfdd�Zdd�Zdd	�Zd
d�Zdd
�Z	dd�Z
dS)�
_MasterReadera�Read a DNS master file

    @ivar tok: The tokenizer
    @type tok: dns.tokenizer.Tokenizer object
    @ivar ttl: The default TTL
    @type ttl: int
    @ivar last_name: The last name read
    @type last_name: dns.name.Name object
    @ivar current_origin: The current origin
    @type current_origin: dns.name.Name object
    @ivar relativize: should names in the zone be relativized?
    @type relativize: bool
    @ivar zone: the zone
    @type zone: dns.zone.Zone object
    @ivar saved_state: saved reader state (used when processing $INCLUDE)
    @type saved_state: list of (tokenizer, current_origin, last_name, file)
    tuples.
    @ivar current_file: the file object of the $INCLUDed file being parsed
    (None if no $INCLUDE is active).
    @ivar allow_include: is $INCLUDE allowed?
    @type allow_include: bool
    @ivar check_origin: should sanity checks of the origin node be done?
    The default is True.
    @type check_origin: bool
    FTcCsbt|t�rtjj|�}||_||_||_d|_|j|_	||||d�|_
g|_d|_||_
||_dS)Nr)r)rrrrr�tok�current_originrrK�	last_name�zone�saved_state�current_file�
allow_includerg)rrlrrr�zone_factoryrrrgr
r
rrfs
z_MasterReader.__init__cCsx|jj�}|j�rPqWdS)N)rlr2�
is_eol_or_eof)r�tokenr
r
r�	_eat_lineus
z_MasterReader._eat_linec"Cs�|jdkrt�|jjdd�}|j�s:tjj|j|j�|_	n"|jj�}|j
�rPdS|jj|�|j	}|j|j
j�s||j�dS|jr�|j|j
j�}|jj�}|j�s�tjj�y,tjj|j�}|jj�}|j�s�tjj�Wntjjk
r�|j}YnXy.tjj|j�}|jj�}|j��s"tjj�Wn>tjjk
�rFtjj�Yntk
�rb|j
j}YnX||j
jk�r~tjjd��ytjj|j�}Wntjjd|j��YnX|j
jj|�}|dk�r�|j
j�}||j
j|<ytjj|||j|jd�}Wnltjjk
�r,tj�dd�\}}	|	�Yn<tj�dd�\}}	tjjdt|�t|	�f��YnX|j |j
j|j�|j!�}
|j"|||
d�}|j#||�dS)	z(Process one line from a DNS master file.NT)Zwant_leadingzRR class is not zone's classzunknown rdatatype '%s'F�zcaught exception %s: %s)$rmrrlr2Z
is_whitespacerrrr(rnrt�ungetr$rorrvr�
is_identifier�	exception�SyntaxErrorrK�BadTTLri�	Exceptionrr:rr4rL�sys�exc_info�str�choose_relativityr=r;�add)rrurrKrr<rb�rd�ty�var=rIr
r
r�_rr_line{sx







z_MasterReader._rr_linec
Cs�tjd�}tjd�}tjd�}|j|�}|rJ|j�\}}}}	}
|dkrJd}|j|�}|rz|j�\}}}|dkrrd}d}	d}
|j|�}|r�|j�\}}}}	|dkr�d}|j�d}	d}
|p�|p�|s�d}d}d}d}	d}
|
dkr�t��||||	|
fS)	Nz"^.*\$({(\+|-?)(\d+),(\d+),(.)}).*$z^.*\$({(\+|-?)(\d+)}).*$z^.*\$({(\+|-?)(\d+),(\d+)}).*$��+r�drw)�re�compile�match�groups�NotImplementedError)
rZsideZis_generate1Zis_generate2Zis_generate3Zg1�modZsign�offset�width�baseZg2Zg3r
r
r�
_parse_modify�s>





z_MasterReader._parse_modifyc!7Cs|jdkrt�|jj�}y2tjj|j�\}}}|jj�}|j�sHtj	j
�Wntj	j
�YnXy$|j}|jj�}|j�s�tj	j
�Wntj	j
�YnXy,tjj|j�}|jj�}|j�s�tj	j
�Wntjjk
r�|j}YnXy.tj
j|j�}|jj�}|j��stj	j
�Wn>tj	j
k
�r6tj	j
�Yntk
�rR|jj}YnX||jjk�rntj	j
d��y.tjj|j�}|jj�}|j��s�tj	j
�Wn(tk
�r�tj	j
d|j��YnXy
|j}	Wntj	j
�YnX|j|�\}
}}}
}|j|	�\}}}}}�x�t||d|�D�]�}|dk�r@|t|�}n|dk�rV|t|�}|dk�rn|t|�}n|dk�r�|t|�}t|�jt|
��}t|�jt|��}|jd|
|�}|	jd||�}tjj||j�|_|j}|j|jj��s�|j�dS|j�r|j|jj�}|jjj|�}|dk�r@|jj�}||jj|<ytj j||||jd�}Wnltj	j
k
�r�t!j"�dd	�\}}|�Yn<t!j"�dd	�\}}tj	j
d
t|�t|�f��YnX|j#|jj|j�|j$�}|j%|||d�} | j&||��q"WdS)zRProcess one line containing the GENERATE statement from a DNS
        master file.NzRR class is not zone's classzunknown rdatatype '%s'rr��-z$%sFrwzcaught exception %s: %sT)'rmrrlr2rZgrangerr(ryrzr{rKr|rir}rorr:r��range�intr��zfill�replacerrnr$rrvrrr4rLr~rr�r=r;r�)!rru�start�stop�stepZlhsrKrr<ZrhsZlmodZlsignZloffsetZlwidthZlbaseZrmodZrsignZroffsetZrwidthZrbase�iZlindex�rindexZlzfindexZrzfindexrrLrbr�r�r�r=rIr
r
r�_generate_line�s�















z_MasterReader._generate_linecCs��y�x|jjdd�}|j�rh|jdk	r2|jj�t|j�dkrb|jjd�\|_|_|_	|_|_
qP�n�|j�rvq�n�|j�r�|jj
�q�nx|jddk�r|jj�}|dkr�|jj�}|j�s�tjjd��tj
j|j�|_
|jj
�q|dk�r$|jj�|_|jj
�|jjdk�r|j|j_q|d	k�r�|j�r�|jj�}|j}|jj�}|j��rxtjj|j|j�}|jj
�n|j��s�tjjd
��n|j}|jj|j|j|j	|j|j
f�t|d�|_tjj|j|�|_||_q|dk�r�|j�qtjjd
|d��q|jj |�|j!�qWWnZtjjk
�rz}z8|jj"�\}}|dk�rTd}tjjd|||f��WYdd}~XnX|j#�r�|jj#�dS)z�Read a DNS master file and build a zone object.

        @raises dns.zone.NoSOA: No SOA RR was found at the zone origin
        @raises dns.zone.NoNS: No NS RRset was found at the zone origin
        TNrr�$z$TTLzbad $TTLz$ORIGINz$INCLUDEzbad origin in $INCLUDE�rz	$GENERATEzUnknown master file directive '�'zsyntax errorz	%s:%d: %s���)$rlr2Zis_eofrqr\rArp�poprmrnrKZis_eolZ
is_commentZget_eolr(�upperryrrzr{rZget_namerorrrrrt�appendrQ�	tokenizer�	Tokenizerr�rxr��whererg)rru�c�filenameZ
new_originZdetailZline_numberr
r
r�reades�

 















"z_MasterReader.readN)r	r
rrrrrvr�r�r�r�r
r
r
rrkJsL)urkTFc
	Cs>|dkrd}tjj||�}t|||||||d�}	|	j�|	jS)arBuild a zone object from a master file format string.

    @param text: the master file format input
    @type text: string.
    @param origin: The origin of the zone; if not specified, the first
    $ORIGIN statement in the master file will determine the origin of the
    zone.
    @type origin: dns.name.Name object or string
    @param rdclass: The zone's rdata class; the default is class IN.
    @type rdclass: int
    @param relativize: should names be relativized?  The default is True
    @type relativize: bool
    @param zone_factory: The zone factory to use
    @type zone_factory: function returning a Zone
    @param filename: The filename to emit when describing where an error
    occurred; the default is '<string>'.
    @type filename: string
    @param allow_include: is $INCLUDE allowed?
    @type allow_include: bool
    @param check_origin: should sanity checks of the origin node be done?
    The default is True.
    @type check_origin: bool
    @raises dns.zone.NoSOA: No SOA RR was found at the zone origin
    @raises dns.zone.NoNS: No NS RRset was found at the zone origin
    @rtype: dns.zone.Zone object
    Nz<string>)rrrg)rr�r�rkr�ro)
�textrrrrsr�rrrgrl�readerr
r
rr�s"rcCslt}d}	t||�r.|dkr|}t||	�}d}
n|dkr:d}d}
zt||||||||�}Wd|
rf|j�X|S)a�Read a master file and build a zone object.

    @param f: file or string.  If I{f} is a string, it is treated
    as the name of a file to open.
    @param origin: The origin of the zone; if not specified, the first
    $ORIGIN statement in the master file will determine the origin of the
    zone.
    @type origin: dns.name.Name object or string
    @param rdclass: The zone's rdata class; the default is class IN.
    @type rdclass: int
    @param relativize: should names be relativized?  The default is True
    @type relativize: bool
    @param zone_factory: The zone factory to use
    @type zone_factory: function returning a Zone
    @param filename: The filename to emit when describing where an error
    occurred; the default is '<file>', or the value of I{f} if I{f} is a
    string.
    @type filename: string
    @param allow_include: is $INCLUDE allowed?
    @type allow_include: bool
    @param check_origin: should sanity checks of the origin node be done?
    The default is True.
    @type check_origin: bool
    @raises dns.zone.NoSOA: No SOA RR was found at the zone origin
    @raises dns.zone.NoNS: No NS RRset was found at the zone origin
    @rtype: dns.zone.Zone object
    ZrUNTz<file>F)rrrQrr\)r]rrrrsr�rrrgZstr_typeZoptsr`�zr
r
r�	from_file�s 


r�cCs�d}x�|D]�}|dkrH|r"|j}n|jdj}|jdj}||||d�}x||jD]r}|jj|j�}	|	sz|j�}	|	|j|j<|	j|j|j|j	d�}
|
j
|j�x$|D]}|j|j|�|
j
|�q�WqPWq
W|r�|j�|S)a�Convert the output of a zone transfer generator into a zone object.

    @param xfr: The xfr generator
    @type xfr: generator of dns.message.Message objects
    @param relativize: should names be relativized?  The default is True.
    It is essential that the relativize setting matches the one specified
    to dns.query.xfr().
    @type relativize: bool
    @param check_origin: should sanity checks of the origin node be done?
    The default is True.
    @type check_origin: bool
    @raises dns.zone.NoSOA: No SOA RR was found at the zone origin
    @raises dns.zone.NoNS: No NS RRset was found at the zone origin
    @rtype: dns.zone.Zone object
    Nr)rT)rZanswerrrrr2r4r;r<r=Z
update_ttlrKr�r�rg)Zxfrrsrrgr�r�rrrCZznodeZzrdsr�r
r
r�from_xfrs,


r�)r)&rZ
__future__rr~r�rS�iorZ
dns.exceptionrZdns.nameZdns.nodeZdns.rdataclassZ
dns.rdatatypeZ	dns.rdataZ	dns.rrsetZ
dns.tokenizerZdns.ttlZ
dns.grangeZ_compatrr�version_infor,rzZDNSExceptionrrrr�objectrrkrirjrr�r�r
r
r
r�<module>sH
o*3__pycache__/rdataset.cpython-36.opt-1.pyc000064400000022447150351404330014157 0ustar003

�b�W$-�@s�dZddlZddlmZddlZddlZddlZddlZddl	Zddl
ZddlmZej
jZGdd�dejj�ZGdd	�d	ejj�ZGd
d�dej
j�Zdd
�Zdd�Zdd�Zdd�ZdS)zHDNS rdatasets (an rdataset is a set of rdatas of a given type and class)�N)�StringIO�)�string_typesc@seZdZdZdS)�DifferingCoversz~An attempt was made to add a DNS SIG/RRSIG whose covered type
    is not the same as that of the other rdatas in the rdataset.N)�__name__�
__module__�__qualname__�__doc__�r
r
�/usr/lib/python3.6/rdataset.pyr!src@seZdZdZdS)�IncompatibleTypesz?An attempt was made to add DNS RR data of an incompatible type.N)rrrr	r
r
r
rr'srcs�eZdZdZddddgZejjf�fdd�	Z�fdd	�Z	d
d�Z
d$�fd
d�	Z�fdd�Z�fdd�Z
�fdd�Zdd�Zdd�Z�fdd�Zdd�Zd%dd�Zd&d d!�Zd"d#�Z�ZS)'�Rdataseta�A DNS rdataset.

    @ivar rdclass: The class of the rdataset
    @type rdclass: int
    @ivar rdtype: The type of the rdataset
    @type rdtype: int
    @ivar covers: The covered type.  Usually this value is
    dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or
    dns.rdatatype.RRSIG, then the covers value will be the rdata
    type the SIG/RRSIG covers.  The library treats the SIG and RRSIG
    types as if they were a family of
    types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA).  This makes RRSIGs much
    easier to work with than if RRSIGs covering different rdata
    types were aggregated into a single RRSIG rdataset.
    @type covers: int
    @ivar ttl: The DNS TTL (Time To Live) value
    @type ttl: int
    �rdclass�rdtype�covers�ttlcs*tt|�j�||_||_||_d|_dS)z�Create a new rdataset of the specified class and type.

        @see: the description of the class instance variables for the
        meaning of I{rdclass} and I{rdtype}rN)�superr
�__init__rrrr)�selfrrr)�	__class__r
rrCs
zRdataset.__init__cs2tt|�j�}|j|_|j|_|j|_|j|_|S)N)rr
�_clonerrrr)r�obj)rr
rrOszRdataset._clonecCs(t|�dkr||_n||jkr$||_dS)z�Set the TTL of the rdataset to be the lesser of the set's current
        TTL or the specified TTL.  If the set contains no rdatas, set the TTL
        to the specified TTL.
        @param ttl: The TTL
        @type ttl: intrN)�lenr)rrr
r
r�
update_ttlWs
zRdataset.update_ttlNcs�|j|jks|j|jkrt�|dk	r.|j|�|jtjjksJ|jtjjkr�|j�}t	|�dkrt|jtjj
krt||_n|j|kr�t�tjj|j�r�t	|�dkr�|j
�tt|�j|�dS)a%Add the specified rdata to the rdataset.

        If the optional I{ttl} parameter is supplied, then
        self.update_ttl(ttl) will be called prior to adding the rdata.

        @param rd: The rdata
        @type rd: dns.rdata.Rdata object
        @param ttl: The TTL
        @type ttl: intNr)rrrr�dns�	rdatatypeZRRSIGZSIGrr�NONErZis_singleton�clearrr
�add)r�rdrr)rr
rrcs

zRdataset.addcs |j|j�tt|�j|�dS)N)rrrr
�union_update)r�other)rr
rr �szRdataset.union_updatecs |j|j�tt|�j|�dS)N)rrrr
�intersection_update)rr!)rr
rr"�szRdataset.intersection_updatecs |j|j�tt|�j|�dS)z�Add all rdatas in other to self.

        @param other: The rdataset from which to update
        @type other: dns.rdataset.Rdataset objectN)rrrr
�update)rr!)rr
rr#�szRdataset.updatecCsR|jdkrd}ndtjj|j�d}dtjj|j�dtjj|j�|dS)Nr��(�)z<DNS � z
 rdataset>)rrr�to_text�
rdataclassrr)rZctextr
r
r�__repr__�s
zRdataset.__repr__cCs|j�S)N)r()rr
r
r�__str__�szRdataset.__str__csFt|t�sdS|j|jks2|j|jks2|j|jkr6dStt|�j|�S)zTwo rdatasets are equal if they have the same class, type, and
        covers, and contain the same rdata.
        @rtype: boolF)�
isinstancer
rrrr�__eq__)rr!)rr
rr-�s
zRdataset.__eq__cCs|j|�S)N)r-)rr!r
r
r�__ne__�szRdataset.__ne__Tc
Ks�|dk	r"|j||�}t|�}d}nd}d}t�}|dk	r>|}	n|j}	t|�dkrz|jd||tjj|	�tj	j|j
�f�nNxL|D]D}
|jd|||jtjj|	�tj	j|j
�|
jf||d�|��f�q�W|j�dd	�S)
a�Convert the rdataset into DNS master file format.

        @see: L{dns.name.Name.choose_relativity} for more information
        on how I{origin} and I{relativize} determine the way names
        are emitted.

        Any additional keyword arguments are passed on to the rdata
        to_text() method.

        @param name: If name is not None, emit a RRs with I{name} as
        the owner name.
        @type name: dns.name.Name object
        @param origin: The origin for relative names, or None.
        @type origin: dns.name.Name object
        @param relativize: True if names should names be relativized
        @type relativize: boolNr'r$rz
%s%s%s %s
z%s%s%d %s %s %s
)�origin�
relativizer���)
Zchoose_relativity�strrrr�writerr)r(rrr�getvalue)r�namer/r0�override_rdclass�kwZntextZpad�srrr
r
rr(�s*


zRdataset.to_textc
Cs|dk	r|}d}n|j}|jdd�t|�dkr`|j|||�tjd|j|dd�}|j|�dS|rxt|�}	t	j
|	�n|}	x�|	D]�}
|j|||�tjd|j||jd�}|j|�|j�}|
j|||�|j�}|j|d�tjd||�}|j|�|jdd�q�Wt|�SdS)a,Convert the rdataset to wire format.

        @param name: The owner name of the RRset that will be emitted
        @type name: dns.name.Name object
        @param file: The file to which the wire format data will be appended
        @type file: file
        @param compress: The compression table to use; the default is None.
        @type compress: dict
        @param origin: The origin to be appended to any relative names when
        they are emitted.  The default is None.
        @returns: the number of records emitted
        @rtype: int
        NFr�z!HHIHrz!H)
r�seekr�to_wire�struct�packrr3�list�randomZshuffler�tell)
rr5�file�compressr/r6Zwant_shufflerZstuff�lr�start�endr
r
rr;�s6




zRdataset.to_wirecCs&|j|kr"|j|kr"|j|kr"dSdS)zSReturns True if this rdataset matches the specified class, type,
        and coversTF)rrr)rrrrr
r
r�matchs



zRdataset.match)N)NNTN)NNNT)rrrr	�	__slots__rrrrrrrr r"r#r*r+r-r.r(r;rF�
__classcell__r
r
)rrr
,s$ 	

2
/r
cCspt|t�rtjj|�}t|t�r,tjj|�}t||�}|j|�x*|D]"}tjj|j	|j
|�}|j|�qFW|S)z�Create an rdataset with the specified class, type, and TTL, and with
    the specified list of rdatas in text format.

    @rtype: dns.rdataset.Rdataset object
    )r,rrr)�	from_textrr
rZrdatarrr)rrr�text_rdatas�r�trr
r
r�from_text_lists




rMcGst||||�S)z�Create an rdataset with the specified class, type, and TTL, and with
    the specified rdatas in text format.

    @rtype: dns.rdataset.Rdataset object
    )rM)rrrrJr
r
rrI/srIcCsTt|�dkrtd��d}x6|D].}|dkrBt|j|j�}|j|�|j|�qW|S)z�Create an rdataset with the specified TTL, and with
    the specified list of rdata objects.

    @rtype: dns.rdataset.Rdataset object
    rzrdata list must not be emptyN)r�
ValueErrorr
rrrr)r�rdatasrKrr
r
r�from_rdata_list9s

rPcGs
t||�S)z�Create an rdataset with the specified TTL, and with
    the specified rdata objects.

    @rtype: dns.rdataset.Rdataset object
    )rP)rrOr
r
r�
from_rdataKsrQ)r	r?�iorr<Z
dns.exceptionrZ
dns.rdatatypeZdns.rdataclassZ	dns.rdataZdns.setZ_compatr�set�SetZ	SimpleSetZ	exceptionZDNSExceptionrrr
rMrIrPrQr
r
r
r�<module>s$q
__pycache__/dnssec.cpython-36.pyc000064400000025243150351404330012665 0ustar003

�b�W�9�@sHdZddlmZddlZddlZddlZddlZddlZddl	Zddl
ZddlZddlZddl
ZddlmZGdd�dejj�ZGdd	�d	ejj�ZdZd
ZdZdZd
ZdZdZdZdZdZdZdZdZ dZ!eeeeeeeeeeeee e!d�Z"e#dd�e"j$�D��Z%dd�Z&dd�Z'dd�Z(dDd d!�Z)dEd"d#�Z*d$d%�Z+d&d'�Z,d(d)�Z-d*d+�Z.d,d-�Z/d.d/�Z0d0d1�Z1d2d3�Z2d4d5�Z3d6d7�Z4d8d9�Z5dFd:d;�Z6dGd<d=�Z7d>d?�Z8y(ddl9Z:ddl;Z:ddl<Z:e7Z=e6Z>d@Z?Wn"e@k
�r�e8Z=e8Z>dAZ?YnXy8ddlAZAddlBZAddlCZAddlDZAd@ZEGdBdC�dCeF�ZGWne@k
�rBdAZEYnXdS)Hz.Common DNSSEC-related functions and constants.�)�BytesION�)�string_typesc@seZdZdZdS)�UnsupportedAlgorithmz&The DNSSEC algorithm is not supported.N)�__name__�
__module__�__qualname__�__doc__�r
r
�/usr/lib/python3.6/dnssec.pyr!src@seZdZdZdS)�ValidationFailurez The DNSSEC signature is invalid.N)rrrr	r
r
r
rr&sr��������
�
����)�RSAMD5�DH�DSA�ECC�RSASHA1�DSANSEC3SHA1�RSASHA1NSEC3SHA1�	RSASHA256�	RSASHA512�INDIRECT�ECDSAP256SHA256�ECDSAP384SHA384�
PRIVATEDNS�
PRIVATEOIDccs|]\}}||fVqdS)Nr
)�.0�x�yr
r
r�	<genexpr>Nsr+cCs"tj|j��}|dkrt|�}|S)z:Convert text into a DNSSEC algorithm value
    @rtype: intN)�_algorithm_by_text�get�upper�int)�text�valuer
r
r�algorithm_from_textQsr2cCstj|�}|dkrt|�}|S)z;Convert a DNSSEC algorithm value to text
    @rtype: stringN)�_algorithm_by_valuer-�str)r1r0r
r
r�algorithm_to_text[s
r5cCst�}|j||d�|j�S)N)�origin)r�to_wire�getvalue)�recordr6�sr
r
r�	_to_rdataesr;cCs�t||�}t|�}|jtkr0|dd>|d	Sd}x<tt|�d�D](}||d|d>|d|d7}qFWt|�ddkr�||t|�dd>7}||d?d@7}|d@SdS)
Nrrr
rr�i��������)r;�	bytearray�	algorithmr�range�len)�keyr6�rdataZtotal�ir
r
r�key_idks

rFcCs�|j�dkr d}tjjd�}n,|j�dkr@d}tjjd�}ntd|��t|t�rdtjj||�}|j	|j
�j��|j	t||��|j
�}tjdt|�|j|�|}tjjtjjtjj|dt|��S)N�SHA1r�SHA256r
zunsupported algorithm "%s"z!HBBr)r.�dns�hash�hashesr�
isinstancer�name�	from_text�updateZcanonicalizer7r;�digest�struct�packrFr@rDZ	from_wire�
rdataclass�IN�	rdatatypeZDSrB)rMrCr@r6ZdsalgrJrPZdsrdatar
r
r�make_ds{s
rVcCs�g}|j|j�}|dkrdSt|tjj�rZy|jtjjtj	j
�}Wq^tk
rVdSXn|}x0|D](}|j|jkrdt
|�|jkrd|j|�qdW|S)N)r-�signerrLrIZnodeZNodeZ
find_rdatasetrSrTrUZDNSKEY�KeyErrorr@rFZkey_tag�append)�keys�rrsigZcandidate_keysr1�rdatasetrDr
r
r�_find_candidate_keys�s 

r]cCs|tttttfkS)N)rrr r!r")r@r
r
r�_is_rsa�sr^cCs|ttfkS)N)rr)r@r
r
r�_is_dsa�sr_cCsto|ttfkS)N)�_have_ecdsar$r%)r@r
r
r�	_is_ecdsa�sracCs|tkS)N)r)r@r
r
r�_is_md5�srbcCs|ttttfkS)N)rrrr )r@r
r
r�_is_sha1�srccCs|ttfkS)N)r!r$)r@r
r
r�
_is_sha256�srdcCs|tkS)N)r%)r@r
r
r�
_is_sha384�srecCs|tkS)N)r")r@r
r
r�
_is_sha512�srfcCs~t|�rtjjd�St|�r,tjjd�St|�rBtjjd�St|�rXtjjd�St|�rntjjd�Std|��dS)NZMD5rGrHZSHA384ZSHA512zunknown hash for algorithm %u)	rbrIrJrKrcrdrerfr)r@r
r
r�
_make_hash�srgc	Cs�t|�rddddddddg}ndt|�r6dd	d
ddg}nLt|�rVdddd
dd
ddd
g	}n,t|�rvdddd
dd
ddd
g	}ntd|��t|�}t|�j}dgd||gd|dgd|g|ddgd|g}tj	dt|�f|��S)N�*��H�rr
r�+rr��`r�erzunknown algorithm %u�0rrrz!%dB)
rbrcrdrfrrBrgZdigest_sizerQrR)r@ZoidZolenZdlenZidbytesr
r
r�_make_algorithm_id�s
<rqc)Cst|t�rtjj|tjj�}�x�t||�D�]�}|s<td��t|t�rX|d}|d}n
|j}|}|dkrrt	j	�}|j
|kr�td��|j|kr�td��t|j
�}t|j
��r`|j}	tjd|	dd��\}
|	dd�}	|
dk�rtjd|	dd	��\}
|	d	d�}	|	d|
�}|	|
d�}t|�d
}
tjjjtjjj|�tjjj|�f�}tjjj|j�f}�n t|j
��rl|j}	tjd|	dd��\}|	dd�}	d|d
}|	dd�}|	dd�}	|	d|�}|	|d�}	|	d|�}|	|d�}	|	d|�}tjjjtjjj|�tjjj|�tjjj|�tjjj|�f�}tjd
|jdd��\}}tjjj|�tjjj|�f}�nt|j
��rr|j
tk�r�tj j!}d}n"|j
t"k�r�tj j#}d}ntd��|j}	tjjj|	d|��}tjjj|	||d	��}tjj$|j%||��st&�tj'j(|j)|||j*�}tj+j,j-||�}t.||�}|jd|�}|j|d�}tjj/tjjj|�tjjj|��}ntd|j
��|j0t1||�dd��|j0|j2j3|��|j4t|�dk�r�|j5|j4d�d} tjjd| �}|j3|�}!tj6d|j7|j8|j9�}"t:|�}#xP|#D]H}$|j0|!�|j0|"�|$j3|�}%tj6dt|%��}&|j0|&�|j0|%��qW|j;�}'t|j
��r�t<|j
�|'}'|
d
t|'�d}(tj6dd	|(dfddgdg|(dg��|'}'n(t|j
��s�t|j
��r�ntd|j
��|j=|'|�r*dSq*Wtd��dS)a�Validate an RRset against a single signature rdata

    The owner name of the rrsig is assumed to be the same as the owner name
    of the rrset.

    @param rrset: The RRset to validate
    @type rrset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset)
    tuple
    @param rrsig: The signature rdata
    @type rrsig: dns.rrset.Rdata
    @param keys: The key dictionary.
    @type keys: a dictionary keyed by dns.name.Name with node or rdataset
    values
    @param origin: The origin to use for relative names
    @type origin: dns.name.Name or None
    @param now: The time to use when validating the signatures.  The default
    is the current time.
    @type now: int
    zunknown keyrrNZexpiredz
not yet validz!Bz!Hr
r�@�z!20s20s� rpzunknown ECDSA curvezunknown algorithm %u��*z!HHIrz!%dB�zverify failure)>rLrrIrMrN�rootr]r�tuple�timeZ
expirationZ	inceptionrgr@r^rCrQ�unpackrB�CryptoZ	PublicKeyZRSAZ	construct�Util�number�
bytes_to_longZ	signaturer_rrar$�ecdsaZcurvesZNIST256pr%ZNIST384pZpoint_is_valid�	generator�AssertionErrorZ
ellipticcurveZPoint�curve�orderrZZVerifyingKeyZfrom_public_point�ECKeyWrapperZ	SignaturerOr;rWZ
to_digestableZlabels�splitrRZrdtypeZrdclassZoriginal_ttl�sortedrPrq�verify))�rrsetr[rZr6�nowZ
candidate_key�rrnamer\rJZkeyptrZbytes_Zrsa_eZrsa_nZkeylen�pubkey�sig�tZoctetsZdsa_qZdsa_pZdsa_gZdsa_yZdsa_rZdsa_sr��key_lenr)r*ZpointZ
verifying_key�rr:�suffixZ	rrnamebufZrrfixedZrrlistZrrZrrdataZrrlenrPZpadlenr
r
r�_validate_rrsig�s�














"r�c	
Cs�t|t�rtjj|tjj�}t|t�r0|d}n|j}t|t�rR|d}|d}n
|j}|}|j|�}|j|�}||kr�td��x6|D].}yt	|||||�dStk
r�Yq�Xq�Wtd��dS)ahValidate an RRset

    @param rrset: The RRset to validate
    @type rrset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset)
    tuple
    @param rrsigset: The signature RRset
    @type rrsigset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset)
    tuple
    @param keys: The key dictionary.
    @type keys: a dictionary keyed by dns.name.Name with node or rdataset
    values
    @param origin: The origin to use for relative names
    @type origin: dns.name.Name or None
    @param now: The time to use when validating the signatures.  The default
    is the current time.
    @type now: int
    rrzowner names do not matchNzno RRSIGs validated)
rLrrIrMrNrxryZchoose_relativityrr�)	r�ZrrsigsetrZr6r�r�Z	rrsignameZ
rrsigrdatasetr[r
r
r�	_validatexs*








r�cOstd��dS)Nz#DNSSEC validation requires pycrypto)�NotImplementedError)�args�kwargsr
r
r�_need_pycrypto�sr�TFc@seZdZdd�Zdd�ZdS)r�cCs||_||_dS)N)rCr�)�selfrCr�r
r
r�__init__�szECKeyWrapper.__init__cCstjjj|�}|jjj||�S)N)r|r}r~rrCr�Zverifies)r�rPr�Zdiglongr
r
rr��szECKeyWrapper.verifyN)rrrr�r�r
r
r
rr��sr�)N)N)NN)NN)Hr	�iorrQrzZ
dns.exceptionrIZdns.hashZdns.nameZdns.nodeZdns.rdatasetZ	dns.rdataZ
dns.rdatatypeZdns.rdataclassZ_compatrZ	exceptionZDNSExceptionrrrrrrrrr r!r"r$r%r#r&r'r,�dict�itemsr3r2r5r;rFrVr]r^r_rarbrcrdrerfrgrqr�r�r�ZCrypto.PublicKey.RSAr|ZCrypto.PublicKey.DSAZCrypto.Util.numberZvalidateZvalidate_rrsigZ_have_pycrypto�ImportErrorr�Zecdsa.ecdsaZecdsa.ellipticcurveZ
ecdsa.keysr`�objectr�r
r
r
r�<module>s�





0

__pycache__/rrset.cpython-36.opt-1.pyc000064400000012167150351404330013505 0ustar003

�$�Wk�@sldZddlZddlZddlZddlZddlmZGdd�dejj	�Z
ddd�Zd	d
�Zddd�Z
d
d�ZdS)z)DNS RRsets (an RRset is a named rdataset)�N�)�string_typescs�eZdZdZddgZejjdf�fdd�	Z�fdd�Z	d	d
�Z
dd�Z�fd
d�Zd�fdd�	Z
d�fdd�	Zd�fdd�	Zdd�Z�ZS)�RRseta6A DNS RRset (named rdataset).

    RRset inherits from Rdataset, and RRsets can be treated as
    Rdatasets in most cases.  There are, however, a few notable
    exceptions.  RRsets have different to_wire() and to_text() method
    arguments, reflecting the fact that RRsets always have an owner
    name.
    �name�deletingNcs$tt|�j|||�||_||_dS)zCreate a new RRset.N)�superr�__init__rr)�selfr�rdclass�rdtype�coversr)�	__class__��/usr/lib/python3.6/rrset.pyr'szRRset.__init__cs"tt|�j�}|j|_|j|_|S)N)rr�_clonerr)r	�obj)r
rrr/szRRset._clonecCs�|jdkrd}ndtjj|j�d}|jdk	rDdtjj|j�}nd}dt|j�dtjj|j�dtjj|j	�||dS)	Nr��(�)z delete=z<DNS � z RRset>)
r�dns�	rdatatype�to_textr�
rdataclass�strrr
r)r	ZctextZdtextrrr�__repr__5s

zRRset.__repr__cCs|j�S)N)r)r	rrr�__str__Bsz
RRset.__str__cs.t|t�sdS|j|jkrdStt|�j|�S)zcTwo RRsets are equal if they have the same name and the same
        rdataset

        @rtype: boolF)�
isinstancerrr�__eq__)r	�other)r
rrrEs

zRRset.__eq__cs4tt|�j|||�sdS|j|ks,|j|kr0dSdS)zaReturns True if this rrset matches the specified class, type,
        covers, and deletion state.FT)rr�matchrr)r	rr
rrr)r
rrr Ps
zRRset.matchTcstt|�j|j|||jf|�S)a�Convert the RRset into DNS master file format.

        @see: L{dns.name.Name.choose_relativity} for more information
        on how I{origin} and I{relativize} determine the way names
        are emitted.

        Any additional keyword arguments are passed on to the rdata
        to_text() method.

        @param origin: The origin for relative names, or None.
        @type origin: dns.name.Name object
        @param relativize: True if names should names be relativized
        @type relativize: bool)rrrrr)r	�originZ
relativize�kw)r
rrrZsz
RRset.to_textcs tt|�j|j||||jf|�S)z!Convert the RRset to wire format.)rr�to_wirerr)r	�file�compressr!r")r
rrr#lsz
RRset.to_wirecCstjj|jt|��S)zYConvert an RRset into an Rdataset.

        @rtype: dns.rdataset.Rdataset object
        )r�rdataset�from_rdata_list�ttl�list)r	rrr�to_rdatasetrszRRset.to_rdataset)N)NT)NN)�__name__�
__module__�__qualname__�__doc__�	__slots__rrZNONErrrrrr rr#r*�
__classcell__rr)r
rrs	

rc	Cs�t|t�rtjj|d|d�}t|t�r2tjj|�}t|t�rHtjj|�}t|||�}|j|�x*|D]"}tj	j|j
|j|�}|j|�qdW|S)z�Create an RRset with the specified name, TTL, class, and type, and with
    the specified list of rdatas in text format.

    @rtype: dns.rrset.RRset object
    N)�
idna_codec)
rrrr�	from_textrrr�
update_ttlZrdatar
r�add)	rr(r
r�text_rdatasr1�r�t�rdrrr�from_text_listzs




r9cGst|||||�S)z�Create an RRset with the specified name, TTL, class, and type and with
    the specified rdatas in text format.

    @rtype: dns.rrset.RRset object
    )r9)rr(r
rr5rrrr2�sr2cCsrt|t�rtjj|d|d�}t|�dkr0td��d}x8|D]0}|dkr`t||j|j	�}|j
|�|j|�q:W|S)z�Create an RRset with the specified name and TTL, and with
    the specified list of rdata objects.

    @rtype: dns.rrset.RRset object
    N)r1rzrdata list must not be empty)rrrrr2�len�
ValueErrorrr
rr3r4)rr(�rdatasr1r6r8rrrr'�s


r'cGst|||�S)z�Create an RRset with the specified name and TTL, and with
    the specified rdata objects.

    @rtype: dns.rrset.RRset object
    )r')rr(r<rrr�
from_rdata�sr=)N)N)r.Zdns.namerZdns.rdatasetZdns.rdataclassZdns.rendererZ_compatrr&ZRdatasetrr9r2r'r=rrrr�<module>sa


__pycache__/_compat.cpython-36.opt-1.pyc000064400000002423150351404330013762 0ustar003

�b�W!�@s�ddlZddlZddlmZejdkr0eZeZneZeZejd
krfeZ	e
ZefZe
Zdd�Zdd�Zn"eZ	eZefZeZdd�Zd	d�Zd
d�ZdS)�N)�Context�cCs|j�S)N)�decode)�x�r�/usr/lib/python3.6/_compat.py�maybe_decodesrcCs|j�S)N)�encode)rrrr�maybe_encodesr
cCs|S)Nr)rrrrrscCs|S)Nr)rrrrr
scCs,tttt|���tjd�jt|��}t|�S)z�
    Python 2 and Python 3 use different rounding strategies in round(). This
    function ensures that results are python2/3 compatible and backward
    compatible with previous py2 releases
    :param what: float
    :return: rounded long
    )ZprecZrounding)r�len�str�long�decimalZ
ROUND_HALF_UPZcreate_decimal)Zwhat�drrr�round_py2_compat#s


r)r)r)�sysrr�version_info�intr
�rangeZxrangerZ	text_type�bytesZbinary_typeZstring_types�chrZunichrrr
ZunicodeZ
basestringrrrrr�<module>s*


__pycache__/wiredata.cpython-36.pyc000064400000004421150351404330013201 0ustar003

�b�W��@s^dZddlZddlZddlmZmZGdd�de�Ze�dd�ZGdd�de�Z	d	d
�Z
dS)zDNS Wire Data Helper�N�)�binary_type�string_typesc@s&eZdZdd�Zejdkr"dd�ZdS)�_SliceUnspecifiedBoundcCs|jS)N)�stop)�self�key�r	�/usr/lib/python3.6/wiredata.py�__getitem__ sz"_SliceUnspecifiedBound.__getitem__�cCs|jt||��S)N)r�slice)r�i�jr	r	r
�__getslice__$sz#_SliceUnspecifiedBound.__getslice__N)r)�__name__�
__module__�__qualname__r�sys�version_inforr	r	r	r
rs
rcs>eZdZ�fdd�Zejd
kr&dd�Zdd�Zdd	�Z�Z	S)�WireDatacs�y�t|t�r�|j}|j}tjdkrx|tkr2t|�}|dksB|dkrJtj	j
�||kr�tt|�j
|�tt|�j
|d�n6x4||fD](}|dkr�q�q�t|�t|�kr�tj	j
�q�Wttt|�j
t||���St|j��|Stk
r�tj	j
�YnXdS)Nrrr)r)�
isinstancer
�startrrr�_unspecified_bound�len�dns�	exception�	FormError�superrr�abs�	bytearray�unwrap�
IndexError)rrrr�index)�	__class__r	r
r-s,

zWireData.__getitem__rcCs|jt||��S)N)rr
)rrrr	r	r
rPszWireData.__getslice__ccsBd}x8y||V|d7}Wqtjjk
r8t�YqXqWdS)Nrr)rrr�
StopIteration)rrr	r	r
�__iter__Ss
zWireData.__iter__cCst|�S)N)r)rr	r	r
r!\szWireData.unwrap)r)
rrrrrrrr&r!�
__classcell__r	r	)r$r
r*s
"
	rcCsJt|t�r|St|t�r t|�St|t�r6t|j��Stdt|���dS)Nzunhandled type %s)rrrr�encode�
ValueError�type)Zwirer	r	r
�
maybe_wrap`s


r+)�__doc__rZ
dns.exceptionrZ_compatrrrrrr+r	r	r	r
�<module>s		6__pycache__/inet.cpython-36.pyc000064400000004414150351404330012342 0ustar003

�b�W��@sjdZddlZddlZddlZejZy
ejZWnek
rDdZYnXdd�Zdd�Z	dd	�Z
d
d�ZdS)z*Generic Internet address helper functions.�Ni'cCs0|tkrtjj|�S|tkr(tjj|�St�dS)a*Convert the textual form of a network address into its binary form.

    @param family: the address family
    @type family: int
    @param text: the textual address
    @type text: string
    @raises NotImplementedError: the address family specified is not
    implemented.
    @rtype: string
    N)�AF_INET�dns�ipv4�	inet_aton�AF_INET6�ipv6�NotImplementedError)�family�text�r�/usr/lib/python3.6/inet.py�	inet_pton&s
r
cCs0|tkrtjj|�S|tkr(tjj|�St�dS)a/Convert the binary form of a network address into its textual form.

    @param family: the address family
    @type family: int
    @param address: the binary address
    @type address: string
    @raises NotImplementedError: the address family specified is not
    implemented.
    @rtype: string
    N)rrrZ	inet_ntoarrr)r	Zaddressrrr�	inet_ntop:s
rcCsLytjj|�tStk
rFytjj|�tSt�YnXYnXdS)z�Determine the address family of a textual-form network address.

    @param text: the textual address
    @type text: string
    @raises ValueError: the address family cannot be determined from the input.
    @rtype: int
    N)rrrr�	Exceptionrr�
ValueError)r
rrr�af_for_addressMsrcCsty$ttjj|�d�}|dko$|dkStk
rnyttjj|�d�}|dkStk
rht�YnXYnXdS)z�Is the textual-form network address a multicast address?

    @param text: the textual address
    @raises ValueError: the address family cannot be determined from the input.
    @rtype: bool
    r�����N)�ordrrrrrr)r
�firstrrr�is_multicast`sr)�__doc__ZsocketZdns.ipv4rZdns.ipv6rr�AttributeErrorr
rrrrrrr�<module>s

__pycache__/_compat.cpython-36.pyc000064400000002423150351404330013023 0ustar003

�b�W!�@s�ddlZddlZddlmZejdkr0eZeZneZeZejd
krfeZ	e
ZefZe
Zdd�Zdd�Zn"eZ	eZefZeZdd�Zd	d�Zd
d�ZdS)�N)�Context�cCs|j�S)N)�decode)�x�r�/usr/lib/python3.6/_compat.py�maybe_decodesrcCs|j�S)N)�encode)rrrr�maybe_encodesr
cCs|S)Nr)rrrrrscCs|S)Nr)rrrrr
scCs,tttt|���tjd�jt|��}t|�S)z�
    Python 2 and Python 3 use different rounding strategies in round(). This
    function ensures that results are python2/3 compatible and backward
    compatible with previous py2 releases
    :param what: float
    :return: rounded long
    )ZprecZrounding)r�len�str�long�decimalZ
ROUND_HALF_UPZcreate_decimal)Zwhat�drrr�round_py2_compat#s


r)r)r)�sysrr�version_info�intr
�rangeZxrangerZ	text_type�bytesZbinary_typeZstring_types�chrZunichrrr
ZunicodeZ
basestringrrrrr�<module>s*


__pycache__/__init__.cpython-36.pyc000064400000001111150351404330013131 0ustar003

�b�W/�#@sRdZddddddddd	d
ddd
ddddddddddddddddddd d!d"d#g#Zd$S)%zdnspython DNS toolkitZdnssecZe164ZednsZentropyZ	exception�flags�hashZinetZipv4Zipv6�message�nameZnamedictZnodeZopcodeZqueryZrcodeZrdataZ
rdataclassZrdatasetZ	rdatatypeZrendererZresolverZreversenameZrrset�setZ	tokenizerZtsigZtsigkeyringZttlZrdtypes�update�versionZwiredataZzoneN)�__doc__�__all__�r
r
�/usr/lib/python3.6/__init__.py�<module>sF__pycache__/__init__.cpython-36.opt-1.pyc000064400000001111150351404340014071 0ustar003

�b�W/�#@sRdZddddddddd	d
ddd
ddddddddddddddddddd d!d"d#g#Zd$S)%zdnspython DNS toolkitZdnssecZe164ZednsZentropyZ	exception�flags�hashZinetZipv4Zipv6�message�nameZnamedictZnodeZopcodeZqueryZrcodeZrdataZ
rdataclassZrdatasetZ	rdatatypeZrendererZresolverZreversenameZrrset�setZ	tokenizerZtsigZtsigkeyringZttlZrdtypes�update�versionZwiredataZzoneN)�__doc__�__all__�r
r
�/usr/lib/python3.6/__init__.py�<module>sF__pycache__/inet.cpython-36.opt-1.pyc000064400000004414150351404340013302 0ustar003

�b�W��@sjdZddlZddlZddlZejZy
ejZWnek
rDdZYnXdd�Zdd�Z	dd	�Z
d
d�ZdS)z*Generic Internet address helper functions.�Ni'cCs0|tkrtjj|�S|tkr(tjj|�St�dS)a*Convert the textual form of a network address into its binary form.

    @param family: the address family
    @type family: int
    @param text: the textual address
    @type text: string
    @raises NotImplementedError: the address family specified is not
    implemented.
    @rtype: string
    N)�AF_INET�dns�ipv4�	inet_aton�AF_INET6�ipv6�NotImplementedError)�family�text�r�/usr/lib/python3.6/inet.py�	inet_pton&s
r
cCs0|tkrtjj|�S|tkr(tjj|�St�dS)a/Convert the binary form of a network address into its textual form.

    @param family: the address family
    @type family: int
    @param address: the binary address
    @type address: string
    @raises NotImplementedError: the address family specified is not
    implemented.
    @rtype: string
    N)rrrZ	inet_ntoarrr)r	Zaddressrrr�	inet_ntop:s
rcCsLytjj|�tStk
rFytjj|�tSt�YnXYnXdS)z�Determine the address family of a textual-form network address.

    @param text: the textual address
    @type text: string
    @raises ValueError: the address family cannot be determined from the input.
    @rtype: int
    N)rrrr�	Exceptionrr�
ValueError)r
rrr�af_for_addressMsrcCsty$ttjj|�d�}|dko$|dkStk
rnyttjj|�d�}|dkStk
rht�YnXYnXdS)z�Is the textual-form network address a multicast address?

    @param text: the textual address
    @raises ValueError: the address family cannot be determined from the input.
    @rtype: bool
    r�����N)�ordrrrrrr)r
�firstrrr�is_multicast`sr)�__doc__ZsocketZdns.ipv4rZdns.ipv6rr�AttributeErrorr
rrrrrrr�<module>s

__pycache__/entropy.cpython-36.pyc000064400000006323150351404340013105 0ustar003

�b�Wq�@s�ddlZddlZddlZddlmZmZyddlZWnek
rPddl	ZYnXGdd�de
�Ze�Zyej
�ZWnek
r�dZYnXdd�Zdd	�ZdS)
�N�)�long�binary_typec@sHeZdZddd�Zddd�Zdd�Zd	d
�Zdd�Zd
d�Zdd�Z	dS)�EntropyPoolNcCs�d|_d|_d|_tj�|_yddl}|j�|_d|_	Wn^t
k
r�yddl}|j�|_d|_	Wn,t
k
r�ddl
}|j�|_d|_	YnXYnXtd|j	�|_|dk	r�|jt|��d|_tj�|_nd|_d|_dS)Nr���TF)�
pool_index�digest�	next_byte�
_threadingZLock�lock�hashlibZsha1�hash�hash_len�ImportError�sha�new�md5�	bytearray�pool�stir�seeded�os�getpid�seed_pid)�self�seedrrr�r�/usr/lib/python3.6/entropy.py�__init__s0





zEntropyPool.__init__FcCsr|s|jj�zNxH|D]@}|j|jkr,d|_|d@}|j|j|N<|jd7_qWWd|sl|jj�XdS)Nr�r)r
�acquirer	rr�release)rZentropyZalready_locked�c�brrrr7s

zEntropyPool.stircCs�|js|jtj�kr�ytjd�}Wn`tk
r�y*tddd�}z|jd�}Wd|j�XWn tk
r~t	t
j
��}YnXYnXd|_tj�|_d|_t|�}|j
|d�dS)Nrz/dev/urandom�rbrT)rrrr�urandom�	Exception�open�read�close�str�timer
rr)rr�rrrr�_maybe_seedEs 
zEntropyPool._maybe_seedc
Cs�|jj�zr|j�|jdks*|j|jkr`|jjt|j	��t
|jj��|_|j|jd�d|_|j|j}|jd7_Wd|jj�X|S)NTrr)
r
r"r/r
rrr�updaterrrrr#)r�valuerrr�random_8Xs
zEntropyPool.random_8cCs|j�d|j�S)N�)r2)rrrr�	random_16gszEntropyPool.random_16cCs|j�d|j�S)Ni)r4)rrrr�	random_32jszEntropyPool.random_32cCsl||d}|td�kr td��|dkr8|j}td�}n|dkrL|j}d}n
|j}d}|||�|dS)	Nrlztoo bigil��r3i��r!)r�
ValueErrorr5r4r2)r�first�last�sizeZrand�maxrrr�random_betweenms
zEntropyPool.random_between)N)F)
�__name__�
__module__�__qualname__r rr/r2r4r5r;rrrrrs

rcCs tdk	rtjdd�Stj�SdS)Nri)�
system_random�	randrangerr4rrrrr4�sr4cCs(tdk	rtj||d�Stj||�SdS)Nr)r?r@rr;)r7r8rrr�between�srA)rZrandomr-Z_compatrrZ	threadingrrZdummy_threading�objectrrZSystemRandomr?r(r4rArrrr�<module>sb
__pycache__/update.cpython-36.opt-1.pyc000064400000015666150351404340013640 0ustar003

�b�W'�@s`dZddlZddlZddlZddlZddlZddlZddlZddl	m
Z
Gdd�dejj�Z
dS)zDNS Dynamic Update Support�N�)�string_typescsxeZdZejjddejjf�fdd�	Zddd�Z	dd�Z
dd	�Zd
d�Zdd
�Z
dd�Zddd�Zd�fdd�	Z�ZS)�UpdateNcs�tt|�j�|jtjjtjj�O_t|t	�r>tj
j|�}||_t|t	�rZtj
j|�}||_|j|j|j|tjjddd�|dk	r�|j|||d�dS)a�Initialize a new DNS Update object.

        @param zone: The zone which is being updated.
        @type zone: A dns.name.Name or string
        @param rdclass: The class of the zone; defaults to dns.rdataclass.IN.
        @type rdclass: An int designating the class, or a string whose value
        is the name of a class.
        @param keyring: The TSIG keyring to use; defaults to None.
        @type keyring: dict
        @param keyname: The name of the TSIG key to use; defaults to None.
        The key must be defined in the keyring.  If a keyring is specified
        but a keyname is not, then the key used will be the first key in the
        keyring.  Note that the order of keys in a dictionary is not defined,
        so applications should supply a keyname when a keyring is used, unless
        they know the keyring contains only one key.
        @type keyname: dns.name.Name or string
        @param keyalgorithm: The TSIG algorithm to use; defaults to
        dns.tsig.default_algorithm.  Constants for TSIG algorithms are defined
        in dns.tsig, and the currently implemented algorithms are
        HMAC_MD5, HMAC_SHA1, HMAC_SHA224, HMAC_SHA256, HMAC_SHA384, and
        HMAC_SHA512.
        @type keyalgorithm: string
        T)ZcreateZforce_uniqueN)�	algorithm)�superr�__init__�flags�dnsZopcodeZto_flagsZUPDATE�
isinstancer�name�	from_text�origin�
rdataclass�zone_rdclass�
find_rrsetZquestion�	rdatatypeZSOAZuse_tsig)�selfZzoneZrdclassZkeyringZkeynameZkeyalgorithm)�	__class__��/usr/lib/python3.6/update.pyrs


zUpdate.__init__c	CsB|dkr|j}|j�}|j|||j|j||dd�}|j||�dS)z&Add a single RR to the update section.NT)�	authority�coversrr�rdtype�add)rr�ttl�rdZdeleting�sectionrZrrsetrrr�_add_rrEszUpdate._add_rrc
Gs:t|t�rtjj|d�}t|dtjj�rnx@|D]8}|rF|j||j�x |D]}|j	||j
||d�qLWq0Wn�t|�}t|j
d��}t|dtjj�r�|r�|j||dj�x�|D]}|j	||||d�q�Wnh|j
d�}t|t�r�tjj|�}|r�|j||�x6|D].}	tjj|j||	|j�}|j	||||d��qWdS)a�Add records.  The first argument is the replace mode.  If
        false, RRs are added to an existing RRset; if true, the RRset
        is replaced with the specified contents.  The second
        argument is the section to add to.  The third argument
        is always a name.  The other arguments can be:

                - rdataset...

                - ttl, rdata...

                - ttl, rdtype, string...Nr)r)r
rr	rr�rdataset�Rdataset�deleterrr�list�int�pop�rdata�Rdatarrr
)
r�replacerr�args�rdsrrr�srrr�_addOs0






zUpdate._addcGs|jd|j|f|��dS)z�Add records.  The first argument is always a name.  The other
        arguments can be:

                - rdataset...

                - ttl, rdata...

                - ttl, rdtype, string...FN)r*r)rrr'rrrrws	z
Update.addc	Gsft|t�rtjj|d�}t|�dkrR|j|j|tjj	tj
j	tj
jtj
j	dd��nt|dtjj
�r�x�|D]&}x |D]}|j|d|tjj�qtWqjWn�t|�}t|dtjj�r�x�|D]}|j|d|tjj�q�Wn�|jd�}t|t�r�tj
j|�}t|�dk�r(|j|j||j|tj
jtjj	dd�n:x8|D]0}tjj|j|||j�}|j|d|tjj��q.WdS)z�Delete records.  The first argument is always a name.  The other
        arguments can be:

                - I{nothing}

                - rdataset...

                - rdata...

                - rdtype, [string...]NrT)r
rr	rr�lenrrr�ANYr�NONErrrr!r$r%r#rr
)rrr'r(rrr)rrrr �s6








z
Update.deletecGs|jd|j|f|��dS)aQReplace records.  The first argument is always a name.  The other
        arguments can be:

                - rdataset...

                - ttl, rdata...

                - ttl, rdtype, string...

        Note that if you want to replace the entire node, you should do
        a delete of the name followed by one or more calls to add.TN)r*r)rrr'rrrr&�s
zUpdate.replacec	Gs�t|t�rtjj|d�}t|�dkrL|j|j|tjj	tj
j	tj
jddd�n�t|dtjj
�s|t|dtjj�s|t|�dkr�t|dtjj
�s�t|�}|jdd�|jd|j|f|��n@|d}t|t�r�tj
j|�}|j|j|tjj	|tj
jddd�dS)aBRequire that an owner name (and optionally an rdata type,
        or specific rdataset) exists as a prerequisite to the
        execution of the update.  The first argument is always a name.
        The other arguments can be:

                - rdataset...

                - rdata...

                - rdtype, string...NrTrF)r
rr	rrr+r�answerrr,rr-rrr$r%r!�insertr*)rrr'rrrr�present�s*




zUpdate.presentc	Cs�t|t�rtjj|d�}|dkrH|j|j|tjjtj	j
tj	jddd�n8t|t�r^tj	j|�}|j|j|tjj|tj	jddd�dS)z�Require that an owner name (and optionally an rdata type) does
        not exist as a prerequisite to the execution of the update.NT)r
rr	rrrr.rr-rr,)rrrrrr�absent�s




z
Update.absent�cs |dkr|j}tt|�j||�S)zcReturn a string containing the update in DNS compressed wire
        format.
        @rtype: stringN)r
rr�to_wire)rr
Zmax_size)rrrr3�szUpdate.to_wire)NN)N)Nr2)�__name__�
__module__�__qualname__r	r�INZtsigZdefault_algorithmrrr*rr r&r0r1r3�
__classcell__rr)rrrs%

(+$
r)�__doc__Zdns.messager	Zdns.nameZ
dns.opcodeZ	dns.rdataZdns.rdataclassZdns.rdatasetZdns.tsigZ_compatr�messageZMessagerrrrr�<module>s__pycache__/node.cpython-36.opt-1.pyc000064400000012636150351404340013275 0ustar003

�b�W��@s<dZddlmZddlZddlZddlZGdd�de�ZdS)z)DNS nodes.  A node is a set of rdatasets.�)�StringIONc@s�eZdZdZdgZdd�Zdd�Zdd�Zd	d
�Zdd�Z	d
d�Z
dd�Zej
jdfdd�Zej
jdfdd�Zej
jfdd�Zdd�ZdS)�Nodez�A DNS node.

    A node is a set of rdatasets

    @ivar rdatasets: the node's rdatasets
    @type rdatasets: list of dns.rdataset.Rdataset objects�	rdatasetscCs
g|_dS)zInitialize a DNS node.
        N)r)�self�r�/usr/lib/python3.6/node.py�__init__$sz
Node.__init__cKsPt�}x8|jD].}t|�dkr|j|j|f|��|jd�qW|j�dd�S)a+Convert a node to text format.

        Each rdataset at the node is printed.  Any keyword arguments
        to this method are passed on to the rdataset's to_text() method.
        @param name: the owner name of the rdatasets
        @type name: dns.name.Name object
        @rtype: string
        r�
N����)rr�len�write�to_text�getvalue)r�name�kw�s�rdsrrrr*s
zNode.to_textcCsdtt|��dS)Nz
<DNS node �>)�str�id)rrrr�__repr__;sz
Node.__repr__cCs@x|jD]}||jkrdSqWx|jD]}||jkr&dSq&WdS)zSTwo nodes are equal if they have the same rdatasets.

        @rtype: bool
        FT)r)r�otherZrdrrr�__eq__>s

zNode.__eq__cCs|j|�S)N)r)rrrrr�__ne__NszNode.__ne__cCs
t|j�S)N)rr)rrrr�__len__QszNode.__len__cCs
t|j�S)N)�iterr)rrrr�__iter__Tsz
Node.__iter__FcCsHx |jD]}|j|||�r|SqW|s*t�tjj||�}|jj|�|S)aFind an rdataset matching the specified properties in the
        current node.

        @param rdclass: The class of the rdataset
        @type rdclass: int
        @param rdtype: The type of the rdataset
        @type rdtype: int
        @param covers: The covered type.  Usually this value is
        dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or
        dns.rdatatype.RRSIG, then the covers value will be the rdata
        type the SIG/RRSIG covers.  The library treats the SIG and RRSIG
        types as if they were a family of
        types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA).  This makes RRSIGs much
        easier to work with than if RRSIGs covering different rdata
        types were aggregated into a single RRSIG rdataset.
        @type covers: int
        @param create: If True, create the rdataset if it is not found.
        @type create: bool
        @raises KeyError: An rdataset of the desired type and class does
        not exist and I{create} is not True.
        @rtype: dns.rdataset.Rdataset object
        )r�match�KeyError�dns�rdataset�Rdataset�append)r�rdclass�rdtype�covers�createrrrr�
find_rdatasetWszNode.find_rdatasetcCs2y|j||||�}Wntk
r,d}YnX|S)aEGet an rdataset matching the specified properties in the
        current node.

        None is returned if an rdataset of the specified type and
        class does not exist and I{create} is not True.

        @param rdclass: The class of the rdataset
        @type rdclass: int
        @param rdtype: The type of the rdataset
        @type rdtype: int
        @param covers: The covered type.
        @type covers: int
        @param create: If True, create the rdataset if it is not found.
        @type create: bool
        @rtype: dns.rdataset.Rdataset object or None
        N)r(r)rr$r%r&r'rrrr�get_rdatasetys

zNode.get_rdatasetcCs&|j|||�}|dk	r"|jj|�dS)azDelete the rdataset matching the specified properties in the
        current node.

        If a matching rdataset does not exist, it is not an error.

        @param rdclass: The class of the rdataset
        @type rdclass: int
        @param rdtype: The type of the rdataset
        @type rdtype: int
        @param covers: The covered type.
        @type covers: int
        N)r)r�remove)rr$r%r&rrrr�delete_rdataset�szNode.delete_rdatasetcCs:t|tjj�std��|j|j|j|j�|j	j
|�dS)a8Replace an rdataset.

        It is not an error if there is no rdataset matching I{replacement}.

        Ownership of the I{replacement} object is transferred to the node;
        in other words, this method does not store a copy of I{replacement}
        at the node, it stores I{replacement} itself.
        zreplacement is not an rdatasetN)�
isinstancer r!r"�
ValueErrorr+r$r%r&rr#)rZreplacementrrr�replace_rdataset�s

zNode.replace_rdatasetN)�__name__�
__module__�__qualname__�__doc__�	__slots__rrrrrrrr Z	rdatatypeZNONEr(r)r+r.rrrrrs!r)	r2�iorZdns.rdatasetr Z
dns.rdatatypeZdns.renderer�objectrrrrr�<module>s
__pycache__/opcode.cpython-36.opt-1.pyc000064400000004002150351404340013605 0ustar003

�b�W�	�@s�dZddlZdZdZdZdZdZeeeeed�Ze	dd	�ej
�D��ZGd
d�dejj
�Zdd
�Zdd�Zdd�Zdd�Zdd�ZdS)zDNS Opcodes.�N����)�QUERY�IQUERY�STATUS�NOTIFY�UPDATEccs|]\}}||fVqdS)N�)�.0�x�yrr�/usr/lib/python3.6/opcode.py�	<genexpr>&src@seZdZdZdS)�
UnknownOpcodezAn DNS opcode is unknown.N)�__name__�
__module__�__qualname__�__doc__rrrrr)srcCsB|j�r$t|�}|dkr$|dkr$|Stj|j��}|dkr>t�|S)z�Convert text into an opcode.

    @param text: the textual opcode
    @type text: string
    @raises UnknownOpcode: the opcode is unknown
    @rtype: int
    r�N)�isdigit�int�_by_text�get�upperr)�text�valuerrr�	from_text.s	rcCs|d@d?S)zUExtract an opcode from DNS message flags.

    @param flags: int
    @rtype: int
    ix�r)�flagsrrr�
from_flagsAsr!cCs|d>d@S)z`Convert an opcode to a value suitable for ORing into DNS message
    flags.
    @rtype: int
    rixr)rrrr�to_flagsKsr"cCstj|�}|dkrt|�}|S)z�Convert an opcode to text.

    @param value: the opcdoe
    @type value: int
    @raises UnknownOpcode: the opcode is unknown
    @rtype: string
    N)�	_by_valuer�str)rrrrr�to_textTs	
r%cCst|�tkS)znTrue if the opcode in flags is UPDATE.

    @param flags: DNS flags
    @type flags: int
    @rtype: bool
    )r!r
)r rrr�	is_updatecsr&)rZ
dns.exceptionZdnsrrrr	r
r�dict�itemsr#Z	exceptionZDNSExceptionrrr!r"r%r&rrrr�<module>s$
	__pycache__/ipv4.cpython-36.opt-1.pyc000064400000002516150351404340013226 0ustar003

�b�W��@s4dZddlZddlZddlmZdd�Zdd�ZdS)	zIPv4 helper functions.�N�)�binary_typecCsJt|�dkrtjj�t|t�s&t|�}d|d|d|d|dfj�S)z�Convert an IPv4 address in network form to text form.

    @param address: The IPv4 address
    @type address: string
    @returns: string
    �z%u.%u.%u.%urr��)�len�dns�	exception�SyntaxError�
isinstance�	bytearray�encode)Zaddress�r�/usr/lib/python3.6/ipv4.py�	inet_ntoas
rc	Cs�t|t�s|j�}|jd�}t|�dkr0tjj�x<|D]4}|j�sJtjj�t|�dkr6|ddkr6tjj�q6Wydd�|D�}t	j
d
|��Stjj�YnXd	S)z�Convert an IPv4 address in text form to network form.

    @param text: The IPv4 address
    @type text: string
    @returns: string
    �.rrr�0cSsg|]}t|��qSr)�int)�.0�partrrr�
<listcomp>8szinet_aton.<locals>.<listcomp>�BBBBN)r)rrr
�splitrrr	r
�isdigit�struct�pack)�text�partsr�bytesrrr�	inet_aton%s


r)�__doc__rZ
dns.exceptionrZ_compatrrrrrrr�<module>s
inet.py000064400000006252150351404340006061 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""Generic Internet address helper functions."""

import socket

import dns.ipv4
import dns.ipv6


# We assume that AF_INET is always defined.

AF_INET = socket.AF_INET

# AF_INET6 might not be defined in the socket module, but we need it.
# We'll try to use the socket module's value, and if it doesn't work,
# we'll use our own value.

try:
    AF_INET6 = socket.AF_INET6
except AttributeError:
    AF_INET6 = 9999


def inet_pton(family, text):
    """Convert the textual form of a network address into its binary form.

    @param family: the address family
    @type family: int
    @param text: the textual address
    @type text: string
    @raises NotImplementedError: the address family specified is not
    implemented.
    @rtype: string
    """

    if family == AF_INET:
        return dns.ipv4.inet_aton(text)
    elif family == AF_INET6:
        return dns.ipv6.inet_aton(text)
    else:
        raise NotImplementedError


def inet_ntop(family, address):
    """Convert the binary form of a network address into its textual form.

    @param family: the address family
    @type family: int
    @param address: the binary address
    @type address: string
    @raises NotImplementedError: the address family specified is not
    implemented.
    @rtype: string
    """
    if family == AF_INET:
        return dns.ipv4.inet_ntoa(address)
    elif family == AF_INET6:
        return dns.ipv6.inet_ntoa(address)
    else:
        raise NotImplementedError


def af_for_address(text):
    """Determine the address family of a textual-form network address.

    @param text: the textual address
    @type text: string
    @raises ValueError: the address family cannot be determined from the input.
    @rtype: int
    """
    try:
        dns.ipv4.inet_aton(text)
        return AF_INET
    except Exception:
        try:
            dns.ipv6.inet_aton(text)
            return AF_INET6
        except:
            raise ValueError


def is_multicast(text):
    """Is the textual-form network address a multicast address?

    @param text: the textual address
    @raises ValueError: the address family cannot be determined from the input.
    @rtype: bool
    """
    try:
        first = ord(dns.ipv4.inet_aton(text)[0])
        return first >= 224 and first <= 239
    except Exception:
        try:
            first = ord(dns.ipv6.inet_aton(text)[0])
            return first == 255
        except Exception:
            raise ValueError
namedict.py000064400000007135150351404340006707 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
# Copyright (C) 2016 Coresec Systems AB
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND CORESEC SYSTEMS AB DISCLAIMS ALL
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CORESEC
# SYSTEMS AB BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS name dictionary"""

import collections
import dns.name
from ._compat import xrange


class NameDict(collections.MutableMapping):

    """A dictionary whose keys are dns.name.Name objects.
    @ivar max_depth: the maximum depth of the keys that have ever been
    added to the dictionary.
    @type max_depth: int
    @ivar max_depth_items: the number of items of maximum depth
    @type max_depth_items: int
    """

    __slots__ = ["max_depth", "max_depth_items", "__store"]

    def __init__(self, *args, **kwargs):
        self.__store = dict()
        self.max_depth = 0
        self.max_depth_items = 0
        self.update(dict(*args, **kwargs))

    def __update_max_depth(self, key):
        if len(key) == self.max_depth:
            self.max_depth_items = self.max_depth_items + 1
        elif len(key) > self.max_depth:
            self.max_depth = len(key)
            self.max_depth_items = 1

    def __getitem__(self, key):
        return self.__store[key]

    def __setitem__(self, key, value):
        if not isinstance(key, dns.name.Name):
            raise ValueError('NameDict key must be a name')
        self.__store[key] = value
        self.__update_max_depth(key)

    def __delitem__(self, key):
        value = self.__store.pop(key)
        if len(value) == self.max_depth:
            self.max_depth_items = self.max_depth_items - 1
        if self.max_depth_items == 0:
            self.max_depth = 0
            for k in self.__store:
                self.__update_max_depth(k)

    def __iter__(self):
        return iter(self.__store)

    def __len__(self):
        return len(self.__store)

    def has_key(self, key):
        return key in self.__store

    def get_deepest_match(self, name):
        """Find the deepest match to I{name} in the dictionary.

        The deepest match is the longest name in the dictionary which is
        a superdomain of I{name}.

        @param name: the name
        @type name: dns.name.Name object
        @rtype: (key, value) tuple
        """

        depth = len(name)
        if depth > self.max_depth:
            depth = self.max_depth
        for i in xrange(-depth, 0):
            n = dns.name.Name(name[i:])
            if n in self:
                return (n, self[n])
        v = self[dns.name.empty]
        return (dns.name.empty, v)
exception.py000064400000011022150351404340007107 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""Common DNS Exceptions."""


class DNSException(Exception):

    """Abstract base class shared by all dnspython exceptions.

    It supports two basic modes of operation:

    a) Old/compatible mode is used if __init__ was called with
    empty **kwargs.
    In compatible mode all *args are passed to standard Python Exception class
    as before and all *args are printed by standard __str__ implementation.
    Class variable msg (or doc string if msg is None) is returned from str()
    if *args is empty.

    b) New/parametrized mode is used if __init__ was called with
    non-empty **kwargs.
    In the new mode *args has to be empty and all kwargs has to exactly match
    set in class variable self.supp_kwargs. All kwargs are stored inside
    self.kwargs and used in new __str__ implementation to construct
    formatted message based on self.fmt string.

    In the simplest case it is enough to override supp_kwargs and fmt
    class variables to get nice parametrized messages.
    """
    msg = None  # non-parametrized message
    supp_kwargs = set()  # accepted parameters for _fmt_kwargs (sanity check)
    fmt = None  # message parametrized with results from _fmt_kwargs

    def __init__(self, *args, **kwargs):
        self._check_params(*args, **kwargs)
        if kwargs:
            self.kwargs = self._check_kwargs(**kwargs)
            self.msg = str(self)
        else:
            self.kwargs = dict()  # defined but empty for old mode exceptions
        if self.msg is None:
            # doc string is better implicit message than empty string
            self.msg = self.__doc__
        if args:
            super(DNSException, self).__init__(*args)
        else:
            super(DNSException, self).__init__(self.msg)

    def _check_params(self, *args, **kwargs):
        """Old exceptions supported only args and not kwargs.

        For sanity we do not allow to mix old and new behavior."""
        if args or kwargs:
            assert bool(args) != bool(kwargs), \
                'keyword arguments are mutually exclusive with positional args'

    def _check_kwargs(self, **kwargs):
        if kwargs:
            assert set(kwargs.keys()) == self.supp_kwargs, \
                'following set of keyword args is required: %s' % (
                    self.supp_kwargs)
        return kwargs

    def _fmt_kwargs(self, **kwargs):
        """Format kwargs before printing them.

        Resulting dictionary has to have keys necessary for str.format call
        on fmt class variable.
        """
        fmtargs = {}
        for kw, data in kwargs.items():
            if isinstance(data, (list, set)):
                # convert list of <someobj> to list of str(<someobj>)
                fmtargs[kw] = list(map(str, data))
                if len(fmtargs[kw]) == 1:
                    # remove list brackets [] from single-item lists
                    fmtargs[kw] = fmtargs[kw].pop()
            else:
                fmtargs[kw] = data
        return fmtargs

    def __str__(self):
        if self.kwargs and self.fmt:
            # provide custom message constructed from keyword arguments
            fmtargs = self._fmt_kwargs(**self.kwargs)
            return self.fmt.format(**fmtargs)
        else:
            # print *args directly in the same way as old DNSException
            return super(DNSException, self).__str__()


class FormError(DNSException):

    """DNS message is malformed."""


class SyntaxError(DNSException):

    """Text input is malformed."""


class UnexpectedEnd(SyntaxError):

    """Text input ended unexpectedly."""


class TooBig(DNSException):

    """The DNS message is too big."""


class Timeout(DNSException):

    """The DNS operation timed out."""
    supp_kwargs = set(['timeout'])
    fmt = "The DNS operation timed out after {timeout} seconds"
tsigkeyring.py000064400000003311150351404340007452 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""A place to store TSIG keys."""

from dns._compat import maybe_decode, maybe_encode

import base64

import dns.name


def from_text(textring):
    """Convert a dictionary containing (textual DNS name, base64 secret) pairs
    into a binary keyring which has (dns.name.Name, binary secret) pairs.
    @rtype: dict"""

    keyring = {}
    for keytext in textring:
        keyname = dns.name.from_text(keytext)
        secret = base64.decodestring(maybe_encode(textring[keytext]))
        keyring[keyname] = secret
    return keyring


def to_text(keyring):
    """Convert a dictionary containing (dns.name.Name, binary secret) pairs
    into a text keyring which has (textual DNS name, base64 secret) pairs.
    @rtype: dict"""

    textring = {}
    for keyname in keyring:
        keytext = maybe_decode(keyname.to_text())
        secret = maybe_decode(base64.encodestring(keyring[keyname]))
        textring[keytext] = secret
    return textring
e164.py000064400000006113150351404340005575 0ustar00# Copyright (C) 2006, 2007, 2009, 2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS E.164 helpers

@var public_enum_domain: The DNS public ENUM domain, e164.arpa.
@type public_enum_domain: dns.name.Name object
"""


import dns.exception
import dns.name
import dns.resolver
from ._compat import string_types

public_enum_domain = dns.name.from_text('e164.arpa.')


def from_e164(text, origin=public_enum_domain):
    """Convert an E.164 number in textual form into a Name object whose
    value is the ENUM domain name for that number.
    @param text: an E.164 number in textual form.
    @type text: str
    @param origin: The domain in which the number should be constructed.
    The default is e164.arpa.
    @type origin: dns.name.Name object or None
    @rtype: dns.name.Name object
    """
    parts = [d for d in text if d.isdigit()]
    parts.reverse()
    return dns.name.from_text('.'.join(parts), origin=origin)


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: dns.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 origin: dns.name.Name object or None
    @param want_plus_prefix: if True, add a '+' to the beginning of the
    returned number.
    @rtype: str
    """
    if origin is not 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 dns.exception.SyntaxError('non-digit labels in ENUM domain name')
    dlabels.reverse()
    text = b''.join(dlabels)
    if want_plus_prefix:
        text = b'+' + text
    return text


def query(number, domains, resolver=None):
    """Look for NAPTR RRs for the specified number in the specified domains.

    e.g. lookup('16505551212', ['e164.dnspython.org.', 'e164.arpa.'])
    """
    if resolver is None:
        resolver = dns.resolver.get_default_resolver()
    e_nx = dns.resolver.NXDOMAIN()
    for domain in domains:
        if isinstance(domain, string_types):
            domain = dns.name.from_text(domain)
        qname = dns.e164.from_e164(number, domain)
        try:
            return resolver.query(qname, 'NAPTR')
        except dns.resolver.NXDOMAIN as e:
            e_nx += e
    raise e_nx
hash.py000064400000002114150351404340006036 0ustar00# Copyright (C) 2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""Hashing backwards compatibility wrapper"""

import hashlib


hashes = {}
hashes['MD5'] = hashlib.md5
hashes['SHA1'] = hashlib.sha1
hashes['SHA224'] = hashlib.sha224
hashes['SHA256'] = hashlib.sha256
hashes['SHA384'] = hashlib.sha384
hashes['SHA512'] = hashlib.sha512


def get(algorithm):
    return hashes[algorithm.upper()]
query.py000064400000046275150351404340006300 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""Talk to a DNS server."""

from __future__ import generators

import errno
import select
import socket
import struct
import sys
import time

import dns.exception
import dns.inet
import dns.name
import dns.message
import dns.rdataclass
import dns.rdatatype
from ._compat import long, string_types

if sys.version_info > (3,):
    select_error = OSError
else:
    select_error = select.error

# Function used to create a socket.  Can be overridden if needed in special
# situations.
socket_factory = socket.socket

class UnexpectedSource(dns.exception.DNSException):

    """A DNS query response came from an unexpected address or port."""


class BadResponse(dns.exception.FormError):

    """A DNS query response does not respond to the question asked."""


def _compute_expiration(timeout):
    if timeout is None:
        return None
    else:
        return time.time() + timeout


def _poll_for(fd, readable, writable, error, timeout):
    """Poll polling backend.
    @param fd: File descriptor
    @type fd: int
    @param readable: Whether to wait for readability
    @type readable: bool
    @param writable: Whether to wait for writability
    @type writable: bool
    @param timeout: Deadline timeout (expiration time, in seconds)
    @type timeout: float
    @return True on success, False on timeout
    """
    event_mask = 0
    if readable:
        event_mask |= select.POLLIN
    if writable:
        event_mask |= select.POLLOUT
    if error:
        event_mask |= select.POLLERR

    pollable = select.poll()
    pollable.register(fd, event_mask)

    if timeout:
        event_list = pollable.poll(long(timeout * 1000))
    else:
        event_list = pollable.poll()

    return bool(event_list)


def _select_for(fd, readable, writable, error, timeout):
    """Select polling backend.
    @param fd: File descriptor
    @type fd: int
    @param readable: Whether to wait for readability
    @type readable: bool
    @param writable: Whether to wait for writability
    @type writable: bool
    @param timeout: Deadline timeout (expiration time, in seconds)
    @type timeout: float
    @return True on success, False on timeout
    """
    rset, wset, xset = [], [], []

    if readable:
        rset = [fd]
    if writable:
        wset = [fd]
    if error:
        xset = [fd]

    if timeout is None:
        (rcount, wcount, xcount) = select.select(rset, wset, xset)
    else:
        (rcount, wcount, xcount) = select.select(rset, wset, xset, timeout)

    return bool((rcount or wcount or xcount))


def _wait_for(fd, readable, writable, error, expiration):
    done = False
    while not done:
        if expiration is None:
            timeout = None
        else:
            timeout = expiration - time.time()
            if timeout <= 0.0:
                raise dns.exception.Timeout
        try:
            if not _polling_backend(fd, readable, writable, error, timeout):
                raise dns.exception.Timeout
        except select_error as e:
            if e.args[0] != errno.EINTR:
                raise e
        done = True


def _set_polling_backend(fn):
    """
    Internal API. Do not use.
    """
    global _polling_backend

    _polling_backend = fn

if hasattr(select, 'poll'):
    # Prefer poll() on platforms that support it because it has no
    # limits on the maximum value of a file descriptor (plus it will
    # be more efficient for high values).
    _polling_backend = _poll_for
else:
    _polling_backend = _select_for


def _wait_for_readable(s, expiration):
    _wait_for(s, True, False, True, expiration)


def _wait_for_writable(s, expiration):
    _wait_for(s, False, True, True, expiration)


def _addresses_equal(af, a1, a2):
    # Convert the first value of the tuple, which is a textual format
    # address into binary form, so that we are not confused by different
    # textual representations of the same address
    n1 = dns.inet.inet_pton(af, a1[0])
    n2 = dns.inet.inet_pton(af, a2[0])
    return n1 == n2 and a1[1:] == a2[1:]


def _matches_destination(af, from_address, destination, ignore_unexpected):
    # Check that from_address is appropriate for a response to a query
    # sent to destination.
    if not destination:
        return True
    if _addresses_equal(af, from_address, destination) or (
        dns.inet.is_multicast(destination[0]) and from_address[1:] == destination[1:]
    ):
        return True
    elif ignore_unexpected:
        return False
    raise UnexpectedSource(
        f"got a response from {from_address} instead of " f"{destination}"
    )


def _destination_and_source(af, where, port, source, source_port):
    # Apply defaults and compute destination and source tuples
    # suitable for use in connect(), sendto(), or bind().
    if af is None:
        try:
            af = dns.inet.af_for_address(where)
        except Exception:
            af = dns.inet.AF_INET
    if af == dns.inet.AF_INET:
        destination = (where, port)
        if source is not None or source_port != 0:
            if source is None:
                source = '0.0.0.0'
            source = (source, source_port)
    elif af == dns.inet.AF_INET6:
        destination = (where, port, 0, 0)
        if source is not None or source_port != 0:
            if source is None:
                source = '::'
            source = (source, source_port, 0, 0)
    return (af, destination, source)


def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
        ignore_unexpected=False, one_rr_per_rrset=False, ignore_errors=False):
    """Return the response obtained after sending a query via UDP.

    @param q: the query
    @type q: dns.message.Message
    @param where: where to send the message
    @type where: string containing an IPv4 or IPv6 address
    @param timeout: The number of seconds to wait before the query times out.
    If None, the default, wait forever.
    @type timeout: float
    @param port: The port to which to send the message.  The default is 53.
    @type port: int
    @param af: the address family to use.  The default is None, which
    causes the address family to use to be inferred from the form of where.
    If the inference attempt fails, AF_INET is used.
    @type af: int
    @rtype: dns.message.Message object
    @param source: source address.  The default is the wildcard address.
    @type source: string
    @param source_port: The port from which to send the message.
    The default is 0.
    @type source_port: int
    @param ignore_unexpected: If True, ignore responses from unexpected
    sources.  The default is False.
    @type ignore_unexpected: bool
    @param one_rr_per_rrset: Put each RR into its own RRset
    @type one_rr_per_rrset: bool
    """

    wire = q.to_wire()
    (af, destination, source) = _destination_and_source(af, where, port,
                                                        source, source_port)
    s = socket_factory(af, socket.SOCK_DGRAM, 0)
    begin_time = None
    try:
        expiration = _compute_expiration(timeout)
        s.setblocking(0)
        if source is not None:
            s.bind(source)
        _wait_for_writable(s, expiration)
        begin_time = time.time()
        s.sendto(wire, destination)
        while 1:
            _wait_for_readable(s, expiration)
            (wire, from_address) = s.recvfrom(65535)
            if not _matches_destination(
                s.family, from_address, destination, ignore_unexpected
            ):
                continue

            response_time = time.time() - begin_time

            try:
                r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
                                  one_rr_per_rrset=one_rr_per_rrset)
                r.time = response_time
            except Exception:
                if ignore_errors:
                    continue
                else:
                    raise

            if q.is_response(r):
                return r
            else:
                if ignore_errors:
                    continue
                else:
                    raise BadResponse
    finally:
        s.close()


def _net_read(sock, count, expiration):
    """Read the specified number of bytes from sock.  Keep trying until we
    either get the desired amount, or we hit EOF.
    A Timeout exception will be raised if the operation is not completed
    by the expiration time.
    """
    s = b''
    while count > 0:
        _wait_for_readable(sock, expiration)
        n = sock.recv(count)
        if n == b'':
            raise EOFError
        count = count - len(n)
        s = s + n
    return s


def _net_write(sock, data, expiration):
    """Write the specified data to the socket.
    A Timeout exception will be raised if the operation is not completed
    by the expiration time.
    """
    current = 0
    l = len(data)
    while current < l:
        _wait_for_writable(sock, expiration)
        current += sock.send(data[current:])


def _connect(s, address):
    try:
        s.connect(address)
    except socket.error:
        (ty, v) = sys.exc_info()[:2]

        if hasattr(v, 'errno'):
            v_err = v.errno
        else:
            v_err = v[0]
        if v_err not in [errno.EINPROGRESS, errno.EWOULDBLOCK, errno.EALREADY]:
            raise v


def tcp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
        one_rr_per_rrset=False):
    """Return the response obtained after sending a query via TCP.

    @param q: the query
    @type q: dns.message.Message object
    @param where: where to send the message
    @type where: string containing an IPv4 or IPv6 address
    @param timeout: The number of seconds to wait before the query times out.
    If None, the default, wait forever.
    @type timeout: float
    @param port: The port to which to send the message.  The default is 53.
    @type port: int
    @param af: the address family to use.  The default is None, which
    causes the address family to use to be inferred from the form of where.
    If the inference attempt fails, AF_INET is used.
    @type af: int
    @rtype: dns.message.Message object
    @param source: source address.  The default is the wildcard address.
    @type source: string
    @param source_port: The port from which to send the message.
    The default is 0.
    @type source_port: int
    @param one_rr_per_rrset: Put each RR into its own RRset
    @type one_rr_per_rrset: bool
    """

    wire = q.to_wire()
    (af, destination, source) = _destination_and_source(af, where, port,
                                                        source, source_port)
    s = socket_factory(af, socket.SOCK_STREAM, 0)
    begin_time = None
    try:
        expiration = _compute_expiration(timeout)
        s.setblocking(0)
        begin_time = time.time()
        if source is not None:
            s.bind(source)
        _connect(s, destination)

        l = len(wire)

        # copying the wire into tcpmsg is inefficient, but lets us
        # avoid writev() or doing a short write that would get pushed
        # onto the net
        tcpmsg = struct.pack("!H", l) + wire
        _net_write(s, tcpmsg, expiration)
        ldata = _net_read(s, 2, expiration)
        (l,) = struct.unpack("!H", ldata)
        wire = _net_read(s, l, expiration)
    finally:
        if begin_time is None:
            response_time = 0
        else:
            response_time = time.time() - begin_time
        s.close()
    r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
                              one_rr_per_rrset=one_rr_per_rrset)
    r.time = response_time
    if not q.is_response(r):
        raise BadResponse
    return r


def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
        timeout=None, port=53, keyring=None, keyname=None, relativize=True,
        af=None, lifetime=None, source=None, source_port=0, serial=0,
        use_udp=False, keyalgorithm=dns.tsig.default_algorithm):
    """Return a generator for the responses to a zone transfer.

    @param where: where to send the message
    @type where: string containing an IPv4 or IPv6 address
    @param zone: The name of the zone to transfer
    @type zone: dns.name.Name object or string
    @param rdtype: The type of zone transfer.  The default is
    dns.rdatatype.AXFR.
    @type rdtype: int or string
    @param rdclass: The class of the zone transfer.  The default is
    dns.rdataclass.IN.
    @type rdclass: int or string
    @param timeout: The number of seconds to wait for each response message.
    If None, the default, wait forever.
    @type timeout: float
    @param port: The port to which to send the message.  The default is 53.
    @type port: int
    @param keyring: The TSIG keyring to use
    @type keyring: dict
    @param keyname: The name of the TSIG key to use
    @type keyname: dns.name.Name object or string
    @param relativize: If True, all names in the zone will be relativized to
    the zone origin.  It is essential that the relativize setting matches
    the one specified to dns.zone.from_xfr().
    @type relativize: bool
    @param af: the address family to use.  The default is None, which
    causes the address family to use to be inferred from the form of where.
    If the inference attempt fails, AF_INET is used.
    @type af: int
    @param lifetime: The total number of seconds to spend doing the transfer.
    If None, the default, then there is no limit on the time the transfer may
    take.
    @type lifetime: float
    @rtype: generator of dns.message.Message objects.
    @param source: source address.  The default is the wildcard address.
    @type source: string
    @param source_port: The port from which to send the message.
    The default is 0.
    @type source_port: int
    @param serial: The SOA serial number to use as the base for an IXFR diff
    sequence (only meaningful if rdtype == dns.rdatatype.IXFR).
    @type serial: int
    @param use_udp: Use UDP (only meaningful for IXFR)
    @type use_udp: bool
    @param keyalgorithm: The TSIG algorithm to use; defaults to
    dns.tsig.default_algorithm
    @type keyalgorithm: string
    """

    if isinstance(zone, string_types):
        zone = dns.name.from_text(zone)
    if isinstance(rdtype, string_types):
        rdtype = dns.rdatatype.from_text(rdtype)
    q = dns.message.make_query(zone, rdtype, rdclass)
    if rdtype == dns.rdatatype.IXFR:
        rrset = dns.rrset.from_text(zone, 0, 'IN', 'SOA',
                                    '. . %u 0 0 0 0' % serial)
        q.authority.append(rrset)
    if keyring is not None:
        q.use_tsig(keyring, keyname, algorithm=keyalgorithm)
    wire = q.to_wire()
    (af, destination, source) = _destination_and_source(af, where, port,
                                                        source, source_port)
    if use_udp:
        if rdtype != dns.rdatatype.IXFR:
            raise ValueError('cannot do a UDP AXFR')
        s = socket_factory(af, socket.SOCK_DGRAM, 0)
    else:
        s = socket_factory(af, socket.SOCK_STREAM, 0)
    s.setblocking(0)
    if source is not None:
        s.bind(source)
    expiration = _compute_expiration(lifetime)
    _connect(s, destination)
    l = len(wire)
    if use_udp:
        _wait_for_writable(s, expiration)
        s.send(wire)
    else:
        tcpmsg = struct.pack("!H", l) + wire
        _net_write(s, tcpmsg, expiration)
    done = False
    delete_mode = True
    expecting_SOA = False
    soa_rrset = None
    if relativize:
        origin = zone
        oname = dns.name.empty
    else:
        origin = None
        oname = zone
    tsig_ctx = None
    first = True
    while not done:
        mexpiration = _compute_expiration(timeout)
        if mexpiration is None or \
           (expiration is not None and mexpiration > expiration):
            mexpiration = expiration
        if use_udp:
            _wait_for_readable(s, expiration)
            (wire, from_address) = s.recvfrom(65535)
        else:
            ldata = _net_read(s, 2, mexpiration)
            (l,) = struct.unpack("!H", ldata)
            wire = _net_read(s, l, mexpiration)
        is_ixfr = (rdtype == dns.rdatatype.IXFR)
        r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
                                  xfr=True, origin=origin, tsig_ctx=tsig_ctx,
                                  multi=True, first=first,
                                  one_rr_per_rrset=is_ixfr)
        tsig_ctx = r.tsig_ctx
        first = False
        answer_index = 0
        if soa_rrset is None:
            if not r.answer or r.answer[0].name != oname:
                raise dns.exception.FormError(
                    "No answer or RRset not for qname")
            rrset = r.answer[0]
            if rrset.rdtype != dns.rdatatype.SOA:
                raise dns.exception.FormError("first RRset is not an SOA")
            answer_index = 1
            soa_rrset = rrset.copy()
            if rdtype == dns.rdatatype.IXFR:
                if soa_rrset[0].serial <= serial:
                    #
                    # We're already up-to-date.
                    #
                    done = True
                else:
                    expecting_SOA = True
        #
        # Process SOAs in the answer section (other than the initial
        # SOA in the first message).
        #
        for rrset in r.answer[answer_index:]:
            if done:
                raise dns.exception.FormError("answers after final SOA")
            if rrset.rdtype == dns.rdatatype.SOA and rrset.name == oname:
                if expecting_SOA:
                    if rrset[0].serial != serial:
                        raise dns.exception.FormError(
                            "IXFR base serial mismatch")
                    expecting_SOA = False
                elif rdtype == dns.rdatatype.IXFR:
                    delete_mode = not delete_mode
                #
                # If this SOA RRset is equal to the first we saw then we're
                # finished. If this is an IXFR we also check that we're seeing
                # the record in the expected part of the response.
                #
                if rrset == soa_rrset and \
                        (rdtype == dns.rdatatype.AXFR or
                         (rdtype == dns.rdatatype.IXFR and delete_mode)):
                    done = True
            elif expecting_SOA:
                #
                # We made an IXFR request and are expecting another
                # SOA RR, but saw something else, so this must be an
                # AXFR response.
                #
                rdtype = dns.rdatatype.AXFR
                expecting_SOA = False
        if done and q.keyring and not r.had_tsig:
            raise dns.exception.FormError("missing TSIG")
        yield r
    s.close()
rdata.py000064400000035225150351404340006217 0ustar00# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS rdata.

@var _rdata_modules: A dictionary mapping a (rdclass, rdtype) tuple to
the module which implements that type.
@type _rdata_modules: dict
@var _module_prefix: The prefix to use when forming modules names.  The
default is 'dns.rdtypes'.  Changing this value will break the library.
@type _module_prefix: string
@var _hex_chunk: At most this many octets that will be represented in each
chunk of hexstring that _hexify() produces before whitespace occurs.
@type _hex_chunk: int"""

from io import BytesIO
import base64
import binascii

import dns.exception
import dns.name
import dns.rdataclass
import dns.rdatatype
import dns.tokenizer
import dns.wiredata
from ._compat import xrange, string_types, text_type

_hex_chunksize = 32


def _hexify(data, chunksize=_hex_chunksize):
    """Convert a binary string into its hex encoding, broken up into chunks
    of I{chunksize} characters separated by a space.

    @param data: the binary string
    @type data: string
    @param chunksize: the chunk size.  Default is L{dns.rdata._hex_chunksize}
    @rtype: string
    """

    line = binascii.hexlify(data)
    return b' '.join([line[i:i + chunksize]
                      for i
                      in range(0, len(line), chunksize)]).decode()

_base64_chunksize = 32


def _base64ify(data, chunksize=_base64_chunksize):
    """Convert a binary string into its base64 encoding, broken up into chunks
    of I{chunksize} characters separated by a space.

    @param data: the binary string
    @type data: string
    @param chunksize: the chunk size.  Default is
    L{dns.rdata._base64_chunksize}
    @rtype: string
    """

    line = base64.b64encode(data)
    return b' '.join([line[i:i + chunksize]
                      for i
                      in range(0, len(line), chunksize)]).decode()

__escaped = bytearray(b'"\\')

def _escapify(qstring):
    """Escape the characters in a quoted string which need it.

    @param qstring: the string
    @type qstring: string
    @returns: the escaped string
    @rtype: string
    """

    if isinstance(qstring, text_type):
        qstring = qstring.encode()
    if not isinstance(qstring, bytearray):
        qstring = bytearray(qstring)

    text = ''
    for c in qstring:
        if c in __escaped:
            text += '\\' + chr(c)
        elif c >= 0x20 and c < 0x7F:
            text += chr(c)
        else:
            text += '\\%03d' % c
    return text


def _truncate_bitmap(what):
    """Determine the index of greatest byte that isn't all zeros, and
    return the bitmap that contains all the bytes less than that index.

    @param what: a string of octets representing a bitmap.
    @type what: string
    @rtype: string
    """

    for i in xrange(len(what) - 1, -1, -1):
        if what[i] != 0:
            return what[0: i + 1]
    return what[0:1]


class Rdata(object):

    """Base class for all DNS rdata types.
    """

    __slots__ = ['rdclass', 'rdtype']

    def __init__(self, rdclass, rdtype):
        """Initialize an rdata.
        @param rdclass: The rdata class
        @type rdclass: int
        @param rdtype: The rdata type
        @type rdtype: int
        """

        self.rdclass = rdclass
        self.rdtype = rdtype

    def covers(self):
        """DNS SIG/RRSIG rdatas apply to a specific type; this type is
        returned by the covers() function.  If the rdata type is not
        SIG or RRSIG, dns.rdatatype.NONE is returned.  This is useful when
        creating rdatasets, allowing the rdataset to contain only RRSIGs
        of a particular type, e.g. RRSIG(NS).
        @rtype: int
        """

        return dns.rdatatype.NONE

    def extended_rdatatype(self):
        """Return a 32-bit type value, the least significant 16 bits of
        which are the ordinary DNS type, and the upper 16 bits of which are
        the "covered" type, if any.
        @rtype: int
        """

        return self.covers() << 16 | self.rdtype

    def to_text(self, origin=None, relativize=True, **kw):
        """Convert an rdata to text format.
        @rtype: string
        """
        raise NotImplementedError

    def to_wire(self, file, compress=None, origin=None):
        """Convert an rdata to wire format.
        @rtype: string
        """

        raise NotImplementedError

    def to_digestable(self, origin=None):
        """Convert rdata to a format suitable for digesting in hashes.  This
        is also the DNSSEC canonical form."""
        f = BytesIO()
        self.to_wire(f, None, origin)
        return f.getvalue()

    def validate(self):
        """Check that the current contents of the rdata's fields are
        valid.  If you change an rdata by assigning to its fields,
        it is a good idea to call validate() when you are done making
        changes.
        """
        dns.rdata.from_text(self.rdclass, self.rdtype, self.to_text())

    def __repr__(self):
        covers = self.covers()
        if covers == dns.rdatatype.NONE:
            ctext = ''
        else:
            ctext = '(' + dns.rdatatype.to_text(covers) + ')'
        return '<DNS ' + dns.rdataclass.to_text(self.rdclass) + ' ' + \
               dns.rdatatype.to_text(self.rdtype) + ctext + ' rdata: ' + \
               str(self) + '>'

    def __str__(self):
        return self.to_text()

    def _cmp(self, other):
        """Compare an rdata with another rdata of the same rdtype and
        rdclass.  Return < 0 if self < other in the DNSSEC ordering,
        0 if self == other, and > 0 if self > other.
        """
        our = self.to_digestable(dns.name.root)
        their = other.to_digestable(dns.name.root)
        if our == their:
            return 0
        if our > their:
            return 1

        return -1

    def __eq__(self, other):
        if not isinstance(other, Rdata):
            return False
        if self.rdclass != other.rdclass or self.rdtype != other.rdtype:
            return False
        return self._cmp(other) == 0

    def __ne__(self, other):
        if not isinstance(other, Rdata):
            return True
        if self.rdclass != other.rdclass or self.rdtype != other.rdtype:
            return True
        return self._cmp(other) != 0

    def __lt__(self, other):
        if not isinstance(other, Rdata) or \
                self.rdclass != other.rdclass or self.rdtype != other.rdtype:

            return NotImplemented
        return self._cmp(other) < 0

    def __le__(self, other):
        if not isinstance(other, Rdata) or \
                self.rdclass != other.rdclass or self.rdtype != other.rdtype:
            return NotImplemented
        return self._cmp(other) <= 0

    def __ge__(self, other):
        if not isinstance(other, Rdata) or \
                self.rdclass != other.rdclass or self.rdtype != other.rdtype:
            return NotImplemented
        return self._cmp(other) >= 0

    def __gt__(self, other):
        if not isinstance(other, Rdata) or \
                self.rdclass != other.rdclass or self.rdtype != other.rdtype:
            return NotImplemented
        return self._cmp(other) > 0

    def __hash__(self):
        return hash(self.to_digestable(dns.name.root))

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        """Build an rdata object from text format.

        @param rdclass: The rdata class
        @type rdclass: int
        @param rdtype: The rdata type
        @type rdtype: int
        @param tok: The tokenizer
        @type tok: dns.tokenizer.Tokenizer
        @param origin: The origin to use for relative names
        @type origin: dns.name.Name
        @param relativize: should names be relativized?
        @type relativize: bool
        @rtype: dns.rdata.Rdata instance
        """

        raise NotImplementedError

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        """Build an rdata object from wire format

        @param rdclass: The rdata class
        @type rdclass: int
        @param rdtype: The rdata type
        @type rdtype: int
        @param wire: The wire-format message
        @type wire: string
        @param current: The offset in wire of the beginning of the rdata.
        @type current: int
        @param rdlen: The length of the wire-format rdata
        @type rdlen: int
        @param origin: The origin to use for relative names
        @type origin: dns.name.Name
        @rtype: dns.rdata.Rdata instance
        """

        raise NotImplementedError

    def choose_relativity(self, origin=None, relativize=True):
        """Convert any domain names in the rdata to the specified
        relativization.
        """

        pass


class GenericRdata(Rdata):

    """Generate Rdata Class

    This class is used for rdata types for which we have no better
    implementation.  It implements the DNS "unknown RRs" scheme.
    """

    __slots__ = ['data']

    def __init__(self, rdclass, rdtype, data):
        super(GenericRdata, self).__init__(rdclass, rdtype)
        self.data = data

    def to_text(self, origin=None, relativize=True, **kw):
        return r'\# %d ' % len(self.data) + _hexify(self.data)

    @classmethod
    def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
        token = tok.get()
        if not token.is_identifier() or token.value != '\#':
            raise dns.exception.SyntaxError(
                r'generic rdata does not start with \#')
        length = tok.get_int()
        chunks = []
        while 1:
            token = tok.get()
            if token.is_eol_or_eof():
                break
            chunks.append(token.value.encode())
        hex = b''.join(chunks)
        data = binascii.unhexlify(hex)
        if len(data) != length:
            raise dns.exception.SyntaxError(
                'generic rdata hex data has wrong length')
        return cls(rdclass, rdtype, data)

    def to_wire(self, file, compress=None, origin=None):
        file.write(self.data)

    @classmethod
    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
        return cls(rdclass, rdtype, wire[current: current + rdlen])

_rdata_modules = {}
_module_prefix = 'dns.rdtypes'


def get_rdata_class(rdclass, rdtype):

    def import_module(name):
        mod = __import__(name)
        components = name.split('.')
        for comp in components[1:]:
            mod = getattr(mod, comp)
        return mod

    mod = _rdata_modules.get((rdclass, rdtype))
    rdclass_text = dns.rdataclass.to_text(rdclass)
    rdtype_text = dns.rdatatype.to_text(rdtype)
    rdtype_text = rdtype_text.replace('-', '_')
    if not mod:
        mod = _rdata_modules.get((dns.rdatatype.ANY, rdtype))
        if not mod:
            try:
                mod = import_module('.'.join([_module_prefix,
                                              rdclass_text, rdtype_text]))
                _rdata_modules[(rdclass, rdtype)] = mod
            except ImportError:
                try:
                    mod = import_module('.'.join([_module_prefix,
                                                  'ANY', rdtype_text]))
                    _rdata_modules[(dns.rdataclass.ANY, rdtype)] = mod
                except ImportError:
                    mod = None
    if mod:
        cls = getattr(mod, rdtype_text)
    else:
        cls = GenericRdata
    return cls


def from_text(rdclass, rdtype, tok, origin=None, relativize=True):
    """Build an rdata object from text format.

    This function attempts to dynamically load a class which
    implements the specified rdata class and type.  If there is no
    class-and-type-specific implementation, the GenericRdata class
    is used.

    Once a class is chosen, its from_text() class method is called
    with the parameters to this function.

    If I{tok} is a string, then a tokenizer is created and the string
    is used as its input.

    @param rdclass: The rdata class
    @type rdclass: int
    @param rdtype: The rdata type
    @type rdtype: int
    @param tok: The tokenizer or input text
    @type tok: dns.tokenizer.Tokenizer or string
    @param origin: The origin to use for relative names
    @type origin: dns.name.Name
    @param relativize: Should names be relativized?
    @type relativize: bool
    @rtype: dns.rdata.Rdata instance"""

    if isinstance(tok, string_types):
        tok = dns.tokenizer.Tokenizer(tok)
    cls = get_rdata_class(rdclass, rdtype)
    if cls != GenericRdata:
        # peek at first token
        token = tok.get()
        tok.unget(token)
        if token.is_identifier() and \
           token.value == r'\#':
            #
            # Known type using the generic syntax.  Extract the
            # wire form from the generic syntax, and then run
            # from_wire on it.
            #
            rdata = GenericRdata.from_text(rdclass, rdtype, tok, origin,
                                           relativize)
            return from_wire(rdclass, rdtype, rdata.data, 0, len(rdata.data),
                             origin)
    return cls.from_text(rdclass, rdtype, tok, origin, relativize)


def from_wire(rdclass, rdtype, wire, current, rdlen, origin=None):
    """Build an rdata object from wire format

    This function attempts to dynamically load a class which
    implements the specified rdata class and type.  If there is no
    class-and-type-specific implementation, the GenericRdata class
    is used.

    Once a class is chosen, its from_wire() class method is called
    with the parameters to this function.

    @param rdclass: The rdata class
    @type rdclass: int
    @param rdtype: The rdata type
    @type rdtype: int
    @param wire: The wire-format message
    @type wire: string
    @param current: The offset in wire of the beginning of the rdata.
    @type current: int
    @param rdlen: The length of the wire-format rdata
    @type rdlen: int
    @param origin: The origin to use for relative names
    @type origin: dns.name.Name
    @rtype: dns.rdata.Rdata instance"""

    wire = dns.wiredata.maybe_wrap(wire)
    cls = get_rdata_class(rdclass, rdtype)
    return cls.from_wire(rdclass, rdtype, wire, current, rdlen, origin)
rdatatype.py000064400000012333150351404340007114 0ustar00# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS Rdata Types.

@var _by_text: The rdata type textual name to value mapping
@type _by_text: dict
@var _by_value: The rdata type value to textual name mapping
@type _by_value: dict
@var _metatypes: If an rdatatype is a metatype, there will be a mapping
whose key is the rdatatype value and whose value is True in this dictionary.
@type _metatypes: dict
@var _singletons: If an rdatatype is a singleton, there will be a mapping
whose key is the rdatatype value and whose value is True in this dictionary.
@type _singletons: dict"""

import re

import dns.exception

NONE = 0
A = 1
NS = 2
MD = 3
MF = 4
CNAME = 5
SOA = 6
MB = 7
MG = 8
MR = 9
NULL = 10
WKS = 11
PTR = 12
HINFO = 13
MINFO = 14
MX = 15
TXT = 16
RP = 17
AFSDB = 18
X25 = 19
ISDN = 20
RT = 21
NSAP = 22
NSAP_PTR = 23
SIG = 24
KEY = 25
PX = 26
GPOS = 27
AAAA = 28
LOC = 29
NXT = 30
SRV = 33
NAPTR = 35
KX = 36
CERT = 37
A6 = 38
DNAME = 39
OPT = 41
APL = 42
DS = 43
SSHFP = 44
IPSECKEY = 45
RRSIG = 46
NSEC = 47
DNSKEY = 48
DHCID = 49
NSEC3 = 50
NSEC3PARAM = 51
TLSA = 52
HIP = 55
CDS = 59
CDNSKEY = 60
CSYNC = 62
SPF = 99
UNSPEC = 103
EUI48 = 108
EUI64 = 109
TKEY = 249
TSIG = 250
IXFR = 251
AXFR = 252
MAILB = 253
MAILA = 254
ANY = 255
URI = 256
CAA = 257
AVC = 258
TA = 32768
DLV = 32769

_by_text = {
    'NONE': NONE,
    'A': A,
    'NS': NS,
    'MD': MD,
    'MF': MF,
    'CNAME': CNAME,
    'SOA': SOA,
    'MB': MB,
    'MG': MG,
    'MR': MR,
    'NULL': NULL,
    'WKS': WKS,
    'PTR': PTR,
    'HINFO': HINFO,
    'MINFO': MINFO,
    'MX': MX,
    'TXT': TXT,
    'RP': RP,
    'AFSDB': AFSDB,
    'X25': X25,
    'ISDN': ISDN,
    'RT': RT,
    'NSAP': NSAP,
    'NSAP-PTR': NSAP_PTR,
    'SIG': SIG,
    'KEY': KEY,
    'PX': PX,
    'GPOS': GPOS,
    'AAAA': AAAA,
    'LOC': LOC,
    'NXT': NXT,
    'SRV': SRV,
    'NAPTR': NAPTR,
    'KX': KX,
    'CERT': CERT,
    'A6': A6,
    'DNAME': DNAME,
    'OPT': OPT,
    'APL': APL,
    'DS': DS,
    'SSHFP': SSHFP,
    'IPSECKEY': IPSECKEY,
    'RRSIG': RRSIG,
    'NSEC': NSEC,
    'DNSKEY': DNSKEY,
    'DHCID': DHCID,
    'NSEC3': NSEC3,
    'NSEC3PARAM': NSEC3PARAM,
    'TLSA': TLSA,
    'HIP': HIP,
    'CDS': CDS,
    'CDNSKEY': CDNSKEY,
    'CSYNC': CSYNC,
    'SPF': SPF,
    'UNSPEC': UNSPEC,
    'EUI48': EUI48,
    'EUI64': EUI64,
    'TKEY': TKEY,
    'TSIG': TSIG,
    'IXFR': IXFR,
    'AXFR': AXFR,
    'MAILB': MAILB,
    'MAILA': MAILA,
    'ANY': ANY,
    'URI': URI,
    'CAA': CAA,
    'AVC': AVC,
    'TA': TA,
    'DLV': DLV,
}

# We construct the inverse mapping programmatically to ensure that we
# cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
# would cause the mapping not to be true inverse.

_by_value = dict((y, x) for x, y in _by_text.items())


_metatypes = {
    OPT: True
}

_singletons = {
    SOA: True,
    NXT: True,
    DNAME: True,
    NSEC: True,
    # CNAME is technically a singleton, but we allow multiple CNAMEs.
}

_unknown_type_pattern = re.compile('TYPE([0-9]+)$', re.I)


class UnknownRdatatype(dns.exception.DNSException):

    """DNS resource record type is unknown."""


def from_text(text):
    """Convert text into a DNS rdata type value.
    @param text: the text
    @type text: string
    @raises dns.rdatatype.UnknownRdatatype: the type is unknown
    @raises ValueError: the rdata type value is not >= 0 and <= 65535
    @rtype: int"""

    value = _by_text.get(text.upper())
    if value is None:
        match = _unknown_type_pattern.match(text)
        if match is None:
            raise UnknownRdatatype
        value = int(match.group(1))
        if value < 0 or value > 65535:
            raise ValueError("type must be between >= 0 and <= 65535")
    return value


def to_text(value):
    """Convert a DNS rdata type to text.
    @param value: the rdata type value
    @type value: int
    @raises ValueError: the rdata type value is not >= 0 and <= 65535
    @rtype: string"""

    if value < 0 or value > 65535:
        raise ValueError("type must be between >= 0 and <= 65535")
    text = _by_value.get(value)
    if text is None:
        text = 'TYPE' + repr(value)
    return text


def is_metatype(rdtype):
    """True if the type is a metatype.
    @param rdtype: the type
    @type rdtype: int
    @rtype: bool"""

    if rdtype >= TKEY and rdtype <= ANY or rdtype in _metatypes:
        return True
    return False


def is_singleton(rdtype):
    """True if the type is a singleton.
    @param rdtype: the type
    @type rdtype: int
    @rtype: bool"""

    if rdtype in _singletons:
        return True
    return False
wiredata.py000064400000007223150351404340006721 0ustar00# Copyright (C) 2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS Wire Data Helper"""

import sys

import dns.exception
from ._compat import binary_type, string_types

# Figure out what constant python passes for an unspecified slice bound.
# It's supposed to be sys.maxint, yet on 64-bit windows sys.maxint is 2^31 - 1
# but Python uses 2^63 - 1 as the constant.  Rather than making pointless
# extra comparisons, duplicating code, or weakening WireData, we just figure
# out what constant Python will use.


class _SliceUnspecifiedBound(binary_type):

    def __getitem__(self, key):
        return key.stop

    if sys.version_info < (3,):
        def __getslice__(self, i, j):  # pylint: disable=getslice-method
            return self.__getitem__(slice(i, j))

_unspecified_bound = _SliceUnspecifiedBound()[1:]


class WireData(binary_type):
    # WireData is a string with stricter slicing

    def __getitem__(self, key):
        try:
            if isinstance(key, slice):
                # make sure we are not going outside of valid ranges,
                # do stricter control of boundaries than python does
                # by default
                start = key.start
                stop = key.stop

                if sys.version_info < (3,):
                    if stop == _unspecified_bound:
                        # handle the case where the right bound is unspecified
                        stop = len(self)

                    if start < 0 or stop < 0:
                        raise dns.exception.FormError
                    # If it's not an empty slice, access left and right bounds
                    # to make sure they're valid
                    if start != stop:
                        super(WireData, self).__getitem__(start)
                        super(WireData, self).__getitem__(stop - 1)
                else:
                    for index in (start, stop):
                        if index is None:
                            continue
                        elif abs(index) > len(self):
                            raise dns.exception.FormError

                return WireData(super(WireData, self).__getitem__(
                    slice(start, stop)))
            return bytearray(self.unwrap())[key]
        except IndexError:
            raise dns.exception.FormError

    if sys.version_info < (3,):
        def __getslice__(self, i, j):  # pylint: disable=getslice-method
            return self.__getitem__(slice(i, j))

    def __iter__(self):
        i = 0
        while 1:
            try:
                yield self[i]
                i += 1
            except dns.exception.FormError:
                raise StopIteration

    def unwrap(self):
        return binary_type(self)


def maybe_wrap(wire):
    if isinstance(wire, WireData):
        return wire
    elif isinstance(wire, binary_type):
        return WireData(wire)
    elif isinstance(wire, string_types):
        return WireData(wire.encode())
    raise ValueError("unhandled type %s" % type(wire))
set.py000064400000017043150351404340005715 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""A simple Set class."""


class Set(object):

    """A simple set class.

    Sets are not in Python until 2.3, and rdata are not immutable so
    we cannot use sets.Set anyway.  This class implements subset of
    the 2.3 Set interface using a list as the container.

    @ivar items: A list of the items which are in the set
    @type items: list"""

    __slots__ = ['items']

    def __init__(self, items=None):
        """Initialize the set.

        @param items: the initial set of items
        @type items: any iterable or None
        """

        self.items = []
        if items is not None:
            for item in items:
                self.add(item)

    def __repr__(self):
        return "dns.simpleset.Set(%s)" % repr(self.items)

    def add(self, item):
        """Add an item to the set."""
        if item not in self.items:
            self.items.append(item)

    def remove(self, item):
        """Remove an item from the set."""
        self.items.remove(item)

    def discard(self, item):
        """Remove an item from the set if present."""
        try:
            self.items.remove(item)
        except ValueError:
            pass

    def _clone(self):
        """Make a (shallow) copy of the set.

        There is a 'clone protocol' that subclasses of this class
        should use.  To make a copy, first call your super's _clone()
        method, and use the object returned as the new instance.  Then
        make shallow copies of the attributes defined in the subclass.

        This protocol allows us to write the set algorithms that
        return new instances (e.g. union) once, and keep using them in
        subclasses.
        """

        cls = self.__class__
        obj = cls.__new__(cls)
        obj.items = list(self.items)
        return obj

    def __copy__(self):
        """Make a (shallow) copy of the set."""
        return self._clone()

    def copy(self):
        """Make a (shallow) copy of the set."""
        return self._clone()

    def union_update(self, other):
        """Update the set, adding any elements from other which are not
        already in the set.
        @param other: the collection of items with which to update the set
        @type other: Set object
        """
        if not isinstance(other, Set):
            raise ValueError('other must be a Set instance')
        if self is other:
            return
        for item in other.items:
            self.add(item)

    def intersection_update(self, other):
        """Update the set, removing any elements from other which are not
        in both sets.
        @param other: the collection of items with which to update the set
        @type other: Set object
        """
        if not isinstance(other, Set):
            raise ValueError('other must be a Set instance')
        if self is other:
            return
        # we make a copy of the list so that we can remove items from
        # the list without breaking the iterator.
        for item in list(self.items):
            if item not in other.items:
                self.items.remove(item)

    def difference_update(self, other):
        """Update the set, removing any elements from other which are in
        the set.
        @param other: the collection of items with which to update the set
        @type other: Set object
        """
        if not isinstance(other, Set):
            raise ValueError('other must be a Set instance')
        if self is other:
            self.items = []
        else:
            for item in other.items:
                self.discard(item)

    def union(self, other):
        """Return a new set which is the union of I{self} and I{other}.

        @param other: the other set
        @type other: Set object
        @rtype: the same type as I{self}
        """

        obj = self._clone()
        obj.union_update(other)
        return obj

    def intersection(self, other):
        """Return a new set which is the intersection of I{self} and I{other}.

        @param other: the other set
        @type other: Set object
        @rtype: the same type as I{self}
        """

        obj = self._clone()
        obj.intersection_update(other)
        return obj

    def difference(self, other):
        """Return a new set which I{self} - I{other}, i.e. the items
        in I{self} which are not also in I{other}.

        @param other: the other set
        @type other: Set object
        @rtype: the same type as I{self}
        """

        obj = self._clone()
        obj.difference_update(other)
        return obj

    def __or__(self, other):
        return self.union(other)

    def __and__(self, other):
        return self.intersection(other)

    def __add__(self, other):
        return self.union(other)

    def __sub__(self, other):
        return self.difference(other)

    def __ior__(self, other):
        self.union_update(other)
        return self

    def __iand__(self, other):
        self.intersection_update(other)
        return self

    def __iadd__(self, other):
        self.union_update(other)
        return self

    def __isub__(self, other):
        self.difference_update(other)
        return self

    def update(self, other):
        """Update the set, adding any elements from other which are not
        already in the set.
        @param other: the collection of items with which to update the set
        @type other: any iterable type"""
        for item in other:
            self.add(item)

    def clear(self):
        """Make the set empty."""
        self.items = []

    def __eq__(self, other):
        # Yes, this is inefficient but the sets we're dealing with are
        # usually quite small, so it shouldn't hurt too much.
        for item in self.items:
            if item not in other.items:
                return False
        for item in other.items:
            if item not in self.items:
                return False
        return True

    def __ne__(self, other):
        return not self.__eq__(other)

    def __len__(self):
        return len(self.items)

    def __iter__(self):
        return iter(self.items)

    def __getitem__(self, i):
        return self.items[i]

    def __delitem__(self, i):
        del self.items[i]

    def issubset(self, other):
        """Is I{self} a subset of I{other}?

        @rtype: bool
        """

        if not isinstance(other, Set):
            raise ValueError('other must be a Set instance')
        for item in self.items:
            if item not in other.items:
                return False
        return True

    def issuperset(self, other):
        """Is I{self} a superset of I{other}?

        @rtype: bool
        """

        if not isinstance(other, Set):
            raise ValueError('other must be a Set instance')
        for item in other.items:
            if item not in self.items:
                return False
        return True
flags.py000064400000005150150351404340006212 0ustar00# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS Message Flags."""

# Standard DNS flags

QR = 0x8000
AA = 0x0400
TC = 0x0200
RD = 0x0100
RA = 0x0080
AD = 0x0020
CD = 0x0010

# EDNS flags

DO = 0x8000

_by_text = {
    'QR': QR,
    'AA': AA,
    'TC': TC,
    'RD': RD,
    'RA': RA,
    'AD': AD,
    'CD': CD
}

_edns_by_text = {
    'DO': DO
}


# We construct the inverse mappings programmatically to ensure that we
# cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
# would cause the mappings not to be true inverses.

_by_value = dict((y, x) for x, y in _by_text.items())

_edns_by_value = dict((y, x) for x, y in _edns_by_text.items())


def _order_flags(table):
    order = list(table.items())
    order.sort()
    order.reverse()
    return order

_flags_order = _order_flags(_by_value)

_edns_flags_order = _order_flags(_edns_by_value)


def _from_text(text, table):
    flags = 0
    tokens = text.split()
    for t in tokens:
        flags = flags | table[t.upper()]
    return flags


def _to_text(flags, table, order):
    text_flags = []
    for k, v in order:
        if flags & k != 0:
            text_flags.append(v)
    return ' '.join(text_flags)


def from_text(text):
    """Convert a space-separated list of flag text values into a flags
    value.
    @rtype: int"""

    return _from_text(text, _by_text)


def to_text(flags):
    """Convert a flags value into a space-separated list of flag text
    values.
    @rtype: string"""

    return _to_text(flags, _by_value, _flags_order)


def edns_from_text(text):
    """Convert a space-separated list of EDNS flag text values into a EDNS
    flags value.
    @rtype: int"""

    return _from_text(text, _edns_by_text)


def edns_to_text(flags):
    """Convert an EDNS flags value into a space-separated list of EDNS flag
    text values.
    @rtype: string"""

    return _to_text(flags, _edns_by_value, _edns_flags_order)
zone.py000064400000116132150351404340006074 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS Zones."""

from __future__ import generators

import sys
import re
import os
from io import BytesIO

import dns.exception
import dns.name
import dns.node
import dns.rdataclass
import dns.rdatatype
import dns.rdata
import dns.rrset
import dns.tokenizer
import dns.ttl
import dns.grange
from ._compat import string_types, text_type


_py3 = sys.version_info > (3,)


class BadZone(dns.exception.DNSException):

    """The DNS zone is malformed."""


class NoSOA(BadZone):

    """The DNS zone has no SOA RR at its origin."""


class NoNS(BadZone):

    """The DNS zone has no NS RRset at its origin."""


class UnknownOrigin(BadZone):

    """The DNS zone's origin is unknown."""


class Zone(object):

    """A DNS zone.

    A Zone is a mapping from names to nodes.  The zone object may be
    treated like a Python dictionary, e.g. zone[name] will retrieve
    the node associated with that name.  The I{name} may be a
    dns.name.Name object, or it may be a string.  In the either case,
    if the name is relative it is treated as relative to the origin of
    the zone.

    @ivar rdclass: The zone's rdata class; the default is class IN.
    @type rdclass: int
    @ivar origin: The origin of the zone.
    @type origin: dns.name.Name object
    @ivar nodes: A dictionary mapping the names of nodes in the zone to the
    nodes themselves.
    @type nodes: dict
    @ivar relativize: should names in the zone be relativized?
    @type relativize: bool
    @cvar node_factory: the factory used to create a new node
    @type node_factory: class or callable
    """

    node_factory = dns.node.Node

    __slots__ = ['rdclass', 'origin', 'nodes', 'relativize']

    def __init__(self, origin, rdclass=dns.rdataclass.IN, relativize=True):
        """Initialize a zone object.

        @param origin: The origin of the zone.
        @type origin: dns.name.Name object
        @param rdclass: The zone's rdata class; the default is class IN.
        @type rdclass: int"""

        if origin is not None:
            if isinstance(origin, string_types):
                origin = dns.name.from_text(origin)
            elif not isinstance(origin, dns.name.Name):
                raise ValueError("origin parameter must be convertible to a "
                                 "DNS name")
            if not origin.is_absolute():
                raise ValueError("origin parameter must be an absolute name")
        self.origin = origin
        self.rdclass = rdclass
        self.nodes = {}
        self.relativize = relativize

    def __eq__(self, other):
        """Two zones are equal if they have the same origin, class, and
        nodes.
        @rtype: bool
        """

        if not isinstance(other, Zone):
            return False
        if self.rdclass != other.rdclass or \
           self.origin != other.origin or \
           self.nodes != other.nodes:
            return False
        return True

    def __ne__(self, other):
        """Are two zones not equal?
        @rtype: bool
        """

        return not self.__eq__(other)

    def _validate_name(self, name):
        if isinstance(name, string_types):
            name = dns.name.from_text(name, None)
        elif not isinstance(name, 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 __getitem__(self, key):
        key = self._validate_name(key)
        return self.nodes[key]

    def __setitem__(self, key, value):
        key = self._validate_name(key)
        self.nodes[key] = value

    def __delitem__(self, key):
        key = self._validate_name(key)
        del self.nodes[key]

    def __iter__(self):
        return self.nodes.__iter__()

    def iterkeys(self):
        if _py3:
            return self.nodes.keys()
        else:
            return self.nodes.iterkeys()  # pylint: disable=dict-iter-method

    def keys(self):
        return self.nodes.keys()

    def itervalues(self):
        if _py3:
            return self.nodes.values()
        else:
            return self.nodes.itervalues()  # pylint: disable=dict-iter-method

    def values(self):
        return self.nodes.values()

    def items(self):
        return self.nodes.items()

    iteritems = items

    def get(self, key):
        key = self._validate_name(key)
        return self.nodes.get(key)

    def __contains__(self, other):
        return other in self.nodes

    def find_node(self, name, create=False):
        """Find a node in the zone, possibly creating it.

        @param name: the name of the node to find
        @type name: dns.name.Name object or string
        @param create: should the node be created if it doesn't exist?
        @type create: bool
        @raises KeyError: the name is not known and create was not specified.
        @rtype: dns.node.Node object
        """

        name = self._validate_name(name)
        node = self.nodes.get(name)
        if node is None:
            if not create:
                raise KeyError
            node = self.node_factory()
            self.nodes[name] = node
        return node

    def get_node(self, name, create=False):
        """Get a node in the zone, possibly creating it.

        This method is like L{find_node}, except it returns None instead
        of raising an exception if the node does not exist and creation
        has not been requested.

        @param name: the name of the node to find
        @type name: dns.name.Name object or string
        @param create: should the node be created if it doesn't exist?
        @type create: bool
        @rtype: dns.node.Node object or None
        """

        try:
            node = self.find_node(name, create)
        except KeyError:
            node = None
        return node

    def delete_node(self, name):
        """Delete the specified node if it exists.

        It is not an error if the node does not exist.
        """

        name = self._validate_name(name)
        if name in self.nodes:
            del self.nodes[name]

    def find_rdataset(self, name, rdtype, covers=dns.rdatatype.NONE,
                      create=False):
        """Look for rdata with the specified name and type in the zone,
        and return an rdataset encapsulating it.

        The I{name}, I{rdtype}, and I{covers} parameters may be
        strings, in which case they will be converted to their proper
        type.

        The rdataset returned is not a copy; changes to it will change
        the zone.

        KeyError is raised if the name or type are not found.
        Use L{get_rdataset} if you want to have None returned instead.

        @param name: the owner name to look for
        @type name: DNS.name.Name object or string
        @param rdtype: the rdata type desired
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        @param create: should the node and rdataset be created if they do not
        exist?
        @type create: bool
        @raises KeyError: the node or rdata could not be found
        @rtype: dns.rrset.RRset object
        """

        name = self._validate_name(name)
        if isinstance(rdtype, string_types):
            rdtype = dns.rdatatype.from_text(rdtype)
        if isinstance(covers, string_types):
            covers = dns.rdatatype.from_text(covers)
        node = self.find_node(name, create)
        return node.find_rdataset(self.rdclass, rdtype, covers, create)

    def get_rdataset(self, name, rdtype, covers=dns.rdatatype.NONE,
                     create=False):
        """Look for rdata with the specified name and type in the zone,
        and return an rdataset encapsulating it.

        The I{name}, I{rdtype}, and I{covers} parameters may be
        strings, in which case they will be converted to their proper
        type.

        The rdataset returned is not a copy; changes to it will change
        the zone.

        None is returned if the name or type are not found.
        Use L{find_rdataset} if you want to have KeyError raised instead.

        @param name: the owner name to look for
        @type name: DNS.name.Name object or string
        @param rdtype: the rdata type desired
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        @param create: should the node and rdataset be created if they do not
        exist?
        @type create: bool
        @rtype: dns.rrset.RRset object
        """

        try:
            rdataset = self.find_rdataset(name, rdtype, covers, create)
        except KeyError:
            rdataset = None
        return rdataset

    def delete_rdataset(self, name, rdtype, covers=dns.rdatatype.NONE):
        """Delete the rdataset matching I{rdtype} and I{covers}, if it
        exists at the node specified by I{name}.

        The I{name}, I{rdtype}, and I{covers} parameters may be
        strings, in which case they will be converted to their proper
        type.

        It is not an error if the node does not exist, or if there is no
        matching rdataset at the node.

        If the node has no rdatasets after the deletion, it will itself
        be deleted.

        @param name: the owner name to look for
        @type name: DNS.name.Name object or string
        @param rdtype: the rdata type desired
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        """

        name = self._validate_name(name)
        if isinstance(rdtype, string_types):
            rdtype = dns.rdatatype.from_text(rdtype)
        if isinstance(covers, string_types):
            covers = dns.rdatatype.from_text(covers)
        node = self.get_node(name)
        if node is not None:
            node.delete_rdataset(self.rdclass, rdtype, covers)
            if len(node) == 0:
                self.delete_node(name)

    def replace_rdataset(self, name, replacement):
        """Replace an rdataset at name.

        It is not an error if there is no rdataset matching I{replacement}.

        Ownership of the I{replacement} object is transferred to the zone;
        in other words, this method does not store a copy of I{replacement}
        at the node, it stores I{replacement} itself.

        If the I{name} node does not exist, it is created.

        @param name: the owner name
        @type name: DNS.name.Name object or string
        @param replacement: the replacement rdataset
        @type replacement: dns.rdataset.Rdataset
        """

        if replacement.rdclass != self.rdclass:
            raise ValueError('replacement.rdclass != zone.rdclass')
        node = self.find_node(name, True)
        node.replace_rdataset(replacement)

    def find_rrset(self, name, rdtype, covers=dns.rdatatype.NONE):
        """Look for rdata with the specified name and type in the zone,
        and return an RRset encapsulating it.

        The I{name}, I{rdtype}, and I{covers} parameters may be
        strings, in which case they will be converted to their proper
        type.

        This method is less efficient than the similar
        L{find_rdataset} because it creates an RRset instead of
        returning the matching rdataset.  It may be more convenient
        for some uses since it returns an object which binds the owner
        name to the rdata.

        This method may not be used to create new nodes or rdatasets;
        use L{find_rdataset} instead.

        KeyError is raised if the name or type are not found.
        Use L{get_rrset} if you want to have None returned instead.

        @param name: the owner name to look for
        @type name: DNS.name.Name object or string
        @param rdtype: the rdata type desired
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        @raises KeyError: the node or rdata could not be found
        @rtype: dns.rrset.RRset object
        """

        name = self._validate_name(name)
        if isinstance(rdtype, string_types):
            rdtype = dns.rdatatype.from_text(rdtype)
        if isinstance(covers, string_types):
            covers = dns.rdatatype.from_text(covers)
        rdataset = self.nodes[name].find_rdataset(self.rdclass, rdtype, covers)
        rrset = dns.rrset.RRset(name, self.rdclass, rdtype, covers)
        rrset.update(rdataset)
        return rrset

    def get_rrset(self, name, rdtype, covers=dns.rdatatype.NONE):
        """Look for rdata with the specified name and type in the zone,
        and return an RRset encapsulating it.

        The I{name}, I{rdtype}, and I{covers} parameters may be
        strings, in which case they will be converted to their proper
        type.

        This method is less efficient than the similar L{get_rdataset}
        because it creates an RRset instead of returning the matching
        rdataset.  It may be more convenient for some uses since it
        returns an object which binds the owner name to the rdata.

        This method may not be used to create new nodes or rdatasets;
        use L{find_rdataset} instead.

        None is returned if the name or type are not found.
        Use L{find_rrset} if you want to have KeyError raised instead.

        @param name: the owner name to look for
        @type name: DNS.name.Name object or string
        @param rdtype: the rdata type desired
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        @rtype: dns.rrset.RRset object
        """

        try:
            rrset = self.find_rrset(name, rdtype, covers)
        except KeyError:
            rrset = None
        return rrset

    def iterate_rdatasets(self, rdtype=dns.rdatatype.ANY,
                          covers=dns.rdatatype.NONE):
        """Return a generator which yields (name, rdataset) tuples for
        all rdatasets in the zone which have the specified I{rdtype}
        and I{covers}.  If I{rdtype} is dns.rdatatype.ANY, the default,
        then all rdatasets will be matched.

        @param rdtype: int or string
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        """

        if isinstance(rdtype, string_types):
            rdtype = dns.rdatatype.from_text(rdtype)
        if isinstance(covers, string_types):
            covers = dns.rdatatype.from_text(covers)
        for (name, node) in self.iteritems():
            for rds in node:
                if rdtype == dns.rdatatype.ANY or \
                   (rds.rdtype == rdtype and rds.covers == covers):
                    yield (name, rds)

    def iterate_rdatas(self, rdtype=dns.rdatatype.ANY,
                       covers=dns.rdatatype.NONE):
        """Return a generator which yields (name, ttl, rdata) tuples for
        all rdatas in the zone which have the specified I{rdtype}
        and I{covers}.  If I{rdtype} is dns.rdatatype.ANY, the default,
        then all rdatas will be matched.

        @param rdtype: int or string
        @type rdtype: int or string
        @param covers: the covered type (defaults to None)
        @type covers: int or string
        """

        if isinstance(rdtype, string_types):
            rdtype = dns.rdatatype.from_text(rdtype)
        if isinstance(covers, string_types):
            covers = dns.rdatatype.from_text(covers)
        for (name, node) in self.iteritems():
            for rds in node:
                if rdtype == dns.rdatatype.ANY or \
                   (rds.rdtype == rdtype and rds.covers == covers):
                    for rdata in rds:
                        yield (name, rds.ttl, rdata)

    def to_file(self, f, sorted=True, relativize=True, nl=None):
        """Write a zone to a file.

        @param f: file or string.  If I{f} is a string, it is treated
        as the name of a file to open.
        @param sorted: if True, the file will be written with the
        names sorted in DNSSEC order from least to greatest.  Otherwise
        the names will be written in whatever order they happen to have
        in the zone's dictionary.
        @param relativize: if True, domain names in the output will be
        relativized to the zone's origin (if possible).
        @type relativize: bool
        @param nl: The end of line string.  If not specified, the
        output will use the platform's native end-of-line marker (i.e.
        LF on POSIX, CRLF on Windows, CR on Macintosh).
        @type nl: string or None
        """

        if isinstance(f, string_types):
            f = open(f, 'wb')
            want_close = True
        else:
            want_close = False

        # must be in this way, f.encoding may contain None, or even attribute
        # may not be there
        file_enc = getattr(f, 'encoding', None)
        if file_enc is None:
            file_enc = 'utf-8'

        if nl is None:
            nl_b = os.linesep.encode(file_enc)  # binary mode, '\n' is not enough
            nl = u'\n'
        elif isinstance(nl, string_types):
            nl_b = nl.encode(file_enc)
        else:
            nl_b = nl
            nl = nl.decode()

        try:
            if sorted:
                names = list(self.keys())
                names.sort()
            else:
                names = self.iterkeys()
            for n in names:
                l = self[n].to_text(n, origin=self.origin,
                                    relativize=relativize)
                if isinstance(l, text_type):
                    l_b = l.encode(file_enc)
                else:
                    l_b = l
                    l = l.decode()

                try:
                    f.write(l_b)
                    f.write(nl_b)
                except TypeError:  # textual mode
                    f.write(l)
                    f.write(nl)
        finally:
            if want_close:
                f.close()

    def to_text(self, sorted=True, relativize=True, nl=None):
        """Return a zone's text as though it were written to a file.

        @param sorted: if True, the file will be written with the
        names sorted in DNSSEC order from least to greatest.  Otherwise
        the names will be written in whatever order they happen to have
        in the zone's dictionary.
        @param relativize: if True, domain names in the output will be
        relativized to the zone's origin (if possible).
        @type relativize: bool
        @param nl: The end of line string.  If not specified, the
        output will use the platform's native end-of-line marker (i.e.
        LF on POSIX, CRLF on Windows, CR on Macintosh).
        @type nl: string or None
        """
        temp_buffer = BytesIO()
        self.to_file(temp_buffer, sorted, relativize, nl)
        return_value = temp_buffer.getvalue()
        temp_buffer.close()
        return return_value

    def check_origin(self):
        """Do some simple checking of the zone's origin.

        @raises dns.zone.NoSOA: there is no SOA RR
        @raises dns.zone.NoNS: there is no NS RRset
        @raises KeyError: there is no origin node
        """
        if self.relativize:
            name = dns.name.empty
        else:
            name = self.origin
        if self.get_rdataset(name, dns.rdatatype.SOA) is None:
            raise NoSOA
        if self.get_rdataset(name, dns.rdatatype.NS) is None:
            raise NoNS


class _MasterReader(object):

    """Read a DNS master file

    @ivar tok: The tokenizer
    @type tok: dns.tokenizer.Tokenizer object
    @ivar ttl: The default TTL
    @type ttl: int
    @ivar last_name: The last name read
    @type last_name: dns.name.Name object
    @ivar current_origin: The current origin
    @type current_origin: dns.name.Name object
    @ivar relativize: should names in the zone be relativized?
    @type relativize: bool
    @ivar zone: the zone
    @type zone: dns.zone.Zone object
    @ivar saved_state: saved reader state (used when processing $INCLUDE)
    @type saved_state: list of (tokenizer, current_origin, last_name, file)
    tuples.
    @ivar current_file: the file object of the $INCLUDed file being parsed
    (None if no $INCLUDE is active).
    @ivar allow_include: is $INCLUDE allowed?
    @type allow_include: bool
    @ivar check_origin: should sanity checks of the origin node be done?
    The default is True.
    @type check_origin: bool
    """

    def __init__(self, tok, origin, rdclass, relativize, zone_factory=Zone,
                 allow_include=False, check_origin=True):
        if isinstance(origin, string_types):
            origin = dns.name.from_text(origin)
        self.tok = tok
        self.current_origin = origin
        self.relativize = relativize
        self.ttl = 0
        self.last_name = self.current_origin
        self.zone = zone_factory(origin, rdclass, relativize=relativize)
        self.saved_state = []
        self.current_file = None
        self.allow_include = allow_include
        self.check_origin = check_origin

    def _eat_line(self):
        while 1:
            token = self.tok.get()
            if token.is_eol_or_eof():
                break

    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 = 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 dns.exception.SyntaxError
        # TTL
        try:
            ttl = dns.ttl.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.ttl.BadTTL:
            ttl = self.ttl
        # Class
        try:
            rdclass = dns.rdataclass.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.exception.SyntaxError:
            raise dns.exception.SyntaxError
        except Exception:
            rdclass = self.zone.rdclass
        if rdclass != self.zone.rdclass:
            raise dns.exception.SyntaxError("RR class is not zone's class")
        # Type
        try:
            rdtype = dns.rdatatype.from_text(token.value)
        except:
            raise 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 = dns.rdata.from_text(rdclass, rdtype, self.tok,
                                     self.current_origin, False)
        except 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 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 _parse_modify(self, side):
        # Here we catch everything in '{' '}' in a group so we can replace it
        # with ''.
        is_generate1 = re.compile("^.*\$({(\+|-?)(\d+),(\d+),(.)}).*$")
        is_generate2 = re.compile("^.*\$({(\+|-?)(\d+)}).*$")
        is_generate3 = re.compile("^.*\$({(\+|-?)(\d+),(\d+)}).*$")
        # Sometimes there are modifiers in the hostname. These come after
        # the dollar sign. They are in the form: ${offset[,width[,base]]}.
        # Make names
        g1 = is_generate1.match(side)
        if g1:
            mod, sign, offset, width, base = g1.groups()
            if sign == '':
                sign = '+'
        g2 = is_generate2.match(side)
        if g2:
            mod, sign, offset = g2.groups()
            if sign == '':
                sign = '+'
            width = 0
            base = 'd'
        g3 = is_generate3.match(side)
        if g3:
            mod, sign, offset, width = g1.groups()
            if sign == '':
                sign = '+'
            width = g1.groups()[2]
            base = 'd'

        if not (g1 or g2 or g3):
            mod = ''
            sign = '+'
            offset = 0
            width = 0
            base = 'd'

        if base != 'd':
            raise NotImplementedError()

        return mod, sign, offset, width, base

    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 = dns.grange.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except:
            raise dns.exception.SyntaxError

        # lhs (required)
        try:
            lhs = token.value
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except:
            raise dns.exception.SyntaxError

        # TTL
        try:
            ttl = dns.ttl.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.ttl.BadTTL:
            ttl = self.ttl
        # Class
        try:
            rdclass = dns.rdataclass.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except dns.exception.SyntaxError:
            raise dns.exception.SyntaxError
        except Exception:
            rdclass = self.zone.rdclass
        if rdclass != self.zone.rdclass:
            raise dns.exception.SyntaxError("RR class is not zone's class")
        # Type
        try:
            rdtype = dns.rdatatype.from_text(token.value)
            token = self.tok.get()
            if not token.is_identifier():
                raise dns.exception.SyntaxError
        except Exception:
            raise dns.exception.SyntaxError("unknown rdatatype '%s'" %
                                            token.value)

        # lhs (required)
        try:
            rhs = token.value
        except:
            raise 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 = 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 = dns.rdata.from_text(rdclass, rdtype, rdata,
                                         self.current_origin, False)
            except 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 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 read(self):
        """Read a DNS master file and build a zone object.

        @raises dns.zone.NoSOA: No SOA RR was found at the zone origin
        @raises dns.zone.NoNS: No NS RRset was found at the zone origin
        """

        try:
            while 1:
                token = self.tok.get(True, True)
                if token.is_eof():
                    if self.current_file is not None:
                        self.current_file.close()
                    if len(self.saved_state) > 0:
                        (self.tok,
                         self.current_origin,
                         self.last_name,
                         self.current_file,
                         self.ttl) = self.saved_state.pop(-1)
                        continue
                    break
                elif token.is_eol():
                    continue
                elif token.is_comment():
                    self.tok.get_eol()
                    continue
                elif token.value[0] == u'$':
                    c = token.value.upper()
                    if c == u'$TTL':
                        token = self.tok.get()
                        if not token.is_identifier():
                            raise dns.exception.SyntaxError("bad $TTL")
                        self.ttl = dns.ttl.from_text(token.value)
                        self.tok.get_eol()
                    elif c == u'$ORIGIN':
                        self.current_origin = self.tok.get_name()
                        self.tok.get_eol()
                        if self.zone.origin is None:
                            self.zone.origin = self.current_origin
                    elif c == u'$INCLUDE' and self.allow_include:
                        token = self.tok.get()
                        filename = token.value
                        token = self.tok.get()
                        if token.is_identifier():
                            new_origin =\
                                dns.name.from_text(token.value,
                                                   self.current_origin)
                            self.tok.get_eol()
                        elif not token.is_eol_or_eof():
                            raise dns.exception.SyntaxError(
                                "bad origin in $INCLUDE")
                        else:
                            new_origin = self.current_origin
                        self.saved_state.append((self.tok,
                                                 self.current_origin,
                                                 self.last_name,
                                                 self.current_file,
                                                 self.ttl))
                        self.current_file = open(filename, 'r')
                        self.tok = dns.tokenizer.Tokenizer(self.current_file,
                                                           filename)
                        self.current_origin = new_origin
                    elif c == u'$GENERATE':
                        self._generate_line()
                    else:
                        raise dns.exception.SyntaxError(
                            "Unknown master file directive '" + c + "'")
                    continue
                self.tok.unget(token)
                self._rr_line()
        except dns.exception.SyntaxError as detail:
            (filename, line_number) = self.tok.where()
            if detail is None:
                detail = "syntax error"
            raise dns.exception.SyntaxError(
                "%s:%d: %s" % (filename, line_number, detail))

        # Now that we're done reading, do some basic checking of the zone.
        if self.check_origin:
            self.zone.check_origin()


def from_text(text, origin=None, rdclass=dns.rdataclass.IN,
              relativize=True, zone_factory=Zone, filename=None,
              allow_include=False, check_origin=True):
    """Build a zone object from a master file format string.

    @param text: the master file format input
    @type text: string.
    @param origin: The origin of the zone; if not specified, the first
    $ORIGIN statement in the master file will determine the origin of the
    zone.
    @type origin: dns.name.Name object or string
    @param rdclass: The zone's rdata class; the default is class IN.
    @type rdclass: int
    @param relativize: should names be relativized?  The default is True
    @type relativize: bool
    @param zone_factory: The zone factory to use
    @type zone_factory: function returning a Zone
    @param filename: The filename to emit when describing where an error
    occurred; the default is '<string>'.
    @type filename: string
    @param allow_include: is $INCLUDE allowed?
    @type allow_include: bool
    @param check_origin: should sanity checks of the origin node be done?
    The default is True.
    @type check_origin: bool
    @raises dns.zone.NoSOA: No SOA RR was found at the zone origin
    @raises dns.zone.NoNS: No NS RRset was found at the zone origin
    @rtype: dns.zone.Zone object
    """

    # 'text' can also be a file, but we don't publish that fact
    # since it's an implementation detail.  The official file
    # interface is from_file().

    if filename is None:
        filename = '<string>'
    tok = dns.tokenizer.Tokenizer(text, filename)
    reader = _MasterReader(tok, origin, rdclass, relativize, zone_factory,
                           allow_include=allow_include,
                           check_origin=check_origin)
    reader.read()
    return reader.zone


def from_file(f, origin=None, rdclass=dns.rdataclass.IN,
              relativize=True, zone_factory=Zone, filename=None,
              allow_include=True, check_origin=True):
    """Read a master file and build a zone object.

    @param f: file or string.  If I{f} is a string, it is treated
    as the name of a file to open.
    @param origin: The origin of the zone; if not specified, the first
    $ORIGIN statement in the master file will determine the origin of the
    zone.
    @type origin: dns.name.Name object or string
    @param rdclass: The zone's rdata class; the default is class IN.
    @type rdclass: int
    @param relativize: should names be relativized?  The default is True
    @type relativize: bool
    @param zone_factory: The zone factory to use
    @type zone_factory: function returning a Zone
    @param filename: The filename to emit when describing where an error
    occurred; the default is '<file>', or the value of I{f} if I{f} is a
    string.
    @type filename: string
    @param allow_include: is $INCLUDE allowed?
    @type allow_include: bool
    @param check_origin: should sanity checks of the origin node be done?
    The default is True.
    @type check_origin: bool
    @raises dns.zone.NoSOA: No SOA RR was found at the zone origin
    @raises dns.zone.NoNS: No NS RRset was found at the zone origin
    @rtype: dns.zone.Zone object
    """

    str_type = string_types
    opts = 'rU'

    if isinstance(f, str_type):
        if filename is None:
            filename = f
        f = open(f, opts)
        want_close = True
    else:
        if filename is None:
            filename = '<file>'
        want_close = False

    try:
        z = from_text(f, origin, rdclass, relativize, zone_factory,
                      filename, allow_include, check_origin)
    finally:
        if want_close:
            f.close()
    return z


def from_xfr(xfr, zone_factory=Zone, relativize=True, check_origin=True):
    """Convert the output of a zone transfer generator into a zone object.

    @param xfr: The xfr generator
    @type xfr: generator of dns.message.Message objects
    @param relativize: should names be relativized?  The default is True.
    It is essential that the relativize setting matches the one specified
    to dns.query.xfr().
    @type relativize: bool
    @param check_origin: should sanity checks of the origin node be done?
    The default is True.
    @type check_origin: bool
    @raises dns.zone.NoSOA: No SOA RR was found at the zone origin
    @raises dns.zone.NoNS: No NS RRset was found at the zone origin
    @rtype: dns.zone.Zone object
    """

    z = None
    for r in xfr:
        if z is None:
            if relativize:
                origin = r.origin
            else:
                origin = r.answer[0].name
            rdclass = r.answer[0].rdclass
            z = zone_factory(origin, rdclass, relativize=relativize)
        for rrset in r.answer:
            znode = z.nodes.get(rrset.name)
            if not znode:
                znode = z.node_factory()
                z.nodes[rrset.name] = znode
            zrds = znode.find_rdataset(rrset.rdclass, rrset.rdtype,
                                       rrset.covers, True)
            zrds.update_ttl(rrset.ttl)
            for rd in rrset:
                rd.choose_relativity(z.origin, relativize)
                zrds.add(rd)
    if check_origin:
        z.check_origin()
    return z
version.py000064400000002352150351404340006604 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""dnspython release version information."""

MAJOR = 1
MINOR = 15
MICRO = 0
RELEASELEVEL = 0x0f
SERIAL = 0

if RELEASELEVEL == 0x0f:
    version = '%d.%d.%d' % (MAJOR, MINOR, MICRO)
elif RELEASELEVEL == 0x00:
    version = '%d.%d.%dx%d' % \
              (MAJOR, MINOR, MICRO, SERIAL)
else:
    version = '%d.%d.%d%x%d' % \
              (MAJOR, MINOR, MICRO, RELEASELEVEL, SERIAL)

hexversion = MAJOR << 24 | MINOR << 16 | MICRO << 8 | RELEASELEVEL << 4 | \
    SERIAL
rdataclass.py000064400000006272150351404340007245 0ustar00# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS Rdata Classes.

@var _by_text: The rdata class textual name to value mapping
@type _by_text: dict
@var _by_value: The rdata class value to textual name mapping
@type _by_value: dict
@var _metaclasses: If an rdataclass is a metaclass, there will be a mapping
whose key is the rdatatype value and whose value is True in this dictionary.
@type _metaclasses: dict"""

import re

import dns.exception

RESERVED0 = 0
IN = 1
CH = 3
HS = 4
NONE = 254
ANY = 255

_by_text = {
    'RESERVED0': RESERVED0,
    'IN': IN,
    'CH': CH,
    'HS': HS,
    'NONE': NONE,
    'ANY': ANY
}

# We construct the inverse mapping programmatically to ensure that we
# cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
# would cause the mapping not to be true inverse.

_by_value = dict((y, x) for x, y in _by_text.items())

# Now that we've built the inverse map, we can add class aliases to
# the _by_text mapping.

_by_text.update({
    'INTERNET': IN,
    'CHAOS': CH,
    'HESIOD': HS
})

_metaclasses = {
    NONE: True,
    ANY: True
}

_unknown_class_pattern = re.compile('CLASS([0-9]+)$', re.I)


class UnknownRdataclass(dns.exception.DNSException):

    """A DNS class is unknown."""


def from_text(text):
    """Convert text into a DNS rdata class value.
    @param text: the text
    @type text: string
    @rtype: int
    @raises dns.rdataclass.UnknownRdataclass: the class is unknown
    @raises ValueError: the rdata class value is not >= 0 and <= 65535
    """

    value = _by_text.get(text.upper())
    if value is None:
        match = _unknown_class_pattern.match(text)
        if match is None:
            raise UnknownRdataclass
        value = int(match.group(1))
        if value < 0 or value > 65535:
            raise ValueError("class must be between >= 0 and <= 65535")
    return value


def to_text(value):
    """Convert a DNS rdata class to text.
    @param value: the rdata class value
    @type value: int
    @rtype: string
    @raises ValueError: the rdata class value is not >= 0 and <= 65535
    """

    if value < 0 or value > 65535:
        raise ValueError("class must be between >= 0 and <= 65535")
    text = _by_value.get(value)
    if text is None:
        text = 'CLASS' + repr(value)
    return text


def is_metaclass(rdclass):
    """True if the class is a metaclass.
    @param rdclass: the rdata class
    @type rdclass: int
    @rtype: bool"""

    if rdclass in _metaclasses:
        return True
    return False
ipv6.py000064400000012255150351404340006006 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""IPv6 helper functions."""

import re
import binascii

import dns.exception
import dns.ipv4
from ._compat import xrange, binary_type, maybe_decode

_leading_zero = re.compile(b'0+([0-9a-f]+)')

def inet_ntoa(address):
    """Convert a network format IPv6 address into text.

    @param address: the binary address
    @type address: string
    @rtype: string
    @raises ValueError: the address isn't 16 bytes long
    """

    if len(address) != 16:
        raise ValueError("IPv6 addresses are 16 bytes long")
    hex = binascii.hexlify(address)
    chunks = []
    i = 0
    l = len(hex)
    while i < l:
        chunk = hex[i : i + 4]
        # strip leading zeros.  we do this with an re instead of
        # with lstrip() because lstrip() didn't support chars until
        # python 2.2.2
        m = _leading_zero.match(chunk)
        if not m is None:
            chunk = m.group(1)
        chunks.append(chunk)
        i += 4
    #
    # Compress the longest subsequence of 0-value chunks to ::
    #
    best_start = 0
    best_len = 0
    start = -1
    last_was_zero = False
    for i in xrange(8):
        if chunks[i] != b'0':
            if last_was_zero:
                end = i
                current_len = end - start
                if current_len > best_len:
                    best_start = start
                    best_len = current_len
                last_was_zero = False
        elif not last_was_zero:
            start = i
            last_was_zero = True
    if last_was_zero:
        end = 8
        current_len = end - start
        if current_len > best_len:
            best_start = start
            best_len = current_len
    if best_len > 1:
        if best_start == 0 and \
           (best_len == 6 or
            best_len == 5 and chunks[5] == b'ffff'):
            # We have an embedded IPv4 address
            if best_len == 6:
                prefix = b'::'
            else:
                prefix = b'::ffff:'
            hex = prefix + dns.ipv4.inet_ntoa(address[12:])
        else:
            hex = b':'.join(chunks[:best_start]) + b'::' + \
                  b':'.join(chunks[best_start + best_len:])
    else:
        hex = b':'.join(chunks)
    return maybe_decode(hex)

_v4_ending = re.compile(b'(.*):(\d+\.\d+\.\d+\.\d+)$')
_colon_colon_start = re.compile(b'::.*')
_colon_colon_end = re.compile(b'.*::$')

def inet_aton(text):
    """Convert a text format IPv6 address into network format.

    @param text: the textual address
    @type text: string
    @rtype: string
    @raises dns.exception.SyntaxError: the text was not properly formatted
    """

    #
    # Our aim here is not something fast; we just want something that works.
    #
    if not isinstance(text, binary_type):
        text = text.encode()

    if text == b'::':
        text = b'0::'
    #
    # Get rid of the icky dot-quad syntax if we have it.
    #
    m = _v4_ending.match(text)
    if not m is None:
        b = bytearray(dns.ipv4.inet_aton(m.group(2)))
        text = (u"%s:%02x%02x:%02x%02x" % (m.group(1).decode(), b[0], b[1],
                                           b[2], b[3])).encode()
    #
    # Try to turn '::<whatever>' into ':<whatever>'; if no match try to
    # turn '<whatever>::' into '<whatever>:'
    #
    m = _colon_colon_start.match(text)
    if not m is None:
        text = text[1:]
    else:
        m = _colon_colon_end.match(text)
        if not m is None:
            text = text[:-1]
    #
    # Now canonicalize into 8 chunks of 4 hex digits each
    #
    chunks = text.split(b':')
    l = len(chunks)
    if l > 8:
        raise dns.exception.SyntaxError
    seen_empty = False
    canonical = []
    for c in chunks:
        if c == b'':
            if seen_empty:
                raise dns.exception.SyntaxError
            seen_empty = True
            for i in xrange(0, 8 - l + 1):
                canonical.append(b'0000')
        else:
            lc = len(c)
            if lc > 4:
                raise dns.exception.SyntaxError
            if lc != 4:
                c = (b'0' * (4 - lc)) + c
            canonical.append(c)
    if l < 8 and not seen_empty:
        raise dns.exception.SyntaxError
    text = b''.join(canonical)

    #
    # Finally we can go to binary.
    #
    try:
        return binascii.unhexlify(text)
    except (binascii.Error, TypeError):
        raise dns.exception.SyntaxError

_mapped_prefix = b'\x00' * 10 + b'\xff\xff'

def is_mapped(address):
    return address.startswith(_mapped_prefix)
update.py000064400000023434150351404340006405 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS Dynamic Update Support"""


import dns.message
import dns.name
import dns.opcode
import dns.rdata
import dns.rdataclass
import dns.rdataset
import dns.tsig
from ._compat import string_types


class Update(dns.message.Message):

    def __init__(self, zone, rdclass=dns.rdataclass.IN, keyring=None,
                 keyname=None, keyalgorithm=dns.tsig.default_algorithm):
        """Initialize a new DNS Update object.

        @param zone: The zone which is being updated.
        @type zone: A dns.name.Name or string
        @param rdclass: The class of the zone; defaults to dns.rdataclass.IN.
        @type rdclass: An int designating the class, or a string whose value
        is the name of a class.
        @param keyring: The TSIG keyring to use; defaults to None.
        @type keyring: dict
        @param keyname: The name of the TSIG key to use; defaults to None.
        The key must be defined in the keyring.  If a keyring is specified
        but a keyname is not, then the key used will be the first key in the
        keyring.  Note that the order of keys in a dictionary is not defined,
        so applications should supply a keyname when a keyring is used, unless
        they know the keyring contains only one key.
        @type keyname: dns.name.Name or string
        @param keyalgorithm: The TSIG algorithm to use; defaults to
        dns.tsig.default_algorithm.  Constants for TSIG algorithms are defined
        in dns.tsig, and the currently implemented algorithms are
        HMAC_MD5, HMAC_SHA1, HMAC_SHA224, HMAC_SHA256, HMAC_SHA384, and
        HMAC_SHA512.
        @type keyalgorithm: string
        """
        super(Update, self).__init__()
        self.flags |= dns.opcode.to_flags(dns.opcode.UPDATE)
        if isinstance(zone, string_types):
            zone = dns.name.from_text(zone)
        self.origin = zone
        if isinstance(rdclass, string_types):
            rdclass = dns.rdataclass.from_text(rdclass)
        self.zone_rdclass = rdclass
        self.find_rrset(self.question, self.origin, rdclass, dns.rdatatype.SOA,
                        create=True, force_unique=True)
        if keyring is not None:
            self.use_tsig(keyring, keyname, algorithm=keyalgorithm)

    def _add_rr(self, name, ttl, rd, deleting=None, section=None):
        """Add a single RR to the update section."""

        if section is None:
            section = self.authority
        covers = rd.covers()
        rrset = self.find_rrset(section, name, self.zone_rdclass, rd.rdtype,
                                covers, deleting, True, True)
        rrset.add(rd, ttl)

    def _add(self, replace, section, name, *args):
        """Add records.  The first argument is the replace mode.  If
        false, RRs are added to an existing RRset; if true, the RRset
        is replaced with the specified contents.  The second
        argument is the section to add to.  The third argument
        is always a name.  The other arguments can be:

                - rdataset...

                - ttl, rdata...

                - ttl, rdtype, string..."""

        if isinstance(name, string_types):
            name = dns.name.from_text(name, None)
        if isinstance(args[0], dns.rdataset.Rdataset):
            for rds in args:
                if replace:
                    self.delete(name, rds.rdtype)
                for rd in rds:
                    self._add_rr(name, rds.ttl, rd, section=section)
        else:
            args = list(args)
            ttl = int(args.pop(0))
            if isinstance(args[0], dns.rdata.Rdata):
                if replace:
                    self.delete(name, args[0].rdtype)
                for rd in args:
                    self._add_rr(name, ttl, rd, section=section)
            else:
                rdtype = args.pop(0)
                if isinstance(rdtype, string_types):
                    rdtype = dns.rdatatype.from_text(rdtype)
                if replace:
                    self.delete(name, rdtype)
                for s in args:
                    rd = dns.rdata.from_text(self.zone_rdclass, rdtype, s,
                                             self.origin)
                    self._add_rr(name, ttl, rd, section=section)

    def add(self, name, *args):
        """Add records.  The first argument is always a name.  The other
        arguments can be:

                - rdataset...

                - ttl, rdata...

                - ttl, rdtype, string..."""
        self._add(False, self.authority, name, *args)

    def delete(self, name, *args):
        """Delete records.  The first argument is always a name.  The other
        arguments can be:

                - I{nothing}

                - rdataset...

                - rdata...

                - rdtype, [string...]"""

        if isinstance(name, string_types):
            name = dns.name.from_text(name, None)
        if len(args) == 0:
            self.find_rrset(self.authority, name, dns.rdataclass.ANY,
                            dns.rdatatype.ANY, dns.rdatatype.NONE,
                            dns.rdatatype.ANY, True, True)
        elif isinstance(args[0], dns.rdataset.Rdataset):
            for rds in args:
                for rd in rds:
                    self._add_rr(name, 0, rd, dns.rdataclass.NONE)
        else:
            args = list(args)
            if isinstance(args[0], dns.rdata.Rdata):
                for rd in args:
                    self._add_rr(name, 0, rd, dns.rdataclass.NONE)
            else:
                rdtype = args.pop(0)
                if isinstance(rdtype, string_types):
                    rdtype = dns.rdatatype.from_text(rdtype)
                if len(args) == 0:
                    self.find_rrset(self.authority, name,
                                    self.zone_rdclass, rdtype,
                                    dns.rdatatype.NONE,
                                    dns.rdataclass.ANY,
                                    True, True)
                else:
                    for s in args:
                        rd = dns.rdata.from_text(self.zone_rdclass, rdtype, s,
                                                 self.origin)
                        self._add_rr(name, 0, rd, dns.rdataclass.NONE)

    def replace(self, name, *args):
        """Replace records.  The first argument is always a name.  The other
        arguments can be:

                - rdataset...

                - ttl, rdata...

                - ttl, rdtype, string...

        Note that if you want to replace the entire node, you should do
        a delete of the name followed by one or more calls to add."""

        self._add(True, self.authority, name, *args)

    def present(self, name, *args):
        """Require that an owner name (and optionally an rdata type,
        or specific rdataset) exists as a prerequisite to the
        execution of the update.  The first argument is always a name.
        The other arguments can be:

                - rdataset...

                - rdata...

                - rdtype, string..."""

        if isinstance(name, string_types):
            name = dns.name.from_text(name, None)
        if len(args) == 0:
            self.find_rrset(self.answer, name,
                            dns.rdataclass.ANY, dns.rdatatype.ANY,
                            dns.rdatatype.NONE, None,
                            True, True)
        elif isinstance(args[0], dns.rdataset.Rdataset) or \
            isinstance(args[0], dns.rdata.Rdata) or \
                len(args) > 1:
            if not isinstance(args[0], dns.rdataset.Rdataset):
                # Add a 0 TTL
                args = list(args)
                args.insert(0, 0)
            self._add(False, self.answer, name, *args)
        else:
            rdtype = args[0]
            if isinstance(rdtype, string_types):
                rdtype = dns.rdatatype.from_text(rdtype)
            self.find_rrset(self.answer, name,
                            dns.rdataclass.ANY, rdtype,
                            dns.rdatatype.NONE, None,
                            True, True)

    def absent(self, name, rdtype=None):
        """Require that an owner name (and optionally an rdata type) does
        not exist as a prerequisite to the execution of the update."""

        if isinstance(name, string_types):
            name = dns.name.from_text(name, None)
        if rdtype is None:
            self.find_rrset(self.answer, name,
                            dns.rdataclass.NONE, dns.rdatatype.ANY,
                            dns.rdatatype.NONE, None,
                            True, True)
        else:
            if isinstance(rdtype, string_types):
                rdtype = dns.rdatatype.from_text(rdtype)
            self.find_rrset(self.answer, name,
                            dns.rdataclass.NONE, rdtype,
                            dns.rdatatype.NONE, None,
                            True, True)

    def to_wire(self, origin=None, max_size=65535):
        """Return a string containing the update in DNS compressed wire
        format.
        @rtype: string"""
        if origin is None:
            origin = self.origin
        return super(Update, self).to_wire(origin, max_size)
name.py000064400000071361150351404340006045 0ustar00# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS Names.

@var root: The DNS root name.
@type root: dns.name.Name object
@var empty: The empty DNS name.
@type empty: dns.name.Name object
"""

from io import BytesIO
import struct
import sys
import copy
import encodings.idna
try:
    import idna
    have_idna_2008 = True
except ImportError:
    have_idna_2008 = False

import dns.exception
import dns.wiredata

from ._compat import long, binary_type, text_type, unichr, maybe_decode

try:
    maxint = sys.maxint
except AttributeError:
    maxint = (1 << (8 * struct.calcsize("P"))) // 2 - 1

NAMERELN_NONE = 0
NAMERELN_SUPERDOMAIN = 1
NAMERELN_SUBDOMAIN = 2
NAMERELN_EQUAL = 3
NAMERELN_COMMONANCESTOR = 4


class EmptyLabel(dns.exception.SyntaxError):

    """A DNS label is empty."""


class BadEscape(dns.exception.SyntaxError):

    """An escaped code in a text format of DNS name is invalid."""


class BadPointer(dns.exception.FormError):

    """A DNS compression pointer points forward instead of backward."""


class BadLabelType(dns.exception.FormError):

    """The label type in DNS name wire format is unknown."""


class NeedAbsoluteNameOrOrigin(dns.exception.DNSException):

    """An attempt was made to convert a non-absolute name to
    wire when there was also a non-absolute (or missing) origin."""


class NameTooLong(dns.exception.FormError):

    """A DNS name is > 255 octets long."""


class LabelTooLong(dns.exception.SyntaxError):

    """A DNS label is > 63 octets long."""


class AbsoluteConcatenation(dns.exception.DNSException):

    """An attempt was made to append anything other than the
    empty name to an absolute DNS name."""


class NoParent(dns.exception.DNSException):

    """An attempt was made to get the parent of the root name
    or the empty name."""

class NoIDNA2008(dns.exception.DNSException):

    """IDNA 2008 processing was requested but the idna module is not
    available."""


class IDNAException(dns.exception.DNSException):

    """IDNA processing raised an exception."""

    supp_kwargs = set(['idna_exception'])
    fmt = "IDNA processing exception: {idna_exception}"

class IDNACodec(object):

    """Abstract base class for IDNA encoder/decoders."""

    def __init__(self):
        pass

    def is_idna(self, label):
        return label.lower().startswith(b'xn--')

    def is_all_ascii(self, label):
        for c in label:
            if ord(c) > 0x7f:
                return False
        return True

    def encode(self, label):
        raise NotImplementedError

    def decode(self, label):
        # We do not apply any IDNA policy on decode.
        if self.is_idna(label):
            try:
                label = label[4:].decode('punycode')
            except Exception as e:
                raise IDNAException(idna_exception=e)
        else:
            label = maybe_decode(label)
        return _escapify(label)

class IDNA2003Codec(IDNACodec):

    """IDNA 2003 encoder/decoder."""

    def __init__(self, strict_decode=False):
        """Initialize the IDNA 2003 encoder/decoder.
        @param strict_decode: If True, then IDNA2003 checking is done when
        decoding.  This can cause failures if the name was encoded with
        IDNA2008.  The default is False.
        @type strict_decode: bool
        """
        super(IDNA2003Codec, self).__init__()
        self.strict_decode = strict_decode

    def encode(self, label):
        if label == '':
            return b''
        try:
            return encodings.idna.ToASCII(label)
        except UnicodeError:
            raise LabelTooLong

    def decode(self, label):
        if not self.strict_decode:
            return super(IDNA2003Codec, self).decode(label)
        if label == b'':
            return u''
        try:
            return _escapify(encodings.idna.ToUnicode(label))
        except Exception as e:
            raise IDNAException(idna_exception=e)

class IDNA2008Codec(IDNACodec):

    """IDNA 2008 encoder/decoder."""

    def __init__(self, uts_46=False, transitional=False,
                 allow_pure_ascii=False, strict_decode=False):
        """Initialize the IDNA 2008 encoder/decoder.
        @param uts_46: If True, apply Unicode IDNA compatibility processing
        as described in Unicode Technical Standard #46
        (U{http://unicode.org/reports/tr46/}).  This parameter is only
        meaningful if IDNA 2008 is in use.  If False, do not apply
        the mapping.  The default is False
        @type uts_46: bool
        @param transitional: If True, use the "transitional" mode described
        in Unicode Technical Standard #46.  This parameter is only
        meaningful if IDNA 2008 is in use.  The default is False.
        @type transitional: bool
        @param allow_pure_ascii: If True, then a label which
        consists of only ASCII characters is allowed.  This is less strict
        than regular IDNA 2008, but is also necessary for mixed names,
        e.g. a name with starting with "_sip._tcp." and ending in an IDN
        suffixm which would otherwise be disallowed.  The default is False
        @type allow_pure_ascii: bool
        @param strict_decode: If True, then IDNA2008 checking is done when
        decoding.  This can cause failures if the name was encoded with
        IDNA2003.  The default is False.
        @type strict_decode: bool
        """
        super(IDNA2008Codec, self).__init__()
        self.uts_46 = uts_46
        self.transitional = transitional
        self.allow_pure_ascii = allow_pure_ascii
        self.strict_decode = strict_decode

    def encode(self, label):
        if label == '':
            return b''
        if self.allow_pure_ascii and self.is_all_ascii(label):
            return label.encode('ascii')
        if not have_idna_2008:
            raise NoIDNA2008
        try:
            if self.uts_46:
                label = idna.uts46_remap(label, False, self.transitional)
            return idna.alabel(label)
        except idna.IDNAError as e:
            raise IDNAException(idna_exception=e)

    def decode(self, label):
        if not self.strict_decode:
            return super(IDNA2008Codec, self).decode(label)
        if label == b'':
            return u''
        if not have_idna_2008:
            raise NoIDNA2008
        try:
            if self.uts_46:
                label = idna.uts46_remap(label, False, False)
            return _escapify(idna.ulabel(label))
        except idna.IDNAError as e:
            raise IDNAException(idna_exception=e)

_escaped = bytearray(b'"().;\\@$')
_escaped_text = '"().;\\@$'

IDNA_2003_Practical = IDNA2003Codec(False)
IDNA_2003_Strict = IDNA2003Codec(True)
IDNA_2003 = IDNA_2003_Practical
IDNA_2008_Practical = IDNA2008Codec(True, False, True, False)
IDNA_2008_UTS_46 = IDNA2008Codec(True, False, False, False)
IDNA_2008_Strict = IDNA2008Codec(False, False, False, True)
IDNA_2008_Transitional = IDNA2008Codec(True, True, False, False)
IDNA_2008 = IDNA_2008_Practical

def _escapify(label):
    """Escape the characters in label which need it.
    @returns: the escaped string
    @rtype: string"""
    if isinstance(label, bytes):
        # Ordinary DNS label mode.  Escape special characters and values
        # < 0x20 or > 0x7f.
        text = ''
        if isinstance(label, text_type):
            label = label.encode()
        for c in bytearray(label):
            if c in _escaped:
                text += '\\' + chr(c)
            elif c > 0x20 and c < 0x7F:
                text += chr(c)
            else:
                text += '\\%03d' % c
        return text

    # Unicode label mode.  Escape only special characters and values < 0x20
    text = u''
    for c in label:
        if c in _escaped_text:
            text += '\\' + c
        elif c <= '\x20':
            text += '\\%03d' % ord(c)
        else:
            text += c
    return text

def _validate_labels(labels):
    """Check for empty labels in the middle of a label sequence,
    labels that are too long, and for too many labels.
    @raises NameTooLong: the name as a whole is too long
    @raises EmptyLabel: a label is empty (i.e. the root label) and appears
    in a position other than the end of the label sequence"""

    l = len(labels)
    total = 0
    i = -1
    j = 0
    for label in labels:
        ll = len(label)
        total += ll + 1
        if ll > 63:
            raise LabelTooLong
        if i < 0 and label == b'':
            i = j
        j += 1
    if total > 255:
        raise NameTooLong
    if i >= 0 and i != l - 1:
        raise EmptyLabel


def _ensure_bytes(label):
    if isinstance(label, binary_type):
        return label
    if isinstance(label, text_type):
        return label.encode()
    raise ValueError


class Name(object):

    """A DNS name.

    The dns.name.Name class represents a DNS name as a tuple of labels.
    Instances of the class are immutable.

    @ivar labels: The tuple of labels in the name. Each label is a string of
    up to 63 octets."""

    __slots__ = ['labels']

    def __init__(self, labels):
        """Initialize a domain name from a list of labels.
        @param labels: the labels
        @type labels: any iterable whose values are strings
        """
        labels = [_ensure_bytes(x) for x in labels]
        super(Name, self).__setattr__('labels', tuple(labels))
        _validate_labels(self.labels)

    def __setattr__(self, name, value):
        raise TypeError("object doesn't support attribute assignment")

    def __copy__(self):
        return Name(self.labels)

    def __deepcopy__(self, memo):
        return Name(copy.deepcopy(self.labels, memo))

    def __getstate__(self):
        return {'labels': self.labels}

    def __setstate__(self, state):
        super(Name, self).__setattr__('labels', state['labels'])
        _validate_labels(self.labels)

    def is_absolute(self):
        """Is the most significant label of this name the root label?
        @rtype: bool
        """

        return len(self.labels) > 0 and self.labels[-1] == b''

    def is_wild(self):
        """Is this name wild?  (I.e. Is the least significant label '*'?)
        @rtype: bool
        """

        return len(self.labels) > 0 and self.labels[0] == b'*'

    def __hash__(self):
        """Return a case-insensitive hash of the name.
        @rtype: int
        """

        h = long(0)
        for label in self.labels:
            for c in bytearray(label.lower()):
                h += (h << 3) + c
        return int(h % maxint)

    def fullcompare(self, other):
        """Compare two names, returning a 3-tuple (relation, order, nlabels).

        I{relation} describes the relation ship between the names,
        and is one of: dns.name.NAMERELN_NONE,
        dns.name.NAMERELN_SUPERDOMAIN, dns.name.NAMERELN_SUBDOMAIN,
        dns.name.NAMERELN_EQUAL, or dns.name.NAMERELN_COMMONANCESTOR

        I{order} is < 0 if self < other, > 0 if self > other, and ==
        0 if self == other.  A relative name is always less than an
        absolute name.  If both names have the same relativity, then
        the DNSSEC order relation is used to order them.

        I{nlabels} is the number of significant labels that the two names
        have in common.
        """

        sabs = self.is_absolute()
        oabs = other.is_absolute()
        if sabs != oabs:
            if sabs:
                return (NAMERELN_NONE, 1, 0)
            else:
                return (NAMERELN_NONE, -1, 0)
        l1 = len(self.labels)
        l2 = len(other.labels)
        ldiff = l1 - l2
        if ldiff < 0:
            l = l1
        else:
            l = l2

        order = 0
        nlabels = 0
        namereln = NAMERELN_NONE
        while l > 0:
            l -= 1
            l1 -= 1
            l2 -= 1
            label1 = self.labels[l1].lower()
            label2 = other.labels[l2].lower()
            if label1 < label2:
                order = -1
                if nlabels > 0:
                    namereln = NAMERELN_COMMONANCESTOR
                return (namereln, order, nlabels)
            elif label1 > label2:
                order = 1
                if nlabels > 0:
                    namereln = NAMERELN_COMMONANCESTOR
                return (namereln, order, nlabels)
            nlabels += 1
        order = ldiff
        if ldiff < 0:
            namereln = NAMERELN_SUPERDOMAIN
        elif ldiff > 0:
            namereln = NAMERELN_SUBDOMAIN
        else:
            namereln = NAMERELN_EQUAL
        return (namereln, order, nlabels)

    def is_subdomain(self, other):
        """Is self a subdomain of other?

        The notion of subdomain includes equality.
        @rtype: bool
        """

        (nr, o, nl) = self.fullcompare(other)
        if nr == NAMERELN_SUBDOMAIN or nr == NAMERELN_EQUAL:
            return True
        return False

    def is_superdomain(self, other):
        """Is self a superdomain of other?

        The notion of subdomain includes equality.
        @rtype: bool
        """

        (nr, o, nl) = self.fullcompare(other)
        if nr == NAMERELN_SUPERDOMAIN or nr == NAMERELN_EQUAL:
            return True
        return False

    def canonicalize(self):
        """Return a name which is equal to the current name, but is in
        DNSSEC canonical form.
        @rtype: dns.name.Name object
        """

        return Name([x.lower() for x in self.labels])

    def __eq__(self, other):
        if isinstance(other, Name):
            return self.fullcompare(other)[1] == 0
        else:
            return False

    def __ne__(self, other):
        if isinstance(other, Name):
            return self.fullcompare(other)[1] != 0
        else:
            return True

    def __lt__(self, other):
        if isinstance(other, Name):
            return self.fullcompare(other)[1] < 0
        else:
            return NotImplemented

    def __le__(self, other):
        if isinstance(other, Name):
            return self.fullcompare(other)[1] <= 0
        else:
            return NotImplemented

    def __ge__(self, other):
        if isinstance(other, Name):
            return self.fullcompare(other)[1] >= 0
        else:
            return NotImplemented

    def __gt__(self, other):
        if isinstance(other, Name):
            return self.fullcompare(other)[1] > 0
        else:
            return NotImplemented

    def __repr__(self):
        return '<DNS name ' + self.__str__() + '>'

    def __str__(self):
        return self.to_text(False)

    def to_text(self, omit_final_dot=False):
        """Convert name to text format.
        @param omit_final_dot: If True, don't emit the final dot (denoting the
        root label) for absolute names.  The default is False.
        @rtype: string
        """

        if len(self.labels) == 0:
            return maybe_decode(b'@')
        if len(self.labels) == 1 and self.labels[0] == b'':
            return maybe_decode(b'.')
        if omit_final_dot and self.is_absolute():
            l = self.labels[:-1]
        else:
            l = self.labels
        s = '.'.join(map(_escapify, l))
        return s

    def to_unicode(self, omit_final_dot=False, idna_codec=None):
        """Convert name to Unicode text format.

        IDN ACE labels are converted to Unicode.

        @param omit_final_dot: If True, don't emit the final dot (denoting the
        root label) for absolute names.  The default is False.
        @type omit_final_dot: bool
        @param idna_codec: IDNA encoder/decoder.  If None, the
        IDNA_2003_Practical encoder/decoder is used.  The IDNA_2003_Practical
        decoder does not impose any policy, it just decodes punycode, so if
        you don't want checking for compliance, you can use this decoder for
        IDNA2008 as well.
        @type idna_codec: dns.name.IDNA
        @rtype: string
        """

        if len(self.labels) == 0:
            return u'@'
        if len(self.labels) == 1 and self.labels[0] == b'':
            return u'.'
        if omit_final_dot and self.is_absolute():
            l = self.labels[:-1]
        else:
            l = self.labels
        if idna_codec is None:
            idna_codec = IDNA_2003_Practical
        return u'.'.join([idna_codec.decode(x) for x in l])

    def to_digestable(self, origin=None):
        """Convert name to a format suitable for digesting in hashes.

        The name is canonicalized and converted to uncompressed wire format.

        @param origin: If the name is relative and origin is not None, then
        origin will be appended to it.
        @type origin: dns.name.Name object
        @raises NeedAbsoluteNameOrOrigin: All names in wire format are
        absolute.  If self is a relative name, then an origin must be supplied;
        if it is missing, then this exception is raised
        @rtype: string
        """

        if not self.is_absolute():
            if origin is None or not origin.is_absolute():
                raise NeedAbsoluteNameOrOrigin
            labels = list(self.labels)
            labels.extend(list(origin.labels))
        else:
            labels = self.labels
        dlabels = [struct.pack('!B%ds' % len(x), len(x), x.lower())
                   for x in labels]
        return b''.join(dlabels)

    def to_wire(self, file=None, compress=None, origin=None):
        """Convert name to wire format, possibly compressing it.

        @param file: the file where the name is emitted (typically
        a BytesIO file).  If None, a string containing the wire name
        will be returned.
        @type file: file or None
        @param compress: The compression table.  If None (the default) names
        will not be compressed.
        @type compress: dict
        @param origin: If the name is relative and origin is not None, then
        origin will be appended to it.
        @type origin: dns.name.Name object
        @raises NeedAbsoluteNameOrOrigin: All names in wire format are
        absolute.  If self is a relative name, then an origin must be supplied;
        if it is missing, then this exception is raised
        """

        if file is None:
            file = BytesIO()
            want_return = True
        else:
            want_return = False

        if not self.is_absolute():
            if origin is None or not origin.is_absolute():
                raise NeedAbsoluteNameOrOrigin
            labels = list(self.labels)
            labels.extend(list(origin.labels))
        else:
            labels = self.labels
        i = 0
        for label in labels:
            n = Name(labels[i:])
            i += 1
            if compress is not None:
                pos = compress.get(n)
            else:
                pos = None
            if pos is not None:
                value = 0xc000 + pos
                s = struct.pack('!H', value)
                file.write(s)
                break
            else:
                if compress is not None and len(n) > 1:
                    pos = file.tell()
                    if pos <= 0x3fff:
                        compress[n] = pos
                l = len(label)
                file.write(struct.pack('!B', l))
                if l > 0:
                    file.write(label)
        if want_return:
            return file.getvalue()

    def __len__(self):
        """The length of the name (in labels).
        @rtype: int
        """

        return len(self.labels)

    def __getitem__(self, index):
        return self.labels[index]

    def __add__(self, other):
        return self.concatenate(other)

    def __sub__(self, other):
        return self.relativize(other)

    def split(self, depth):
        """Split a name into a prefix and suffix at depth.

        @param depth: the number of labels in the suffix
        @type depth: int
        @raises ValueError: the depth was not >= 0 and <= the length of the
        name.
        @returns: the tuple (prefix, suffix)
        @rtype: tuple
        """

        l = len(self.labels)
        if depth == 0:
            return (self, dns.name.empty)
        elif depth == l:
            return (dns.name.empty, self)
        elif depth < 0 or depth > l:
            raise ValueError(
                'depth must be >= 0 and <= the length of the name')
        return (Name(self[: -depth]), Name(self[-depth:]))

    def concatenate(self, other):
        """Return a new name which is the concatenation of self and other.
        @rtype: dns.name.Name object
        @raises AbsoluteConcatenation: self is absolute and other is
        not the empty name
        """

        if self.is_absolute() and len(other) > 0:
            raise AbsoluteConcatenation
        labels = list(self.labels)
        labels.extend(list(other.labels))
        return Name(labels)

    def relativize(self, origin):
        """If self is a subdomain of origin, return a new name which is self
        relative to origin.  Otherwise return self.
        @rtype: dns.name.Name object
        """

        if origin is not None and self.is_subdomain(origin):
            return Name(self[: -len(origin)])
        else:
            return self

    def derelativize(self, origin):
        """If self is a relative name, return a new name which is the
        concatenation of self and origin.  Otherwise return self.
        @rtype: dns.name.Name object
        """

        if not self.is_absolute():
            return self.concatenate(origin)
        else:
            return self

    def choose_relativity(self, origin=None, relativize=True):
        """Return a name with the relativity desired by the caller.  If
        origin is None, then self is returned.  Otherwise, if
        relativize is true the name is relativized, and if relativize is
        false the name is derelativized.
        @rtype: dns.name.Name object
        """

        if origin:
            if relativize:
                return self.relativize(origin)
            else:
                return self.derelativize(origin)
        else:
            return self

    def parent(self):
        """Return the parent of the name.
        @rtype: dns.name.Name object
        @raises NoParent: the name is either the root name or the empty name,
        and thus has no parent.
        """
        if self == root or self == empty:
            raise NoParent
        return Name(self.labels[1:])

root = Name([b''])
empty = Name([])


def from_unicode(text, origin=root, idna_codec=None):
    """Convert unicode text into a Name object.

    Labels are encoded in IDN ACE form.

    @param text: The text to convert into a name.
    @type text: Unicode string
    @param origin: The origin to append to non-absolute names.
    @type origin: dns.name.Name
    @param idna_codec: IDNA encoder/decoder.  If None, the default IDNA 2003
    encoder/decoder is used.
    @type idna_codec: dns.name.IDNA
    @rtype: dns.name.Name object
    """

    if not isinstance(text, text_type):
        raise ValueError("input to from_unicode() must be a unicode string")
    if not (origin is None or isinstance(origin, Name)):
        raise ValueError("origin must be a Name or None")
    labels = []
    label = u''
    escaping = False
    edigits = 0
    total = 0
    if idna_codec is None:
        idna_codec = IDNA_2003
    if text == u'@':
        text = u''
    if text:
        if text == u'.':
            return Name([b''])        # no Unicode "u" on this constant!
        for c in text:
            if escaping:
                if edigits == 0:
                    if c.isdigit():
                        total = int(c)
                        edigits += 1
                    else:
                        label += c
                        escaping = False
                else:
                    if not c.isdigit():
                        raise BadEscape
                    total *= 10
                    total += int(c)
                    edigits += 1
                    if edigits == 3:
                        escaping = False
                        label += unichr(total)
            elif c in [u'.', u'\u3002', u'\uff0e', u'\uff61']:
                if len(label) == 0:
                    raise EmptyLabel
                labels.append(idna_codec.encode(label))
                label = u''
            elif c == u'\\':
                escaping = True
                edigits = 0
                total = 0
            else:
                label += c
        if escaping:
            raise BadEscape
        if len(label) > 0:
            labels.append(idna_codec.encode(label))
        else:
            labels.append(b'')

    if (len(labels) == 0 or labels[-1] != b'') and origin is not None:
        labels.extend(list(origin.labels))
    return Name(labels)


def from_text(text, origin=root, idna_codec=None):
    """Convert text into a Name object.

    @param text: The text to convert into a name.
    @type text: string
    @param origin: The origin to append to non-absolute names.
    @type origin: dns.name.Name
    @param idna_codec: IDNA encoder/decoder.  If None, the default IDNA 2003
    encoder/decoder is used.
    @type idna_codec: dns.name.IDNA
    @rtype: dns.name.Name object
    """

    if isinstance(text, text_type):
        return from_unicode(text, origin, idna_codec)
    if not isinstance(text, binary_type):
        raise ValueError("input to from_text() must be a string")
    if not (origin is None or isinstance(origin, Name)):
        raise ValueError("origin must be a Name or None")
    labels = []
    label = b''
    escaping = False
    edigits = 0
    total = 0
    if text == b'@':
        text = b''
    if text:
        if text == b'.':
            return Name([b''])
        for c in bytearray(text):
            byte_ = struct.pack('!B', c)
            if escaping:
                if edigits == 0:
                    if byte_.isdigit():
                        total = int(byte_)
                        edigits += 1
                    else:
                        label += byte_
                        escaping = False
                else:
                    if not byte_.isdigit():
                        raise BadEscape
                    total *= 10
                    total += int(byte_)
                    edigits += 1
                    if edigits == 3:
                        escaping = False
                        label += struct.pack('!B', total)
            elif byte_ == b'.':
                if len(label) == 0:
                    raise EmptyLabel
                labels.append(label)
                label = b''
            elif byte_ == b'\\':
                escaping = True
                edigits = 0
                total = 0
            else:
                label += byte_
        if escaping:
            raise BadEscape
        if len(label) > 0:
            labels.append(label)
        else:
            labels.append(b'')
    if (len(labels) == 0 or labels[-1] != b'') and origin is not None:
        labels.extend(list(origin.labels))
    return Name(labels)


def from_wire(message, current):
    """Convert possibly compressed wire format into a Name.
    @param message: the entire DNS message
    @type message: string
    @param current: the offset of the beginning of the name from the start
    of the message
    @type current: int
    @raises dns.name.BadPointer: a compression pointer did not point backwards
    in the message
    @raises dns.name.BadLabelType: an invalid label type was encountered.
    @returns: a tuple consisting of the name that was read and the number
    of bytes of the wire format message which were consumed reading it
    @rtype: (dns.name.Name object, int) tuple
    """

    if not isinstance(message, binary_type):
        raise ValueError("input to from_wire() must be a byte string")
    message = dns.wiredata.maybe_wrap(message)
    labels = []
    biggest_pointer = current
    hops = 0
    count = message[current]
    current += 1
    cused = 1
    while count != 0:
        if count < 64:
            labels.append(message[current: current + count].unwrap())
            current += count
            if hops == 0:
                cused += count
        elif count >= 192:
            current = (count & 0x3f) * 256 + message[current]
            if hops == 0:
                cused += 1
            if current >= biggest_pointer:
                raise BadPointer
            biggest_pointer = current
            hops += 1
        else:
            raise BadLabelType
        count = message[current]
        current += 1
        if hops == 0:
            cused += 1
    labels.append('')
    return (Name(labels), cused)
rdataset.py000064400000026444150351404340006736 0ustar00# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS rdatasets (an rdataset is a set of rdatas of a given type and class)"""

import random
from io import StringIO
import struct

import dns.exception
import dns.rdatatype
import dns.rdataclass
import dns.rdata
import dns.set
from ._compat import string_types

# define SimpleSet here for backwards compatibility
SimpleSet = dns.set.Set


class DifferingCovers(dns.exception.DNSException):

    """An attempt was made to add a DNS SIG/RRSIG whose covered type
    is not the same as that of the other rdatas in the rdataset."""


class IncompatibleTypes(dns.exception.DNSException):

    """An attempt was made to add DNS RR data of an incompatible type."""


class Rdataset(dns.set.Set):

    """A DNS rdataset.

    @ivar rdclass: The class of the rdataset
    @type rdclass: int
    @ivar rdtype: The type of the rdataset
    @type rdtype: int
    @ivar covers: The covered type.  Usually this value is
    dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or
    dns.rdatatype.RRSIG, then the covers value will be the rdata
    type the SIG/RRSIG covers.  The library treats the SIG and RRSIG
    types as if they were a family of
    types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA).  This makes RRSIGs much
    easier to work with than if RRSIGs covering different rdata
    types were aggregated into a single RRSIG rdataset.
    @type covers: int
    @ivar ttl: The DNS TTL (Time To Live) value
    @type ttl: int
    """

    __slots__ = ['rdclass', 'rdtype', 'covers', 'ttl']

    def __init__(self, rdclass, rdtype, covers=dns.rdatatype.NONE):
        """Create a new rdataset of the specified class and type.

        @see: the description of the class instance variables for the
        meaning of I{rdclass} and I{rdtype}"""

        super(Rdataset, self).__init__()
        self.rdclass = rdclass
        self.rdtype = rdtype
        self.covers = covers
        self.ttl = 0

    def _clone(self):
        obj = super(Rdataset, self)._clone()
        obj.rdclass = self.rdclass
        obj.rdtype = self.rdtype
        obj.covers = self.covers
        obj.ttl = self.ttl
        return obj

    def update_ttl(self, ttl):
        """Set the TTL of the rdataset to be the lesser of the set's current
        TTL or the specified TTL.  If the set contains no rdatas, set the TTL
        to the specified TTL.
        @param ttl: The TTL
        @type ttl: int"""

        if len(self) == 0:
            self.ttl = ttl
        elif ttl < self.ttl:
            self.ttl = ttl

    def add(self, rd, ttl=None):
        """Add the specified rdata to the rdataset.

        If the optional I{ttl} parameter is supplied, then
        self.update_ttl(ttl) will be called prior to adding the rdata.

        @param rd: The rdata
        @type rd: dns.rdata.Rdata object
        @param ttl: The TTL
        @type ttl: int"""

        #
        # If we're adding a signature, do some special handling to
        # check that the signature covers the same type as the
        # other rdatas in this rdataset.  If this is the first rdata
        # in the set, initialize the covers field.
        #
        if self.rdclass != rd.rdclass or self.rdtype != rd.rdtype:
            raise IncompatibleTypes
        if ttl is not None:
            self.update_ttl(ttl)
        if self.rdtype == dns.rdatatype.RRSIG or \
           self.rdtype == dns.rdatatype.SIG:
            covers = rd.covers()
            if len(self) == 0 and self.covers == dns.rdatatype.NONE:
                self.covers = covers
            elif self.covers != covers:
                raise DifferingCovers
        if dns.rdatatype.is_singleton(rd.rdtype) and len(self) > 0:
            self.clear()
        super(Rdataset, self).add(rd)

    def union_update(self, other):
        self.update_ttl(other.ttl)
        super(Rdataset, self).union_update(other)

    def intersection_update(self, other):
        self.update_ttl(other.ttl)
        super(Rdataset, self).intersection_update(other)

    def update(self, other):
        """Add all rdatas in other to self.

        @param other: The rdataset from which to update
        @type other: dns.rdataset.Rdataset object"""

        self.update_ttl(other.ttl)
        super(Rdataset, self).update(other)

    def __repr__(self):
        if self.covers == 0:
            ctext = ''
        else:
            ctext = '(' + dns.rdatatype.to_text(self.covers) + ')'
        return '<DNS ' + dns.rdataclass.to_text(self.rdclass) + ' ' + \
               dns.rdatatype.to_text(self.rdtype) + ctext + ' rdataset>'

    def __str__(self):
        return self.to_text()

    def __eq__(self, other):
        """Two rdatasets are equal if they have the same class, type, and
        covers, and contain the same rdata.
        @rtype: bool"""

        if not isinstance(other, Rdataset):
            return False
        if self.rdclass != other.rdclass or \
           self.rdtype != other.rdtype or \
           self.covers != other.covers:
            return False
        return super(Rdataset, self).__eq__(other)

    def __ne__(self, other):
        return not self.__eq__(other)

    def to_text(self, name=None, origin=None, relativize=True,
                override_rdclass=None, **kw):
        """Convert the rdataset into DNS master file format.

        @see: L{dns.name.Name.choose_relativity} for more information
        on how I{origin} and I{relativize} determine the way names
        are emitted.

        Any additional keyword arguments are passed on to the rdata
        to_text() method.

        @param name: If name is not None, emit a RRs with I{name} as
        the owner name.
        @type name: dns.name.Name object
        @param origin: The origin for relative names, or None.
        @type origin: dns.name.Name object
        @param relativize: True if names should names be relativized
        @type relativize: bool"""
        if name is not None:
            name = name.choose_relativity(origin, relativize)
            ntext = str(name)
            pad = ' '
        else:
            ntext = ''
            pad = ''
        s = StringIO()
        if override_rdclass is not None:
            rdclass = override_rdclass
        else:
            rdclass = self.rdclass
        if len(self) == 0:
            #
            # Empty rdatasets are used for the question section, and in
            # some dynamic updates, so we don't need to print out the TTL
            # (which is meaningless anyway).
            #
            s.write(u'%s%s%s %s\n' % (ntext, pad,
                                      dns.rdataclass.to_text(rdclass),
                                      dns.rdatatype.to_text(self.rdtype)))
        else:
            for rd in self:
                s.write(u'%s%s%d %s %s %s\n' %
                        (ntext, pad, self.ttl, dns.rdataclass.to_text(rdclass),
                         dns.rdatatype.to_text(self.rdtype),
                         rd.to_text(origin=origin, relativize=relativize,
                         **kw)))
        #
        # We strip off the final \n for the caller's convenience in printing
        #
        return s.getvalue()[:-1]

    def to_wire(self, name, file, compress=None, origin=None,
                override_rdclass=None, want_shuffle=True):
        """Convert the rdataset to wire format.

        @param name: The owner name of the RRset that will be emitted
        @type name: dns.name.Name object
        @param file: The file to which the wire format data will be appended
        @type file: file
        @param compress: The compression table to use; the default is None.
        @type compress: dict
        @param origin: The origin to be appended to any relative names when
        they are emitted.  The default is None.
        @returns: the number of records emitted
        @rtype: int
        """

        if override_rdclass is not None:
            rdclass = override_rdclass
            want_shuffle = False
        else:
            rdclass = self.rdclass
        file.seek(0, 2)
        if len(self) == 0:
            name.to_wire(file, compress, origin)
            stuff = struct.pack("!HHIH", self.rdtype, rdclass, 0, 0)
            file.write(stuff)
            return 1
        else:
            if want_shuffle:
                l = list(self)
                random.shuffle(l)
            else:
                l = self
            for rd in l:
                name.to_wire(file, compress, origin)
                stuff = struct.pack("!HHIH", self.rdtype, rdclass,
                                    self.ttl, 0)
                file.write(stuff)
                start = file.tell()
                rd.to_wire(file, compress, origin)
                end = file.tell()
                assert end - start < 65536
                file.seek(start - 2)
                stuff = struct.pack("!H", end - start)
                file.write(stuff)
                file.seek(0, 2)
            return len(self)

    def match(self, rdclass, rdtype, covers):
        """Returns True if this rdataset matches the specified class, type,
        and covers"""
        if self.rdclass == rdclass and \
           self.rdtype == rdtype and \
           self.covers == covers:
            return True
        return False


def from_text_list(rdclass, rdtype, ttl, text_rdatas):
    """Create an rdataset with the specified class, type, and TTL, and with
    the specified list of rdatas in text format.

    @rtype: dns.rdataset.Rdataset object
    """

    if isinstance(rdclass, string_types):
        rdclass = dns.rdataclass.from_text(rdclass)
    if isinstance(rdtype, string_types):
        rdtype = dns.rdatatype.from_text(rdtype)
    r = Rdataset(rdclass, rdtype)
    r.update_ttl(ttl)
    for t in text_rdatas:
        rd = dns.rdata.from_text(r.rdclass, r.rdtype, t)
        r.add(rd)
    return r


def from_text(rdclass, rdtype, ttl, *text_rdatas):
    """Create an rdataset with the specified class, type, and TTL, and with
    the specified rdatas in text format.

    @rtype: dns.rdataset.Rdataset object
    """

    return from_text_list(rdclass, rdtype, ttl, text_rdatas)


def from_rdata_list(ttl, rdatas):
    """Create an rdataset with the specified TTL, and with
    the specified list of rdata objects.

    @rtype: dns.rdataset.Rdataset object
    """

    if len(rdatas) == 0:
        raise ValueError("rdata list must not be empty")
    r = None
    for rd in rdatas:
        if r is None:
            r = Rdataset(rd.rdclass, rd.rdtype)
            r.update_ttl(ttl)
        r.add(rd)
    return r


def from_rdata(ttl, *rdatas):
    """Create an rdataset with the specified TTL, and with
    the specified rdata objects.

    @rtype: dns.rdataset.Rdataset object
    """

    return from_rdata_list(ttl, rdatas)
rcode.py000064400000006040150351404340006211 0ustar00# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS Result Codes."""

import dns.exception
from ._compat import long


NOERROR = 0
FORMERR = 1
SERVFAIL = 2
NXDOMAIN = 3
NOTIMP = 4
REFUSED = 5
YXDOMAIN = 6
YXRRSET = 7
NXRRSET = 8
NOTAUTH = 9
NOTZONE = 10
BADVERS = 16

_by_text = {
    'NOERROR': NOERROR,
    'FORMERR': FORMERR,
    'SERVFAIL': SERVFAIL,
    'NXDOMAIN': NXDOMAIN,
    'NOTIMP': NOTIMP,
    'REFUSED': REFUSED,
    'YXDOMAIN': YXDOMAIN,
    'YXRRSET': YXRRSET,
    'NXRRSET': NXRRSET,
    'NOTAUTH': NOTAUTH,
    'NOTZONE': NOTZONE,
    'BADVERS': BADVERS
}

# We construct the inverse mapping programmatically to ensure that we
# cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
# would cause the mapping not to be a true inverse.

_by_value = dict((y, x) for x, y in _by_text.items())


class UnknownRcode(dns.exception.DNSException):

    """A DNS rcode is unknown."""


def from_text(text):
    """Convert text into an rcode.

    @param text: the textual rcode
    @type text: string
    @raises UnknownRcode: the rcode is unknown
    @rtype: int
    """

    if text.isdigit():
        v = int(text)
        if v >= 0 and v <= 4095:
            return v
    v = _by_text.get(text.upper())
    if v is None:
        raise UnknownRcode
    return v


def from_flags(flags, ednsflags):
    """Return the rcode value encoded by flags and ednsflags.

    @param flags: the DNS flags
    @type flags: int
    @param ednsflags: the EDNS flags
    @type ednsflags: int
    @raises ValueError: rcode is < 0 or > 4095
    @rtype: int
    """

    value = (flags & 0x000f) | ((ednsflags >> 20) & 0xff0)
    if value < 0 or value > 4095:
        raise ValueError('rcode must be >= 0 and <= 4095')
    return value


def to_flags(value):
    """Return a (flags, ednsflags) tuple which encodes the rcode.

    @param value: the rcode
    @type value: int
    @raises ValueError: rcode is < 0 or > 4095
    @rtype: (int, int) tuple
    """

    if value < 0 or value > 4095:
        raise ValueError('rcode must be >= 0 and <= 4095')
    v = value & 0xf
    ev = long(value & 0xff0) << 20
    return (v, ev)


def to_text(value):
    """Convert rcode into text.

    @param value: the rcode
    @type value: int
    @rtype: string
    """

    text = _by_value.get(value)
    if text is None:
        text = str(value)
    return text
dnssec.py000064400000034707150351404340006407 0ustar00# Copyright (C) 2003-2007, 2009, 2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""Common DNSSEC-related functions and constants."""

from io import BytesIO
import struct
import time

import dns.exception
import dns.hash
import dns.name
import dns.node
import dns.rdataset
import dns.rdata
import dns.rdatatype
import dns.rdataclass
from ._compat import string_types


class UnsupportedAlgorithm(dns.exception.DNSException):

    """The DNSSEC algorithm is not supported."""


class ValidationFailure(dns.exception.DNSException):

    """The DNSSEC signature is invalid."""

RSAMD5 = 1
DH = 2
DSA = 3
ECC = 4
RSASHA1 = 5
DSANSEC3SHA1 = 6
RSASHA1NSEC3SHA1 = 7
RSASHA256 = 8
RSASHA512 = 10
ECDSAP256SHA256 = 13
ECDSAP384SHA384 = 14
INDIRECT = 252
PRIVATEDNS = 253
PRIVATEOID = 254

_algorithm_by_text = {
    'RSAMD5': RSAMD5,
    'DH': DH,
    'DSA': DSA,
    'ECC': ECC,
    'RSASHA1': RSASHA1,
    'DSANSEC3SHA1': DSANSEC3SHA1,
    'RSASHA1NSEC3SHA1': RSASHA1NSEC3SHA1,
    'RSASHA256': RSASHA256,
    'RSASHA512': RSASHA512,
    'INDIRECT': INDIRECT,
    'ECDSAP256SHA256': ECDSAP256SHA256,
    'ECDSAP384SHA384': ECDSAP384SHA384,
    'PRIVATEDNS': PRIVATEDNS,
    'PRIVATEOID': PRIVATEOID,
}

# We construct the inverse mapping programmatically to ensure that we
# cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
# would cause the mapping not to be true inverse.

_algorithm_by_value = dict((y, x) for x, y in _algorithm_by_text.items())


def algorithm_from_text(text):
    """Convert text into a DNSSEC algorithm value
    @rtype: int"""

    value = _algorithm_by_text.get(text.upper())
    if value is None:
        value = int(text)
    return value


def algorithm_to_text(value):
    """Convert a DNSSEC algorithm value to text
    @rtype: string"""

    text = _algorithm_by_value.get(value)
    if text is None:
        text = str(value)
    return text


def _to_rdata(record, origin):
    s = BytesIO()
    record.to_wire(s, origin=origin)
    return s.getvalue()


def key_id(key, origin=None):
    rdata = _to_rdata(key, origin)
    rdata = bytearray(rdata)
    if key.algorithm == RSAMD5:
        return (rdata[-3] << 8) + rdata[-2]
    else:
        total = 0
        for i in range(len(rdata) // 2):
            total += (rdata[2 * i] << 8) + \
                rdata[2 * i + 1]
        if len(rdata) % 2 != 0:
            total += rdata[len(rdata) - 1] << 8
        total += ((total >> 16) & 0xffff)
        return total & 0xffff


def make_ds(name, key, algorithm, origin=None):
    if algorithm.upper() == 'SHA1':
        dsalg = 1
        hash = dns.hash.hashes['SHA1']()
    elif algorithm.upper() == 'SHA256':
        dsalg = 2
        hash = dns.hash.hashes['SHA256']()
    else:
        raise UnsupportedAlgorithm('unsupported algorithm "%s"' % algorithm)

    if isinstance(name, string_types):
        name = dns.name.from_text(name, origin)
    hash.update(name.canonicalize().to_wire())
    hash.update(_to_rdata(key, origin))
    digest = hash.digest()

    dsrdata = struct.pack("!HBB", key_id(key), key.algorithm, dsalg) + digest
    return dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.DS, dsrdata, 0,
                               len(dsrdata))


def _find_candidate_keys(keys, rrsig):
    candidate_keys = []
    value = keys.get(rrsig.signer)
    if value is None:
        return None
    if isinstance(value, dns.node.Node):
        try:
            rdataset = value.find_rdataset(dns.rdataclass.IN,
                                           dns.rdatatype.DNSKEY)
        except KeyError:
            return None
    else:
        rdataset = value
    for rdata in rdataset:
        if rdata.algorithm == rrsig.algorithm and \
                key_id(rdata) == rrsig.key_tag:
            candidate_keys.append(rdata)
    return candidate_keys


def _is_rsa(algorithm):
    return algorithm in (RSAMD5, RSASHA1,
                         RSASHA1NSEC3SHA1, RSASHA256,
                         RSASHA512)


def _is_dsa(algorithm):
    return algorithm in (DSA, DSANSEC3SHA1)


def _is_ecdsa(algorithm):
    return _have_ecdsa and (algorithm in (ECDSAP256SHA256, ECDSAP384SHA384))


def _is_md5(algorithm):
    return algorithm == RSAMD5


def _is_sha1(algorithm):
    return algorithm in (DSA, RSASHA1,
                         DSANSEC3SHA1, RSASHA1NSEC3SHA1)


def _is_sha256(algorithm):
    return algorithm in (RSASHA256, ECDSAP256SHA256)


def _is_sha384(algorithm):
    return algorithm == ECDSAP384SHA384


def _is_sha512(algorithm):
    return algorithm == RSASHA512


def _make_hash(algorithm):
    if _is_md5(algorithm):
        return dns.hash.hashes['MD5']()
    if _is_sha1(algorithm):
        return dns.hash.hashes['SHA1']()
    if _is_sha256(algorithm):
        return dns.hash.hashes['SHA256']()
    if _is_sha384(algorithm):
        return dns.hash.hashes['SHA384']()
    if _is_sha512(algorithm):
        return dns.hash.hashes['SHA512']()
    raise ValidationFailure('unknown hash for algorithm %u' % algorithm)


def _make_algorithm_id(algorithm):
    if _is_md5(algorithm):
        oid = [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05]
    elif _is_sha1(algorithm):
        oid = [0x2b, 0x0e, 0x03, 0x02, 0x1a]
    elif _is_sha256(algorithm):
        oid = [0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01]
    elif _is_sha512(algorithm):
        oid = [0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03]
    else:
        raise ValidationFailure('unknown algorithm %u' % algorithm)
    olen = len(oid)
    dlen = _make_hash(algorithm).digest_size
    idbytes = [0x30] + [8 + olen + dlen] + \
              [0x30, olen + 4] + [0x06, olen] + oid + \
              [0x05, 0x00] + [0x04, dlen]
    return struct.pack('!%dB' % len(idbytes), *idbytes)


def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
    """Validate an RRset against a single signature rdata

    The owner name of the rrsig is assumed to be the same as the owner name
    of the rrset.

    @param rrset: The RRset to validate
    @type rrset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset)
    tuple
    @param rrsig: The signature rdata
    @type rrsig: dns.rrset.Rdata
    @param keys: The key dictionary.
    @type keys: a dictionary keyed by dns.name.Name with node or rdataset
    values
    @param origin: The origin to use for relative names
    @type origin: dns.name.Name or None
    @param now: The time to use when validating the signatures.  The default
    is the current time.
    @type now: int
    """

    if isinstance(origin, string_types):
        origin = dns.name.from_text(origin, dns.name.root)

    for candidate_key in _find_candidate_keys(keys, rrsig):
        if not candidate_key:
            raise ValidationFailure('unknown key')

        # For convenience, allow the rrset to be specified as a (name,
        # rdataset) tuple as well as a proper rrset
        if isinstance(rrset, tuple):
            rrname = rrset[0]
            rdataset = rrset[1]
        else:
            rrname = rrset.name
            rdataset = rrset

        if now is None:
            now = time.time()
        if rrsig.expiration < now:
            raise ValidationFailure('expired')
        if rrsig.inception > now:
            raise ValidationFailure('not yet valid')

        hash = _make_hash(rrsig.algorithm)

        if _is_rsa(rrsig.algorithm):
            keyptr = candidate_key.key
            (bytes_,) = struct.unpack('!B', keyptr[0:1])
            keyptr = keyptr[1:]
            if bytes_ == 0:
                (bytes_,) = struct.unpack('!H', keyptr[0:2])
                keyptr = keyptr[2:]
            rsa_e = keyptr[0:bytes_]
            rsa_n = keyptr[bytes_:]
            keylen = len(rsa_n) * 8
            pubkey = Crypto.PublicKey.RSA.construct(
                (Crypto.Util.number.bytes_to_long(rsa_n),
                 Crypto.Util.number.bytes_to_long(rsa_e)))
            sig = (Crypto.Util.number.bytes_to_long(rrsig.signature),)
        elif _is_dsa(rrsig.algorithm):
            keyptr = candidate_key.key
            (t,) = struct.unpack('!B', keyptr[0:1])
            keyptr = keyptr[1:]
            octets = 64 + t * 8
            dsa_q = keyptr[0:20]
            keyptr = keyptr[20:]
            dsa_p = keyptr[0:octets]
            keyptr = keyptr[octets:]
            dsa_g = keyptr[0:octets]
            keyptr = keyptr[octets:]
            dsa_y = keyptr[0:octets]
            pubkey = Crypto.PublicKey.DSA.construct(
                (Crypto.Util.number.bytes_to_long(dsa_y),
                 Crypto.Util.number.bytes_to_long(dsa_g),
                 Crypto.Util.number.bytes_to_long(dsa_p),
                 Crypto.Util.number.bytes_to_long(dsa_q)))
            (dsa_r, dsa_s) = struct.unpack('!20s20s', rrsig.signature[1:])
            sig = (Crypto.Util.number.bytes_to_long(dsa_r),
                   Crypto.Util.number.bytes_to_long(dsa_s))
        elif _is_ecdsa(rrsig.algorithm):
            if rrsig.algorithm == ECDSAP256SHA256:
                curve = ecdsa.curves.NIST256p
                key_len = 32
            elif rrsig.algorithm == ECDSAP384SHA384:
                curve = ecdsa.curves.NIST384p
                key_len = 48
            else:
                # shouldn't happen
                raise ValidationFailure('unknown ECDSA curve')
            keyptr = candidate_key.key
            x = Crypto.Util.number.bytes_to_long(keyptr[0:key_len])
            y = Crypto.Util.number.bytes_to_long(keyptr[key_len:key_len * 2])
            assert ecdsa.ecdsa.point_is_valid(curve.generator, x, y)
            point = ecdsa.ellipticcurve.Point(curve.curve, x, y, curve.order)
            verifying_key = ecdsa.keys.VerifyingKey.from_public_point(point,
                                                                      curve)
            pubkey = ECKeyWrapper(verifying_key, key_len)
            r = rrsig.signature[:key_len]
            s = rrsig.signature[key_len:]
            sig = ecdsa.ecdsa.Signature(Crypto.Util.number.bytes_to_long(r),
                                        Crypto.Util.number.bytes_to_long(s))
        else:
            raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm)

        hash.update(_to_rdata(rrsig, origin)[:18])
        hash.update(rrsig.signer.to_digestable(origin))

        if rrsig.labels < len(rrname) - 1:
            suffix = rrname.split(rrsig.labels + 1)[1]
            rrname = dns.name.from_text('*', suffix)
        rrnamebuf = rrname.to_digestable(origin)
        rrfixed = struct.pack('!HHI', rdataset.rdtype, rdataset.rdclass,
                              rrsig.original_ttl)
        rrlist = sorted(rdataset)
        for rr in rrlist:
            hash.update(rrnamebuf)
            hash.update(rrfixed)
            rrdata = rr.to_digestable(origin)
            rrlen = struct.pack('!H', len(rrdata))
            hash.update(rrlen)
            hash.update(rrdata)

        digest = hash.digest()

        if _is_rsa(rrsig.algorithm):
            # PKCS1 algorithm identifier goop
            digest = _make_algorithm_id(rrsig.algorithm) + digest
            padlen = keylen // 8 - len(digest) - 3
            digest = struct.pack('!%dB' % (2 + padlen + 1),
                                 *([0, 1] + [0xFF] * padlen + [0])) + digest
        elif _is_dsa(rrsig.algorithm) or _is_ecdsa(rrsig.algorithm):
            pass
        else:
            # Raise here for code clarity; this won't actually ever happen
            # since if the algorithm is really unknown we'd already have
            # raised an exception above
            raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm)

        if pubkey.verify(digest, sig):
            return
    raise ValidationFailure('verify failure')


def _validate(rrset, rrsigset, keys, origin=None, now=None):
    """Validate an RRset

    @param rrset: The RRset to validate
    @type rrset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset)
    tuple
    @param rrsigset: The signature RRset
    @type rrsigset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset)
    tuple
    @param keys: The key dictionary.
    @type keys: a dictionary keyed by dns.name.Name with node or rdataset
    values
    @param origin: The origin to use for relative names
    @type origin: dns.name.Name or None
    @param now: The time to use when validating the signatures.  The default
    is the current time.
    @type now: int
    """

    if isinstance(origin, string_types):
        origin = dns.name.from_text(origin, dns.name.root)

    if isinstance(rrset, tuple):
        rrname = rrset[0]
    else:
        rrname = rrset.name

    if isinstance(rrsigset, tuple):
        rrsigname = rrsigset[0]
        rrsigrdataset = rrsigset[1]
    else:
        rrsigname = rrsigset.name
        rrsigrdataset = rrsigset

    rrname = rrname.choose_relativity(origin)
    rrsigname = rrname.choose_relativity(origin)
    if rrname != rrsigname:
        raise ValidationFailure("owner names do not match")

    for rrsig in rrsigrdataset:
        try:
            _validate_rrsig(rrset, rrsig, keys, origin, now)
            return
        except ValidationFailure:
            pass
    raise ValidationFailure("no RRSIGs validated")


def _need_pycrypto(*args, **kwargs):
    raise NotImplementedError("DNSSEC validation requires pycrypto")

try:
    import Crypto.PublicKey.RSA
    import Crypto.PublicKey.DSA
    import Crypto.Util.number
    validate = _validate
    validate_rrsig = _validate_rrsig
    _have_pycrypto = True
except ImportError:
    validate = _need_pycrypto
    validate_rrsig = _need_pycrypto
    _have_pycrypto = False

try:
    import ecdsa
    import ecdsa.ecdsa
    import ecdsa.ellipticcurve
    import ecdsa.keys
    _have_ecdsa = True

    class ECKeyWrapper(object):

        def __init__(self, key, key_len):
            self.key = key
            self.key_len = key_len

        def verify(self, digest, sig):
            diglong = Crypto.Util.number.bytes_to_long(digest)
            return self.key.pubkey.verifies(diglong, sig)

except ImportError:
    _have_ecdsa = False
edns.py000064400000010440150351404340006045 0ustar00# Copyright (C) 2009, 2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""EDNS Options"""

NSID = 3


class Option(object):

    """Base class for all EDNS option types.
    """

    def __init__(self, otype):
        """Initialize an option.
        @param otype: The rdata type
        @type otype: int
        """
        self.otype = otype

    def to_wire(self, file):
        """Convert an option to wire format.
        """
        raise NotImplementedError

    @classmethod
    def from_wire(cls, otype, wire, current, olen):
        """Build an EDNS option object from wire format

        @param otype: The option type
        @type otype: int
        @param wire: The wire-format message
        @type wire: string
        @param current: The offset in wire of the beginning of the rdata.
        @type current: int
        @param olen: The length of the wire-format option data
        @type olen: int
        @rtype: dns.edns.Option instance"""
        raise NotImplementedError

    def _cmp(self, other):
        """Compare an EDNS option with another option of the same type.
        Return < 0 if self < other, 0 if self == other,
        and > 0 if self > other.
        """
        raise NotImplementedError

    def __eq__(self, other):
        if not isinstance(other, Option):
            return False
        if self.otype != other.otype:
            return False
        return self._cmp(other) == 0

    def __ne__(self, other):
        if not isinstance(other, Option):
            return False
        if self.otype != other.otype:
            return False
        return self._cmp(other) != 0

    def __lt__(self, other):
        if not isinstance(other, Option) or \
                self.otype != other.otype:
            return NotImplemented
        return self._cmp(other) < 0

    def __le__(self, other):
        if not isinstance(other, Option) or \
                self.otype != other.otype:
            return NotImplemented
        return self._cmp(other) <= 0

    def __ge__(self, other):
        if not isinstance(other, Option) or \
                self.otype != other.otype:
            return NotImplemented
        return self._cmp(other) >= 0

    def __gt__(self, other):
        if not isinstance(other, Option) or \
                self.otype != other.otype:
            return NotImplemented
        return self._cmp(other) > 0


class GenericOption(Option):

    """Generate Rdata Class

    This class is used for EDNS option types for which we have no better
    implementation.
    """

    def __init__(self, otype, data):
        super(GenericOption, self).__init__(otype)
        self.data = data

    def to_wire(self, file):
        file.write(self.data)

    @classmethod
    def from_wire(cls, otype, wire, current, olen):
        return cls(otype, wire[current: current + olen])

    def _cmp(self, other):
        if self.data == other.data:
            return 0
        if self.data > other.data:
            return 1
        return -1

_type_to_class = {
}


def get_option_class(otype):
    cls = _type_to_class.get(otype)
    if cls is None:
        cls = GenericOption
    return cls


def option_from_wire(otype, wire, current, olen):
    """Build an EDNS option object from wire format

    @param otype: The option type
    @type otype: int
    @param wire: The wire-format message
    @type wire: string
    @param current: The offset in wire of the beginning of the rdata.
    @type current: int
    @param olen: The length of the wire-format option data
    @type olen: int
    @rtype: dns.edns.Option instance"""

    cls = get_option_class(otype)
    return cls.from_wire(otype, wire, current, olen)
resolver.py000064400000145611150351404340006766 0ustar00# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""DNS stub resolver.

@var default_resolver: The default resolver object
@type default_resolver: dns.resolver.Resolver object"""

import socket
import sys
import time
import random

try:
    import threading as _threading
except ImportError:
    import dummy_threading as _threading

import dns.exception
import dns.flags
import dns.ipv4
import dns.ipv6
import dns.message
import dns.name
import dns.query
import dns.rcode
import dns.rdataclass
import dns.rdatatype
import dns.reversename
import dns.tsig
from ._compat import xrange, string_types

if sys.platform == 'win32':
    try:
        import winreg as _winreg
    except ImportError:
        import _winreg  # pylint: disable=import-error

class NXDOMAIN(dns.exception.DNSException):

    """The DNS query name does not exist."""
    supp_kwargs = set(['qnames', 'responses'])
    fmt = None  # we have our own __str__ implementation

    def _check_kwargs(self, qnames, responses=None):
        if not isinstance(qnames, (list, tuple, set)):
            raise AttributeError("qnames must be a list, tuple or set")
        if len(qnames) == 0:
            raise AttributeError("qnames must contain at least one element")
        if responses is None:
            responses = {}
        elif not isinstance(responses, dict):
            raise AttributeError("responses must be a dict(qname=response)")
        kwargs = dict(qnames=qnames, responses=responses)
        return kwargs

    def __str__(self):
        if 'qnames' not in self.kwargs:
            return super(NXDOMAIN, self).__str__()
        qnames = self.kwargs['qnames']
        if len(qnames) > 1:
            msg = 'None of DNS query names exist'
        else:
            msg = self.__doc__[:-1]
        qnames = ', '.join(map(str, qnames))
        return "%s: %s" % (msg, qnames)

    def canonical_name(self):
        if not 'qnames' in self.kwargs:
            raise TypeError("parametrized exception required")
        IN = dns.rdataclass.IN
        CNAME = dns.rdatatype.CNAME
        cname = None
        for qname in self.kwargs['qnames']:
            response = self.kwargs['responses'][qname]
            for answer in response.answer:
                if answer.rdtype != CNAME or answer.rdclass != IN:
                    continue
                cname = answer.items[0].target.to_text()
            if cname is not None:
                return dns.name.from_text(cname)
        return self.kwargs['qnames'][0]
    canonical_name = property(canonical_name, doc=(
        "Return the unresolved canonical name."))

    def __add__(self, e_nx):
        """Augment by results from another NXDOMAIN exception."""
        qnames0 = list(self.kwargs.get('qnames', []))
        responses0 = dict(self.kwargs.get('responses', {}))
        responses1 = e_nx.kwargs.get('responses', {})
        for qname1 in e_nx.kwargs.get('qnames', []):
            if qname1 not in qnames0:
                qnames0.append(qname1)
            if qname1 in responses1:
                responses0[qname1] = responses1[qname1]
        return NXDOMAIN(qnames=qnames0, responses=responses0)


class YXDOMAIN(dns.exception.DNSException):

    """The DNS query name is too long after DNAME substitution."""

# The definition of the Timeout exception has moved from here to the
# dns.exception module.  We keep dns.resolver.Timeout defined for
# backwards compatibility.

Timeout = dns.exception.Timeout


class NoAnswer(dns.exception.DNSException):

    """The DNS response does not contain an answer to the question."""
    fmt = 'The DNS response does not contain an answer ' + \
          'to the question: {query}'
    supp_kwargs = set(['response'])

    def _fmt_kwargs(self, **kwargs):
        return super(NoAnswer, self)._fmt_kwargs(
            query=kwargs['response'].question)


class NoNameservers(dns.exception.DNSException):

    """All nameservers failed to answer the query.

    errors: list of servers and respective errors
    The type of errors is
    [(server ip address, any object convertible to string)].
    Non-empty errors list will add explanatory message ()
    """

    msg = "All nameservers failed to answer the query."
    fmt = "%s {query}: {errors}" % msg[:-1]
    supp_kwargs = set(['request', 'errors'])

    def _fmt_kwargs(self, **kwargs):
        srv_msgs = []
        for err in kwargs['errors']:
            srv_msgs.append('Server %s %s port %s answered %s' % (err[0],
                            'TCP' if err[1] else 'UDP', err[2], err[3]))
        return super(NoNameservers, self)._fmt_kwargs(
            query=kwargs['request'].question, errors='; '.join(srv_msgs))


class NotAbsolute(dns.exception.DNSException):

    """An absolute domain name is required but a relative name was provided."""


class NoRootSOA(dns.exception.DNSException):

    """There is no SOA RR at the DNS root name. This should never happen!"""


class NoMetaqueries(dns.exception.DNSException):

    """DNS metaqueries are not allowed."""


class Answer(object):

    """DNS stub resolver answer

    Instances of this class bundle up the result of a successful DNS
    resolution.

    For convenience, the answer object implements much of the sequence
    protocol, forwarding to its rrset.  E.g. "for a in answer" is
    equivalent to "for a in answer.rrset", "answer[i]" is equivalent
    to "answer.rrset[i]", and "answer[i:j]" is equivalent to
    "answer.rrset[i:j]".

    Note that CNAMEs or DNAMEs in the response may mean that answer
    node's name might not be the query name.

    @ivar qname: The query name
    @type qname: dns.name.Name object
    @ivar rdtype: The query type
    @type rdtype: int
    @ivar rdclass: The query class
    @type rdclass: int
    @ivar response: The response message
    @type response: dns.message.Message object
    @ivar rrset: The answer
    @type rrset: dns.rrset.RRset object
    @ivar expiration: The time when the answer expires
    @type expiration: float (seconds since the epoch)
    @ivar canonical_name: The canonical name of the query name
    @type canonical_name: dns.name.Name object
    """

    def __init__(self, qname, rdtype, rdclass, response,
                 raise_on_no_answer=True):
        self.qname = qname
        self.rdtype = rdtype
        self.rdclass = rdclass
        self.response = response
        min_ttl = -1
        rrset = None
        for count in xrange(0, 15):
            try:
                rrset = response.find_rrset(response.answer, qname,
                                            rdclass, rdtype)
                if min_ttl == -1 or rrset.ttl < min_ttl:
                    min_ttl = rrset.ttl
                break
            except KeyError:
                if rdtype != dns.rdatatype.CNAME:
                    try:
                        crrset = response.find_rrset(response.answer,
                                                     qname,
                                                     rdclass,
                                                     dns.rdatatype.CNAME)
                        if min_ttl == -1 or crrset.ttl < min_ttl:
                            min_ttl = crrset.ttl
                        for rd in crrset:
                            qname = rd.target
                            break
                        continue
                    except KeyError:
                        if raise_on_no_answer:
                            raise NoAnswer(response=response)
                if raise_on_no_answer:
                    raise NoAnswer(response=response)
        if rrset is None and raise_on_no_answer:
            raise NoAnswer(response=response)
        self.canonical_name = qname
        self.rrset = rrset
        if rrset is None:
            while 1:
                # Look for a SOA RR whose owner name is a superdomain
                # of qname.
                try:
                    srrset = response.find_rrset(response.authority, qname,
                                                 rdclass, dns.rdatatype.SOA)
                    if min_ttl == -1 or srrset.ttl < min_ttl:
                        min_ttl = srrset.ttl
                    if srrset[0].minimum < min_ttl:
                        min_ttl = srrset[0].minimum
                    break
                except KeyError:
                    try:
                        qname = qname.parent()
                    except dns.name.NoParent:
                        break
        self.expiration = time.time() + min_ttl

    def __getattr__(self, attr):
        if attr == 'name':
            return self.rrset.name
        elif attr == 'ttl':
            return self.rrset.ttl
        elif attr == 'covers':
            return self.rrset.covers
        elif attr == 'rdclass':
            return self.rrset.rdclass
        elif attr == 'rdtype':
            return self.rrset.rdtype
        else:
            raise AttributeError(attr)

    def __len__(self):
        return self.rrset and len(self.rrset) or 0

    def __iter__(self):
        return self.rrset and iter(self.rrset) or iter(tuple())

    def __getitem__(self, i):
        return self.rrset[i]

    def __delitem__(self, i):
        del self.rrset[i]


class Cache(object):

    """Simple DNS answer cache.

    @ivar data: A dictionary of cached data
    @type data: dict
    @ivar cleaning_interval: The number of seconds between cleanings.  The
    default is 300 (5 minutes).
    @type cleaning_interval: float
    @ivar next_cleaning: The time the cache should next be cleaned (in seconds
    since the epoch.)
    @type next_cleaning: float
    """

    def __init__(self, cleaning_interval=300.0):
        """Initialize a DNS cache.

        @param cleaning_interval: the number of seconds between periodic
        cleanings.  The default is 300.0
        @type cleaning_interval: float.
        """

        self.data = {}
        self.cleaning_interval = cleaning_interval
        self.next_cleaning = time.time() + self.cleaning_interval
        self.lock = _threading.Lock()

    def _maybe_clean(self):
        """Clean the cache if it's time to do so."""

        now = time.time()
        if self.next_cleaning <= now:
            keys_to_delete = []
            for (k, v) in self.data.items():
                if v.expiration <= now:
                    keys_to_delete.append(k)
            for k in keys_to_delete:
                del self.data[k]
            now = time.time()
            self.next_cleaning = now + self.cleaning_interval

    def get(self, key):
        """Get the answer associated with I{key}.  Returns None if
        no answer is cached for the key.
        @param key: the key
        @type key: (dns.name.Name, int, int) tuple whose values are the
        query name, rdtype, and rdclass.
        @rtype: dns.resolver.Answer object or None
        """

        try:
            self.lock.acquire()
            self._maybe_clean()
            v = self.data.get(key)
            if v is None or v.expiration <= time.time():
                return None
            return v
        finally:
            self.lock.release()

    def put(self, key, value):
        """Associate key and value in the cache.
        @param key: the key
        @type key: (dns.name.Name, int, int) tuple whose values are the
        query name, rdtype, and rdclass.
        @param value: The answer being cached
        @type value: dns.resolver.Answer object
        """

        try:
            self.lock.acquire()
            self._maybe_clean()
            self.data[key] = value
        finally:
            self.lock.release()

    def flush(self, key=None):
        """Flush the cache.

        If I{key} is specified, only that item is flushed.  Otherwise
        the entire cache is flushed.

        @param key: the key to flush
        @type key: (dns.name.Name, int, int) tuple or None
        """

        try:
            self.lock.acquire()
            if key is not None:
                if key in self.data:
                    del self.data[key]
            else:
                self.data = {}
                self.next_cleaning = time.time() + self.cleaning_interval
        finally:
            self.lock.release()


class LRUCacheNode(object):

    """LRUCache node.
    """

    def __init__(self, key, value):
        self.key = key
        self.value = value
        self.prev = self
        self.next = self

    def link_before(self, node):
        self.prev = node.prev
        self.next = node
        node.prev.next = self
        node.prev = self

    def link_after(self, node):
        self.prev = node
        self.next = node.next
        node.next.prev = self
        node.next = self

    def unlink(self):
        self.next.prev = self.prev
        self.prev.next = self.next


class LRUCache(object):

    """Bounded least-recently-used DNS answer cache.

    This cache is better than the simple cache (above) if you're
    running a web crawler or other process that does a lot of
    resolutions.  The LRUCache has a maximum number of nodes, and when
    it is full, the least-recently used node is removed to make space
    for a new one.

    @ivar data: A dictionary of cached data
    @type data: dict
    @ivar sentinel: sentinel node for circular doubly linked list of nodes
    @type sentinel: LRUCacheNode object
    @ivar max_size: The maximum number of nodes
    @type max_size: int
    """

    def __init__(self, max_size=100000):
        """Initialize a DNS cache.

        @param max_size: The maximum number of nodes to cache; the default is
        100,000. Must be greater than 1.
        @type max_size: int
        """
        self.data = {}
        self.set_max_size(max_size)
        self.sentinel = LRUCacheNode(None, None)
        self.lock = _threading.Lock()

    def set_max_size(self, max_size):
        if max_size < 1:
            max_size = 1
        self.max_size = max_size

    def get(self, key):
        """Get the answer associated with I{key}.  Returns None if
        no answer is cached for the key.
        @param key: the key
        @type key: (dns.name.Name, int, int) tuple whose values are the
        query name, rdtype, and rdclass.
        @rtype: dns.resolver.Answer object or None
        """
        try:
            self.lock.acquire()
            node = self.data.get(key)
            if node is None:
                return None
            # Unlink because we're either going to move the node to the front
            # of the LRU list or we're going to free it.
            node.unlink()
            if node.value.expiration <= time.time():
                del self.data[node.key]
                return None
            node.link_after(self.sentinel)
            return node.value
        finally:
            self.lock.release()

    def put(self, key, value):
        """Associate key and value in the cache.
        @param key: the key
        @type key: (dns.name.Name, int, int) tuple whose values are the
        query name, rdtype, and rdclass.
        @param value: The answer being cached
        @type value: dns.resolver.Answer object
        """
        try:
            self.lock.acquire()
            node = self.data.get(key)
            if node is not None:
                node.unlink()
                del self.data[node.key]
            while len(self.data) >= self.max_size:
                node = self.sentinel.prev
                node.unlink()
                del self.data[node.key]
            node = LRUCacheNode(key, value)
            node.link_after(self.sentinel)
            self.data[key] = node
        finally:
            self.lock.release()

    def flush(self, key=None):
        """Flush the cache.

        If I{key} is specified, only that item is flushed.  Otherwise
        the entire cache is flushed.

        @param key: the key to flush
        @type key: (dns.name.Name, int, int) tuple or None
        """
        try:
            self.lock.acquire()
            if key is not None:
                node = self.data.get(key)
                if node is not None:
                    node.unlink()
                    del self.data[node.key]
            else:
                node = self.sentinel.next
                while node != self.sentinel:
                    next = node.next
                    node.prev = None
                    node.next = None
                    node = next
                self.data = {}
        finally:
            self.lock.release()


class Resolver(object):

    """DNS stub resolver

    @ivar domain: The domain of this host
    @type domain: dns.name.Name object
    @ivar nameservers: A list of nameservers to query.  Each nameserver is
    a string which contains the IP address of a nameserver.
    @type nameservers: list of strings
    @ivar search: The search list.  If the query name is a relative name,
    the resolver will construct an absolute query name by appending the search
    names one by one to the query name.
    @type search: list of dns.name.Name objects
    @ivar port: The port to which to send queries.  The default is 53.
    @type port: int
    @ivar timeout: The number of seconds to wait for a response from a
    server, before timing out.
    @type timeout: float
    @ivar lifetime: The total number of seconds to spend trying to get an
    answer to the question.  If the lifetime expires, a Timeout exception
    will occur.
    @type lifetime: float
    @ivar keyring: The TSIG keyring to use.  The default is None.
    @type keyring: dict
    @ivar keyname: The TSIG keyname to use.  The default is None.
    @type keyname: dns.name.Name object
    @ivar keyalgorithm: The TSIG key algorithm to use.  The default is
    dns.tsig.default_algorithm.
    @type keyalgorithm: string
    @ivar edns: The EDNS level to use.  The default is -1, no Edns.
    @type edns: int
    @ivar ednsflags: The EDNS flags
    @type ednsflags: int
    @ivar payload: The EDNS payload size.  The default is 0.
    @type payload: int
    @ivar flags: The message flags to use.  The default is None (i.e. not
    overwritten)
    @type flags: int
    @ivar cache: The cache to use.  The default is None.
    @type cache: dns.resolver.Cache object
    @ivar retry_servfail: should we retry a nameserver if it says SERVFAIL?
    The default is 'false'.
    @type retry_servfail: bool
    """

    def __init__(self, filename='/etc/resolv.conf', configure=True):
        """Initialize a resolver instance.

        @param filename: The filename of a configuration file in
        standard /etc/resolv.conf format.  This parameter is meaningful
        only when I{configure} is true and the platform is POSIX.
        @type filename: string or file object
        @param configure: If True (the default), the resolver instance
        is configured in the normal fashion for the operating system
        the resolver is running on.  (I.e. a /etc/resolv.conf file on
        POSIX systems and from the registry on Windows systems.)
        @type configure: bool"""

        self.domain = None
        self.nameservers = None
        self.nameserver_ports = None
        self.port = None
        self.search = None
        self.timeout = None
        self.lifetime = None
        self.keyring = None
        self.keyname = None
        self.keyalgorithm = None
        self.edns = None
        self.ednsflags = None
        self.payload = None
        self.cache = None
        self.flags = None
        self.retry_servfail = False
        self.rotate = False

        self.reset()
        if configure:
            if sys.platform == 'win32':
                self.read_registry()
            elif filename:
                self.read_resolv_conf(filename)

    def reset(self):
        """Reset all resolver configuration to the defaults."""
        self.domain = \
            dns.name.Name(dns.name.from_text(socket.gethostname())[1:])
        if len(self.domain) == 0:
            self.domain = dns.name.root
        self.nameservers = []
        self.nameserver_ports = {}
        self.port = 53
        self.search = []
        self.timeout = 2.0
        self.lifetime = 30.0
        self.keyring = None
        self.keyname = None
        self.keyalgorithm = dns.tsig.default_algorithm
        self.edns = -1
        self.ednsflags = 0
        self.payload = 0
        self.cache = None
        self.flags = None
        self.retry_servfail = False
        self.rotate = False

    def read_resolv_conf(self, f):
        """Process f as a file in the /etc/resolv.conf format.  If f is
        a string, it is used as the name of the file to open; otherwise it
        is treated as the file itself."""
        if isinstance(f, string_types):
            try:
                f = open(f, 'r')
            except IOError:
                # /etc/resolv.conf doesn't exist, can't be read, etc.
                # We'll just use the default resolver configuration.
                self.nameservers = ['127.0.0.1']
                return
            want_close = True
        else:
            want_close = False
        try:
            for l in f:
                if len(l) == 0 or l[0] == '#' or l[0] == ';':
                    continue
                tokens = l.split()

                # Any line containing less than 2 tokens is malformed
                if len(tokens) < 2:
                    continue

                if tokens[0] == 'nameserver':
                    self.nameservers.append(tokens[1])
                elif tokens[0] == 'domain':
                    self.domain = dns.name.from_text(tokens[1])
                elif tokens[0] == 'search':
                    for suffix in tokens[1:]:
                        self.search.append(dns.name.from_text(suffix))
                elif tokens[0] == 'options':
                    if 'rotate' in tokens[1:]:
                        self.rotate = True
        finally:
            if want_close:
                f.close()
        if len(self.nameservers) == 0:
            self.nameservers.append('127.0.0.1')

    def _determine_split_char(self, entry):
        #
        # The windows registry irritatingly changes the list element
        # delimiter in between ' ' and ',' (and vice-versa) in various
        # versions of windows.
        #
        if entry.find(' ') >= 0:
            split_char = ' '
        elif entry.find(',') >= 0:
            split_char = ','
        else:
            # probably a singleton; treat as a space-separated list.
            split_char = ' '
        return split_char

    def _config_win32_nameservers(self, nameservers):
        """Configure a NameServer registry entry."""
        # we call str() on nameservers to convert it from unicode to ascii
        nameservers = str(nameservers)
        split_char = self._determine_split_char(nameservers)
        ns_list = nameservers.split(split_char)
        for ns in ns_list:
            if ns not in self.nameservers:
                self.nameservers.append(ns)

    def _config_win32_domain(self, domain):
        """Configure a Domain registry entry."""
        # we call str() on domain to convert it from unicode to ascii
        self.domain = dns.name.from_text(str(domain))

    def _config_win32_search(self, search):
        """Configure a Search registry entry."""
        # we call str() on search to convert it from unicode to ascii
        search = str(search)
        split_char = self._determine_split_char(search)
        search_list = search.split(split_char)
        for s in search_list:
            if s not in self.search:
                self.search.append(dns.name.from_text(s))

    def _config_win32_fromkey(self, key):
        """Extract DNS info from a registry key."""
        try:
            servers, rtype = _winreg.QueryValueEx(key, 'NameServer')
        except WindowsError:  # pylint: disable=undefined-variable
            servers = None
        if servers:
            self._config_win32_nameservers(servers)
            try:
                dom, rtype = _winreg.QueryValueEx(key, 'Domain')
                if dom:
                    self._config_win32_domain(dom)
            except WindowsError:  # pylint: disable=undefined-variable
                pass
        else:
            try:
                servers, rtype = _winreg.QueryValueEx(key, 'DhcpNameServer')
            except WindowsError:  # pylint: disable=undefined-variable
                servers = None
            if servers:
                self._config_win32_nameservers(servers)
                try:
                    dom, rtype = _winreg.QueryValueEx(key, 'DhcpDomain')
                    if dom:
                        self._config_win32_domain(dom)
                except WindowsError:  # pylint: disable=undefined-variable
                    pass
        try:
            search, rtype = _winreg.QueryValueEx(key, 'SearchList')
        except WindowsError:  # pylint: disable=undefined-variable
            search = None
        if search:
            self._config_win32_search(search)

    def read_registry(self):
        """Extract resolver configuration from the Windows registry."""
        lm = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
        want_scan = False
        try:
            try:
                # XP, 2000
                tcp_params = _winreg.OpenKey(lm,
                                             r'SYSTEM\CurrentControlSet'
                                             r'\Services\Tcpip\Parameters')
                want_scan = True
            except EnvironmentError:
                # ME
                tcp_params = _winreg.OpenKey(lm,
                                             r'SYSTEM\CurrentControlSet'
                                             r'\Services\VxD\MSTCP')
            try:
                self._config_win32_fromkey(tcp_params)
            finally:
                tcp_params.Close()
            if want_scan:
                interfaces = _winreg.OpenKey(lm,
                                             r'SYSTEM\CurrentControlSet'
                                             r'\Services\Tcpip\Parameters'
                                             r'\Interfaces')
                try:
                    i = 0
                    while True:
                        try:
                            guid = _winreg.EnumKey(interfaces, i)
                            i += 1
                            key = _winreg.OpenKey(interfaces, guid)
                            if not self._win32_is_nic_enabled(lm, guid, key):
                                continue
                            try:
                                self._config_win32_fromkey(key)
                            finally:
                                key.Close()
                        except EnvironmentError:
                            break
                finally:
                    interfaces.Close()
        finally:
            lm.Close()

    def _win32_is_nic_enabled(self, lm, guid, interface_key):
        # Look in the Windows Registry to determine whether the network
        # interface corresponding to the given guid is enabled.
        #
        # (Code contributed by Paul Marks, thanks!)
        #
        try:
            # This hard-coded location seems to be consistent, at least
            # from Windows 2000 through Vista.
            connection_key = _winreg.OpenKey(
                lm,
                r'SYSTEM\CurrentControlSet\Control\Network'
                r'\{4D36E972-E325-11CE-BFC1-08002BE10318}'
                r'\%s\Connection' % guid)

            try:
                # The PnpInstanceID points to a key inside Enum
                (pnp_id, ttype) = _winreg.QueryValueEx(
                    connection_key, 'PnpInstanceID')

                if ttype != _winreg.REG_SZ:
                    raise ValueError

                device_key = _winreg.OpenKey(
                    lm, r'SYSTEM\CurrentControlSet\Enum\%s' % pnp_id)

                try:
                    # Get ConfigFlags for this device
                    (flags, ttype) = _winreg.QueryValueEx(
                        device_key, 'ConfigFlags')

                    if ttype != _winreg.REG_DWORD:
                        raise ValueError

                    # Based on experimentation, bit 0x1 indicates that the
                    # device is disabled.
                    return not flags & 0x1

                finally:
                    device_key.Close()
            finally:
                connection_key.Close()
        except (EnvironmentError, ValueError):
            # Pre-vista, enabled interfaces seem to have a non-empty
            # NTEContextList; this was how dnspython detected enabled
            # nics before the code above was contributed.  We've retained
            # the old method since we don't know if the code above works
            # on Windows 95/98/ME.
            try:
                (nte, ttype) = _winreg.QueryValueEx(interface_key,
                                                    'NTEContextList')
                return nte is not None
            except WindowsError:  # pylint: disable=undefined-variable
                return False

    def _compute_timeout(self, start):
        now = time.time()
        duration = now - start
        if duration < 0:
            if duration < -1:
                # Time going backwards is bad.  Just give up.
                raise Timeout(timeout=duration)
            else:
                # Time went backwards, but only a little.  This can
                # happen, e.g. under vmware with older linux kernels.
                # Pretend it didn't happen.
                now = start
        if duration >= self.lifetime:
            raise Timeout(timeout=duration)
        return min(self.lifetime - duration, self.timeout)

    def query(self, qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN,
              tcp=False, source=None, raise_on_no_answer=True, source_port=0):
        """Query nameservers to find the answer to the question.

        The I{qname}, I{rdtype}, and I{rdclass} parameters may be objects
        of the appropriate type, or strings that can be converted into objects
        of the appropriate type.  E.g. For I{rdtype} the integer 2 and the
        the string 'NS' both mean to query for records with DNS rdata type NS.

        @param qname: the query name
        @type qname: dns.name.Name object or string
        @param rdtype: the query type
        @type rdtype: int or string
        @param rdclass: the query class
        @type rdclass: int or string
        @param tcp: use TCP to make the query (default is False).
        @type tcp: bool
        @param source: bind to this IP address (defaults to machine default
        IP).
        @type source: IP address in dotted quad notation
        @param raise_on_no_answer: raise NoAnswer if there's no answer
        (defaults is True).
        @type raise_on_no_answer: bool
        @param source_port: The port from which to send the message.
        The default is 0.
        @type source_port: int
        @rtype: dns.resolver.Answer instance
        @raises Timeout: no answers could be found in the specified lifetime
        @raises NXDOMAIN: the query name does not exist
        @raises YXDOMAIN: the query name is too long after DNAME substitution
        @raises NoAnswer: the response did not contain an answer and
        raise_on_no_answer is True.
        @raises NoNameservers: no non-broken nameservers are available to
        answer the question."""

        if isinstance(qname, string_types):
            qname = dns.name.from_text(qname, None)
        if isinstance(rdtype, string_types):
            rdtype = dns.rdatatype.from_text(rdtype)
        if dns.rdatatype.is_metatype(rdtype):
            raise NoMetaqueries
        if isinstance(rdclass, string_types):
            rdclass = dns.rdataclass.from_text(rdclass)
        if dns.rdataclass.is_metaclass(rdclass):
            raise NoMetaqueries
        qnames_to_try = []
        if qname.is_absolute():
            qnames_to_try.append(qname)
        else:
            if len(qname) > 1:
                qnames_to_try.append(qname.concatenate(dns.name.root))
            if self.search:
                for suffix in self.search:
                    qnames_to_try.append(qname.concatenate(suffix))
            else:
                qnames_to_try.append(qname.concatenate(self.domain))
        all_nxdomain = True
        nxdomain_responses = {}
        start = time.time()
        _qname = None # make pylint happy
        for _qname in qnames_to_try:
            if self.cache:
                answer = self.cache.get((_qname, rdtype, rdclass))
                if answer is not None:
                    if answer.rrset is None and raise_on_no_answer:
                        raise NoAnswer(response=answer.response)
                    else:
                        return answer
            request = dns.message.make_query(_qname, rdtype, rdclass)
            if self.keyname is not None:
                request.use_tsig(self.keyring, self.keyname,
                                 algorithm=self.keyalgorithm)
            request.use_edns(self.edns, self.ednsflags, self.payload)
            if self.flags is not None:
                request.flags = self.flags
            response = None
            #
            # make a copy of the servers list so we can alter it later.
            #
            nameservers = self.nameservers[:]
            errors = []
            if self.rotate:
                random.shuffle(nameservers)
            backoff = 0.10
            while response is None:
                if len(nameservers) == 0:
                    raise NoNameservers(request=request, errors=errors)
                for nameserver in nameservers[:]:
                    timeout = self._compute_timeout(start)
                    port = self.nameserver_ports.get(nameserver, self.port)
                    try:
                        tcp_attempt = tcp
                        if tcp:
                            response = dns.query.tcp(request, nameserver,
                                                     timeout, port,
                                                     source=source,
                                                     source_port=source_port)
                        else:
                            response = dns.query.udp(request, nameserver,
                                                     timeout, port,
                                                     source=source,
                                                     source_port=source_port)
                            if response.flags & dns.flags.TC:
                                # Response truncated; retry with TCP.
                                tcp_attempt = True
                                timeout = self._compute_timeout(start)
                                response = \
                                    dns.query.tcp(request, nameserver,
                                                  timeout, port,
                                                  source=source,
                                                  source_port=source_port)
                    except (socket.error, dns.exception.Timeout) as ex:
                        #
                        # Communication failure or timeout.  Go to the
                        # next server
                        #
                        errors.append((nameserver, tcp_attempt, port, ex,
                                       response))
                        response = None
                        continue
                    except dns.query.UnexpectedSource as ex:
                        #
                        # Who knows?  Keep going.
                        #
                        errors.append((nameserver, tcp_attempt, port, ex,
                                       response))
                        response = None
                        continue
                    except dns.exception.FormError as ex:
                        #
                        # We don't understand what this server is
                        # saying.  Take it out of the mix and
                        # continue.
                        #
                        nameservers.remove(nameserver)
                        errors.append((nameserver, tcp_attempt, port, ex,
                                       response))
                        response = None
                        continue
                    except EOFError as ex:
                        #
                        # We're using TCP and they hung up on us.
                        # Probably they don't support TCP (though
                        # they're supposed to!).  Take it out of the
                        # mix and continue.
                        #
                        nameservers.remove(nameserver)
                        errors.append((nameserver, tcp_attempt, port, ex,
                                       response))
                        response = None
                        continue
                    rcode = response.rcode()
                    if rcode == dns.rcode.YXDOMAIN:
                        ex = YXDOMAIN()
                        errors.append((nameserver, tcp_attempt, port, ex,
                                       response))
                        raise ex
                    if rcode == dns.rcode.NOERROR or \
                            rcode == dns.rcode.NXDOMAIN:
                        break
                    #
                    # We got a response, but we're not happy with the
                    # rcode in it.  Remove the server from the mix if
                    # the rcode isn't SERVFAIL.
                    #
                    if rcode != dns.rcode.SERVFAIL or not self.retry_servfail:
                        nameservers.remove(nameserver)
                    errors.append((nameserver, tcp_attempt, port,
                                   dns.rcode.to_text(rcode), response))
                    response = None
                if response is not None:
                    break
                #
                # All nameservers failed!
                #
                if len(nameservers) > 0:
                    #
                    # But we still have servers to try.  Sleep a bit
                    # so we don't pound them!
                    #
                    timeout = self._compute_timeout(start)
                    sleep_time = min(timeout, backoff)
                    backoff *= 2
                    time.sleep(sleep_time)
            if response.rcode() == dns.rcode.NXDOMAIN:
                nxdomain_responses[_qname] = response
                continue
            all_nxdomain = False
            break
        if all_nxdomain:
            raise NXDOMAIN(qnames=qnames_to_try, responses=nxdomain_responses)
        answer = Answer(_qname, rdtype, rdclass, response,
                        raise_on_no_answer)
        if self.cache:
            self.cache.put((_qname, rdtype, rdclass), answer)
        return answer

    def use_tsig(self, keyring, keyname=None,
                 algorithm=dns.tsig.default_algorithm):
        """Add a TSIG signature to the query.

        @param keyring: The TSIG keyring to use; defaults to None.
        @type keyring: dict
        @param keyname: The name of the TSIG key to use; defaults to None.
        The key must be defined in the keyring.  If a keyring is specified
        but a keyname is not, then the key used will be the first key in the
        keyring.  Note that the order of keys in a dictionary is not defined,
        so applications should supply a keyname when a keyring is used, unless
        they know the keyring contains only one key.
        @param algorithm: The TSIG key algorithm to use.  The default
        is dns.tsig.default_algorithm.
        @type algorithm: string"""
        self.keyring = keyring
        if keyname is None:
            self.keyname = list(self.keyring.keys())[0]
        else:
            self.keyname = keyname
        self.keyalgorithm = algorithm

    def use_edns(self, edns, ednsflags, payload):
        """Configure Edns.

        @param edns: The EDNS level to use.  The default is -1, no Edns.
        @type edns: int
        @param ednsflags: The EDNS flags
        @type ednsflags: int
        @param payload: The EDNS payload size.  The default is 0.
        @type payload: int"""

        if edns is None:
            edns = -1
        self.edns = edns
        self.ednsflags = ednsflags
        self.payload = payload

    def set_flags(self, flags):
        """Overrides the default flags with your own

        @param flags: The flags to overwrite the default with
        @type flags: int"""
        self.flags = flags

default_resolver = None


def get_default_resolver():
    """Get the default resolver, initializing it if necessary."""
    if default_resolver is None:
        reset_default_resolver()
    return default_resolver


def reset_default_resolver():
    """Re-initialize default resolver.

    resolv.conf will be re-read immediatelly.
    """
    global default_resolver
    default_resolver = Resolver()


def query(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN,
          tcp=False, source=None, raise_on_no_answer=True,
          source_port=0):
    """Query nameservers to find the answer to the question.

    This is a convenience function that uses the default resolver
    object to make the query.
    @see: L{dns.resolver.Resolver.query} for more information on the
    parameters."""
    return get_default_resolver().query(qname, rdtype, rdclass, tcp, source,
                                        raise_on_no_answer, source_port)


def zone_for_name(name, rdclass=dns.rdataclass.IN, tcp=False, resolver=None):
    """Find the name of the zone which contains the specified name.

    @param name: the query name
    @type name: absolute dns.name.Name object or string
    @param rdclass: The query class
    @type rdclass: int
    @param tcp: use TCP to make the query (default is False).
    @type tcp: bool
    @param resolver: the resolver to use
    @type resolver: dns.resolver.Resolver object or None
    @rtype: dns.name.Name"""

    if isinstance(name, string_types):
        name = dns.name.from_text(name, dns.name.root)
    if resolver is None:
        resolver = get_default_resolver()
    if not name.is_absolute():
        raise NotAbsolute(name)
    while 1:
        try:
            answer = resolver.query(name, dns.rdatatype.SOA, rdclass, tcp)
            if answer.rrset.name == name:
                return name
            # otherwise we were CNAMEd or DNAMEd and need to look higher
        except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
            pass
        try:
            name = name.parent()
        except dns.name.NoParent:
            raise NoRootSOA

#
# Support for overriding the system resolver for all python code in the
# running process.
#

_protocols_for_socktype = {
    socket.SOCK_DGRAM: [socket.SOL_UDP],
    socket.SOCK_STREAM: [socket.SOL_TCP],
}

_resolver = None
_original_getaddrinfo = socket.getaddrinfo
_original_getnameinfo = socket.getnameinfo
_original_getfqdn = socket.getfqdn
_original_gethostbyname = socket.gethostbyname
_original_gethostbyname_ex = socket.gethostbyname_ex
_original_gethostbyaddr = socket.gethostbyaddr


def _getaddrinfo(host=None, service=None, family=socket.AF_UNSPEC, socktype=0,
                 proto=0, flags=0):
    if flags & (socket.AI_ADDRCONFIG | socket.AI_V4MAPPED) != 0:
        raise NotImplementedError
    if host is None and service is None:
        raise socket.gaierror(socket.EAI_NONAME)
    v6addrs = []
    v4addrs = []
    canonical_name = None
    try:
        # Is host None or a V6 address literal?
        if host is None:
            canonical_name = 'localhost'
            if flags & socket.AI_PASSIVE != 0:
                v6addrs.append('::')
                v4addrs.append('0.0.0.0')
            else:
                v6addrs.append('::1')
                v4addrs.append('127.0.0.1')
        else:
            parts = host.split('%')
            if len(parts) == 2:
                ahost = parts[0]
            else:
                ahost = host
            addr = dns.ipv6.inet_aton(ahost)
            v6addrs.append(host)
            canonical_name = host
    except Exception:
        try:
            # Is it a V4 address literal?
            addr = dns.ipv4.inet_aton(host)
            v4addrs.append(host)
            canonical_name = host
        except Exception:
            if flags & socket.AI_NUMERICHOST == 0:
                try:
                    if family == socket.AF_INET6 or family == socket.AF_UNSPEC:
                        v6 = _resolver.query(host, dns.rdatatype.AAAA,
                                             raise_on_no_answer=False)
                        # Note that setting host ensures we query the same name
                        # for A as we did for AAAA.
                        host = v6.qname
                        canonical_name = v6.canonical_name.to_text(True)
                        if v6.rrset is not None:
                            for rdata in v6.rrset:
                                v6addrs.append(rdata.address)
                    if family == socket.AF_INET or family == socket.AF_UNSPEC:
                        v4 = _resolver.query(host, dns.rdatatype.A,
                                             raise_on_no_answer=False)
                        host = v4.qname
                        canonical_name = v4.canonical_name.to_text(True)
                        if v4.rrset is not None:
                            for rdata in v4.rrset:
                                v4addrs.append(rdata.address)
                except dns.resolver.NXDOMAIN:
                    raise socket.gaierror(socket.EAI_NONAME)
                except:
                    raise socket.gaierror(socket.EAI_SYSTEM)
    port = None
    try:
        # Is it a port literal?
        if service is None:
            port = 0
        else:
            port = int(service)
    except Exception:
        if flags & socket.AI_NUMERICSERV == 0:
            try:
                port = socket.getservbyname(service)
            except Exception:
                pass
    if port is None:
        raise socket.gaierror(socket.EAI_NONAME)
    tuples = []
    if socktype == 0:
        socktypes = [socket.SOCK_DGRAM, socket.SOCK_STREAM]
    else:
        socktypes = [socktype]
    if flags & socket.AI_CANONNAME != 0:
        cname = canonical_name
    else:
        cname = ''
    if family == socket.AF_INET6 or family == socket.AF_UNSPEC:
        for addr in v6addrs:
            for socktype in socktypes:
                for proto in _protocols_for_socktype[socktype]:
                    tuples.append((socket.AF_INET6, socktype, proto,
                                   cname, (addr, port, 0, 0)))
    if family == socket.AF_INET or family == socket.AF_UNSPEC:
        for addr in v4addrs:
            for socktype in socktypes:
                for proto in _protocols_for_socktype[socktype]:
                    tuples.append((socket.AF_INET, socktype, proto,
                                   cname, (addr, port)))
    if len(tuples) == 0:
        raise socket.gaierror(socket.EAI_NONAME)
    return tuples


def _getnameinfo(sockaddr, flags=0):
    host = sockaddr[0]
    port = sockaddr[1]
    if len(sockaddr) == 4:
        scope = sockaddr[3]
        family = socket.AF_INET6
    else:
        scope = None
        family = socket.AF_INET
    tuples = _getaddrinfo(host, port, family, socket.SOCK_STREAM,
                          socket.SOL_TCP, 0)
    if len(tuples) > 1:
        raise socket.error('sockaddr resolved to multiple addresses')
    addr = tuples[0][4][0]
    if flags & socket.NI_DGRAM:
        pname = 'udp'
    else:
        pname = 'tcp'
    qname = dns.reversename.from_address(addr)
    if flags & socket.NI_NUMERICHOST == 0:
        try:
            answer = _resolver.query(qname, 'PTR')
            hostname = answer.rrset[0].target.to_text(True)
        except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
            if flags & socket.NI_NAMEREQD:
                raise socket.gaierror(socket.EAI_NONAME)
            hostname = addr
            if scope is not None:
                hostname += '%' + str(scope)
    else:
        hostname = addr
        if scope is not None:
            hostname += '%' + str(scope)
    if flags & socket.NI_NUMERICSERV:
        service = str(port)
    else:
        service = socket.getservbyport(port, pname)
    return (hostname, service)


def _getfqdn(name=None):
    if name is None:
        name = socket.gethostname()
    try:
        return _getnameinfo(_getaddrinfo(name, 80)[0][4])[0]
    except Exception:
        return name


def _gethostbyname(name):
    return _gethostbyname_ex(name)[2][0]


def _gethostbyname_ex(name):
    aliases = []
    addresses = []
    tuples = _getaddrinfo(name, 0, socket.AF_INET, socket.SOCK_STREAM,
                          socket.SOL_TCP, socket.AI_CANONNAME)
    canonical = tuples[0][3]
    for item in tuples:
        addresses.append(item[4][0])
    # XXX we just ignore aliases
    return (canonical, aliases, addresses)


def _gethostbyaddr(ip):
    try:
        dns.ipv6.inet_aton(ip)
        sockaddr = (ip, 80, 0, 0)
        family = socket.AF_INET6
    except Exception:
        sockaddr = (ip, 80)
        family = socket.AF_INET
    (name, port) = _getnameinfo(sockaddr, socket.NI_NAMEREQD)
    aliases = []
    addresses = []
    tuples = _getaddrinfo(name, 0, family, socket.SOCK_STREAM, socket.SOL_TCP,
                          socket.AI_CANONNAME)
    canonical = tuples[0][3]
    for item in tuples:
        addresses.append(item[4][0])
    # XXX we just ignore aliases
    return (canonical, aliases, addresses)


def override_system_resolver(resolver=None):
    """Override the system resolver routines in the socket module with
    versions which use dnspython's resolver.

    This can be useful in testing situations where you want to control
    the resolution behavior of python code without having to change
    the system's resolver settings (e.g. /etc/resolv.conf).

    The resolver to use may be specified; if it's not, the default
    resolver will be used.

    @param resolver: the resolver to use
    @type resolver: dns.resolver.Resolver object or None
    """
    if resolver is None:
        resolver = get_default_resolver()
    global _resolver
    _resolver = resolver
    socket.getaddrinfo = _getaddrinfo
    socket.getnameinfo = _getnameinfo
    socket.getfqdn = _getfqdn
    socket.gethostbyname = _gethostbyname
    socket.gethostbyname_ex = _gethostbyname_ex
    socket.gethostbyaddr = _gethostbyaddr


def restore_system_resolver():
    """Undo the effects of override_system_resolver().
    """
    global _resolver
    _resolver = None
    socket.getaddrinfo = _original_getaddrinfo
    socket.getnameinfo = _original_getnameinfo
    socket.getfqdn = _original_getfqdn
    socket.gethostbyname = _original_gethostbyname
    socket.gethostbyname_ex = _original_gethostbyname_ex
    socket.gethostbyaddr = _original_gethostbyaddr
keyvalues.h000064400000010077150415243020006726 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_KEYVALUES_H
#define DNS_KEYVALUES_H 1

/*! \file dns/keyvalues.h */

/*
 * Flags field of the KEY RR rdata
 */
#define DNS_KEYFLAG_TYPEMASK	0xC000	/*%< Mask for "type" bits */
#define DNS_KEYTYPE_AUTHCONF	0x0000	/*%< Key usable for both */
#define DNS_KEYTYPE_CONFONLY	0x8000	/*%< Key usable for confidentiality */
#define DNS_KEYTYPE_AUTHONLY	0x4000	/*%< Key usable for authentication */
#define DNS_KEYTYPE_NOKEY	0xC000	/*%< No key usable for either; no key */
#define DNS_KEYTYPE_NOAUTH	DNS_KEYTYPE_CONFONLY
#define DNS_KEYTYPE_NOCONF	DNS_KEYTYPE_AUTHONLY

#define DNS_KEYFLAG_RESERVED2	0x2000	/*%< reserved - must be zero */
#define DNS_KEYFLAG_EXTENDED	0x1000	/*%< key has extended flags */
#define DNS_KEYFLAG_RESERVED4	0x0800	/*%< reserved - must be zero */
#define DNS_KEYFLAG_RESERVED5	0x0400	/*%< reserved - must be zero */
#define DNS_KEYFLAG_OWNERMASK	0x0300	/*%< these bits determine the type */
#define DNS_KEYOWNER_USER	0x0000	/*%< key is assoc. with user */
#define DNS_KEYOWNER_ENTITY	0x0200	/*%< key is assoc. with entity eg host */
#define DNS_KEYOWNER_ZONE	0x0100	/*%< key is zone key */
#define DNS_KEYOWNER_RESERVED	0x0300	/*%< reserved meaning */
#define DNS_KEYFLAG_REVOKE	0x0080	/*%< key revoked (per rfc5011) */
#define DNS_KEYFLAG_RESERVED9	0x0040	/*%< reserved - must be zero */
#define DNS_KEYFLAG_RESERVED10	0x0020	/*%< reserved - must be zero */
#define DNS_KEYFLAG_RESERVED11	0x0010	/*%< reserved - must be zero */
#define DNS_KEYFLAG_SIGNATORYMASK 0x000F /*%< key can sign RR's of same name */

#define DNS_KEYFLAG_RESERVEDMASK (DNS_KEYFLAG_RESERVED2 | \
				  DNS_KEYFLAG_RESERVED4 | \
				  DNS_KEYFLAG_RESERVED5 | \
				  DNS_KEYFLAG_RESERVED9 | \
				  DNS_KEYFLAG_RESERVED10 | \
				  DNS_KEYFLAG_RESERVED11 )
#define DNS_KEYFLAG_KSK		0x0001	/*%< key signing key */

#define DNS_KEYFLAG_RESERVEDMASK2 0xFFFF	/*%< no bits defined here */

/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */
#define DNS_KEYALG_RSAMD5	1       /*%< RSA with MD5 */
#define DNS_KEYALG_RSA		DNS_KEYALG_RSAMD5
#define DNS_KEYALG_DH		2       /*%< Diffie Hellman KEY */
#define DNS_KEYALG_DSA		3       /*%< DSA KEY */
#define DNS_KEYALG_NSEC3DSA	6
#define DNS_KEYALG_DSS		DNS_ALG_DSA
#define DNS_KEYALG_ECC		4
#define DNS_KEYALG_RSASHA1	5
#define DNS_KEYALG_NSEC3RSASHA1	7
#define DNS_KEYALG_RSASHA256	8
#define DNS_KEYALG_RSASHA512	10
#define DNS_KEYALG_ECCGOST	12
#define DNS_KEYALG_ECDSA256	13
#define DNS_KEYALG_ECDSA384	14
#define DNS_KEYALG_ED25519	15
#define DNS_KEYALG_ED448	16
#define DNS_KEYALG_INDIRECT	252
#define DNS_KEYALG_PRIVATEDNS	253
#define DNS_KEYALG_PRIVATEOID	254     /*%< Key begins with OID giving alg */

/* Protocol values  */
#define	DNS_KEYPROTO_RESERVED	0
#define DNS_KEYPROTO_TLS	1
#define DNS_KEYPROTO_EMAIL	2
#define DNS_KEYPROTO_DNSSEC	3
#define DNS_KEYPROTO_IPSEC	4
#define DNS_KEYPROTO_ANY	255

/* Signatures */
#define DNS_SIG_RSAMINBITS	512	/*%< Size of a mod or exp in bits */
#define DNS_SIG_RSAMAXBITS	2552
	/* Total of binary mod and exp */
#define DNS_SIG_RSAMAXBYTES	((DNS_SIG_RSAMAXBITS+7/8)*2+3)
	/*%< Max length of text sig block */
#define DNS_SIG_RSAMAXBASE64	(((DNS_SIG_RSAMAXBYTES+2)/3)*4)
#define DNS_SIG_RSAMINSIZE	((DNS_SIG_RSAMINBITS+7)/8)
#define DNS_SIG_RSAMAXSIZE	((DNS_SIG_RSAMAXBITS+7)/8)

#define DNS_SIG_DSASIGSIZE	41
#define DNS_SIG_DSAMINBITS	512
#define DNS_SIG_DSAMAXBITS	1024
#define DNS_SIG_DSAMINBYTES	213
#define DNS_SIG_DSAMAXBYTES	405

#define DNS_SIG_GOSTSIGSIZE	64

#define DNS_SIG_ECDSA256SIZE	64
#define DNS_SIG_ECDSA384SIZE	96

#define DNS_KEY_ECDSA256SIZE	64
#define DNS_KEY_ECDSA384SIZE	96

#define DNS_SIG_ED25519SIZE	64
#define DNS_SIG_ED448SIZE	114

#define DNS_KEY_ED25519SIZE	32
#define DNS_KEY_ED448SIZE	57

#endif /* DNS_KEYVALUES_H */
private.h000064400000003617150415243020006372 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#include <stdbool.h>

#include <isc/lang.h>
#include <isc/types.h>

#include <dns/types.h>
#include <dns/db.h>

#ifndef DNS_PRIVATE_H
#define DNS_PRIVATE_H

ISC_LANG_BEGINDECLS

isc_result_t
dns_private_chains(dns_db_t *db, dns_dbversion_t *ver,
		   dns_rdatatype_t privatetype,
		   bool *build_nsec, bool *build_nsec3);
/*%<
 * Examine the NSEC, NSEC3PARAM and privatetype RRsets at the apex of the
 * database to determine which of NSEC or NSEC3 chains we are currently
 * maintaining.  In normal operations only one of NSEC or NSEC3 is being
 * maintained but when we are transitiong between NSEC and NSEC3 we need
 * to update both sets of chains.  If 'privatetype' is zero then the
 * privatetype RRset will not be examined.
 *
 * Requires:
 * \li	'db' is valid.
 * \li	'version' is valid or NULL.
 * \li	'build_nsec' is a pointer to a bool or NULL.
 * \li	'build_nsec3' is a pointer to a bool or NULL.
 *
 * Returns:
 * \li 	ISC_R_SUCCESS, 'build_nsec' and 'build_nsec3' will be valid.
 * \li	other on error
 */

isc_result_t
dns_private_totext(dns_rdata_t *privaterdata, isc_buffer_t *buffer);
/*%<
 * Convert a private-type RR 'privaterdata' to human-readable form,
 * and place the result in 'buffer'.  The text should indicate
 * which action the private-type record specifies and whether the
 * action has been completed.
 *
 * Requires:
 * \li	'privaterdata' is a valid rdata containing at least five bytes
 * \li	'buffer' is a valid buffer
 *
 * Returns:
 * \li 	ISC_R_SUCCESS
 * \li	other on error
 */

ISC_LANG_ENDDECLS

#endif
lookup.h000064400000005554150415243020006233 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_LOOKUP_H
#define DNS_LOOKUP_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/lookup.h
 * \brief
 * The lookup module performs simple DNS lookups.  It implements
 * the full resolver algorithm, both looking for local data and
 * resolving external names as necessary.
 *
 * MP:
 *\li	The module ensures appropriate synchronization of data structures it
 *	creates and manipulates.
 *
 * Reliability:
 *\li	No anticipated impact.
 *
 * Resources:
 *\li	TBS
 *
 * Security:
 *\li	No anticipated impact.
 *
 * Standards:
 *\li	RFCs:	1034, 1035, 2181, TBS
 *\li	Drafts:	TBS
 */

#include <isc/lang.h>
#include <isc/event.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

/*%
 * A 'dns_lookupevent_t' is returned when a lookup completes.
 * The sender field will be set to the lookup that completed.  If 'result'
 * is ISC_R_SUCCESS, then 'names' will contain a list of names associated
 * with the address.  The recipient of the event must not change the list
 * and must not refer to any of the name data after the event is freed.
 */
typedef struct dns_lookupevent {
	ISC_EVENT_COMMON(struct dns_lookupevent);
	isc_result_t			result;
	dns_name_t			*name;
	dns_rdataset_t			*rdataset;
	dns_rdataset_t			*sigrdataset;
	dns_db_t			*db;
	dns_dbnode_t			*node;
} dns_lookupevent_t;

isc_result_t
dns_lookup_create(isc_mem_t *mctx, dns_name_t *name, dns_rdatatype_t type,
		  dns_view_t *view, unsigned int options, isc_task_t *task,
		  isc_taskaction_t action, void *arg, dns_lookup_t **lookupp);
/*%<
 * Finds the rrsets matching 'name' and 'type'.
 *
 * Requires:
 *
 *\li	'mctx' is a valid mctx.
 *
 *\li	'name' is a valid name.
 *
 *\li	'view' is a valid view which has a resolver.
 *
 *\li	'task' is a valid task.
 *
 *\li	lookupp != NULL && *lookupp == NULL
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_NOMEMORY
 *
 *\li	Any resolver-related error (e.g. ISC_R_SHUTTINGDOWN) may also be
 *	returned.
 */

void
dns_lookup_cancel(dns_lookup_t *lookup);
/*%<
 * Cancel 'lookup'.
 *
 * Notes:
 *
 *\li	If 'lookup' has not completed, post its LOOKUPDONE event with a
 *	result code of ISC_R_CANCELED.
 *
 * Requires:
 *
 *\li	'lookup' is a valid lookup.
 */

void
dns_lookup_destroy(dns_lookup_t **lookupp);
/*%<
 * Destroy 'lookup'.
 *
 * Requires:
 *
 *\li	'*lookupp' is a valid lookup.
 *
 *\li	The caller has received the LOOKUPDONE event (either because the
 *	lookup completed or because dns_lookup_cancel() was called).
 *
 * Ensures:
 *
 *\li	*lookupp == NULL.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_LOOKUP_H */
zonekey.h000064400000001411150415243020006372 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_ZONEKEY_H
#define DNS_ZONEKEY_H 1

/*! \file dns/zonekey.h */

#include <stdbool.h>

#include <isc/lang.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

bool
dns_zonekey_iszonekey(dns_rdata_t *keyrdata);
/*%<
 *	Determines if the key record contained in the rdata is a zone key.
 *
 *	Requires:
 *		'keyrdata' is not NULL.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_ZONEKEY_H */
rdataset.h000064400000052040150415243030006522 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_RDATASET_H
#define DNS_RDATASET_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/rdataset.h
 * \brief
 * A DNS rdataset is a handle that can be associated with a collection of
 * rdata all having a common owner name, class, and type.
 *
 * The dns_rdataset_t type is like a "virtual class".  To actually use
 * rdatasets, an implementation of the method suite (e.g. "slabbed rdata") is
 * required.
 *
 * XXX &lt;more&gt; XXX
 *
 * MP:
 *\li	Clients of this module must impose any required synchronization.
 *
 * Reliability:
 *\li	No anticipated impact.
 *
 * Resources:
 *\li	TBS
 *
 * Security:
 *\li	No anticipated impact.
 *
 * Standards:
 *\li	None.
 */

#include <inttypes.h>
#include <stdbool.h>

#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/stdtime.h>

#include <dns/types.h>
#include <dns/rdatastruct.h>

#define DNS_RDATASET_MAXADDITIONAL 13

ISC_LANG_BEGINDECLS

typedef enum {
	dns_rdatasetadditional_fromauth,
	dns_rdatasetadditional_fromcache,
	dns_rdatasetadditional_fromglue
} dns_rdatasetadditional_t;

typedef struct dns_rdatasetmethods {
	void			(*disassociate)(dns_rdataset_t *rdataset);
	isc_result_t		(*first)(dns_rdataset_t *rdataset);
	isc_result_t		(*next)(dns_rdataset_t *rdataset);
	void			(*current)(dns_rdataset_t *rdataset,
					   dns_rdata_t *rdata);
	void			(*clone)(dns_rdataset_t *source,
					 dns_rdataset_t *target);
	unsigned int		(*count)(dns_rdataset_t *rdataset);
	isc_result_t		(*addnoqname)(dns_rdataset_t *rdataset,
					      dns_name_t *name);
	isc_result_t		(*getnoqname)(dns_rdataset_t *rdataset,
					      dns_name_t *name,
					      dns_rdataset_t *neg,
					      dns_rdataset_t *negsig);
	isc_result_t		(*addclosest)(dns_rdataset_t *rdataset,
					      dns_name_t *name);
	isc_result_t		(*getclosest)(dns_rdataset_t *rdataset,
					      dns_name_t *name,
					      dns_rdataset_t *neg,
					      dns_rdataset_t *negsig);
	isc_result_t		(*getadditional)(dns_rdataset_t *rdataset,
						 dns_rdatasetadditional_t type,
						 dns_rdatatype_t qtype,
						 dns_acache_t *acache,
						 dns_zone_t **zonep,
						 dns_db_t **dbp,
						 dns_dbversion_t **versionp,
						 dns_dbnode_t **nodep,
						 dns_name_t *fname,
						 dns_message_t *msg,
						 isc_stdtime_t now);
	isc_result_t		(*setadditional)(dns_rdataset_t *rdataset,
						 dns_rdatasetadditional_t type,
						 dns_rdatatype_t qtype,
						 dns_acache_t *acache,
						 dns_zone_t *zone,
						 dns_db_t *db,
						 dns_dbversion_t *version,
						 dns_dbnode_t *node,
						 dns_name_t *fname);
	isc_result_t		(*putadditional)(dns_acache_t *acache,
						 dns_rdataset_t *rdataset,
						 dns_rdatasetadditional_t type,
						 dns_rdatatype_t qtype);
	void			(*settrust)(dns_rdataset_t *rdataset,
					    dns_trust_t trust);
	void			(*expire)(dns_rdataset_t *rdataset);
	void			(*clearprefetch)(dns_rdataset_t *rdataset);
	void			(*setownercase)(dns_rdataset_t *rdataset,
						const dns_name_t *name);
	void			(*getownercase)(const dns_rdataset_t *rdataset,							dns_name_t *name);
} dns_rdatasetmethods_t;

#define DNS_RDATASET_MAGIC	       ISC_MAGIC('D','N','S','R')
#define DNS_RDATASET_VALID(set)	       ISC_MAGIC_VALID(set, DNS_RDATASET_MAGIC)

/*%
 * Direct use of this structure by clients is strongly discouraged, except
 * for the 'link' field which may be used however the client wishes.  The
 * 'private', 'current', and 'index' fields MUST NOT be changed by clients.
 * rdataset implementations may change any of the fields.
 */
struct dns_rdataset {
	unsigned int			magic;		/* XXX ? */
	dns_rdatasetmethods_t *		methods;
	ISC_LINK(dns_rdataset_t)	link;

	/*
	 * XXX do we need these, or should they be retrieved by methods?
	 * Leaning towards the latter, since they are not frequently required
	 * once you have the rdataset.
	 */
	dns_rdataclass_t		rdclass;
	dns_rdatatype_t			type;
	dns_ttl_t			ttl;
	/*
	 * Stale ttl is used to see how long this RRset can still be used
	 * to serve to clients, after the TTL has expired.
	 */
	dns_ttl_t			stale_ttl;
	dns_trust_t			trust;
	dns_rdatatype_t			covers;

	/*
	 * attributes
	 */
	unsigned int			attributes;

	/*%
	 * the counter provides the starting point in the "cyclic" order.
	 * The value UINT32_MAX has a special meaning of "picking up a
	 * random value." in order to take care of databases that do not
	 * increment the counter.
	 */
	uint32_t			count;

	/*
	 * This RRSIG RRset should be re-generated around this time.
	 * Only valid if DNS_RDATASETATTR_RESIGN is set in attributes.
	 */
	isc_stdtime_t			resign;

	/*@{*/
	/*%
	 * These are for use by the rdataset implementation, and MUST NOT
	 * be changed by clients.
	 */
	void *				private1;
	void *				private2;
	void *				private3;
	unsigned int			privateuint4;
	void *				private5;
	void *				private6;
	void *				private7;
	/*@}*/

};

/*!
 * \def DNS_RDATASETATTR_RENDERED
 *	Used by message.c to indicate that the rdataset was rendered.
 *
 * \def DNS_RDATASETATTR_TTLADJUSTED
 *	Used by message.c to indicate that the rdataset's rdata had differing
 *	TTL values, and the rdataset->ttl holds the smallest.
 *
 * \def DNS_RDATASETATTR_LOADORDER
 *	Output the RRset in load order.
 */

#define DNS_RDATASETATTR_QUESTION	0x00000001
#define DNS_RDATASETATTR_RENDERED	0x00000002	/*%< Used by message.c */
#define DNS_RDATASETATTR_ANSWERED	0x00000004	/*%< Used by server. */
#define DNS_RDATASETATTR_CACHE		0x00000008	/*%< Used by resolver. */
#define DNS_RDATASETATTR_ANSWER		0x00000010	/*%< Used by resolver. */
#define DNS_RDATASETATTR_ANSWERSIG	0x00000020	/*%< Used by resolver. */
#define DNS_RDATASETATTR_EXTERNAL	0x00000040	/*%< Used by resolver. */
#define DNS_RDATASETATTR_NCACHE		0x00000080	/*%< Used by resolver. */
#define DNS_RDATASETATTR_CHAINING	0x00000100	/*%< Used by resolver. */
#define DNS_RDATASETATTR_TTLADJUSTED	0x00000200	/*%< Used by message.c */
#define DNS_RDATASETATTR_FIXEDORDER	0x00000400
#define DNS_RDATASETATTR_RANDOMIZE	0x00000800
#define DNS_RDATASETATTR_CHASE		0x00001000	/*%< Used by resolver. */
#define DNS_RDATASETATTR_NXDOMAIN	0x00002000
#define DNS_RDATASETATTR_NOQNAME	0x00004000
#define DNS_RDATASETATTR_CHECKNAMES	0x00008000	/*%< Used by resolver. */
#define DNS_RDATASETATTR_REQUIRED	0x00010000
#define DNS_RDATASETATTR_REQUIREDGLUE	DNS_RDATASETATTR_REQUIRED
#define DNS_RDATASETATTR_LOADORDER	0x00020000
#define DNS_RDATASETATTR_RESIGN		0x00040000
#define DNS_RDATASETATTR_CLOSEST	0x00080000
#define DNS_RDATASETATTR_OPTOUT		0x00100000	/*%< OPTOUT proof */
#define DNS_RDATASETATTR_NEGATIVE	0x00200000
#define DNS_RDATASETATTR_PREFETCH	0x00400000
#define DNS_RDATASETATTR_STALE		0x01000000

/*%
 * _OMITDNSSEC:
 * 	Omit DNSSEC records when rendering ncache records.
 */
#define DNS_RDATASETTOWIRE_OMITDNSSEC	0x0001

void
dns_rdataset_init(dns_rdataset_t *rdataset);
/*%<
 * Make 'rdataset' a valid, disassociated rdataset.
 *
 * Requires:
 *\li	'rdataset' is not NULL.
 *
 * Ensures:
 *\li	'rdataset' is a valid, disassociated rdataset.
 */

void
dns_rdataset_invalidate(dns_rdataset_t *rdataset);
/*%<
 * Invalidate 'rdataset'.
 *
 * Requires:
 *\li	'rdataset' is a valid, disassociated rdataset.
 *
 * Ensures:
 *\li	If assertion checking is enabled, future attempts to use 'rdataset'
 *	without initializing it will cause an assertion failure.
 */

void
dns_rdataset_disassociate(dns_rdataset_t *rdataset);
/*%<
 * Disassociate 'rdataset' from its rdata, allowing it to be reused.
 *
 * Notes:
 *\li	The client must ensure it has no references to rdata in the rdataset
 *	before disassociating.
 *
 * Requires:
 *\li	'rdataset' is a valid, associated rdataset.
 *
 * Ensures:
 *\li	'rdataset' is a valid, disassociated rdataset.
 */

bool
dns_rdataset_isassociated(dns_rdataset_t *rdataset);
/*%<
 * Is 'rdataset' associated?
 *
 * Requires:
 *\li	'rdataset' is a valid rdataset.
 *
 * Returns:
 *\li	#true			'rdataset' is associated.
 *\li	#false			'rdataset' is not associated.
 */

void
dns_rdataset_makequestion(dns_rdataset_t *rdataset, dns_rdataclass_t rdclass,
			  dns_rdatatype_t type);
/*%<
 * Make 'rdataset' a valid, associated, question rdataset, with a
 * question class of 'rdclass' and type 'type'.
 *
 * Notes:
 *\li	Question rdatasets have a class and type, but no rdata.
 *
 * Requires:
 *\li	'rdataset' is a valid, disassociated rdataset.
 *
 * Ensures:
 *\li	'rdataset' is a valid, associated, question rdataset.
 */

void
dns_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target);
/*%<
 * Make 'target' refer to the same rdataset as 'source'.
 *
 * Requires:
 *\li	'source' is a valid, associated rdataset.
 *
 *\li	'target' is a valid, dissociated rdataset.
 *
 * Ensures:
 *\li	'target' references the same rdataset as 'source'.
 */

unsigned int
dns_rdataset_count(dns_rdataset_t *rdataset);
/*%<
 * Return the number of records in 'rdataset'.
 *
 * Requires:
 *\li	'rdataset' is a valid, associated rdataset.
 *
 * Returns:
 *\li	The number of records in 'rdataset'.
 */

isc_result_t
dns_rdataset_first(dns_rdataset_t *rdataset);
/*%<
 * Move the rdata cursor to the first rdata in the rdataset (if any).
 *
 * Requires:
 *\li	'rdataset' is a valid, associated rdataset.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMORE			There are no rdata in the set.
 */

isc_result_t
dns_rdataset_next(dns_rdataset_t *rdataset);
/*%<
 * Move the rdata cursor to the next rdata in the rdataset (if any).
 *
 * Requires:
 *\li	'rdataset' is a valid, associated rdataset.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMORE			There are no more rdata in the set.
 */

void
dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
/*%<
 * Make 'rdata' refer to the current rdata.
 *
 * Notes:
 *
 *\li	The data returned in 'rdata' is valid for the life of the
 *	rdataset; in particular, subsequent changes in the cursor position
 *	do not invalidate 'rdata'.
 *
 * Requires:
 *\li	'rdataset' is a valid, associated rdataset.
 *
 *\li	The rdata cursor of 'rdataset' is at a valid location (i.e. the
 *	result of last call to a cursor movement command was ISC_R_SUCCESS).
 *
 * Ensures:
 *\li	'rdata' refers to the rdata at the rdata cursor location of
 *\li	'rdataset'.
 */

isc_result_t
dns_rdataset_totext(dns_rdataset_t *rdataset,
		    dns_name_t *owner_name,
		    bool omit_final_dot,
		    bool question,
		    isc_buffer_t *target);
/*%<
 * Convert 'rdataset' to text format, storing the result in 'target'.
 *
 * Notes:
 *\li	The rdata cursor position will be changed.
 *
 *\li	The 'question' flag should normally be #false.  If it is
 *	#true, the TTL and rdata fields are not printed.  This is
 *	for use when printing an rdata representing a question section.
 *
 *\li	This interface is deprecated; use dns_master_rdatasettottext()
 * 	and/or dns_master_questiontotext() instead.
 *
 * Requires:
 *\li	'rdataset' is a valid rdataset.
 *
 *\li	'rdataset' is not empty.
 */

isc_result_t
dns_rdataset_towire(dns_rdataset_t *rdataset,
		    dns_name_t *owner_name,
		    dns_compress_t *cctx,
		    isc_buffer_t *target,
		    unsigned int options,
		    unsigned int *countp);
/*%<
 * Convert 'rdataset' to wire format, compressing names as specified
 * in 'cctx', and storing the result in 'target'.
 *
 * Notes:
 *\li	The rdata cursor position will be changed.
 *
 *\li	The number of RRs added to target will be added to *countp.
 *
 * Requires:
 *\li	'rdataset' is a valid rdataset.
 *
 *\li	'rdataset' is not empty.
 *
 *\li	'countp' is a valid pointer.
 *
 * Ensures:
 *\li	On a return of ISC_R_SUCCESS, 'target' contains a wire format
 *	for the data contained in 'rdataset'.  Any error return leaves
 *	the buffer unchanged.
 *
 *\li	*countp has been incremented by the number of RRs added to
 *	target.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		- all ok
 *\li	#ISC_R_NOSPACE		- 'target' doesn't have enough room
 *
 *\li	Any error returned by dns_rdata_towire(), dns_rdataset_next(),
 *	dns_name_towire().
 */

isc_result_t
dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
			  const dns_name_t *owner_name,
			  dns_compress_t *cctx,
			  isc_buffer_t *target,
			  dns_rdatasetorderfunc_t order,
			  const void *order_arg,
			  unsigned int options,
			  unsigned int *countp);
/*%<
 * Like dns_rdataset_towire(), but sorting the rdatasets according to
 * the integer value returned by 'order' when called with the rdataset
 * and 'order_arg' as arguments.
 *
 * Requires:
 *\li	All the requirements of dns_rdataset_towire(), and
 *	that order_arg is NULL if and only if order is NULL.
 */

isc_result_t
dns_rdataset_towirepartial(dns_rdataset_t *rdataset,
			   const dns_name_t *owner_name,
			   dns_compress_t *cctx,
			   isc_buffer_t *target,
			   dns_rdatasetorderfunc_t order,
			   const void *order_arg,
			   unsigned int options,
			   unsigned int *countp,
			   void **state);
/*%<
 * Like dns_rdataset_towiresorted() except that a partial rdataset
 * may be written.
 *
 * Requires:
 *\li	All the requirements of dns_rdataset_towiresorted().
 *	If 'state' is non NULL then the current position in the
 *	rdataset will be remembered if the rdataset in not
 *	completely written and should be passed on on subsequent
 *	calls (NOT CURRENTLY IMPLEMENTED).
 *
 * Returns:
 *\li	#ISC_R_SUCCESS if all of the records were written.
 *\li	#ISC_R_NOSPACE if unable to fit in all of the records. *countp
 *		      will be updated to reflect the number of records
 *		      written.
 */

isc_result_t
dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
			    dns_additionaldatafunc_t add, void *arg);
/*%<
 * For each rdata in rdataset, call 'add' for each name and type in the
 * rdata which is subject to additional section processing.
 *
 * Requires:
 *
 *\li	'rdataset' is a valid, non-question rdataset.
 *
 *\li	'add' is a valid dns_additionaldatafunc_t
 *
 * Ensures:
 *
 *\li	If successful, dns_rdata_additionaldata() will have been called for
 *	each rdata in 'rdataset'.
 *
 *\li	If a call to dns_rdata_additionaldata() is not successful, the
 *	result returned will be the result of dns_rdataset_additionaldata().
 *
 *\li	If 'limit' is non-zero and the number of the rdatasets is larger
 *	than 'limit', no additional data will be processed.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS
 *
 *\li	#DNS_R_TOOMANYRECORDS in case rdataset count is larger than 'limit'
 *
 *\li	Any error that dns_rdata_additionaldata() can return.
 */

isc_result_t
dns_rdataset_additionaldata2(dns_rdataset_t	   *rdataset,
			     dns_additionaldatafunc_t add, void *arg,
			     size_t limit);

isc_result_t
dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
			dns_rdataset_t *neg, dns_rdataset_t *negsig);
/*%<
 * Return the noqname proof for this record.
 *
 * Requires:
 *\li	'rdataset' to be valid and #DNS_RDATASETATTR_NOQNAME to be set.
 *\li	'name' to be valid.
 *\li	'neg' and 'negsig' to be valid and not associated.
 */

isc_result_t
dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name);
/*%<
 * Associate a noqname proof with this record.
 * Sets #DNS_RDATASETATTR_NOQNAME if successful.
 * Adjusts the 'rdataset->ttl' to minimum of the 'rdataset->ttl' and
 * the 'nsec'/'nsec3' and 'rrsig(nsec)'/'rrsig(nsec3)' ttl.
 *
 * Requires:
 *\li	'rdataset' to be valid and #DNS_RDATASETATTR_NOQNAME to be set.
 *\li	'name' to be valid and have NSEC or NSEC3 and associated RRSIG
 *	 rdatasets.
 */

isc_result_t
dns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
			dns_rdataset_t *nsec, dns_rdataset_t *nsecsig);
/*%<
 * Return the closest encloser for this record.
 *
 * Requires:
 *\li	'rdataset' to be valid and #DNS_RDATASETATTR_CLOSEST to be set.
 *\li	'name' to be valid.
 *\li	'nsec' and 'nsecsig' to be valid and not associated.
 */

isc_result_t
dns_rdataset_addclosest(dns_rdataset_t *rdataset, dns_name_t *name);
/*%<
 * Associate a closest encloset proof with this record.
 * Sets #DNS_RDATASETATTR_CLOSEST if successful.
 * Adjusts the 'rdataset->ttl' to minimum of the 'rdataset->ttl' and
 * the 'nsec' and 'rrsig(nsec)' ttl.
 *
 * Requires:
 *\li	'rdataset' to be valid and #DNS_RDATASETATTR_CLOSEST to be set.
 *\li	'name' to be valid and have NSEC3 and RRSIG(NSEC3) rdatasets.
 */

isc_result_t
dns_rdataset_getadditional(dns_rdataset_t *rdataset,
			   dns_rdatasetadditional_t type,
			   dns_rdatatype_t qtype,
			   dns_acache_t *acache,
			   dns_zone_t **zonep,
			   dns_db_t **dbp,
			   dns_dbversion_t **versionp,
			   dns_dbnode_t **nodep,
			   dns_name_t *fname,
			   dns_message_t *msg,
			   isc_stdtime_t now);
/*%<
 * Get cached additional information from the DB node for a particular
 * 'rdataset.'  'type' is one of dns_rdatasetadditional_fromauth,
 * dns_rdatasetadditional_fromcache, and dns_rdatasetadditional_fromglue,
 * which specifies the origin of the information.  'qtype' is intended to
 * be used for specifying a particular rdata type in the cached information.
 *
 * Requires:
 * \li	'rdataset' is a valid rdataset.
 * \li	'acache' can be NULL, in which case this function will simply return
 * 	ISC_R_FAILURE.
 * \li	For the other pointers, see dns_acache_getentry().
 *
 * Ensures:
 * \li	See dns_acache_getentry().
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_FAILURE	- additional information caching is not supported.
 * \li	#ISC_R_NOTFOUND	- the corresponding DB node has not cached additional
 *			  information for 'rdataset.'
 * \li	Any error that dns_acache_getentry() can return.
 */

isc_result_t
dns_rdataset_setadditional(dns_rdataset_t *rdataset,
			   dns_rdatasetadditional_t type,
			   dns_rdatatype_t qtype,
			   dns_acache_t *acache,
			   dns_zone_t *zone,
			   dns_db_t *db,
			   dns_dbversion_t *version,
			   dns_dbnode_t *node,
			   dns_name_t *fname);
/*%<
 * Set cached additional information to the DB node for a particular
 * 'rdataset.'  See dns_rdataset_getadditional for the semantics of 'type'
 * and 'qtype'.
 *
 * Requires:
 * \li	'rdataset' is a valid rdataset.
 * \li	'acache' can be NULL, in which case this function will simply return
 *	ISC_R_FAILURE.
 * \li	For the other pointers, see dns_acache_setentry().
 *
 * Ensures:
 * \li	See dns_acache_setentry().
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_FAILURE	- additional information caching is not supported.
 * \li	#ISC_R_NOMEMORY
 * \li	Any error that dns_acache_setentry() can return.
 */

isc_result_t
dns_rdataset_putadditional(dns_acache_t *acache,
			   dns_rdataset_t *rdataset,
			   dns_rdatasetadditional_t type,
			   dns_rdatatype_t qtype);
/*%<
 * Discard cached additional information stored in the DB node for a particular
 * 'rdataset.'  See dns_rdataset_getadditional for the semantics of 'type'
 * and 'qtype'.
 *
 * Requires:
 * \li	'rdataset' is a valid rdataset.
 * \li	'acache' can be NULL, in which case this function will simply return
 *	ISC_R_FAILURE.
 *
 * Ensures:
 * \li	See dns_acache_cancelentry().
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_FAILURE	- additional information caching is not supported.
 * \li	#ISC_R_NOTFOUND	- the corresponding DB node has not cached additional
 *			  information for 'rdataset.'
 */

void
dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust);
/*%<
 * Set the trust of the 'rdataset' to trust in any in the backing database.
 * The local trust level of 'rdataset' is also set.
 */

void
dns_rdataset_expire(dns_rdataset_t *rdataset);
/*%<
 * Mark the rdataset to be expired in the backing database.
 */

void
dns_rdataset_clearprefetch(dns_rdataset_t *rdataset);
/*%<
 * Clear the PREFETCH attribute for the given rdataset in the
 * underlying database.
 *
 * In the cache database, this signals that the rdataset is not
 * eligible to be prefetched when the TTL is close to expiring.
 * It has no function in other databases.
 */

void
dns_rdataset_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name);
/*%<
 * Store the casing of 'name', the owner name of 'rdataset', into
 * a bitfield so that the name can be capitalized the same when when
 * the rdataset is used later. This sets the CASESET attribute.
 */

void
dns_rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name);
/*%<
 * If the CASESET attribute is set, retrieve the case bitfield that was
 * previously stored by dns_rdataset_getownername(), and capitalize 'name'
 * according to it. If CASESET is not set, do nothing.
 */

void
dns_rdataset_trimttl(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
		     dns_rdata_rrsig_t *rrsig, isc_stdtime_t now,
		     bool acceptexpired);
/*%<
 * Trim the ttl of 'rdataset' and 'sigrdataset' so that they will expire
 * at or before 'rrsig->expiretime'.  If 'acceptexpired' is true and the
 * signature has expired or will expire in the next 120 seconds, limit
 * the ttl to be no more than 120 seconds.
 *
 * The ttl is further limited by the original ttl as stored in 'rrsig'
 * and the original ttl values of 'rdataset' and 'sigrdataset'.
 *
 * Requires:
 * \li	'rdataset' is a valid rdataset.
 * \li	'sigrdataset' is a valid rdataset.
 * \li	'rrsig' is non NULL.
 */

const char *
dns_trust_totext(dns_trust_t trust);
/*%<
 * Display trust in textual form.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_RDATASET_H */
validator.h000064400000015771150415243030006712 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_VALIDATOR_H
#define DNS_VALIDATOR_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/validator.h
 *
 * \brief
 * DNS Validator
 * This is the BIND 9 validator, the module responsible for validating the
 * rdatasets and negative responses (messages).  It makes use of zones in
 * the view and may fetch RRset to complete trust chains.  It implements
 * DNSSEC as specified in RFC 4033, 4034 and 4035.
 *
 * It can also optionally implement ISC's DNSSEC look-aside validation.
 *
 * Correct operation is critical to preventing spoofed answers from secure
 * zones being accepted.
 *
 * MP:
 *\li	The module ensures appropriate synchronization of data structures it
 *	creates and manipulates.
 *
 * Reliability:
 *\li	No anticipated impact.
 *
 * Resources:
 *\li	TBS
 *
 * Security:
 *\li	No anticipated impact.
 *
 * Standards:
 *\li	RFCs:	1034, 1035, 2181, 4033, 4034, 4035.
 */

#include <stdbool.h>

#include <isc/lang.h>
#include <isc/event.h>
#include <isc/mutex.h>

#include <dns/fixedname.h>
#include <dns/types.h>
#include <dns/rdataset.h>
#include <dns/rdatastruct.h> /* for dns_rdata_rrsig_t */

#include <dst/dst.h>

/*%
 * A dns_validatorevent_t is sent when a 'validation' completes.
 * \brief
 * 'name', 'rdataset', 'sigrdataset', and 'message' are the values that were
 * supplied when dns_validator_create() was called.  They are returned to the
 * caller so that they may be freed.
 *
 * If the RESULT is ISC_R_SUCCESS and the answer is secure then
 * proofs[] will contain the names of the NSEC records that hold the
 * various proofs.  Note the same name may appear multiple times.
 */
typedef struct dns_validatorevent {
	ISC_EVENT_COMMON(struct dns_validatorevent);
	dns_validator_t *		validator;
	isc_result_t			result;
	/*
	 * Name and type of the response to be validated.
	 */
	dns_name_t *			name;
	dns_rdatatype_t			type;
	/*
	 * Rdata and RRSIG (if any) for positive responses.
	 */
	dns_rdataset_t *		rdataset;
	dns_rdataset_t *		sigrdataset;
	/*
	 * The full response.  Required for negative responses.
	 * Also required for positive wildcard responses.
	 */
	dns_message_t *			message;
	/*
	 * Proofs to be cached.
	 */
	dns_name_t *			proofs[4];
	/*
	 * Optout proof seen.
	 */
	bool			optout;
	/*
	 * Answer is secure.
	 */
	bool			secure;
} dns_validatorevent_t;

#define DNS_VALIDATOR_NOQNAMEPROOF 0
#define DNS_VALIDATOR_NODATAPROOF 1
#define DNS_VALIDATOR_NOWILDCARDPROOF 2
#define DNS_VALIDATOR_CLOSESTENCLOSER 3

/*%
 * A validator object represents a validation in progress.
 * \brief
 * Clients are strongly discouraged from using this type directly, with
 * the exception of the 'link' field, which may be used directly for
 * whatever purpose the client desires.
 */
struct dns_validator {
	/* Unlocked. */
	unsigned int			magic;
	isc_mutex_t			lock;
	dns_view_t *			view;
	/* Locked by lock. */
	unsigned int			options;
	unsigned int			attributes;
	dns_validatorevent_t *		event;
	dns_fetch_t *			fetch;
	dns_validator_t *		subvalidator;
	dns_validator_t *		parent;
	dns_keytable_t *		keytable;
	dns_keynode_t *			keynode;
	dst_key_t *			key;
	dns_rdata_rrsig_t *		siginfo;
	isc_task_t *			task;
	isc_taskaction_t		action;
	void *				arg;
	unsigned int			labels;
	dns_rdataset_t *		currentset;
	bool			seensig;
	dns_rdataset_t *		keyset;
	dns_rdataset_t *		dsset;
	dns_rdataset_t *		soaset;
	dns_rdataset_t *		nsecset;
	dns_rdataset_t *		nsec3set;
	dns_name_t *			soaname;
	dns_rdataset_t			frdataset;
	dns_rdataset_t			fsigrdataset;
	dns_fixedname_t			fname;
	dns_fixedname_t			wild;
	dns_fixedname_t			nearest;
	dns_fixedname_t			closest;
	ISC_LINK(dns_validator_t)	link;
	dns_rdataset_t 			dlv;
	dns_fixedname_t			dlvsep;
	bool			havedlvsep;
	bool			mustbesecure;
	unsigned int			dlvlabels;
	unsigned int			depth;
	unsigned int			authcount;
	unsigned int			authfail;
	bool				failed;
	isc_stdtime_t			start;
};

/*%
 * dns_validator_create() options.
 */
#define DNS_VALIDATOR_DLV		0x0001U
#define DNS_VALIDATOR_DEFER		0x0002U
#define DNS_VALIDATOR_NOCDFLAG		0x0004U
#define DNS_VALIDATOR_NONTA		0x0008U  /*% Ignore NTA table */

ISC_LANG_BEGINDECLS

isc_result_t
dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
		     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
		     dns_message_t *message, unsigned int options,
		     isc_task_t *task, isc_taskaction_t action, void *arg,
		     dns_validator_t **validatorp);
/*%<
 * Start a DNSSEC validation.
 *
 * This validates a response to the question given by
 * 'name' and 'type'.
 *
 * To validate a positive response, the response data is
 * given by 'rdataset' and 'sigrdataset'.  If 'sigrdataset'
 * is NULL, the data is presumed insecure and an attempt
 * is made to prove its insecurity by finding the appropriate
 * null key.
 *
 * The complete response message may be given in 'message',
 * to make available any authority section NSECs that may be
 * needed for validation of a response resulting from a
 * wildcard expansion (though no such wildcard validation
 * is implemented yet).  If the complete response message
 * is not available, 'message' is NULL.
 *
 * To validate a negative response, the complete negative response
 * message is given in 'message'.  The 'rdataset', and
 * 'sigrdataset' arguments must be NULL, but the 'name' and 'type'
 * arguments must be provided.
 *
 * The validation is performed in the context of 'view'.
 *
 * When the validation finishes, a dns_validatorevent_t with
 * the given 'action' and 'arg' are sent to 'task'.
 * Its 'result' field will be ISC_R_SUCCESS iff the
 * response was successfully proven to be either secure or
 * part of a known insecure domain.
 *
 * options:
 * If DNS_VALIDATOR_DLV is set the caller knows there is not a
 * trusted key and the validator should immediately attempt to validate
 * the answer by looking for an appropriate DLV RRset.
 */

void
dns_validator_send(dns_validator_t *validator);
/*%<
 * Send a deferred validation request
 *
 * Requires:
 *	'validator' to points to a valid DNSSEC validator.
 */

void
dns_validator_cancel(dns_validator_t *validator);
/*%<
 * Cancel a DNSSEC validation in progress.
 *
 * Requires:
 *\li	'validator' points to a valid DNSSEC validator, which
 *	may or may not already have completed.
 *
 * Ensures:
 *\li	It the validator has not already sent its completion
 *	event, it will send it with result code ISC_R_CANCELED.
 */

void
dns_validator_destroy(dns_validator_t **validatorp);
/*%<
 * Destroy a DNSSEC validator.
 *
 * Requires:
 *\li	'*validatorp' points to a valid DNSSEC validator.
 * \li	The validator must have completed and sent its completion
 * 	event.
 *
 * Ensures:
 *\li	All resources used by the validator are freed.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_VALIDATOR_H */
masterdump.h000064400000030547150415243030007104 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_MASTERDUMP_H
#define DNS_MASTERDUMP_H 1

/*! \file dns/masterdump.h */

/***
 ***	Imports
 ***/

#include <stdio.h>

#include <isc/lang.h>

#include <dns/types.h>

/***
 *** Types
 ***/

typedef struct dns_master_style dns_master_style_t;

/***
 *** Definitions
 ***/

/*
 * Flags affecting master file formatting.  Flags 0x0000FFFF
 * define the formatting of the rdata part and are defined in
 * rdata.h.
 */

/*% Omit the owner name when possible. */
#define	DNS_STYLEFLAG_OMIT_OWNER        0x000010000ULL

/*%
 * Omit the TTL when possible.  If DNS_STYLEFLAG_TTL is
 * also set, this means no TTLs are ever printed
 * because $TTL directives are generated before every
 * change in the TTL.  In this case, no columns need to
 * be reserved for the TTL.  Master files generated with
 * these options will be rejected by BIND 4.x because it
 * does not recognize the $TTL directive.
 *
 * If DNS_STYLEFLAG_TTL is not also set, the TTL will be
 * omitted when it is equal to the previous TTL.
 * This is correct according to RFC1035, but the
 * TTLs may be silently misinterpreted by older
 * versions of BIND which use the SOA MINTTL as a
 * default TTL value.
 */
#define	DNS_STYLEFLAG_OMIT_TTL		0x000020000ULL

/*% Omit the class when possible. */
#define	DNS_STYLEFLAG_OMIT_CLASS	0x000040000ULL

/*% Output $TTL directives. */
#define	DNS_STYLEFLAG_TTL		0x000080000ULL

/*%
 * Output $ORIGIN directives and print owner names relative to
 * the origin when possible.
 */
#define	DNS_STYLEFLAG_REL_OWNER		0x000100000ULL

/*% Print domain names in RR data in relative form when possible.
   For this to take effect, DNS_STYLEFLAG_REL_OWNER must also be set. */
#define	DNS_STYLEFLAG_REL_DATA		0x000200000ULL

/*% Print the trust level of each rdataset. */
#define	DNS_STYLEFLAG_TRUST		0x000400000ULL

/*% Print negative caching entries. */
#define	DNS_STYLEFLAG_NCACHE		0x000800000ULL

/*% Never print the TTL. */
#define	DNS_STYLEFLAG_NO_TTL		0x001000000ULL

/*% Never print the CLASS. */
#define	DNS_STYLEFLAG_NO_CLASS		0x002000000ULL

/*% Report re-signing time. */
#define	DNS_STYLEFLAG_RESIGN		0x004000000ULL

/*% Don't printout the cryptographic parts of DNSSEC records. */
#define	DNS_STYLEFLAG_NOCRYPTO		0x008000000ULL

/*% Comment out data by prepending with ";" */
#define	DNS_STYLEFLAG_COMMENTDATA	0x010000000ULL

/*% Print TTL with human-readable units. */
#define DNS_STYLEFLAG_TTL_UNITS		0x020000000ULL

/*% Indent output. */
#define DNS_STYLEFLAG_INDENT		0x040000000ULL

/*% Output in YAML style. */
#define DNS_STYLEFLAG_YAML		0x080000000ULL

/*% Print ECS cache entries as comments (reserved for future use). */
#define DNS_STYLEFLAG_ECSCACHE		0x100000000ULL

ISC_LANG_BEGINDECLS

/***
 ***	Constants
 ***/

/*%
 * The default master file style.
 *
 * This uses $TTL directives to avoid the need to dedicate a
 * tab stop for the TTL.  The class is only printed for the first
 * rrset in the file and shares a tab stop with the RR type.
 */
LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_default;

/*%
 * A master file style that dumps zones to a very generic format easily
 * imported/checked with external tools.
 */
LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_full;

/*%
 * A master file style that prints explicit TTL values on each
 * record line, never using $TTL statements.  The TTL has a tab
 * stop of its own, but the class and type share one.
 */
LIBDNS_EXTERNAL_DATA extern const dns_master_style_t
					dns_master_style_explicitttl;

/*%
 * A master style format designed for cache files.  It prints explicit TTL
 * values on each record line and never uses $ORIGIN or relative names.
 */
LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_cache;

/*%
 * A master style that prints name, ttl, class, type, and value on
 * every line.  Similar to explicitttl above, but more verbose.
 * Intended for generating master files which can be easily parsed
 * by perl scripts and similar applications.
 */
LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_simple;

/*%
 * The style used for debugging, "dig" output, etc.
 */
LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_debug;

/*%
 * Similar to dns_master_style_debug but data is prepended with ";"
 */
LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_comment;

/*%
 * Similar to dns_master_style_debug but data is indented with
 * dns_master_indentstr (defaults to tab).
 */
LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_indent;

/*%
 * The style used for dumping "key" zones.
 */
LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_keyzone;

/*%
 * YAML-compatible output
 */
LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_yaml;

/*%
 * The default indent string to prepend lines with when using
 * styleflag DNS_STYLEFLAG_INDENT or DNS_STYLEFLAG_YAML.
 * This is set to "\t" by default. The indent is repeated
 * 'dns_master_indent' times. This precedes everything else
 * on the line, including comment characters (;).
 *
 * XXX: Changing this value at runtime is not thread-safe.
 */
LIBDNS_EXTERNAL_DATA extern const char *dns_master_indentstr;

/*%
 * The number of copies of the indent string to put at the beginning
 * of the line when using DNS_STYLEFLAG_INDENT or DNS_STYLEFLAG_YAML.
 * This is set to 1 by default. It is increased and decreased
 * to adjust indentation levels when producing YAML output.
 *
 * XXX: This is not thread-safe.
 */
LIBDNS_EXTERNAL_DATA extern unsigned int dns_master_indent;

/***
 ***	Functions
 ***/

void
dns_dumpctx_attach(dns_dumpctx_t *source, dns_dumpctx_t **target);
/*%<
 * Attach to a dump context.
 *
 * Require:
 *\li	'source' to be valid.
 *\li	'target' to be non NULL and '*target' to be NULL.
 */

void
dns_dumpctx_detach(dns_dumpctx_t **dctxp);
/*%<
 * Detach from a dump context.
 *
 * Require:
 *\li	'dctxp' to point to a valid dump context.
 *
 * Ensures:
 *\li	'*dctxp' is NULL.
 */

void
dns_dumpctx_cancel(dns_dumpctx_t *dctx);
/*%<
 * Cancel a in progress dump.
 *
 * Require:
 *\li	'dctx' to be valid.
 */

dns_dbversion_t *
dns_dumpctx_version(dns_dumpctx_t *dctx);
/*%<
 * Return the version handle (if any) of the database being dumped.
 *
 * Require:
 *\li	'dctx' to be valid.
 */

dns_db_t *
dns_dumpctx_db(dns_dumpctx_t *dctx);
/*%<
 * Return the database being dumped.
 *
 * Require:
 *\li	'dctx' to be valid.
 */


/*@{*/
isc_result_t
dns_master_dumptostreaminc(isc_mem_t *mctx, dns_db_t *db,
			   dns_dbversion_t *version,
			   const dns_master_style_t *style, FILE *f,
			   isc_task_t *task, dns_dumpdonefunc_t done,
			   void *done_arg, dns_dumpctx_t **dctxp);

isc_result_t
dns_master_dumptostream(isc_mem_t *mctx, dns_db_t *db,
			dns_dbversion_t *version,
			const dns_master_style_t *style, FILE *f);

isc_result_t
dns_master_dumptostream2(isc_mem_t *mctx, dns_db_t *db,
			 dns_dbversion_t *version,
			 const dns_master_style_t *style,
			 dns_masterformat_t format, FILE *f);

isc_result_t
dns_master_dumptostream3(isc_mem_t *mctx, dns_db_t *db,
			 dns_dbversion_t *version,
			 const dns_master_style_t *style,
			 dns_masterformat_t format,
			 dns_masterrawheader_t *header, FILE *f);
/*%<
 * Dump the database 'db' to the steam 'f' in the specified format by
 * 'format'.  If the format is dns_masterformat_text (the RFC1035 format),
 * 'style' specifies the file style (e.g., &dns_master_style_default).
 *
 * dns_master_dumptostream() is an old form of dns_master_dumptostream3(),
 * which always specifies the dns_masterformat_text format.
 * dns_master_dumptostream2() is an old form which always specifies
 * a NULL header.
 *
 * If 'format' is dns_masterformat_raw, then 'header' can contain
 * information to be written to the file header.
 *
 * Temporary dynamic memory may be allocated from 'mctx'.
 *
 * Require:
 *\li	'task' to be valid.
 *\li	'done' to be non NULL.
 *\li	'dctxp' to be non NULL && '*dctxp' to be NULL.
 *
 * Returns:
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_CONTINUE	dns_master_dumptostreaminc() only.
 *\li	ISC_R_NOMEMORY
 *\li	Any database or rrset iterator error.
 *\li	Any dns_rdata_totext() error code.
 */
/*@}*/

/*@{*/
isc_result_t
dns_master_dumpinc(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
		   const dns_master_style_t *style, const char *filename,
		   isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg,
		   dns_dumpctx_t **dctxp);

isc_result_t
dns_master_dumpinc2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
		    const dns_master_style_t *style, const char *filename,
		    isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg,			    dns_dumpctx_t **dctxp, dns_masterformat_t format);

isc_result_t
dns_master_dumpinc3(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
		    const dns_master_style_t *style, const char *filename,
		    isc_task_t *task, dns_dumpdonefunc_t done, void
		    *done_arg, dns_dumpctx_t **dctxp,
		    dns_masterformat_t format, dns_masterrawheader_t *header);

isc_result_t
dns_master_dump(isc_mem_t *mctx, dns_db_t *db,
		dns_dbversion_t *version,
		const dns_master_style_t *style, const char *filename);

isc_result_t
dns_master_dump2(isc_mem_t *mctx, dns_db_t *db,
		 dns_dbversion_t *version,
		 const dns_master_style_t *style, const char *filename,
		 dns_masterformat_t format);

isc_result_t
dns_master_dump3(isc_mem_t *mctx, dns_db_t *db,
		 dns_dbversion_t *version,
		 const dns_master_style_t *style, const char *filename,
		 dns_masterformat_t format, dns_masterrawheader_t *header);

/*%<
 * Dump the database 'db' to the file 'filename' in the specified format by
 * 'format'.  If the format is dns_masterformat_text (the RFC1035 format),
 * 'style' specifies the file style (e.g., &dns_master_style_default).
 *
 * dns_master_dumpinc() and dns_master_dump() are old forms of _dumpinc3()
 * and _dump3(), respectively, which always specify the dns_masterformat_text
 * format.  dns_master_dumpinc2() and dns_master_dump2() are old forms which
 * always specify a NULL header.
 *
 * If 'format' is dns_masterformat_raw, then 'header' can contain
 * information to be written to the file header.
 *
 * Temporary dynamic memory may be allocated from 'mctx'.
 *
 * Returns:
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_CONTINUE	dns_master_dumpinc() only.
 *\li	ISC_R_NOMEMORY
 *\li	Any database or rrset iterator error.
 *\li	Any dns_rdata_totext() error code.
 */
/*@}*/

isc_result_t
dns_master_rdatasettotext(dns_name_t *owner_name,
			  dns_rdataset_t *rdataset,
			  const dns_master_style_t *style,
			  isc_buffer_t *target);
/*%<
 * Convert 'rdataset' to text format, storing the result in 'target'.
 *
 * Notes:
 *\li	The rdata cursor position will be changed.
 *
 * Requires:
 *\li	'rdataset' is a valid non-question rdataset.
 *
 *\li	'rdataset' is not empty.
 */

isc_result_t
dns_master_questiontotext(dns_name_t *owner_name,
			  dns_rdataset_t *rdataset,
			  const dns_master_style_t *style,
			  isc_buffer_t *target);

isc_result_t
dns_master_dumpnodetostream(isc_mem_t *mctx, dns_db_t *db,
			    dns_dbversion_t *version,
			    dns_dbnode_t *node, dns_name_t *name,
			    const dns_master_style_t *style,
			    FILE *f);

isc_result_t
dns_master_dumpnode(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
		    dns_dbnode_t *node, dns_name_t *name,
		    const dns_master_style_t *style, const char *filename);

dns_masterstyle_flags_t
dns_master_styleflags(const dns_master_style_t *style);

isc_result_t
dns_master_stylecreate(dns_master_style_t **style, unsigned int flags,
		       unsigned int ttl_column, unsigned int class_column,
		       unsigned int type_column, unsigned int rdata_column,
		       unsigned int line_length, unsigned int tab_width,
		       isc_mem_t *mctx);

isc_result_t
dns_master_stylecreate2(dns_master_style_t **style, unsigned int flags,
		       unsigned int ttl_column, unsigned int class_column,
		       unsigned int type_column, unsigned int rdata_column,
		       unsigned int line_length, unsigned int tab_width,
		       unsigned int split_width, isc_mem_t *mctx);

void
dns_master_styledestroy(dns_master_style_t **style, isc_mem_t *mctx);

ISC_LANG_ENDDECLS

#endif /* DNS_MASTERDUMP_H */
ncache.h000064400000011501150415243030006131 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_NCACHE_H
#define DNS_NCACHE_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/ncache.h
 *\brief
 * DNS Ncache
 *
 * XXX TBS XXX
 *
 * MP:
 *\li	The caller must ensure any required synchronization.
 *
 * Reliability:
 *\li	No anticipated impact.
 *
 * Resources:
 *\li	TBS
 *
 * Security:
 *\li	No anticipated impact.
 *
 * Standards:
 *\li	RFC2308
 */

#include <stdbool.h>

#include <isc/lang.h>
#include <isc/stdtime.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

/*%
 * _OMITDNSSEC:
 *      Omit DNSSEC records when rendering.
 */
#define DNS_NCACHETOWIRE_OMITDNSSEC   0x0001

isc_result_t
dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
	       dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
	       dns_rdataset_t *addedrdataset);
isc_result_t
dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
		     dns_dbnode_t *node, dns_rdatatype_t covers,
		     isc_stdtime_t now, dns_ttl_t maxttl,
		     bool optout, dns_rdataset_t *addedrdataset);
/*%<
 * Convert the authority data from 'message' into a negative cache
 * rdataset, and store it in 'cache' at 'node' with a TTL limited to
 * 'maxttl'.
 *
 * \li dns_ncache_add produces a negative cache entry with a trust of no
 *     more than answer
 * \li dns_ncache_addoptout produces a negative cache entry which will have
 *     a trust of secure if all the records that make up the entry are secure.
 *
 * The 'covers' argument is the RR type whose nonexistence we are caching,
 * or dns_rdatatype_any when caching a NXDOMAIN response.
 *
 * 'optout' indicates a DNS_RDATASETATTR_OPTOUT should be set.
 *
 * Note:
 *\li	If 'addedrdataset' is not NULL, then it will be attached to the added
 *	rdataset.  See dns_db_addrdataset() for more details.
 *
 * Requires:
 *\li	'message' is a valid message with a properly formatting negative cache
 *	authority section.
 *
 *\li	The requirements of dns_db_addrdataset() apply to 'cache', 'node',
 *	'now', and 'addedrdataset'.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOSPACE
 *
 *\li	Any result code of dns_db_addrdataset() is a possible result code
 *	of dns_ncache_add().
 */

isc_result_t
dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
		  isc_buffer_t *target, unsigned int options,
		  unsigned int *countp);
/*%<
 * Convert the negative caching rdataset 'rdataset' to wire format,
 * compressing names as specified in 'cctx', and storing the result in
 * 'target'.  If 'omit_dnssec' is set, DNSSEC records will not
 * be added to 'target'.
 *
 * Notes:
 *\li	The number of RRs added to target will be added to *countp.
 *
 * Requires:
 *\li	'rdataset' is a valid negative caching rdataset.
 *
 *\li	'rdataset' is not empty.
 *
 *\li	'countp' is a valid pointer.
 *
 * Ensures:
 *\li	On a return of ISC_R_SUCCESS, 'target' contains a wire format
 *	for the data contained in 'rdataset'.  Any error return leaves
 *	the buffer unchanged.
 *
 *\li	*countp has been incremented by the number of RRs added to
 *	target.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		- all ok
 *\li	#ISC_R_NOSPACE		- 'target' doesn't have enough room
 *
 *\li	Any error returned by dns_rdata_towire(), dns_rdataset_next(),
 *	dns_name_towire().
 */

isc_result_t
dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
		       dns_rdatatype_t type, dns_rdataset_t *rdataset);
/*%<
 * Search the negative caching rdataset for an rdataset with the
 * specified name and type.
 *
 * Requires:
 *\li	'ncacherdataset' is a valid negative caching rdataset.
 *
 *\li	'ncacherdataset' is not empty.
 *
 *\li	'name' is a valid name.
 *
 *\li	'type' is not SIG, or a meta-RR type.
 *
 *\li	'rdataset' is a valid disassociated rdataset.
 *
 * Ensures:
 *\li	On a return of ISC_R_SUCCESS, 'rdataset' is bound to the found
 *	rdataset.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		- the rdataset was found.
 *\li	#ISC_R_NOTFOUND		- the rdataset was not found.
 *
 */

isc_result_t
dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
			  dns_rdatatype_t covers, dns_rdataset_t *rdataset);
/*%<
 * Similar to dns_ncache_getrdataset() but get the rrsig that matches.
 */

void
dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found,
		   dns_rdataset_t *rdataset);

/*%<
 * Extract the current rdataset and name from a ncache entry.
 *
 * Requires:
 * \li	'ncacherdataset' to be valid and to be a negative cache entry
 * \li	'found' to be valid.
 * \li	'rdataset' to be unassociated.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_NCACHE_H */
ipkeylist.h000064400000004212150415243030006726 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_IPKEYLIST_H
#define DNS_IPKEYLIST_H 1

#include <inttypes.h>

#include <isc/types.h>
#include <dns/types.h>

/*%
 * A structure holding a list of addresses, dscps and keys.  Used to
 * store masters for a slave zone, created by parsing config options.
 */
struct dns_ipkeylist {
	isc_sockaddr_t		*addrs;
	isc_dscp_t		*dscps;
	dns_name_t		**keys;
	dns_name_t		**labels;
	uint32_t		count;
	uint32_t		allocated;
};

void
dns_ipkeylist_init(dns_ipkeylist_t *ipkl);
/*%<
 * Reset ipkl to empty state
 *
 * Requires:
 *\li	'ipkl' to be non NULL.
 */

void
dns_ipkeylist_clear(isc_mem_t *mctx, dns_ipkeylist_t *ipkl);
/*%<
 * Free `ipkl` contents using `mctx`.
 *
 * After this call, `ipkl` is a freshly cleared structure with all
 * pointers set to `NULL` and count set to 0.
 *
 * Requires:
 *\li	'mctx' to be a valid memory context.
 *\li	'ipkl' to be non NULL.
 */

isc_result_t
dns_ipkeylist_copy(isc_mem_t *mctx, const dns_ipkeylist_t *src,
		   dns_ipkeylist_t *dst);
/*%<
 * Deep copy `src` into empty `dst`, allocating `dst`'s contents.
 *
 * Requires:
 *\li	'mctx' to be a valid memory context.
 *\li	'src' to be non NULL
 *\li	'dst' to be non NULL and point to an empty \ref dns_ipkeylist_t
 *       with all pointers set to `NULL` and count set to 0.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS	-- success
 *\li	any other value -- failure
 */
isc_result_t
dns_ipkeylist_resize(isc_mem_t *mctx, dns_ipkeylist_t *ipkl, unsigned int n);
/*%<
 * Resize ipkl to contain n elements. Size (count) is not changed, and the
 * added space is zeroed.
 *
 * Requires:
 * \li	'mctx' to be a valid memory context.
 * \li	'ipk' to be non NULL
 * \li	'n' >= ipkl->count
 *
 * Returns:
 * \li	#ISC_R_SUCCESS if success
 * \li	#ISC_R_NOMEMORY if there's no memory, ipkeylist is left untouched
 */

#endif
badcache.h000064400000006451150415243030006432 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_BADCACHE_H
#define DNS_BADCACHE_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/badcache.h
 * \brief
 * Defines dns_badcache_t, the "bad cache" object.
 *
 * Notes:
 *\li 	A bad cache object is a hash table of name/type tuples,
 *	indicating whether a given tuple known to be "bad" in some
 *	sense (e.g., queries for that name and type have been
 *	returning SERVFAIL). This is used for both the "bad server
 *	cache" in the resolver and for the "servfail cache" in
 *	the view.
 *
 * Reliability:
 *
 * Resources:
 *
 * Security:
 *
 * Standards:
 */

/***
 ***	Imports
 ***/

#include <inttypes.h>
#include <stdbool.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

/***
 ***	Functions
 ***/

isc_result_t
dns_badcache_init(isc_mem_t *mctx, unsigned int size, dns_badcache_t **bcp);
/*%
 * Allocate and initialize a badcache and store it in '*bcp'.
 *
 * Requires:
 * \li	mctx != NULL
 * \li	bcp != NULL
 * \li	*bcp == NULL
 */

void
dns_badcache_destroy(dns_badcache_t **bcp);
/*%
 * Flush and then free badcache in 'bcp'. '*bcp' is set to NULL on return.
 *
 * Requires:
 * \li	'*bcp' to be a valid badcache
 */

void
dns_badcache_add(dns_badcache_t *bc, dns_name_t *name,
		 dns_rdatatype_t type, bool update,
		 uint32_t flags, isc_time_t *expire);
/*%
 * Adds a badcache entry to the badcache 'bc' for name 'name' and
 * type 'type'.  If an entry already exists, then it will be updated if
 * 'update' is true.  The entry will be stored with flags 'flags'
 * and expiration date 'expire'.
 *
 * Requires:
 * \li	bc to be a valid badcache.
 * \li	name != NULL
 * \li	expire != NULL
 */

bool
dns_badcache_find(dns_badcache_t *bc, dns_name_t *name,
		  dns_rdatatype_t type, uint32_t *flagp,
		  isc_time_t *now);
/*%
 * Returns true if a record is found in the badcache 'bc' matching
 * 'name' and 'type', with an expiration date later than 'now'.
 * If 'flagp' is not NULL, then '*flagp' is updated to the flags
 * that were stored in the badcache entry.  Returns false if
 * no matching record is found.
 *
 * Requires:
 * \li	bc to be a valid badcache.
 * \li	name != NULL
 * \li	now != NULL
 */

void
dns_badcache_flush(dns_badcache_t *bc);
/*%
 * Flush the entire bad cache.
 *
 * Requires:
 * \li	bc to be a valid badcache
 */

void
dns_badcache_flushname(dns_badcache_t *bc, dns_name_t *name);
/*%
 * Flush the bad cache of all entries at 'name'.
 *
 * Requires:
 * \li	bc to be a valid badcache
 * \li	name != NULL
 */

void
dns_badcache_flushtree(dns_badcache_t *bc, dns_name_t *name);
/*%
 * Flush the bad cache of all entries at or below 'name'.
 *
 * Requires:
 * \li	bc to be a valid badcache
 * \li	name != NULL
 */

void
dns_badcache_print(dns_badcache_t *bc, const char *cachename, FILE *fp);
/*%
 * Print the contents of badcache 'bc' (headed by the title 'cachename')
 * to file pointer 'fp'.
 *
 * Requires:
 * \li	bc to be a valid badcache
 * \li	cachename != NULL
 * \li	fp != NULL
 */

ISC_LANG_ENDDECLS

#endif /* DNS_BADCACHE_H */
dbiterator.h000064400000016376150415243030007066 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_DBITERATOR_H
#define DNS_DBITERATOR_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/dbiterator.h
 * \brief
 * The DNS DB Iterator interface allows iteration of all of the nodes in a
 * database.
 *
 * The dns_dbiterator_t type is like a "virtual class".  To actually use
 * it, an implementation of the class is required.  This implementation is
 * supplied by the database.
 *
 * It is the client's responsibility to call dns_db_detachnode() on all
 * nodes returned.
 *
 * XXX &lt;more&gt; XXX
 *
 * MP:
 *\li	The iterator itself is not locked.  The caller must ensure
 *	synchronization.
 *
 *\li	The iterator methods ensure appropriate database locking.
 *
 * Reliability:
 *\li	No anticipated impact.
 *
 * Resources:
 *\li	TBS
 *
 * Security:
 *\li	No anticipated impact.
 *
 * Standards:
 *\li	None.
 */

/*****
 ***** Imports
 *****/

#include <stdbool.h>

#include <isc/lang.h>
#include <isc/magic.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

/*****
 ***** Types
 *****/

typedef struct dns_dbiteratormethods {
	void		(*destroy)(dns_dbiterator_t **iteratorp);
	isc_result_t	(*first)(dns_dbiterator_t *iterator);
	isc_result_t	(*last)(dns_dbiterator_t *iterator);
	isc_result_t	(*seek)(dns_dbiterator_t *iterator, dns_name_t *name);
	isc_result_t	(*prev)(dns_dbiterator_t *iterator);
	isc_result_t	(*next)(dns_dbiterator_t *iterator);
	isc_result_t	(*current)(dns_dbiterator_t *iterator,
				   dns_dbnode_t **nodep, dns_name_t *name);
	isc_result_t	(*pause)(dns_dbiterator_t *iterator);
	isc_result_t	(*origin)(dns_dbiterator_t *iterator,
				  dns_name_t *name);
} dns_dbiteratormethods_t;

#define DNS_DBITERATOR_MAGIC	     ISC_MAGIC('D','N','S','I')
#define DNS_DBITERATOR_VALID(dbi)    ISC_MAGIC_VALID(dbi, DNS_DBITERATOR_MAGIC)
/*%
 * This structure is actually just the common prefix of a DNS db
 * implementation's version of a dns_dbiterator_t.
 *
 * Clients may use the 'db' field of this structure.  Except for that field,
 * direct use of this structure by clients is forbidden.  DB implementations
 * may change the structure.  'magic' must be DNS_DBITERATOR_MAGIC for any of
 * the dns_dbiterator routines to work.  DB iterator implementations must
 * maintain all DB iterator invariants.
 */
struct dns_dbiterator {
	/* Unlocked. */
	unsigned int			magic;
	dns_dbiteratormethods_t *	methods;
	dns_db_t *			db;
	bool			relative_names;
	bool			cleaning;
};

void
dns_dbiterator_destroy(dns_dbiterator_t **iteratorp);
/*%<
 * Destroy '*iteratorp'.
 *
 * Requires:
 *
 *\li	'*iteratorp' is a valid iterator.
 *
 * Ensures:
 *
 *\li	All resources used by the iterator are freed.
 *
 *\li	*iteratorp == NULL.
 */

isc_result_t
dns_dbiterator_first(dns_dbiterator_t *iterator);
/*%<
 * Move the node cursor to the first node in the database (if any).
 *
 * Requires:
 *\li	'iterator' is a valid iterator.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMORE			There are no nodes in the database.
 *
 *\li	Other results are possible, depending on the DB implementation.
 */

isc_result_t
dns_dbiterator_last(dns_dbiterator_t *iterator);
/*%<
 * Move the node cursor to the last node in the database (if any).
 *
 * Requires:
 *\li	'iterator' is a valid iterator.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMORE			There are no nodes in the database.
 *
 *\li	Other results are possible, depending on the DB implementation.
 */

isc_result_t
dns_dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name);
/*%<
 * Move the node cursor to the node with name 'name'.
 *
 * Requires:
 *\li	'iterator' is a valid iterator.
 *
 *\li	'name' is a valid name.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOTFOUND
 *\li	#DNS_R_PARTIALMATCH
 *	(node is at name above requested named when name has children)
 *
 *\li	Other results are possible, depending on the DB implementation.
 */

isc_result_t
dns_dbiterator_prev(dns_dbiterator_t *iterator);
/*%<
 * Move the node cursor to the previous node in the database (if any).
 *
 * Requires:
 *\li	'iterator' is a valid iterator.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMORE			There are no more nodes in the
 *					database.
 *
 *\li	Other results are possible, depending on the DB implementation.
 */

isc_result_t
dns_dbiterator_next(dns_dbiterator_t *iterator);
/*%<
 * Move the node cursor to the next node in the database (if any).
 *
 * Requires:
 *\li	'iterator' is a valid iterator.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMORE			There are no more nodes in the
 *					database.
 *
 *\li	Other results are possible, depending on the DB implementation.
 */

isc_result_t
dns_dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
		       dns_name_t *name);
/*%<
 * Return the current node.
 *
 * Notes:
 *\li	If 'name' is not NULL, it will be set to the name of the node.
 *
 * Requires:
 *\li	'iterator' is a valid iterator.
 *
 *\li	nodep != NULL && *nodep == NULL
 *
 *\li	The node cursor of 'iterator' is at a valid location (i.e. the
 *	result of last call to a cursor movement command was ISC_R_SUCCESS).
 *
 *\li	'name' is NULL, or is a valid name with a dedicated buffer.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS
 *\li	#DNS_R_NEWORIGIN			If this iterator was created with
 *					'relative_names' set to true,
 *					then #DNS_R_NEWORIGIN will be returned
 *					when the origin the names are
 *					relative to changes.  This result
 *					can occur only when 'name' is not
 *					NULL.  This is also a successful
 *					result.
 *
 *\li	Other results are possible, depending on the DB implementation.
 */

isc_result_t
dns_dbiterator_pause(dns_dbiterator_t *iterator);
/*%<
 * Pause iteration.
 *
 * Calling a cursor movement method or dns_dbiterator_current() may cause
 * database locks to be acquired.  Rather than reacquire these locks every
 * time one of these routines is called, the locks may simply be held.
 * Calling dns_dbiterator_pause() releases any such locks.  Iterator clients
 * should call this routine any time they are not going to execute another
 * iterator method in the immediate future.
 *
 * Requires:
 *\li	'iterator' is a valid iterator.
 *
 * Ensures:
 *\li	Any database locks being held for efficiency of iterator access are
 *	released.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *
 *\li	Other results are possible, depending on the DB implementation.
 */

isc_result_t
dns_dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name);
/*%<
 * Return the origin to which returned node names are relative.
 *
 * Requires:
 *
 *\li	'iterator' is a valid relative_names iterator.
 *
 *\li	'name' is a valid name with a dedicated buffer.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOSPACE
 *
 *\li	Other results are possible, depending on the DB implementation.
 */

void
dns_dbiterator_setcleanmode(dns_dbiterator_t *iterator, bool mode);
/*%<
 * Indicate that the given iterator is/is not cleaning the DB.
 *
 * Notes:
 *\li	When 'mode' is true,
 *
 * Requires:
 *\li	'iterator' is a valid iterator.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_DBITERATOR_H */
diff.h000064400000015504150415243030005627 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_DIFF_H
#define DNS_DIFF_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/diff.h
 * \brief
 * A diff is a convenience type representing a list of changes to be
 * made to a database.
 */

/***
 *** Imports
 ***/

#include <isc/lang.h>
#include <isc/magic.h>

#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/types.h>

/***
 *** Types
 ***/

/*%
 * A dns_difftuple_t represents a single RR being added or deleted.
 * The RR type and class are in the 'rdata' member; the class is always
 * the real one, not a DynDNS meta-class, so that the rdatas can be
 * compared using dns_rdata_compare().  The TTL is significant
 * even for deletions, because a deletion/addition pair cannot
 * be canceled out if the TTL differs (it might be an explicit
 * TTL update).
 *
 * Tuples are also used to represent complete RRs with owner
 * names for a couple of other purposes, such as the
 * individual RRs of a "RRset exists (value dependent)"
 * prerequisite set.  In this case, op==DNS_DIFFOP_EXISTS,
 * and the TTL is ignored.
 *
 * DNS_DIFFOP_*RESIGN will cause the 'resign' attribute of the resulting
 * RRset to be recomputed to be 'resign' seconds before the earliest RRSIG
 * timeexpire.
 */

typedef enum {
	DNS_DIFFOP_ADD = 0,		/*%< Add an RR. */
	DNS_DIFFOP_DEL = 1,		/*%< Delete an RR. */
	DNS_DIFFOP_EXISTS = 2,		/*%< Assert RR existence. */
	DNS_DIFFOP_ADDRESIGN = 4,	/*%< ADD + RESIGN. */
	DNS_DIFFOP_DELRESIGN = 5	/*%< DEL + RESIGN. */
} dns_diffop_t;

typedef struct dns_difftuple dns_difftuple_t;

#define DNS_DIFFTUPLE_MAGIC	ISC_MAGIC('D','I','F','T')
#define DNS_DIFFTUPLE_VALID(t)	ISC_MAGIC_VALID(t, DNS_DIFFTUPLE_MAGIC)

struct dns_difftuple {
	unsigned int			magic;
	isc_mem_t			*mctx;
	dns_diffop_t			op;
	dns_name_t			name;
	dns_ttl_t			ttl;
	dns_rdata_t			rdata;
	ISC_LINK(dns_difftuple_t)	link;
	/* Variable-size name data and rdata follows. */
};

/*%
 * A dns_diff_t represents a set of changes being applied to
 * a zone.  Diffs are also used to represent "RRset exists
 * (value dependent)" prerequisites.
 */
typedef struct dns_diff dns_diff_t;

#define DNS_DIFF_MAGIC		ISC_MAGIC('D','I','F','F')
#define DNS_DIFF_VALID(t)	ISC_MAGIC_VALID(t, DNS_DIFF_MAGIC)

struct dns_diff {
	unsigned int			magic;
	isc_mem_t *			mctx;
	ISC_LIST(dns_difftuple_t)	tuples;
};

/* Type of comparison function for sorting diffs. */
typedef int dns_diff_compare_func(const void *, const void *);

/***
 *** Functions
 ***/

ISC_LANG_BEGINDECLS

/**************************************************************************/
/*
 * Manipulation of diffs and tuples.
 */

isc_result_t
dns_difftuple_create(isc_mem_t *mctx,
		     dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
		     dns_rdata_t *rdata, dns_difftuple_t **tp);
/*%<
 * Create a tuple.  Deep copies are made of the name and rdata, so
 * they need not remain valid after the call.
 *
 * Requires:
 *\li	*tp != NULL && *tp == NULL.
 *
 * Returns:
 *\li	ISC_R_SUCCESS
 *  \li    ISC_R_NOMEMORY
 */

void
dns_difftuple_free(dns_difftuple_t **tp);
/*%<
 * Free a tuple.
 *
 * Requires:
 *    \li   **tp is a valid tuple.
 *
 * Ensures:
 *     \li  *tp == NULL
 *      \li All memory used by the tuple is freed.
 */

isc_result_t
dns_difftuple_copy(dns_difftuple_t *orig, dns_difftuple_t **copyp);
/*%<
 * Copy a tuple.
 *
 * Requires:
 * \li	'orig' points to a valid tuple
 *\li	copyp != NULL && *copyp == NULL
 */

void
dns_diff_init(isc_mem_t *mctx, dns_diff_t *diff);
/*%<
 * Initialize a diff.
 *
 * Requires:
 * \li   'diff' points to an uninitialized dns_diff_t
 *  \li  allocated by the caller.
 *
 * Ensures:
 * \li   '*diff' is a valid, empty diff.
 */

void
dns_diff_clear(dns_diff_t *diff);
/*%<
 * Clear a diff, destroying all its tuples.
 *
 * Requires:
 * \li   'diff' points to a valid dns_diff_t.
 *
 * Ensures:
 * \li    Any tuples in the diff are destroyed.
 *     The diff now empty, but it is still valid
 *     and may be reused without calling dns_diff_init
 *     again.  The only memory used is that of the
 *     dns_diff_t structure itself.
 *
 * Notes:
 * \li    Managing the memory of the dns_diff_t structure itself
 *     is the caller's responsibility.
 */

void
dns_diff_append(dns_diff_t *diff, dns_difftuple_t **tuple);
/*%<
 * Append a single tuple to a diff.
 *
 *\li	'diff' is a valid diff.
 * \li	'*tuple' is a valid tuple.
 *
 * Ensures:
 *\li	*tuple is NULL.
 *\li	The tuple has been freed, or will be freed when the diff is cleared.
 */

void
dns_diff_appendminimal(dns_diff_t *diff, dns_difftuple_t **tuple);
/*%<
 * Append 'tuple' to 'diff', removing any duplicate
 * or conflicting updates as needed to create a minimal diff.
 *
 * Requires:
 *\li	'diff' is a minimal diff.
 *
 * Ensures:
 *\li	'diff' is still a minimal diff.
 *  \li 	*tuple is NULL.
 *   \li	The tuple has been freed, or will be freed when the diff is cleared.
 *
 */

isc_result_t
dns_diff_sort(dns_diff_t *diff, dns_diff_compare_func *compare);
/*%<
 * Sort 'diff' in-place according to the comparison function 'compare'.
 */

isc_result_t
dns_diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver);
isc_result_t
dns_diff_applysilently(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver);
/*%<
 * Apply 'diff' to the database 'db'.
 *
 * dns_diff_apply() logs warnings about updates with no effect or
 * with inconsistent TTLs; dns_diff_applysilently() does not.
 *
 * For efficiency, the diff should be sorted by owner name.
 * If it is not sorted, operation will still be correct,
 * but less efficient.
 *
 * Requires:
 *\li	*diff is a valid diff (possibly empty), containing
 *   	tuples of type #DNS_DIFFOP_ADD and/or
 *  	For #DNS_DIFFOP_DEL tuples, the TTL is ignored.
 *
 */

isc_result_t
dns_diff_load(dns_diff_t *diff, dns_addrdatasetfunc_t addfunc,
	      void *add_private);
/*%<
 * Like dns_diff_apply, but for use when loading a new database
 * instead of modifying an existing one.  This bypasses the
 * database transaction mechanisms.
 *
 * Requires:
 *\li 	'addfunc' is a valid dns_addradatasetfunc_t obtained from
 * 	dns_db_beginload()
 *
 *\li	'add_private' points to a corresponding dns_dbload_t *
 *      (XXX why is it a void pointer, then?)
 */

isc_result_t
dns_diff_print(dns_diff_t *diff, FILE *file);

/*%<
 * Print the differences to 'file' or if 'file' is NULL via the
 * logging system.
 *
 * Require:
 *\li	'diff' to be valid.
 *\li	'file' to refer to a open file or NULL.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *\li	#ISC_R_UNEXPECTED
 *\li	any error from dns_rdataset_totext()
 */

ISC_LANG_ENDDECLS

#endif /* DNS_DIFF_H */
name.h000064400000110373150415243030005637 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_NAME_H
#define DNS_NAME_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/name.h
 * \brief
 * Provides facilities for manipulating DNS names and labels, including
 * conversions to and from wire format and text format.
 *
 * Given the large number of names possible in a nameserver, and because
 * names occur in rdata, it was important to come up with a very efficient
 * way of storing name data, but at the same time allow names to be
 * manipulated.  The decision was to store names in uncompressed wire format,
 * and not to make them fully abstracted objects; i.e. certain parts of the
 * server know names are stored that way.  This saves a lot of memory, and
 * makes adding names to messages easy.  Having much of the server know
 * the representation would be perilous, and we certainly don't want each
 * user of names to be manipulating such a low-level structure.  This is
 * where the Names and Labels module comes in.  The module allows name or
 * label handles to be created and attached to uncompressed wire format
 * regions.  All name operations and conversions are done through these
 * handles.
 *
 * MP:
 *\li	Clients of this module must impose any required synchronization.
 *
 * Reliability:
 *\li	This module deals with low-level byte streams.  Errors in any of
 *	the functions are likely to crash the server or corrupt memory.
 *
 * Resources:
 *\li	None.
 *
 * Security:
 *
 *\li	*** WARNING ***
 *
 *\li	dns_name_fromwire() deals with raw network data.  An error in
 *	this routine could result in the failure or hijacking of the server.
 *
 * Standards:
 *\li	RFC1035
 *\li	Draft EDNS0 (0)
 *\li	Draft Binary Labels (2)
 *
 */

/***
 *** Imports
 ***/

#include <stdio.h>
#include <inttypes.h>
#include <stdbool.h>

#include <isc/ht.h>
#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/region.h>		/* Required for storage size of dns_label_t. */

#include <dns/types.h>

ISC_LANG_BEGINDECLS

/*****
 ***** Labels
 *****
 ***** A 'label' is basically a region.  It contains one DNS wire format
 ***** label of type 00 (ordinary).
 *****/

/*****
 ***** Names
 *****
 ***** A 'name' is a handle to a binary region.  It contains a sequence of one
 ***** or more DNS wire format labels of type 00 (ordinary).
 ***** Note that all names are not required to end with the root label,
 ***** as they are in the actual DNS wire protocol.
 *****/

/***
 *** Types
 ***/

/*%
 * Clients are strongly discouraged from using this type directly,  with
 * the exception of the 'link' and 'list' fields which may be used directly
 * for whatever purpose the client desires.
 */
struct dns_name {
	unsigned int			magic;
	unsigned char *			ndata;
	unsigned int			length;
	unsigned int			labels;
	unsigned int			attributes;
	unsigned char *			offsets;
	isc_buffer_t *			buffer;
	ISC_LINK(dns_name_t)		link;
	ISC_LIST(dns_rdataset_t)	list;
	isc_ht_t *ht;
};

#define DNS_NAME_MAGIC			ISC_MAGIC('D','N','S','n')

#define DNS_NAMEATTR_ABSOLUTE		0x00000001
#define DNS_NAMEATTR_READONLY		0x00000002
#define DNS_NAMEATTR_DYNAMIC		0x00000004
#define DNS_NAMEATTR_DYNOFFSETS		0x00000008
#define DNS_NAMEATTR_NOCOMPRESS		0x00000010
/*
 * Attributes below 0x0100 reserved for name.c usage.
 */
#define DNS_NAMEATTR_CACHE		0x00000100	/*%< Used by resolver. */
#define DNS_NAMEATTR_ANSWER		0x00000200	/*%< Used by resolver. */
#define DNS_NAMEATTR_NCACHE		0x00000400	/*%< Used by resolver. */
#define DNS_NAMEATTR_CHAINING		0x00000800	/*%< Used by resolver. */
#define DNS_NAMEATTR_CHASE		0x00001000	/*%< Used by resolver. */
#define DNS_NAMEATTR_WILDCARD		0x00002000	/*%< Used by server. */
#define DNS_NAMEATTR_PREREQUISITE	0x00004000	/*%< Used by client. */
#define DNS_NAMEATTR_UPDATE		0x00008000	/*%< Used by client. */
#define DNS_NAMEATTR_HASUPDATEREC	0x00010000	/*%< Used by client. */

/*
 * Various flags.
 */
#define DNS_NAME_DOWNCASE		0x0001
#define DNS_NAME_CHECKNAMES		0x0002		/*%< Used by rdata. */
#define DNS_NAME_CHECKNAMESFAIL		0x0004		/*%< Used by rdata. */
#define DNS_NAME_CHECKREVERSE		0x0008		/*%< Used by rdata. */
#define DNS_NAME_CHECKMX		0x0010		/*%< Used by rdata. */
#define DNS_NAME_CHECKMXFAIL		0x0020		/*%< Used by rdata. */

LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_rootname;
LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_wildcardname;

/*%<
 * DNS_NAME_INITNONABSOLUTE and DNS_NAME_INITABSOLUTE are macros for
 * initializing dns_name_t structures.
 *
 * Note[1]: 'length' is set to (sizeof(A) - 1) in DNS_NAME_INITNONABSOLUTE
 * and sizeof(A) in DNS_NAME_INITABSOLUTE to allow C strings to be used
 * to initialize 'ndata'.
 *
 * Note[2]: The final value of offsets for DNS_NAME_INITABSOLUTE should
 * match (sizeof(A) - 1) which is the offset of the root label.
 *
 * Typical usage:
 *	unsigned char data[] = "\005value";
 *	unsigned char offsets[] = { 0 };
 *	dns_name_t value = DNS_NAME_INITNONABSOLUTE(data, offsets);
 *
 *	unsigned char data[] = "\005value";
 *	unsigned char offsets[] = { 0, 6 };
 *	dns_name_t value = DNS_NAME_INITABSOLUTE(data, offsets);
 */
#define DNS_NAME_INITNONABSOLUTE(A,B) { \
	DNS_NAME_MAGIC, \
	A, (sizeof(A) - 1), sizeof(B), \
	DNS_NAMEATTR_READONLY, \
	B, NULL, { (void *)-1, (void *)-1}, \
	{NULL, NULL}, NULL			    \
}

#define DNS_NAME_INITABSOLUTE(A,B) { \
	DNS_NAME_MAGIC, \
	A, sizeof(A), sizeof(B), \
	DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, \
	B, NULL, { (void *)-1, (void *)-1}, \
	{NULL, NULL}, NULL			    \
}

#define DNS_NAME_INITEMPTY { \
	DNS_NAME_MAGIC, NULL, 0, 0, 0, NULL, NULL, \
	{ (void *)-1, (void *)-1 }, { NULL, NULL }, NULL	\
}

/*%
 * Standard size of a wire format name
 */
#define DNS_NAME_MAXWIRE 255

/*
 * Text output filter procedure.
 * 'target' is the buffer to be converted.  The region to be converted
 * is from 'buffer'->base + 'used_org' to the end of the used region.
 */
typedef isc_result_t (*dns_name_totextfilter_t)(isc_buffer_t *target,
						unsigned int used_org,
						bool absolute);

/***
 *** Initialization
 ***/

void
dns_name_init(dns_name_t *name, unsigned char *offsets);
/*%<
 * Initialize 'name'.
 *
 * Notes:
 * \li	'offsets' is never required to be non-NULL, but specifying a
 *	dns_offsets_t for 'offsets' will improve the performance of most
 *	name operations if the name is used more than once.
 *
 * Requires:
 * \li	'name' is not NULL and points to a struct dns_name.
 *
 * \li	offsets == NULL or offsets is a dns_offsets_t.
 *
 * Ensures:
 * \li	'name' is a valid name.
 * \li	dns_name_countlabels(name) == 0
 * \li	dns_name_isabsolute(name) == false
 */

void
dns_name_reset(dns_name_t *name);
/*%<
 * Reinitialize 'name'.
 *
 * Notes:
 * \li	This function distinguishes itself from dns_name_init() in two
 *	key ways:
 *
 * \li	+ If any buffer is associated with 'name' (via dns_name_setbuffer()
 *	  or by being part of a dns_fixedname_t) the link to the buffer
 *	  is retained but the buffer itself is cleared.
 *
 * \li	+ Of the attributes associated with 'name', all are retained except
 *	  DNS_NAMEATTR_ABSOLUTE.
 *
 * Requires:
 * \li	'name' is a valid name.
 *
 * Ensures:
 * \li	'name' is a valid name.
 * \li	dns_name_countlabels(name) == 0
 * \li	dns_name_isabsolute(name) == false
 */

void
dns_name_invalidate(dns_name_t *name);
/*%<
 * Make 'name' invalid.
 *
 * Requires:
 * \li	'name' is a valid name.
 *
 * Ensures:
 * \li	If assertion checking is enabled, future attempts to use 'name'
 *	without initializing it will cause an assertion failure.
 *
 * \li	If the name had a dedicated buffer, that association is ended.
 */

bool
dns_name_isvalid(const dns_name_t *name);
/*%<
 * Check whether 'name' points to a valid dns_name
 */

/***
 *** Dedicated Buffers
 ***/

void
dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer);
/*%<
 * Dedicate a buffer for use with 'name'.
 *
 * Notes:
 * \li	Specification of a target buffer in dns_name_fromwire(),
 *	dns_name_fromtext(), and dns_name_concatenate() is optional if
 *	'name' has a dedicated buffer.
 *
 * \li	The caller must not write to buffer until the name has been
 *	invalidated or is otherwise known not to be in use.
 *
 * \li	If buffer is NULL and the name previously had a dedicated buffer,
 *	than that buffer is no longer dedicated to use with this name.
 *	The caller is responsible for ensuring that the storage used by
 *	the name remains valid.
 *
 * Requires:
 * \li	'name' is a valid name.
 *
 * \li	'buffer' is a valid binary buffer and 'name' doesn't have a
 *	dedicated buffer already, or 'buffer' is NULL.
 */

bool
dns_name_hasbuffer(const dns_name_t *name);
/*%<
 * Does 'name' have a dedicated buffer?
 *
 * Requires:
 * \li	'name' is a valid name.
 *
 * Returns:
 * \li	true	'name' has a dedicated buffer.
 * \li	false	'name' does not have a dedicated buffer.
 */

/***
 *** Properties
 ***/

bool
dns_name_isabsolute(const dns_name_t *name);
/*%<
 * Does 'name' end in the root label?
 *
 * Requires:
 * \li	'name' is a valid name
 *
 * Returns:
 * \li	TRUE		The last label in 'name' is the root label.
 * \li	FALSE		The last label in 'name' is not the root label.
 */

bool
dns_name_iswildcard(const dns_name_t *name);
/*%<
 * Is 'name' a wildcard name?
 *
 * Requires:
 * \li	'name' is a valid name
 *
 * \li	dns_name_countlabels(name) > 0
 *
 * Returns:
 * \li	TRUE		The least significant label of 'name' is '*'.
 * \li	FALSE		The least significant label of 'name' is not '*'.
 */

unsigned int
dns_name_hash(dns_name_t *name, bool case_sensitive);
/*%<
 * Provide a hash value for 'name'.
 *
 * Note: if 'case_sensitive' is false, then names which differ only in
 * case will have the same hash value.
 *
 * Requires:
 * \li	'name' is a valid name
 *
 * Returns:
 * \li	A hash value
 */

unsigned int
dns_name_fullhash(dns_name_t *name, bool case_sensitive);
/*%<
 * Provide a hash value for 'name'.  Unlike dns_name_hash(), this function
 * always takes into account of the entire name to calculate the hash value.
 *
 * Note: if 'case_sensitive' is false, then names which differ only in
 * case will have the same hash value.
 *
 * Requires:
 *\li	'name' is a valid name
 *
 * Returns:
 *\li	A hash value
 */

unsigned int
dns_name_hashbylabel(dns_name_t *name, bool case_sensitive);
/*%<
 * Provide a hash value for 'name', where the hash value is the sum
 * of the hash values of each label.  This function should only be used
 * when incremental hashing is necessary, for example, during RBT
 * traversal. It is not currently used in BIND. Generally,
 * dns_name_fullhash() is the correct function to use for name
 * hashing.
 *
 * Note: if 'case_sensitive' is false, then names which differ only in
 * case will have the same hash value.
 *
 * Requires:
 *\li	'name' is a valid name
 *
 * Returns:
 *\li	A hash value
 */

/*
 *** Comparisons
 ***/

dns_namereln_t
dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
		     int *orderp, unsigned int *nlabelsp);
/*%<
 * Determine the relative ordering under the DNSSEC order relation of
 * 'name1' and 'name2', and also determine the hierarchical
 * relationship of the names.
 *
 * Note: It makes no sense for one of the names to be relative and the
 * other absolute.  If both names are relative, then to be meaningfully
 * compared the caller must ensure that they are both relative to the
 * same domain.
 *
 * Requires:
 *\li	'name1' is a valid name
 *
 *\li	dns_name_countlabels(name1) > 0
 *
 *\li	'name2' is a valid name
 *
 *\li	dns_name_countlabels(name2) > 0
 *
 *\li	orderp and nlabelsp are valid pointers.
 *
 *\li	Either name1 is absolute and name2 is absolute, or neither is.
 *
 * Ensures:
 *
 *\li	*orderp is < 0 if name1 < name2, 0 if name1 = name2, > 0 if
 *	name1 > name2.
 *
 *\li	*nlabelsp is the number of common significant labels.
 *
 * Returns:
 *\li	dns_namereln_none		There's no hierarchical relationship
 *					between name1 and name2.
 *\li	dns_namereln_contains		name1 properly contains name2; i.e.
 *					name2 is a proper subdomain of name1.
 *\li	dns_namereln_subdomain		name1 is a proper subdomain of name2.
 *\li	dns_namereln_equal		name1 and name2 are equal.
 *\li	dns_namereln_commonancestor	name1 and name2 share a common
 *					ancestor.
 */

int
dns_name_compare(const dns_name_t *name1, const dns_name_t *name2);
/*%<
 * Determine the relative ordering under the DNSSEC order relation of
 * 'name1' and 'name2'.
 *
 * Note: It makes no sense for one of the names to be relative and the
 * other absolute.  If both names are relative, then to be meaningfully
 * compared the caller must ensure that they are both relative to the
 * same domain.
 *
 * Requires:
 * \li	'name1' is a valid name
 *
 * \li	'name2' is a valid name
 *
 * \li	Either name1 is absolute and name2 is absolute, or neither is.
 *
 * Returns:
 * \li	< 0		'name1' is less than 'name2'
 * \li	0		'name1' is equal to 'name2'
 * \li	> 0		'name1' is greater than 'name2'
 */

bool
dns_name_equal(const dns_name_t *name1, const dns_name_t *name2);
/*%<
 * Are 'name1' and 'name2' equal?
 *
 * Notes:
 * \li	Because it only needs to test for equality, dns_name_equal() can be
 *	significantly faster than dns_name_fullcompare() or dns_name_compare().
 *
 * \li	Offsets tables are not used in the comparison.
 *
 * \li	It makes no sense for one of the names to be relative and the
 *	other absolute.  If both names are relative, then to be meaningfully
 * 	compared the caller must ensure that they are both relative to the
 * 	same domain.
 *
 * Requires:
 * \li	'name1' is a valid name
 *
 * \li	'name2' is a valid name
 *
 * \li	Either name1 is absolute and name2 is absolute, or neither is.
 *
 * Returns:
 * \li	true	'name1' and 'name2' are equal
 * \li	false	'name1' and 'name2' are not equal
 */

bool
dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2);
/*%<
 * Case sensitive version of dns_name_equal().
 */

int
dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2);
/*%<
 * Compare two names as if they are part of rdata in DNSSEC canonical
 * form.
 *
 * Requires:
 * \li	'name1' is a valid absolute name
 *
 * \li	dns_name_countlabels(name1) > 0
 *
 * \li	'name2' is a valid absolute name
 *
 * \li	dns_name_countlabels(name2) > 0
 *
 * Returns:
 * \li	< 0		'name1' is less than 'name2'
 * \li	0		'name1' is equal to 'name2'
 * \li	> 0		'name1' is greater than 'name2'
 */

bool
dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2);
/*%<
 * Is 'name1' a subdomain of 'name2'?
 *
 * Notes:
 * \li	name1 is a subdomain of name2 if name1 is contained in name2, or
 *	name1 equals name2.
 *
 * \li	It makes no sense for one of the names to be relative and the
 *	other absolute.  If both names are relative, then to be meaningfully
 *	compared the caller must ensure that they are both relative to the
 *	same domain.
 *
 * Requires:
 * \li	'name1' is a valid name
 *
 * \li	'name2' is a valid name
 *
 * \li	Either name1 is absolute and name2 is absolute, or neither is.
 *
 * Returns:
 * \li	TRUE		'name1' is a subdomain of 'name2'
 * \li	FALSE		'name1' is not a subdomain of 'name2'
 */

bool
dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname);
/*%<
 * Does 'name' match the wildcard specified in 'wname'?
 *
 * Notes:
 * \li	name matches the wildcard specified in wname if all labels
 *	following the wildcard in wname are identical to the same number
 *	of labels at the end of name.
 *
 * \li	It makes no sense for one of the names to be relative and the
 *	other absolute.  If both names are relative, then to be meaningfully
 *	compared the caller must ensure that they are both relative to the
 *	same domain.
 *
 * Requires:
 * \li	'name' is a valid name
 *
 * \li	dns_name_countlabels(name) > 0
 *
 * \li	'wname' is a valid name
 *
 * \li	dns_name_countlabels(wname) > 0
 *
 * \li	dns_name_iswildcard(wname) is true
 *
 * \li	Either name is absolute and wname is absolute, or neither is.
 *
 * Returns:
 * \li	TRUE		'name' matches the wildcard specified in 'wname'
 * \li	FALSE		'name' does not match the wildcard specified in 'wname'
 */

/***
 *** Labels
 ***/

unsigned int
dns_name_countlabels(const dns_name_t *name);
/*%<
 * How many labels does 'name' have?
 *
 * Notes:
 * \li	In this case, as in other places, a 'label' is an ordinary label.
 *
 * Requires:
 * \li	'name' is a valid name
 *
 * Ensures:
 * \li	The result is <= 128.
 *
 * Returns:
 * \li	The number of labels in 'name'.
 */

void
dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label);
/*%<
 * Make 'label' refer to the 'n'th least significant label of 'name'.
 *
 * Notes:
 * \li	Numbering starts at 0.
 *
 * \li	Given "rc.vix.com.", the label 0 is "rc", and label 3 is the
 *	root label.
 *
 * \li	'label' refers to the same memory as 'name', so 'name' must not
 *	be changed while 'label' is still in use.
 *
 * Requires:
 * \li	n < dns_name_countlabels(name)
 */

void
dns_name_getlabelsequence(const dns_name_t *source, unsigned int first,
			  unsigned int n, dns_name_t *target);
/*%<
 * Make 'target' refer to the 'n' labels including and following 'first'
 * in 'source'.
 *
 * Notes:
 * \li	Numbering starts at 0.
 *
 * \li	Given "rc.vix.com.", the label 0 is "rc", and label 3 is the
 *	root label.
 *
 * \li	'target' refers to the same memory as 'source', so 'source'
 *	must not be changed while 'target' is still in use.
 *
 * Requires:
 * \li	'source' and 'target' are valid names.
 *
 * \li	first < dns_name_countlabels(name)
 *
 * \li	first + n <= dns_name_countlabels(name)
 */


void
dns_name_clone(const dns_name_t *source, dns_name_t *target);
/*%<
 * Make 'target' refer to the same name as 'source'.
 *
 * Notes:
 *
 * \li	'target' refers to the same memory as 'source', so 'source'
 *	must not be changed while 'target' is still in use.
 *
 * \li	This call is functionally equivalent to:
 *
 * \code
 *		dns_name_getlabelsequence(source, 0,
 *					  dns_name_countlabels(source),
 *					  target);
 * \endcode
 *
 *	but is more efficient.  Also, dns_name_clone() works even if 'source'
 *	is empty.
 *
 * Requires:
 *
 * \li	'source' is a valid name.
 *
 * \li	'target' is a valid name that is not read-only.
 */

/***
 *** Conversions
 ***/

void
dns_name_fromregion(dns_name_t *name, const isc_region_t *r);
/*%<
 * Make 'name' refer to region 'r'.
 *
 * Note:
 * \li	If the conversion encounters a root label before the end of the
 *	region the conversion stops and the length is set to the length
 *	so far converted.  A maximum of 255 bytes is converted.
 *
 * Requires:
 * \li	The data in 'r' is a sequence of one or more type 00 or type 01000001
 *	labels.
 */

void
dns_name_toregion(dns_name_t *name, isc_region_t *r);
/*%<
 * Make 'r' refer to 'name'.
 *
 * Requires:
 *
 * \li	'name' is a valid name.
 *
 * \li	'r' is a valid region.
 */

isc_result_t
dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
		  dns_decompress_t *dctx, unsigned int options,
		  isc_buffer_t *target);
/*%<
 * Copy the possibly-compressed name at source (active region) into target,
 * decompressing it.
 *
 * Notes:
 * \li	Decompression policy is controlled by 'dctx'.
 *
 * \li	If DNS_NAME_DOWNCASE is set, any uppercase letters in 'source' will be
 *	downcased when they are copied into 'target'.
 *
 * Security:
 *
 * \li	*** WARNING ***
 *
 * \li	This routine will often be used when 'source' contains raw network
 *	data.  A programming error in this routine could result in a denial
 *	of service, or in the hijacking of the server.
 *
 * Requires:
 *
 * \li	'name' is a valid name.
 *
 * \li	'source' is a valid buffer and the first byte of the active
 *	region should be the first byte of a DNS wire format domain name.
 *
 * \li	'target' is a valid buffer or 'target' is NULL and 'name' has
 *	a dedicated buffer.
 *
 * \li	'dctx' is a valid decompression context.
 *
 * Ensures:
 *
 *	If result is success:
 * \li	 	If 'target' is not NULL, 'name' is attached to it.
 *
 * \li		Uppercase letters are downcased in the copy iff
 *		DNS_NAME_DOWNCASE is set in options.
 *
 * \li		The current location in source is advanced, and the used space
 *		in target is updated.
 *
 * Result:
 * \li	Success
 * \li	Bad Form: Label Length
 * \li	Bad Form: Unknown Label Type
 * \li	Bad Form: Name Length
 * \li	Bad Form: Compression type not allowed
 * \li	Bad Form: Bad compression pointer
 * \li	Bad Form: Input too short
 * \li	Resource Limit: Too many compression pointers
 * \li	Resource Limit: Not enough space in buffer
 */

isc_result_t
dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
		isc_buffer_t *target);
/*%<
 * Convert 'name' into wire format, compressing it as specified by the
 * compression context 'cctx', and storing the result in 'target'.
 *
 * Notes:
 * \li	If the compression context allows global compression, then the
 *	global compression table may be updated.
 *
 * Requires:
 * \li	'name' is a valid name
 *
 * \li	dns_name_countlabels(name) > 0
 *
 * \li	dns_name_isabsolute(name) == TRUE
 *
 * \li	target is a valid buffer.
 *
 * \li	Any offsets specified in a global compression table are valid
 *	for buffer.
 *
 * Ensures:
 *
 *	If the result is success:
 *
 * \li		The used space in target is updated.
 *
 * Returns:
 * \li	Success
 * \li	Resource Limit: Not enough space in buffer
 */

isc_result_t
dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
		  const dns_name_t *origin, unsigned int options,
		  isc_buffer_t *target);
/*%<
 * Convert the textual representation of a DNS name at source
 * into uncompressed wire form stored in target.
 *
 * Notes:
 * \li	Relative domain names will have 'origin' appended to them
 *	unless 'origin' is NULL, in which case relative domain names
 *	will remain relative.
 *
 * \li	If DNS_NAME_DOWNCASE is set in 'options', any uppercase letters
 *	in 'source' will be downcased when they are copied into 'target'.
 *
 * Requires:
 *
 * \li	'name' is a valid name.
 *
 * \li	'source' is a valid buffer.
 *
 * \li	'target' is a valid buffer or 'target' is NULL and 'name' has
 *	a dedicated buffer.
 *
 * Ensures:
 *
 *	If result is success:
 * \li	 	If 'target' is not NULL, 'name' is attached to it.
 *
 * \li		Uppercase letters are downcased in the copy iff
 *		DNS_NAME_DOWNCASE is set in 'options'.
 *
 * \li		The current location in source is advanced, and the used space
 *		in target is updated.
 *
 * Result:
 *\li	#ISC_R_SUCCESS
 *\li	#DNS_R_EMPTYLABEL
 *\li	#DNS_R_LABELTOOLONG
 *\li	#DNS_R_BADESCAPE
 *\li	#DNS_R_BADDOTTEDQUAD
 *\li	#ISC_R_NOSPACE
 *\li	#ISC_R_UNEXPECTEDEND
 */

#define DNS_NAME_OMITFINALDOT	0x01U
#define DNS_NAME_MASTERFILE	0x02U	/* escape $ and @ */

isc_result_t
dns_name_toprincipal(const dns_name_t *name, isc_buffer_t *target);

isc_result_t
dns_name_totext(const dns_name_t *name, bool omit_final_dot,
		isc_buffer_t *target);

isc_result_t
dns_name_totext2(const dns_name_t *name, unsigned int options,
		 isc_buffer_t *target);
/*%<
 * Convert 'name' into text format, storing the result in 'target'.
 *
 * Notes:
 *\li	If 'omit_final_dot' is true, then the final '.' in absolute
 *	names other than the root name will be omitted.
 *
 *\li	If DNS_NAME_OMITFINALDOT is set in options, then the final '.'
 *	in absolute names other than the root name will be omitted.
 *
 *\li	If DNS_NAME_MASTERFILE is set in options, '$' and '@' will also
 *	be escaped.
 *
 *\li	If dns_name_countlabels == 0, the name will be "@", representing the
 *	current origin as described by RFC1035.
 *
 *\li	The name is not NUL terminated.
 *
 * Requires:
 *
 *\li	'name' is a valid name
 *
 *\li	'target' is a valid buffer.
 *
 *\li	if dns_name_isabsolute == FALSE, then omit_final_dot == FALSE
 *
 * Ensures:
 *
 *\li	If the result is success:
 *		the used space in target is updated.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOSPACE
 */

#define DNS_NAME_MAXTEXT 1023
/*%<
 * The maximum length of the text representation of a domain
 * name as generated by dns_name_totext().  This does not
 * include space for a terminating NULL.
 *
 * This definition is conservative - the actual maximum
 * is 1004, derived as follows:
 *
 *   A backslash-decimal escaped character takes 4 bytes.
 *   A wire-encoded name can be up to 255 bytes and each
 *   label is one length byte + at most 63 bytes of data.
 *   Maximizing the label lengths gives us a name of
 *   three 63-octet labels, one 61-octet label, and the
 *   root label:
 *
 *      1 + 63 + 1 + 63 + 1 + 63 + 1 + 61 + 1 = 255
 *
 *   When printed, this is (3 * 63 + 61) * 4
 *   bytes for the escaped label data + 4 bytes for the
 *   dot terminating each label = 1004 bytes total.
 */

isc_result_t
dns_name_tofilenametext(dns_name_t *name, bool omit_final_dot,
			isc_buffer_t *target);
/*%<
 * Convert 'name' into an alternate text format appropriate for filenames,
 * storing the result in 'target'.  The name data is downcased, guaranteeing
 * that the filename does not depend on the case of the converted name.
 *
 * Notes:
 *\li	If 'omit_final_dot' is true, then the final '.' in absolute
 *	names other than the root name will be omitted.
 *
 *\li	The name is not NUL terminated.
 *
 * Requires:
 *
 *\li	'name' is a valid absolute name
 *
 *\li	'target' is a valid buffer.
 *
 * Ensures:
 *
 *\li	If the result is success:
 *		the used space in target is updated.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOSPACE
 */

isc_result_t
dns_name_downcase(dns_name_t *source, dns_name_t *name,
		  isc_buffer_t *target);
/*%<
 * Downcase 'source'.
 *
 * Requires:
 *
 *\li	'source' and 'name' are valid names.
 *
 *\li	If source == name, then
 *		'source' must not be read-only
 *
 *\li	Otherwise,
 *		'target' is a valid buffer or 'target' is NULL and
 *		'name' has a dedicated buffer.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOSPACE
 *
 * Note: if source == name, then the result will always be ISC_R_SUCCESS.
 */

isc_result_t
dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix,
		     dns_name_t *name, isc_buffer_t *target);
/*%<
 *	Concatenate 'prefix' and 'suffix'.
 *
 * Requires:
 *
 *\li	'prefix' is a valid name or NULL.
 *
 *\li	'suffix' is a valid name or NULL.
 *
 *\li	'name' is a valid name or NULL.
 *
 *\li	'target' is a valid buffer or 'target' is NULL and 'name' has
 *	a dedicated buffer.
 *
 *\li	If 'prefix' is absolute, 'suffix' must be NULL or the empty name.
 *
 * Ensures:
 *
 *\li	On success,
 *	 	If 'target' is not NULL and 'name' is not NULL, then 'name'
 *		is attached to it.
 *		The used space in target is updated.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOSPACE
 *\li	#DNS_R_NAMETOOLONG
 */

void
dns_name_split(dns_name_t *name, unsigned int suffixlabels,
	       dns_name_t *prefix, dns_name_t *suffix);
/*%<
 *
 * Split 'name' into two pieces on a label boundary.
 *
 * Notes:
 * \li     'name' is split such that 'suffix' holds the most significant
 *      'suffixlabels' labels.  All other labels are stored in 'prefix'.
 *
 *\li	Copying name data is avoided as much as possible, so 'prefix'
 *	and 'suffix' will end up pointing at the data for 'name'.
 *
 *\li	It is legitimate to pass a 'prefix' or 'suffix' that has
 *	its name data stored someplace other than the dedicated buffer.
 *	This is useful to avoid name copying in the calling function.
 *
 *\li	It is also legitimate to pass a 'prefix' or 'suffix' that is
 *	the same dns_name_t as 'name'.
 *
 * Requires:
 *\li	'name' is a valid name.
 *
 *\li	'suffixlabels' cannot exceed the number of labels in 'name'.
 *
 * \li	'prefix' is a valid name or NULL, and cannot be read-only.
 *
 *\li	'suffix' is a valid name or NULL, and cannot be read-only.
 *
 * Ensures:
 *
 *\li	On success:
 *		If 'prefix' is not NULL it will contain the least significant
 *		labels.
 *		If 'suffix' is not NULL it will contain the most significant
 *		labels.  dns_name_countlabels(suffix) will be equal to
 *		suffixlabels.
 *
 *\li	On failure:
 *		Either 'prefix' or 'suffix' is invalidated (depending
 *		on which one the problem was encountered with).
 *
 * Returns:
 *\li	#ISC_R_SUCCESS	No worries.  (This function should always success).
 */

isc_result_t
dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
	     dns_name_t *target);
/*%<
 * Make 'target' a dynamically allocated copy of 'source'.
 *
 * Requires:
 *
 *\li	'source' is a valid non-empty name.
 *
 *\li	'target' is a valid name that is not read-only.
 *
 *\li	'mctx' is a valid memory context.
 */

isc_result_t
dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
			dns_name_t *target);
/*%<
 * Make 'target' a read-only dynamically allocated copy of 'source'.
 * 'target' will also have a dynamically allocated offsets table.
 *
 * Requires:
 *
 *\li	'source' is a valid non-empty name.
 *
 *\li	'target' is a valid name that is not read-only.
 *
 *\li	'target' has no offsets table.
 *
 *\li	'mctx' is a valid memory context.
 */

void
dns_name_free(dns_name_t *name, isc_mem_t *mctx);
/*%<
 * Free 'name'.
 *
 * Requires:
 *
 *\li	'name' is a valid name created previously in 'mctx' by dns_name_dup().
 *
 *\li	'mctx' is a valid memory context.
 *
 * Ensures:
 *
 *\li	All dynamic resources used by 'name' are freed and the name is
 *	invalidated.
 */

isc_result_t
dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg);
/*%<
 * Send 'name' in DNSSEC canonical form to 'digest'.
 *
 * Requires:
 *
 *\li	'name' is a valid name.
 *
 *\li	'digest' is a valid dns_digestfunc_t.
 *
 * Ensures:
 *
 *\li	If successful, the DNSSEC canonical form of 'name' will have been
 *	sent to 'digest'.
 *
 *\li	If digest() returns something other than ISC_R_SUCCESS, that result
 *	will be returned as the result of dns_name_digest().
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS
 *
 *\li	Many other results are possible if not successful.
 *
 */

bool
dns_name_dynamic(dns_name_t *name);
/*%<
 * Returns whether there is dynamic memory associated with this name.
 *
 * Requires:
 *
 *\li	'name' is a valid name.
 *
 * Returns:
 *
 *\li	'true' if the name is dynamic otherwise 'false'.
 */

isc_result_t
dns_name_print(dns_name_t *name, FILE *stream);
/*%<
 * Print 'name' on 'stream'.
 *
 * Requires:
 *
 *\li	'name' is a valid name.
 *
 *\li	'stream' is a valid stream.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS
 *
 *\li	Any error that dns_name_totext() can return.
 */

void
dns_name_format(const dns_name_t *name, char *cp, unsigned int size);
/*%<
 * Format 'name' as text appropriate for use in log messages.
 *
 * Store the formatted name at 'cp', writing no more than
 * 'size' bytes.  The resulting string is guaranteed to be
 * null terminated.
 *
 * The formatted name will have a terminating dot only if it is
 * the root.
 *
 * This function cannot fail, instead any errors are indicated
 * in the returned text.
 *
 * Requires:
 *
 *\li	'name' is a valid name.
 *
 *\li	'cp' points a valid character array of size 'size'.
 *
 *\li	'size' > 0.
 *
 */

isc_result_t
dns_name_tostring(dns_name_t *source, char **target, isc_mem_t *mctx);
/*%<
 * Convert 'name' to string format, allocating sufficient memory to
 * hold it (free with isc_mem_free()).
 *
 * Differs from dns_name_format in that it allocates its own memory.
 *
 * Requires:
 *
 *\li	'name' is a valid name.
 *\li	'target' is not NULL.
 *\li	'*target' is NULL.
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_NOMEMORY
 *
 *\li	Any error that dns_name_totext() can return.
 */

isc_result_t
dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
		    isc_mem_t *mctx);
isc_result_t
dns_name_fromstring2(dns_name_t *target, const char *src,
		     const dns_name_t *origin, unsigned int options,
		     isc_mem_t *mctx);
/*%<
 * Convert a string to a name and place it in target, allocating memory
 * as necessary.  'options' has the same semantics as that of
 * dns_name_fromtext().
 *
 * If 'target' has a buffer then the name will be copied into it rather than
 * memory being allocated.
 *
 * Requires:
 *
 * \li	'target' is a valid name that is not read-only.
 * \li	'src' is not NULL.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS
 *
 *\li	Any error that dns_name_fromtext() can return.
 *
 *\li	Any error that dns_name_dup() can return.
 */

isc_result_t
dns_name_settotextfilter(dns_name_totextfilter_t proc);
/*%<
 * Set / clear a thread specific function 'proc' to be called at the
 * end of dns_name_totext().
 *
 * Note: Under Windows you need to call "dns_name_settotextfilter(NULL);"
 * prior to exiting the thread otherwise memory will be leaked.
 * For other platforms, which are pthreads based, this is still a good
 * idea but not required.
 *
 * Returns
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_UNEXPECTED
 */

#define DNS_NAME_FORMATSIZE (DNS_NAME_MAXTEXT + 1)
/*%<
 * Suggested size of buffer passed to dns_name_format().
 * Includes space for the terminating NULL.
 */

isc_result_t
dns_name_copy(const dns_name_t *source, dns_name_t *dest, isc_buffer_t *target);
/*%<
 * Makes 'dest' refer to a copy of the name in 'source'.  The data are
 * either copied to 'target' or the dedicated buffer in 'dest'.
 *
 * Requires:
 * \li	'source' is a valid name.
 *
 * \li	'dest' is an initialized name with a dedicated buffer.
 *
 * \li	'target' is NULL or an initialized buffer.
 *
 * \li	Either dest has a dedicated buffer or target != NULL.
 *
 * Ensures:
 *
 *\li	On success, the used space in target is updated.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOSPACE
 */

bool
dns_name_ishostname(const dns_name_t *name, bool wildcard);
/*%<
 * Return if 'name' is a valid hostname.  RFC 952 / RFC 1123.
 * If 'wildcard' is true then allow the first label of name to
 * be a wildcard.
 * The root is also accepted.
 *
 * Requires:
 *	'name' to be valid.
 */


bool
dns_name_ismailbox(const dns_name_t *name);
/*%<
 * Return if 'name' is a valid mailbox.  RFC 821.
 *
 * Requires:
 * \li	'name' to be valid.
 */

bool
dns_name_internalwildcard(const dns_name_t *name);
/*%<
 * Return if 'name' contains a internal wildcard name.
 *
 * Requires:
 * \li	'name' to be valid.
 */

void
dns_name_destroy(void);
/*%<
 * Cleanup dns_name_settotextfilter() / dns_name_totext() state.
 *
 * This should be called as part of the final cleanup process.
 *
 * Note: dns_name_settotextfilter(NULL); should be called for all
 * threads which have called dns_name_settotextfilter() with a
 * non-NULL argument prior to calling dns_name_destroy();
 */

bool
dns_name_isdnssd(const dns_name_t *owner);
/*%<
 * Determine if the 'owner' is a DNS-SD prefix.
 */

bool
dns_name_isrfc1918(const dns_name_t *owner);
/*%<
 * Determine if the 'name' is in the RFC 1918 reverse namespace.
 */

bool
dns_name_isula(const dns_name_t *owner);
/*%<
 * Determine if the 'name' is in the ULA reverse namespace.
 */

bool
dns_name_istat(const dns_name_t *name);
/*
 * Determine if 'name' is a potential 'trust-anchor-telemetry' name.
 */

ISC_LANG_ENDDECLS

/*
 *** High Performance Macros
 ***/

/*
 * WARNING:  Use of these macros by applications may require recompilation
 *           of the application in some situations where calling the function
 *           would not.
 *
 * WARNING:  No assertion checking is done for these macros.
 */

#define DNS_NAME_INIT(n, o) \
do { \
	dns_name_t *_n = (n); \
	/* memset(_n, 0, sizeof(*_n)); */ \
	_n->magic = DNS_NAME_MAGIC; \
	_n->ndata = NULL; \
	_n->length = 0; \
	_n->labels = 0; \
	_n->attributes = 0; \
	_n->offsets = (o); \
	_n->buffer = NULL; \
	ISC_LINK_INIT(_n, link); \
	ISC_LIST_INIT(_n->list); \
	_n->ht = NULL; \
} while (0)

#define DNS_NAME_RESET(n) \
do { \
	(n)->ndata = NULL; \
	(n)->length = 0; \
	(n)->labels = 0; \
	(n)->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
	if ((n)->buffer != NULL) \
		isc_buffer_clear((n)->buffer); \
} while (0)

#define DNS_NAME_SETBUFFER(n, b) \
	(n)->buffer = (b)

#define DNS_NAME_ISABSOLUTE(n) \
	(((n)->attributes & DNS_NAMEATTR_ABSOLUTE) != 0 ? true : false)

#define DNS_NAME_COUNTLABELS(n) \
	((n)->labels)

#define DNS_NAME_TOREGION(n, r) \
do { \
	(r)->base = (n)->ndata; \
	(r)->length = (n)->length; \
} while (0)

#define DNS_NAME_SPLIT(n, l, p, s) \
do { \
	dns_name_t *_n = (n); \
	dns_name_t *_p = (p); \
	dns_name_t *_s = (s); \
	unsigned int _l = (l); \
	if (_p != NULL) \
		dns_name_getlabelsequence(_n, 0, _n->labels - _l, _p); \
	if (_s != NULL) \
		dns_name_getlabelsequence(_n, _n->labels - _l, _l, _s); \
} while (0)

#ifdef DNS_NAME_USEINLINE

#define dns_name_init(n, o)		DNS_NAME_INIT(n, o)
#define dns_name_reset(n)		DNS_NAME_RESET(n)
#define dns_name_setbuffer(n, b)	DNS_NAME_SETBUFFER(n, b)
#define dns_name_countlabels(n)		DNS_NAME_COUNTLABELS(n)
#define dns_name_isabsolute(n)		DNS_NAME_ISABSOLUTE(n)
#define dns_name_toregion(n, r)		DNS_NAME_TOREGION(n, r)
#define dns_name_split(n, l, p, s)	DNS_NAME_SPLIT(n, l, p, s)

#endif /* DNS_NAME_USEINLINE */

#endif /* DNS_NAME_H */
view.h000064400000104712150415243030005671 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_VIEW_H
#define DNS_VIEW_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/view.h
 * \brief
 * DNS View
 *
 * A "view" is a DNS namespace, together with an optional resolver and a
 * forwarding policy.  A "DNS namespace" is a (possibly empty) set of
 * authoritative zones together with an optional cache and optional
 * "hints" information.
 *
 * Views start out "unfrozen".  In this state, core attributes like
 * the cache, set of zones, and forwarding policy may be set.  While
 * "unfrozen", the caller (e.g. nameserver configuration loading
 * code), must ensure exclusive access to the view.  When the view is
 * "frozen", the core attributes become immutable, and the view module
 * will ensure synchronization.  Freezing allows the view's core attributes
 * to be accessed without locking.
 *
 * MP:
 *\li	Before the view is frozen, the caller must ensure synchronization.
 *
 *\li	After the view is frozen, the module guarantees appropriate
 *	synchronization of any data structures it creates and manipulates.
 *
 * Reliability:
 *\li	No anticipated impact.
 *
 * Resources:
 *\li	TBS
 *
 * Security:
 *\li	No anticipated impact.
 *
 * Standards:
 *\li	None.
 */

#include <stdio.h>
#include <inttypes.h>
#include <stdbool.h>

#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/event.h>
#include <isc/mutex.h>
#include <isc/net.h>
#include <isc/refcount.h>
#include <isc/rwlock.h>
#include <isc/stdtime.h>

#include <dns/acl.h>
#include <dns/catz.h>
#include <dns/clientinfo.h>
#include <dns/dnstap.h>
#include <dns/fixedname.h>
#include <dns/rrl.h>
#include <dns/rdatastruct.h>
#include <dns/rpz.h>
#include <dns/types.h>
#include <dns/zt.h>

ISC_LANG_BEGINDECLS

struct dns_view {
	/* Unlocked. */
	unsigned int			magic;
	isc_mem_t *			mctx;
	dns_rdataclass_t		rdclass;
	char *				name;
	dns_zt_t *			zonetable;
	dns_resolver_t *		resolver;
	dns_adb_t *			adb;
	dns_requestmgr_t *		requestmgr;
	dns_acache_t *			acache;
	dns_cache_t *			cache;
	dns_db_t *			cachedb;
	dns_db_t *			hints;

	/*
	 * security roots and negative trust anchors.
	 * internal use only; access via * dns_view_getsecroots()
	 */
	dns_keytable_t *		secroots_priv;
	dns_ntatable_t *		ntatable_priv;

	isc_mutex_t			lock;
	bool			frozen;
	isc_task_t *			task;
	isc_event_t			resevent;
	isc_event_t			adbevent;
	isc_event_t			reqevent;
	isc_stats_t *			adbstats;
	isc_stats_t *			resstats;
	dns_stats_t *			resquerystats;
	bool			cacheshared;

	/* Configurable data. */
	dns_tsig_keyring_t *		statickeys;
	dns_tsig_keyring_t *		dynamickeys;
	dns_peerlist_t *		peers;
	dns_order_t *			order;
	dns_fwdtable_t *		fwdtable;
	bool			recursion;
	bool			auth_nxdomain;
	bool			additionalfromcache;
	bool			additionalfromauth;
	bool			minimal_any;
	dns_minimaltype_t		minimalresponses;
	bool			enablednssec;
	bool			enablevalidation;
	bool			acceptexpired;
	bool			requireservercookie;
	bool			trust_anchor_telemetry;
	bool			root_key_sentinel;
	dns_transfer_format_t		transfer_format;
	dns_acl_t *			cacheacl;
	dns_acl_t *			cacheonacl;
	dns_acl_t *			queryacl;
	dns_acl_t *			queryonacl;
	dns_acl_t *			recursionacl;
	dns_acl_t *			recursiononacl;
	dns_acl_t *			sortlist;
	dns_acl_t *			notifyacl;
	dns_acl_t *			transferacl;
	dns_acl_t *			updateacl;
	dns_acl_t *			upfwdacl;
	dns_acl_t *			denyansweracl;
	dns_acl_t *			nocasecompress;
	bool			msgcompression;
	dns_rbt_t *			answeracl_exclude;
	dns_rbt_t *			denyanswernames;
	dns_rbt_t *			answernames_exclude;
	dns_rrl_t *			rrl;
	bool			provideixfr;
	bool			requestnsid;
	bool			sendcookie;
	dns_ttl_t			maxcachettl;
	dns_ttl_t			maxncachettl;
	uint32_t			nta_lifetime;
	uint32_t			nta_recheck;
	char				*nta_file;
	dns_ttl_t			prefetch_trigger;
	dns_ttl_t			prefetch_eligible;
	in_port_t			dstport;
	dns_aclenv_t			aclenv;
	dns_rdatatype_t			preferred_glue;
	bool			flush;
	dns_namelist_t *		delonly;
	bool			rootdelonly;
	dns_namelist_t *		rootexclude;
	bool			checknames;
	dns_name_t *			dlv;
	dns_fixedname_t			dlv_fixed;
	uint16_t			maxudp;
	uint16_t			nocookieudp;
	unsigned int			maxbits;
	dns_aaaa_t			v4_aaaa;
	dns_aaaa_t			v6_aaaa;
	dns_acl_t *			aaaa_acl;
	dns_dns64list_t 		dns64;
	unsigned int 			dns64cnt;
	dns_rpz_zones_t			*rpzs;
	dns_catz_zones_t		*catzs;
	dns_dlzdblist_t 		dlz_searched;
	dns_dlzdblist_t 		dlz_unsearched;
	uint32_t			fail_ttl;
	dns_badcache_t			*failcache;

	/*
	 * Configurable data for server use only,
	 * locked by server configuration lock.
	 */
	dns_acl_t *			matchclients;
	dns_acl_t *			matchdestinations;
	bool			matchrecursiveonly;

	/* Locked by themselves. */
	isc_refcount_t			references;
	isc_refcount_t			weakrefs;

	/* Locked by lock. */
	unsigned int			attributes;
	/* Under owner's locking control. */
	ISC_LINK(struct dns_view)	link;
	dns_viewlist_t *		viewlist;

	dns_zone_t *			managed_keys;
	dns_zone_t *			redirect;
	dns_name_t *			redirectzone;	/* points to
							 * redirectfixed
							 * when valid */
	dns_fixedname_t 		redirectfixed;

	/*
	 * File and configuration data for zones added at runtime
	 * (only used in BIND9).
	 *
	 * XXX: This should be a pointer to an opaque type that
	 * named implements.
	 */
	char *				new_zone_file;
	char *			        new_zone_db;
	void *				new_zone_dbenv;
	uint64_t			new_zone_mapsize;
	void *				new_zone_config;
	void				(*cfg_destroy)(void **);
	isc_mutex_t			new_zone_lock;

	unsigned char			secret[32];	/* Client secret */
	unsigned int			v6bias;

	dns_dtenv_t			*dtenv;		/* Dnstap environment */
	dns_dtmsgtype_t			dttypes;	/* Dnstap message types
							   to log */
	dns_ttl_t			staleanswerttl;
	dns_stale_answer_t		staleanswersok;		/* rndc setting */
	bool				staleanswersenable;	/* named.conf setting */
};

#define DNS_VIEW_MAGIC			ISC_MAGIC('V','i','e','w')
#define DNS_VIEW_VALID(view)		ISC_MAGIC_VALID(view, DNS_VIEW_MAGIC)

#define DNS_VIEWATTR_RESSHUTDOWN	0x01
#define DNS_VIEWATTR_ADBSHUTDOWN	0x02
#define DNS_VIEWATTR_REQSHUTDOWN	0x04

#ifdef HAVE_LMDB
#include <lmdb.h>
#define DNS_LMDB_COMMON_FLAGS		(MDB_CREATE | MDB_NOSUBDIR | MDB_NOLOCK)
#ifndef __OpenBSD__
#define DNS_LMDB_FLAGS			(DNS_LMDB_COMMON_FLAGS)
#else /* __OpenBSD__ */
/*
 * OpenBSD does not have a unified buffer cache, which requires both reads and
 * writes to be performed using mmap().
 */
#define DNS_LMDB_FLAGS			(DNS_LMDB_COMMON_FLAGS | MDB_WRITEMAP)
#endif /* __OpenBSD__ */
#endif /* HAVE_LMDB */

isc_result_t
dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
		const char *name, dns_view_t **viewp);
/*%<
 * Create a view.
 *
 * Notes:
 *
 *\li	The newly created view has no cache, no resolver, and an empty
 *	zone table.  The view is not frozen.
 *
 * Requires:
 *
 *\li	'mctx' is a valid memory context.
 *
 *\li	'rdclass' is a valid class.
 *
 *\li	'name' is a valid C string.
 *
 *\li	viewp != NULL && *viewp == NULL
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *
 *\li	Other errors are possible.
 */

void
dns_view_attach(dns_view_t *source, dns_view_t **targetp);
/*%<
 * Attach '*targetp' to 'source'.
 *
 * Requires:
 *
 *\li	'source' is a valid, frozen view.
 *
 *\li	'targetp' points to a NULL dns_view_t *.
 *
 * Ensures:
 *
 *\li	*targetp is attached to source.
 *
 *\li	While *targetp is attached, the view will not shut down.
 */

void
dns_view_detach(dns_view_t **viewp);
/*%<
 * Detach '*viewp' from its view.
 *
 * Requires:
 *
 *\li	'viewp' points to a valid dns_view_t *
 *
 * Ensures:
 *
 *\li	*viewp is NULL.
 */

void
dns_view_flushanddetach(dns_view_t **viewp);
/*%<
 * Detach '*viewp' from its view.  If this was the last reference
 * uncommitted changed in zones will be flushed to disk.
 *
 * Requires:
 *
 *\li	'viewp' points to a valid dns_view_t *
 *
 * Ensures:
 *
 *\li	*viewp is NULL.
 */

void
dns_view_weakattach(dns_view_t *source, dns_view_t **targetp);
/*%<
 * Weakly attach '*targetp' to 'source'.
 *
 * Requires:
 *
 *\li	'source' is a valid, frozen view.
 *
 *\li	'targetp' points to a NULL dns_view_t *.
 *
 * Ensures:
 *
 *\li	*targetp is attached to source.
 *
 * \li	While *targetp is attached, the view will not be freed.
 */

void
dns_view_weakdetach(dns_view_t **targetp);
/*%<
 * Detach '*viewp' from its view.
 *
 * Requires:
 *
 *\li	'viewp' points to a valid dns_view_t *.
 *
 * Ensures:
 *
 *\li	*viewp is NULL.
 */

isc_result_t
dns_view_createzonetable(dns_view_t *view);
/*%<
 * Create a zonetable for the view.
 *
 * Requires:
 *
 *\li	'view' is a valid, unfrozen view.
 *
 *\li	'view' does not have a zonetable already.
 *
 * Returns:
 *
 *\li   	#ISC_R_SUCCESS
 *
 *\li	Any error that dns_zt_create() can return.
 */

isc_result_t
dns_view_createresolver(dns_view_t *view,
			isc_taskmgr_t *taskmgr,
			unsigned int ntasks, unsigned int ndisp,
			isc_socketmgr_t *socketmgr,
			isc_timermgr_t *timermgr,
			unsigned int options,
			dns_dispatchmgr_t *dispatchmgr,
			dns_dispatch_t *dispatchv4,
			dns_dispatch_t *dispatchv6);
/*%<
 * Create a resolver and address database for the view.
 *
 * Requires:
 *
 *\li	'view' is a valid, unfrozen view.
 *
 *\li	'view' does not have a resolver already.
 *
 *\li	The requirements of dns_resolver_create() apply to 'taskmgr',
 *	'ntasks', 'socketmgr', 'timermgr', 'options', 'dispatchv4', and
 *	'dispatchv6'.
 *
 * Returns:
 *
 *\li   	#ISC_R_SUCCESS
 *
 *\li	Any error that dns_resolver_create() can return.
 */

void
dns_view_setcache(dns_view_t *view, dns_cache_t *cache);
void
dns_view_setcache2(dns_view_t *view, dns_cache_t *cache, bool shared);
/*%<
 * Set the view's cache database.  If 'shared' is true, this means the cache
 * is created by another view and is shared with that view.  dns_view_setcache()
 * is a backward compatible version equivalent to setcache2(..., false).
 *
 * Requires:
 *
 *\li	'view' is a valid, unfrozen view.
 *
 *\li	'cache' is a valid cache.
 *
 * Ensures:
 *
 * \li    	The cache of 'view' is 'cached.
 *
 *\li	If this is not the first call to dns_view_setcache() for this
 *	view, then previously set cache is detached.
 */

void
dns_view_sethints(dns_view_t *view, dns_db_t *hints);
/*%<
 * Set the view's hints database.
 *
 * Requires:
 *
 *\li	'view' is a valid, unfrozen view, whose hints database has not been
 *	set.
 *
 *\li	'hints' is a valid zone database.
 *
 * Ensures:
 *
 * \li    	The hints database of 'view' is 'hints'.
 */

void
dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring);
void
dns_view_setdynamickeyring(dns_view_t *view, dns_tsig_keyring_t *ring);
/*%<
 * Set the view's static TSIG keys
 *
 * Requires:
 *
 *   \li   'view' is a valid, unfrozen view, whose static TSIG keyring has not
 *	been set.
 *
 *\li      'ring' is a valid TSIG keyring
 *
 * Ensures:
 *
 *\li      The static TSIG keyring of 'view' is 'ring'.
 */

void
dns_view_getdynamickeyring(dns_view_t *view, dns_tsig_keyring_t **ringp);
/*%<
 * Return the views dynamic keys.
 *
 *   \li  'view' is a valid, unfrozen view.
 *   \li  'ringp' != NULL && ringp == NULL.
 */

void
dns_view_setdstport(dns_view_t *view, in_port_t dstport);
/*%<
 * Set the view's destination port.  This is the port to
 * which outgoing queries are sent.  The default is 53,
 * the standard DNS port.
 *
 * Requires:
 *
 *\li      'view' is a valid view.
 *
 *\li      'dstport' is a valid TCP/UDP port number.
 *
 * Ensures:
 *\li	External name servers will be assumed to be listening
 *	on 'dstport'.  For servers whose address has already
 *	obtained obtained at the time of the call, the view may
 *	continue to use the previously set port until the address
 *	times out from the view's address database.
 */


isc_result_t
dns_view_addzone(dns_view_t *view, dns_zone_t *zone);
/*%<
 * Add zone 'zone' to 'view'.
 *
 * Requires:
 *
 *\li	'view' is a valid, unfrozen view.
 *
 *\li	'zone' is a valid zone.
 */

void
dns_view_freeze(dns_view_t *view);
/*%<
 * Freeze view.  No changes can be made to view configuration while frozen.
 *
 * Requires:
 *
 *\li	'view' is a valid, unfrozen view.
 *
 * Ensures:
 *
 *\li	'view' is frozen.
 */

void
dns_view_thaw(dns_view_t *view);
/*%<
 * Thaw view.  This allows zones to be added or removed at runtime.  This is
 * NOT thread-safe; the caller MUST have run isc_task_exclusive() prior to
 * thawing the view.
 *
 * Requires:
 *
 *\li	'view' is a valid, frozen view.
 *
 * Ensures:
 *
 *\li	'view' is no longer frozen.
 */
isc_result_t
dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
	      isc_stdtime_t now, unsigned int options, bool use_hints,
	      dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname,
	      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
isc_result_t
dns_view_find2(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
	       isc_stdtime_t now, unsigned int options,
	       bool use_hints, bool use_static_stub,
	       dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname,
	       dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
/*%<
 * Find an rdataset whose owner name is 'name', and whose type is
 * 'type'.
 * In general, this function first searches view's zone and cache DBs for the
 * best match data against 'name'.  If nothing found there, and if 'use_hints'
 * is true, the view's hint DB (if configured) is searched.
 * If the view is configured with a static-stub zone which gives the longest
 * match for 'name' among the zones, however, the cache DB is not consulted
 * unless 'use_static_stub' is false (see below about this argument).
 *
 * dns_view_find() is a backward compatible version equivalent to
 * dns_view_find2() with use_static_stub argument being false.
 *
 * Notes:
 *
 *\li	See the description of dns_db_find() for information about 'options'.
 *	If the caller sets #DNS_DBFIND_GLUEOK, it must ensure that 'name'
 *	and 'type' are appropriate for glue retrieval.
 *
 *\li	If 'now' is zero, then the current time will be used.
 *
 *\li	If 'use_hints' is true, and the view has a hints database, then
 *	it will be searched last.  If the answer is found in the hints
 *	database, the result code will be DNS_R_HINT.  If the name is found
 *	in the hints database but not the type, the result code will be
 *	#DNS_R_HINTNXRRSET.
 *
 *\li	If 'use_static_stub' is false and the longest match zone for 'name'
 *	is a static-stub zone, it's ignored and the cache and/or hints will be
 *	searched.  In the majority of the cases this argument should be
 *	false.  The only known usage of this argument being true is
 *	if this search is for a "bailiwick" glue A or AAAA RRset that may
 *	best match a static-stub zone.  Consider the following example:
 *	this view is configured with a static-stub zone "example.com",
 *	and an attempt of recursive resolution needs to send a query for the
 *	zone.  In this case it's quite likely that the resolver is trying to
 *	find A/AAAA RRs for the apex name "example.com".  And, to honor the
 *	static-stub configuration it needs to return the glue RRs in the
 *	static-stub zone even if that exact RRs coming from the authoritative
 *	zone has been cached.
 *	In other general cases, the requested data is better to be
 *	authoritative, either locally configured or retrieved from an external
 *	server, and the data in the static-stub zone should better be ignored.
 *
 *\li	'foundname' must meet the requirements of dns_db_find().
 *
 *\li	If 'sigrdataset' is not NULL, and there is a SIG rdataset which
 *	covers 'type', then 'sigrdataset' will be bound to it.
 *
 * Requires:
 *
 *\li	'view' is a valid, frozen view.
 *
 *\li	'name' is valid name.
 *
 *\li	'type' is a valid dns_rdatatype_t, and is not a meta query type
 *	except dns_rdatatype_any.
 *
 *\li	dbp == NULL || *dbp == NULL
 *
 *\li	nodep == NULL || *nodep == NULL.  If nodep != NULL, dbp != NULL.
 *
 *\li	'foundname' is a valid name with a dedicated buffer or NULL.
 *
 *\li	'rdataset' is a valid, disassociated rdataset.
 *
 *\li	'sigrdataset' is NULL, or is a valid, disassociated rdataset.
 *
 * Ensures:
 *
 *\li	In successful cases, 'rdataset', and possibly 'sigrdataset', are
 *	bound to the found data.
 *
 *\li	If dbp != NULL, it points to the database containing the data.
 *
 *\li	If nodep != NULL, it points to the database node containing the data.
 *
 *\li	If foundname != NULL, it contains the full name of the found data.
 *
 * Returns:
 *
 *\li	Any result that dns_db_find() can return, with the exception of
 *	#DNS_R_DELEGATION.
 */

isc_result_t
dns_view_simplefind(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
		    isc_stdtime_t now, unsigned int options,
		    bool use_hints,
		    dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
/*%<
 * Find an rdataset whose owner name is 'name', and whose type is
 * 'type'.
 *
 * Notes:
 *
 *\li	This routine is appropriate for simple, exact-match queries of the
 *	view.  'name' must be a canonical name; there is no DNAME or CNAME
 *	processing.
 *
 *\li	See the description of dns_db_find() for information about 'options'.
 *	If the caller sets DNS_DBFIND_GLUEOK, it must ensure that 'name'
 *	and 'type' are appropriate for glue retrieval.
 *
 *\li	If 'now' is zero, then the current time will be used.
 *
 *\li	If 'use_hints' is true, and the view has a hints database, then
 *	it will be searched last.  If the answer is found in the hints
 *	database, the result code will be DNS_R_HINT.  If the name is found
 *	in the hints database but not the type, the result code will be
 *	DNS_R_HINTNXRRSET.
 *
 *\li	If 'sigrdataset' is not NULL, and there is a SIG rdataset which
 *	covers 'type', then 'sigrdataset' will be bound to it.
 *
 * Requires:
 *
 *\li	'view' is a valid, frozen view.
 *
 *\li	'name' is valid name.
 *
 *\li	'type' is a valid dns_rdatatype_t, and is not a meta query type
 *	(e.g. dns_rdatatype_any), or dns_rdatatype_rrsig.
 *
 *\li	'rdataset' is a valid, disassociated rdataset.
 *
 *\li	'sigrdataset' is NULL, or is a valid, disassociated rdataset.
 *
 * Ensures:
 *
 *\li	In successful cases, 'rdataset', and possibly 'sigrdataset', are
 *	bound to the found data.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS			Success; result is desired type.
 *\li	DNS_R_GLUE			Success; result is glue.
 *\li	DNS_R_HINT			Success; result is a hint.
 *\li	DNS_R_NCACHENXDOMAIN		Success; result is a ncache entry.
 *\li	DNS_R_NCACHENXRRSET		Success; result is a ncache entry.
 *\li	DNS_R_NXDOMAIN			The name does not exist.
 *\li	DNS_R_NXRRSET			The rrset does not exist.
 *\li	#ISC_R_NOTFOUND			No matching data found,
 *					or an error occurred.
 */

/*% See dns_view_findzonecut2() */
isc_result_t
dns_view_findzonecut(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
		     isc_stdtime_t now, unsigned int options,
		     bool use_hints,
		     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);

isc_result_t
dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
		      isc_stdtime_t now, unsigned int options,
		      bool use_hints, bool use_cache,
		      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
/*%<
 * Find the best known zonecut containing 'name'.
 *
 * This uses local authority, cache, and optionally hints data.
 * No external queries are performed.
 *
 * Notes:
 *
 *\li	If 'now' is zero, then the current time will be used.
 *
 *\li	If 'use_hints' is true, and the view has a hints database, then
 *	it will be searched last.
 *
 *\li	If 'use_cache' is true, and the view has a cache, then it will be
 *	searched.
 *
 *\li	If 'sigrdataset' is not NULL, and there is a SIG rdataset which
 *	covers 'type', then 'sigrdataset' will be bound to it.
 *
 *\li	If the DNS_DBFIND_NOEXACT option is set, then the zonecut returned
 *	(if any) will be the deepest known ancestor of 'name'.
 *
 * Requires:
 *
 *\li	'view' is a valid, frozen view.
 *
 *\li	'name' is valid name.
 *
 *\li	'rdataset' is a valid, disassociated rdataset.
 *
 *\li	'sigrdataset' is NULL, or is a valid, disassociated rdataset.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS				Success.
 *
 *\li	Many other results are possible.
 */

isc_result_t
dns_viewlist_find(dns_viewlist_t *list, const char *name,
		  dns_rdataclass_t rdclass, dns_view_t **viewp);
/*%<
 * Search for a view with name 'name' and class 'rdclass' in 'list'.
 * If found, '*viewp' is (strongly) attached to it.
 *
 * Requires:
 *
 *\li	'viewp' points to a NULL dns_view_t *.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS		A matching view was found.
 *\li	#ISC_R_NOTFOUND		No matching view was found.
 */

isc_result_t
dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name, bool allclasses,
		      dns_rdataclass_t rdclass, dns_zone_t **zonep);

/*%<
 * Search zone with 'name' in view with 'rdclass' in viewlist 'list'
 * If found, zone is returned in *zonep. If allclasses is set rdclass is ignored
 *
 * Returns:
 *\li	#ISC_R_SUCCESS          A matching zone was found.
 *\li	#ISC_R_NOTFOUND         No matching zone was found.
 *\li	#ISC_R_MULTIPLE         Multiple zones with the same name were found.
 */

isc_result_t
dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep);
/*%<
 * Search for the zone 'name' in the zone table of 'view'.
 * If found, 'zonep' is (strongly) attached to it.  There
 * are no partial matches.
 *
 * Requires:
 *
 *\li	'zonep' points to a NULL dns_zone_t *.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		A matching zone was found.
 *\li	#ISC_R_NOTFOUND		No matching zone was found.
 *\li	others			An error occurred.
 */

isc_result_t
dns_view_load(dns_view_t *view, bool stop);

isc_result_t
dns_view_loadnew(dns_view_t *view, bool stop);

isc_result_t
dns_view_asyncload(dns_view_t *view, dns_zt_allloaded_t callback, void *arg);

isc_result_t
dns_view_asyncload2(dns_view_t *view, dns_zt_allloaded_t callback, void *arg,
		    bool newonly);
/*%<
 * Load zones attached to this view.  dns_view_load() loads
 * all zones whose master file has changed since the last
 * load; dns_view_loadnew() loads only zones that have never
 * been loaded.
 *
 * dns_view_asyncload() loads zones asynchronously.  When all zones
 * in the view have finished loading, 'callback' is called with argument
 * 'arg' to inform the caller.
 *
 * If 'stop' is true, stop on the first error and return it.
 * If 'stop' is false (or we are loading asynchronously), ignore errors.
 *
 * Requires:
 *
 *\li	'view' is valid.
 */

isc_result_t
dns_view_gettsig(dns_view_t *view, dns_name_t *keyname,
		 dns_tsigkey_t **keyp);
/*%<
 * Find the TSIG key configured in 'view' with name 'keyname',
 * if any.
 *
 * Requires:
 *\li	keyp points to a NULL dns_tsigkey_t *.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS	A key was found and '*keyp' now points to it.
 *\li	#ISC_R_NOTFOUND	No key was found.
 *\li	others		An error occurred.
 */

isc_result_t
dns_view_getpeertsig(dns_view_t *view, isc_netaddr_t *peeraddr,
		     dns_tsigkey_t **keyp);
/*%<
 * Find the TSIG key configured in 'view' for the server whose
 * address is 'peeraddr', if any.
 *
 * Requires:
 *	keyp points to a NULL dns_tsigkey_t *.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS	A key was found and '*keyp' now points to it.
 *\li	#ISC_R_NOTFOUND	No key was found.
 *\li	others		An error occurred.
 */

isc_result_t
dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg);
/*%<
 * Verifies the signature of a message.
 *
 * Requires:
 *
 *\li	'view' is a valid view.
 *\li	'source' is a valid buffer containing the message
 *\li	'msg' is a valid message
 *
 * Returns:
 *\li	see dns_tsig_verify()
 */

void
dns_view_dialup(dns_view_t *view);
/*%<
 * Perform dialup-time maintenance on the zones of 'view'.
 */

isc_result_t
dns_view_dumpdbtostream(dns_view_t *view, FILE *fp);
/*%<
 * Dump the current state of the view 'view' to the stream 'fp'
 * for purposes of analysis or debugging.
 *
 * Currently the dumped state includes the view's cache; in the future
 * it may also include other state such as the address database.
 * It will not not include authoritative data since it is voluminous and
 * easily obtainable by other means.
 *
 * Requires:
 *
 *\li	'view' is valid.
 *
 *\li	'fp' refers to a file open for writing.
 *
 * Returns:
 * \li	ISC_R_SUCCESS	The cache was successfully dumped.
 * \li	others		An error occurred (see dns_master_dump)
 */

isc_result_t
dns_view_flushcache(dns_view_t *view);
isc_result_t
dns_view_flushcache2(dns_view_t *view, bool fixuponly);
/*%<
 * Flush the view's cache (and ADB).  If 'fixuponly' is true, it only updates
 * the internal reference to the cache DB with omitting actual flush operation.
 * 'fixuponly' is intended to be used for a view that shares a cache with
 * a different view.  dns_view_flushcache() is a backward compatible version
 * that always sets fixuponly to false.
 *
 * Requires:
 * 	'view' is valid.
 *
 * 	No other tasks are executing.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 */

isc_result_t
dns_view_flushnode(dns_view_t *view, dns_name_t *name, bool tree);
/*%<
 * Flush the given name from the view's cache (and optionally ADB/badcache).
 *
 * Flush the given name from the cache, ADB, and bad cache.  If 'tree'
 * is true, also flush all subdomains of 'name'.
 *
 * Requires:
 *\li	'view' is valid.
 *\li	'name' is valid.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *	other returns are failures.
 */

isc_result_t
dns_view_flushname(dns_view_t *view, dns_name_t *name);
/*%<
 * Flush the given name from the view's cache, ADB and badcache.
 * Equivalent to dns_view_flushnode(view, name, false).
 *
 *
 * Requires:
 *\li	'view' is valid.
 *\li	'name' is valid.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *	other returns are failures.
 */

isc_result_t
dns_view_adddelegationonly(dns_view_t *view, dns_name_t *name);
/*%<
 * Add the given name to the delegation only table.
 *
 * Requires:
 *\li	'view' is valid.
 *\li	'name' is valid.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 */

isc_result_t
dns_view_excludedelegationonly(dns_view_t *view, dns_name_t *name);
/*%<
 * Add the given name to be excluded from the root-delegation-only.
 *
 *
 * Requires:
 *\li	'view' is valid.
 *\li	'name' is valid.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 */

bool
dns_view_isdelegationonly(dns_view_t *view, dns_name_t *name);
/*%<
 * Check if 'name' is in the delegation only table or if
 * rootdelonly is set that name is not being excluded.
 *
 * Requires:
 *\li	'view' is valid.
 *\li	'name' is valid.
 *
 * Returns:
 *\li	#true if the name is the table.
 *\li	#false otherwise.
 */

void
dns_view_setrootdelonly(dns_view_t *view, bool value);
/*%<
 * Set the root delegation only flag.
 *
 * Requires:
 *\li	'view' is valid.
 */

bool
dns_view_getrootdelonly(dns_view_t *view);
/*%<
 * Get the root delegation only flag.
 *
 * Requires:
 *\li	'view' is valid.
 */

isc_result_t
dns_view_freezezones(dns_view_t *view, bool freeze);
/*%<
 * Freeze/thaw updates to master zones.
 *
 * Requires:
 * \li	'view' is valid.
 */

void
dns_view_setadbstats(dns_view_t *view, isc_stats_t *stats);
/*%<
 * Set a adb statistics set 'stats' for 'view'.
 *
 * Requires:
 * \li	'view' is valid and is not frozen.
 *
 *\li	stats is a valid statistics supporting adb statistics
 *	(see dns/stats.h).
 */

void
dns_view_getadbstats(dns_view_t *view, isc_stats_t **statsp);
/*%<
 * Get the adb statistics counter set for 'view'.  If a statistics set is
 * set '*statsp' will be attached to the set; otherwise, '*statsp' will be
 * untouched.
 *
 * Requires:
 * \li	'view' is valid and is not frozen.
 *
 *\li	'statsp' != NULL && '*statsp' != NULL
 */

void
dns_view_setresstats(dns_view_t *view, isc_stats_t *stats);
/*%<
 * Set a general resolver statistics counter set 'stats' for 'view'.
 *
 * Requires:
 * \li	'view' is valid and is not frozen.
 *
 *\li	stats is a valid statistics supporting resolver statistics counters
 *	(see dns/stats.h).
 */

void
dns_view_getresstats(dns_view_t *view, isc_stats_t **statsp);
/*%<
 * Get the general statistics counter set for 'view'.  If a statistics set is
 * set '*statsp' will be attached to the set; otherwise, '*statsp' will be
 * untouched.
 *
 * Requires:
 * \li	'view' is valid and is not frozen.
 *
 *\li	'statsp' != NULL && '*statsp' != NULL
 */

void
dns_view_setresquerystats(dns_view_t *view, dns_stats_t *stats);
/*%<
 * Set a statistics counter set of rdata type, 'stats', for 'view'.  Once the
 * statistic set is installed, view's resolver will count outgoing queries
 * per rdata type.
 *
 * Requires:
 * \li	'view' is valid and is not frozen.
 *
 *\li	stats is a valid statistics created by dns_rdatatypestats_create().
 */

void
dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp);
/*%<
 * Get the rdatatype statistics counter set for 'view'.  If a statistics set is
 * set '*statsp' will be attached to the set; otherwise, '*statsp' will be
 * untouched.
 *
 * Requires:
 * \li	'view' is valid and is not frozen.
 *
 *\li	'statsp' != NULL && '*statsp' != NULL
 */

bool
dns_view_iscacheshared(dns_view_t *view);
/*%<
 * Check if the view shares the cache created by another view.
 *
 * Requires:
 * \li	'view' is valid.
 *
 * Returns:
 *\li	#true if the cache is shared.
 *\li	#false otherwise.
 */

isc_result_t
dns_view_initntatable(dns_view_t *view,
		      isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr);
/*%<
 * Initialize the negative trust anchor table for the view.
 *
 * Requires:
 * \li	'view' is valid.
 *
 * Returns:
 *\li	ISC_R_SUCCESS
 *\li	Any other result indicates failure
 */

isc_result_t
dns_view_getntatable(dns_view_t *view, dns_ntatable_t **ntp);
/*%<
 * Get the negative trust anchor table for this view.  Returns
 * ISC_R_NOTFOUND if the table not been initialized for the view.
 *
 * '*ntp' is attached on success; the caller is responsible for
 * detaching it with dns_ntatable_detach().
 *
 * Requires:
 * \li	'view' is valid.
 * \li	'nta' is not NULL and '*nta' is NULL.
 *
 * Returns:
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_NOTFOUND
 */

isc_result_t
dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx);
/*%<
 * Initialize security roots for the view, detaching any previously
 * existing security roots first.  (Note that secroots_priv is
 * NULL until this function is called, so any function using
 * security roots must check that they have been initialized first.
 * One way to do this is use dns_view_getsecroots() and check its
 * return value.)
 *
 * Requires:
 * \li	'view' is valid.
 *
 * Returns:
 *\li	ISC_R_SUCCESS
 *\li	Any other result indicates failure
 */

isc_result_t
dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp);
/*%<
 * Get the security roots for this view.  Returns ISC_R_NOTFOUND if
 * the security roots keytable has not been initialized for the view.
 *
 * '*ktp' is attached on success; the caller is responsible for
 * detaching it with dns_keytable_detach().
 *
 * Requires:
 * \li	'view' is valid.
 * \li	'ktp' is not NULL and '*ktp' is NULL.
 *
 * Returns:
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_NOTFOUND
 */

isc_result_t
dns_view_issecuredomain(dns_view_t *view, dns_name_t *name,
			isc_stdtime_t now, bool checknta, bool *ntap,
			bool *secure_domain);
/*%<
 * Is 'name' at or beneath a trusted key, and not covered by a valid
 * negative trust anchor?  Put answer in '*secure_domain'.
 *
 * If 'checknta' is false, ignore the NTA table in determining
 * whether this is a secure domain. If 'checknta' is not false, and if
 * 'ntap' is non-NULL, then '*ntap' will be updated with true if the
 * name is covered by an NTA.
 *
 * Requires:
 * \li	'view' is valid.
 *
 * Returns:
 *\li	ISC_R_SUCCESS
 *\li	Any other value indicates failure
 */

bool
dns_view_ntacovers(dns_view_t *view, isc_stdtime_t now,
		   dns_name_t *name, dns_name_t *anchor);
/*%<
 * Is there a current negative trust anchor above 'name' and below 'anchor'?
 *
 * Requires:
 * \li	'view' is valid.
 *
 * Returns:
 *\li	ISC_R_TRUE
 *\li	ISC_R_FALSE
 */

void
dns_view_untrust(dns_view_t *view, dns_name_t *keyname,
		 dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx);
/*%<
 * Remove keys that match 'keyname' and 'dnskey' from the views trust
 * anchors.
 *
 * (NOTE: If the configuration specifies that there should be a
 * trust anchor at 'keyname', but no keys are left after this
 * operation, that is an error.  We fail closed, inserting a NULL
 * key so as to prevent validation until a legimitate key has been
 * provided.)
 *
 * Requires:
 * \li	'view' is valid.
 * \li	'keyname' is valid.
 * \li	'mctx' is valid.
 * \li	'dnskey' is valid.
 */

isc_result_t
dns_view_setnewzones(dns_view_t *view, bool allow, void *cfgctx,
		     void (*cfg_destroy)(void **), uint64_t mapsize);
/*%<
 * Set whether or not to allow zones to be created or deleted at runtime.
 *
 * If 'allow' is true, determines the filename into which new zone
 * configuration will be written.  Preserves the configuration context
 * (a pointer to which is passed in 'cfgctx') for use when parsing new
 * zone configuration.  'cfg_destroy' points to a callback routine to
 * destroy the configuration context when the view is destroyed.  (This
 * roundabout method is used in order to avoid libdns having a dependency
 * on libisccfg and libbind9.)
 *
 * If 'allow' is false, removes any existing references to
 * configuration context and frees any memory.
 *
 * Requires:
 * \li 'view' is valid.
 *
 * Returns:
 * \li ISC_R_SUCCESS
 * \li ISC_R_NOSPACE
 */

void
dns_view_restorekeyring(dns_view_t *view);

isc_result_t
dns_view_searchdlz(dns_view_t *view, dns_name_t *name,
		   unsigned int minlabels,
		   dns_clientinfomethods_t *methods,
		   dns_clientinfo_t *clientinfo,
		   dns_db_t **dbp);

/*%<
 * Search through the DLZ database(s) in view->dlz_searched to find
 * one that can answer a query for 'name', using the DLZ driver's
 * findzone method.  If successful, '*dbp' is set to point to the
 * DLZ database.
 *
 * Returns:
 * \li ISC_R_SUCCESS
 * \li ISC_R_NOTFOUND
 *
 * Requires:
 * \li 'view' is valid.
 * \li 'name' is not NULL.
 * \li 'dbp' is not NULL and *dbp is NULL.
 */

uint32_t
dns_view_getfailttl(dns_view_t *view);
/*%<
 * Get the view's servfail-ttl.  zero => no servfail caching.
 *
 * Requires:
 *\li	'view' to be valid.
 */

void
dns_view_setfailttl(dns_view_t *view, uint32_t failttl);
/*%<
 * Set the view's servfail-ttl.  zero => no servfail caching.
 *
 * Requires:
 *\li	'view' to be valid.
 */

isc_result_t
dns_view_saventa(dns_view_t *view);
/*%<
 * Save NTA for names in this view to a file.
 *
 * Requires:
 *\li	'view' to be valid.
 */

isc_result_t
dns_view_loadnta(dns_view_t *view);
/*%<
 * Loads NTA for names in this view from a file.
 *
 * Requires:
 *\li	'view' to be valid.
 */

void
dns_view_setviewcommit(dns_view_t *view);
/*%<
 * Commit dns_zone_setview() calls previously made for all zones in this
 * view.
 *
 * Requires:
 *\li	'view' to be valid.
 */

void
dns_view_setviewrevert(dns_view_t *view);
/*%<
 * Revert dns_zone_setview() calls previously made for all zones in this
 * view.
 *
 * Requires:
 *\li	'view' to be valid.
 */


ISC_LANG_ENDDECLS

#endif /* DNS_VIEW_H */
cache.h000064400000020703150415243030005757 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_CACHE_H
#define DNS_CACHE_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/cache.h
 * \brief
 * Defines dns_cache_t, the cache object.
 *
 * Notes:
 *\li 	A cache object contains DNS data of a single class.
 *	Multiple classes will be handled by creating multiple
 *	views, each with a different class and its own cache.
 *
 * MP:
 *\li	See notes at the individual functions.
 *
 * Reliability:
 *
 * Resources:
 *
 * Security:
 *
 * Standards:
 */

/***
 ***	Imports
 ***/

#include <stdbool.h>

#include <isc/json.h>
#include <isc/lang.h>
#include <isc/stats.h>
#include <isc/stdtime.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

/***
 ***	Functions
 ***/

isc_result_t
dns_cache_create(isc_mem_t *cmctx, isc_taskmgr_t *taskmgr,
		 isc_timermgr_t *timermgr, dns_rdataclass_t rdclass,
		 const char *db_type, unsigned int db_argc, char **db_argv,
		 dns_cache_t **cachep);
isc_result_t
dns_cache_create2(isc_mem_t *cmctx, isc_taskmgr_t *taskmgr,
		  isc_timermgr_t *timermgr, dns_rdataclass_t rdclass,
		  const char *cachename, const char *db_type,
		  unsigned int db_argc, char **db_argv, dns_cache_t **cachep);
isc_result_t
dns_cache_create3(isc_mem_t *cmctx, isc_mem_t *hmctx, isc_taskmgr_t *taskmgr,
		  isc_timermgr_t *timermgr, dns_rdataclass_t rdclass,
		  const char *cachename, const char *db_type,
		  unsigned int db_argc, char **db_argv, dns_cache_t **cachep);
/*%<
 * Create a new DNS cache.
 *
 * dns_cache_create2() will create a named cache.
 *
 * dns_cache_create3() will create a named cache using two separate memory
 * contexts, one for cache data which can be cleaned and a separate one for
 * memory allocated for the heap (which can grow without an upper limit and
 * has no mechanism for shrinking).
 *
 * dns_cache_create() is a backward compatible version that internally
 * specifies an empty cache name and a single memory context.
 *
 * Requires:
 *
 *\li	'cmctx' (and 'hmctx' if applicable) is a valid memory context.
 *
 *\li	'taskmgr' is a valid task manager and 'timermgr' is a valid timer
 * 	manager, or both are NULL.  If NULL, no periodic cleaning of the
 * 	cache will take place.
 *
 *\li	'cachename' is a valid string.  This must not be NULL.
 *
 *\li	'cachep' is a valid pointer, and *cachep == NULL
 *
 * Ensures:
 *
 *\li	'*cachep' is attached to the newly created cache
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 */

void
dns_cache_attach(dns_cache_t *cache, dns_cache_t **targetp);
/*%<
 * Attach *targetp to cache.
 *
 * Requires:
 *
 *\li	'cache' is a valid cache.
 *
 *\li	'targetp' points to a NULL dns_cache_t *.
 *
 * Ensures:
 *
 *\li	*targetp is attached to cache.
 */

void
dns_cache_detach(dns_cache_t **cachep);
/*%<
 * Detach *cachep from its cache.
 *
 * Requires:
 *
 *\li	'cachep' points to a valid cache.
 *
 * Ensures:
 *
 *\li	*cachep is NULL.
 *
 *\li	If '*cachep' is the last reference to the cache,
 *		all resources used by the cache will be freed
 */

void
dns_cache_attachdb(dns_cache_t *cache, dns_db_t **dbp);
/*%<
 * Attach *dbp to the cache's database.
 *
 * Notes:
 *
 *\li	This may be used to get a reference to the database for
 *	the purpose of cache lookups (XXX currently it is also
 * 	the way to add data to the cache, but having a
 * 	separate dns_cache_add() interface instead would allow
 * 	more control over memory usage).
 *	The caller should call dns_db_detach() on the reference
 *	when it is no longer needed.
 *
 * Requires:
 *
 *\li	'cache' is a valid cache.
 *
 *\li	'dbp' points to a NULL dns_db *.
 *
 * Ensures:
 *
 *\li	*dbp is attached to the database.
 */


isc_result_t
dns_cache_setfilename(dns_cache_t *cache, const char *filename);
/*%<
 * If 'filename' is non-NULL, make the cache persistent.
 * The cache's data will be stored in the given file.
 * If 'filename' is NULL, make the cache non-persistent.
 * Files that are no longer used are not unlinked automatically.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *\li	Various file-related failures
 */

isc_result_t
dns_cache_load(dns_cache_t *cache);
/*%<
 * If the cache has a file name, load the cache contents from the file.
 * Previous cache contents are not discarded.
 * If no file name has been set, do nothing and return success.
 *
 * MT:
 *\li	Multiple simultaneous attempts to load or dump the cache
 * 	will be serialized with respect to one another, but
 *	the cache may be read and updated while the dump is
 *	in progress.  Updates performed during loading
 *	may or may not be preserved, and reads may return
 * 	either the old or the newly loaded data.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS
 *  \li    Various failures depending on the database implementation type
 */

isc_result_t
dns_cache_dump(dns_cache_t *cache);
/*%<
 * If the cache has a file name, write the cache contents to disk,
 * overwriting any preexisting file.  If no file name has been set,
 * do nothing and return success.
 *
 * MT:
 *\li	Multiple simultaneous attempts to load or dump the cache
 * 	will be serialized with respect to one another, but
 *	the cache may be read and updated while the dump is
 *	in progress.  Updates performed during the dump may
 * 	or may not be reflected in the dumped file.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS
 *  \li    Various failures depending on the database implementation type
 */

isc_result_t
dns_cache_clean(dns_cache_t *cache, isc_stdtime_t now);
/*%<
 * Force immediate cleaning of the cache, freeing all rdatasets
 * whose TTL has expired as of 'now' and that have no pending
 * references.
 */

void
dns_cache_setcleaninginterval(dns_cache_t *cache, unsigned int interval);
/*%<
 * Set the periodic cache cleaning interval to 'interval' seconds.
 */

unsigned int
dns_cache_getcleaninginterval(dns_cache_t *cache);
/*%<
 * Get the periodic cache cleaning interval to 'interval' seconds.
 */

const char *
dns_cache_getname(dns_cache_t *cache);
/*%<
 * Get the cache name.
 */

void
dns_cache_setcachesize(dns_cache_t *cache, size_t size);
/*%<
 * Set the maximum cache size.  0 means unlimited.
 */

size_t
dns_cache_getcachesize(dns_cache_t *cache);
/*%<
 * Get the maximum cache size.
 */

void
dns_cache_setservestalettl(dns_cache_t *cache, dns_ttl_t ttl);
/*%<
 * Sets the maximum length of time that cached answers may be retained
 * past their normal TTL.  Default value for the library is 0, disabling
 * the use of stale data.
 *
 * Requires:
 *\li	'cache' to be valid.
 */

dns_ttl_t
dns_cache_getservestalettl(dns_cache_t *cache);
/*%<
 * Gets the maximum length of time that cached answers may be kept past
 * normal expiry.
 *
 * Requires:
 *\li	'cache' to be valid.
 */

isc_result_t
dns_cache_flush(dns_cache_t *cache);
/*%<
 * Flushes all data from the cache.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 */

isc_result_t
dns_cache_flushnode(dns_cache_t *cache, dns_name_t *name,
		    bool tree);
/*
 * Flush a given name from the cache.  If 'tree' is true, then
 * also flush all names under 'name'.
 *
 * Requires:
 *\li	'cache' to be valid.
 *\li	'name' to be valid.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *\li	other error returns.
 */

isc_result_t
dns_cache_flushname(dns_cache_t *cache, dns_name_t *name);
/*
 * Flush a given name from the cache.  Equivalent to
 * dns_cache_flushpartial(cache, name, false).
 *
 * Requires:
 *\li	'cache' to be valid.
 *\li	'name' to be valid.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *\li	other error returns.
 */

isc_stats_t *
dns_cache_getstats(dns_cache_t *cache);
/*
 * Return a pointer to the stats collection object for 'cache'
 */

void
dns_cache_dumpstats(dns_cache_t *cache, FILE *fp);
/*
 * Dump cache statistics and status in text to 'fp'
 */

void
dns_cache_updatestats(dns_cache_t *cache, isc_result_t result);
/*
 * Update cache statistics based on result code in 'result'
 */

#ifdef HAVE_LIBXML2
int
dns_cache_renderxml(dns_cache_t *cache, xmlTextWriterPtr writer);
/*
 * Render cache statistics and status in XML for 'writer'.
 */
#endif /* HAVE_LIBXML2 */

#ifdef HAVE_JSON
isc_result_t
dns_cache_renderjson(dns_cache_t *cache, json_object *cstats);
/*
 * Render cache statistics and status in JSON
 */
#endif /* HAVE_JSON */

ISC_LANG_ENDDECLS

#endif /* DNS_CACHE_H */
keytable.h000064400000022366150415243030006523 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_KEYTABLE_H
#define DNS_KEYTABLE_H 1

/*****
 ***** Module Info
 *****/

/*! \file
 * \brief
 * The keytable module provides services for storing and retrieving DNSSEC
 * trusted keys, as well as the ability to find the deepest matching key
 * for a given domain name.
 *
 * MP:
 *\li	The module ensures appropriate synchronization of data structures it
 *	creates and manipulates.
 *
 * Resources:
 *\li	TBS
 *
 * Security:
 *\li	No anticipated impact.
 */

#include <stdbool.h>

#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/rwlock.h>
#include <isc/stdtime.h>

#include <dns/types.h>

#include <dst/dst.h>

ISC_LANG_BEGINDECLS

isc_result_t
dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep);
/*%<
 * Create a keytable.
 *
 * Requires:
 *
 *\li	'mctx' is a valid memory context.
 *
 *\li	keytablep != NULL && *keytablep == NULL
 *
 * Ensures:
 *
 *\li	On success, *keytablep is a valid, empty key table.
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *
 *\li	Any other result indicates failure.
 */


void
dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp);
/*%<
 * Attach *targetp to source.
 *
 * Requires:
 *
 *\li	'source' is a valid keytable.
 *
 *\li	'targetp' points to a NULL dns_keytable_t *.
 *
 * Ensures:
 *
 *\li	*targetp is attached to source.
 */

void
dns_keytable_detach(dns_keytable_t **keytablep);
/*%<
 * Detach *keytablep from its keytable.
 *
 * Requires:
 *
 *\li	'keytablep' points to a valid keytable.
 *
 * Ensures:
 *
 *\li	*keytablep is NULL.
 *
 *\li	If '*keytablep' is the last reference to the keytable,
 *		all resources used by the keytable will be freed
 */

isc_result_t
dns_keytable_add(dns_keytable_t *keytable, bool managed,
		 dst_key_t **keyp);
/*%<
 * Add '*keyp' to 'keytable' (using the name in '*keyp').
 * The value of keynode->managed is set to 'managed'
 *
 * Notes:
 *
 *\li	Ownership of *keyp is transferred to the keytable.
 *\li   If the key already exists in the table, ISC_R_EXISTS is
 *      returned and the new key is freed.
 *
 * Requires:
 *
 *\li	'keytable' points to a valid keytable.
 *
 *\li	keyp != NULL && *keyp is a valid dst_key_t *.
 *
 * Ensures:
 *
 *\li	On success, *keyp == NULL
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_EXISTS
 *
 *\li	Any other result indicates failure.
 */

isc_result_t
dns_keytable_marksecure(dns_keytable_t *keytable, dns_name_t *name);
/*%<
 * Add a null key to 'keytable' for name 'name'.  This marks the
 * name as a secure domain, but doesn't supply any key data to allow the
 * domain to be validated.  (Used when automated trust anchor management
 * has gotten broken by a zone misconfiguration; for example, when the
 * active key has been revoked but the stand-by key was still in its 30-day
 * waiting period for validity.)
 *
 * Notes:
 *
 *\li   If a key already exists in the table, ISC_R_EXISTS is
 *      returned and nothing is done.
 *
 * Requires:
 *
 *\li	'keytable' points to a valid keytable.
 *
 *\li	keyp != NULL && *keyp is a valid dst_key_t *.
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_EXISTS
 *
 *\li	Any other result indicates failure.
 */

isc_result_t
dns_keytable_delete(dns_keytable_t *keytable, dns_name_t *keyname);
/*%<
 * Delete node(s) from 'keytable' matching name 'keyname'
 *
 * Requires:
 *
 *\li	'keytable' points to a valid keytable.
 *
 *\li	'name' is not NULL
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *
 *\li	Any other result indicates failure.
 */

isc_result_t
dns_keytable_deletekeynode(dns_keytable_t *keytable, dst_key_t *dstkey);
/*%<
 * Delete node(s) from 'keytable' containing copies of the key pointed
 * to by 'dstkey'
 *
 * Requires:
 *
 *\li	'keytable' points to a valid keytable.
 *\li	'dstkey' is not NULL
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *
 *\li	Any other result indicates failure.
 */

isc_result_t
dns_keytable_find(dns_keytable_t *keytable, dns_name_t *keyname,
		  dns_keynode_t **keynodep);
/*%<
 * Search for the first instance of a key named 'name' in 'keytable',
 * without regard to keyid and algorithm.  Use dns_keytable_nextkeynode()
 * to find subsequent instances.
 *
 * Requires:
 *
 *\li	'keytable' is a valid keytable.
 *
 *\li	'name' is a valid absolute name.
 *
 *\li	keynodep != NULL && *keynodep == NULL
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_NOTFOUND
 *
 *\li	Any other result indicates an error.
 */

isc_result_t
dns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
			 dns_keynode_t **nextnodep);
/*%<
 * Return for the next key after 'keynode' in 'keytable', without regard to
 * keyid and algorithm.
 *
 * Requires:
 *
 *\li	'keytable' is a valid keytable.
 *
 *\li	'keynode' is a valid keynode.
 *
 *\li	nextnodep != NULL && *nextnodep == NULL
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_NOTFOUND
 *
 *\li	Any other result indicates an error.
 */

isc_result_t
dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name,
			 dns_secalg_t algorithm, dns_keytag_t tag,
			 dns_keynode_t **keynodep);
/*%<
 * Search for a key named 'name', matching 'algorithm' and 'tag' in
 * 'keytable'.  This finds the first instance which matches.  Use
 * dns_keytable_findnextkeynode() to find other instances.
 *
 * Requires:
 *
 *\li	'keytable' is a valid keytable.
 *
 *\li	'name' is a valid absolute name.
 *
 *\li	keynodep != NULL && *keynodep == NULL
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *\li	DNS_R_PARTIALMATCH	the name existed in the keytable.
 *\li	ISC_R_NOTFOUND
 *
 *\li	Any other result indicates an error.
 */

isc_result_t
dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
					     dns_keynode_t **nextnodep);
/*%<
 * Search for the next key with the same properties as 'keynode' in
 * 'keytable' as found by dns_keytable_findkeynode().
 *
 * Requires:
 *
 *\li	'keytable' is a valid keytable.
 *
 *\li	'keynode' is a valid keynode.
 *
 *\li	nextnodep != NULL && *nextnodep == NULL
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_NOTFOUND
 *
 *\li	Any other result indicates an error.
 */

isc_result_t
dns_keytable_finddeepestmatch(dns_keytable_t *keytable, dns_name_t *name,
			      dns_name_t *foundname);
/*%<
 * Search for the deepest match of 'name' in 'keytable'.
 *
 * Requires:
 *
 *\li	'keytable' is a valid keytable.
 *
 *\li	'name' is a valid absolute name.
 *
 *\li	'foundname' is a name with a dedicated buffer.
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_NOTFOUND
 *
 *\li	Any other result indicates an error.
 */

void
dns_keytable_attachkeynode(dns_keytable_t *keytable, dns_keynode_t *source,
			   dns_keynode_t **target);
/*%<
 * Attach a keynode and and increment the active_nodes counter in a
 * corresponding keytable.
 *
 * Requires:
 *
 *\li	'keytable' is a valid keytable.
 *
 *\li	'source' is a valid keynode.
 *
 *\li	'target' is not null and '*target' is null.
 */

void
dns_keytable_detachkeynode(dns_keytable_t *keytable,
			   dns_keynode_t **keynodep);
/*%<
 * Give back a keynode found via dns_keytable_findkeynode().
 *
 * Requires:
 *
 *\li	'keytable' is a valid keytable.
 *
 *\li	*keynodep is a valid keynode returned by a call to
 *	dns_keytable_findkeynode().
 *
 * Ensures:
 *
 *\li	*keynodep == NULL
 */

isc_result_t
dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name,
			    dns_name_t *foundname, bool *wantdnssecp);
/*%<
 * Is 'name' at or beneath a trusted key?
 *
 * Requires:
 *
 *\li	'keytable' is a valid keytable.
 *
 *\li	'name' is a valid absolute name.
 *
 *\li	'foundanme' is NULL or is a pointer to an initialized dns_name_t
 *
 *\li	'*wantsdnssecp' is a valid bool.

 * Ensures:
 *
 *\li	On success, *wantsdnssecp will be true if and only if 'name'
 *	is at or beneath a trusted key.  If 'foundname' is not NULL, then
 *	it will be updated to contain the name of the closest enclosing
 *	trust anchor.
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *
 *\li	Any other result is an error.
 */

isc_result_t
dns_keytable_dump(dns_keytable_t *keytable, FILE *fp);
/*%<
 * Dump the keytable on fp.
 */

isc_result_t
dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **buf);
/*%<
 * Dump the keytable to buffer at 'buf'
 */

dst_key_t *
dns_keynode_key(dns_keynode_t *keynode);
/*%<
 * Get the DST key associated with keynode.
 */

bool
dns_keynode_managed(dns_keynode_t *keynode);
/*%<
 * Is this flagged as a managed key?
 */

isc_result_t
dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target);
/*%<
 * Allocate space for a keynode
 */

void
dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target);
/*%<
 * Attach keynode 'source' to '*target'
 */

void
dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **target);
/*%<
 * Detach a single keynode, without touching any keynodes that
 * may be pointed to by its 'next' pointer
 */

void
dns_keynode_detachall(isc_mem_t *mctx, dns_keynode_t **target);
/*%<
 * Detach a keynode and all its successors.
 */

isc_result_t
dns_keytable_forall(dns_keytable_t *keytable,
		    void (*func)(dns_keytable_t *, dns_keynode_t *, void *),
		    void *arg);
ISC_LANG_ENDDECLS

#endif /* DNS_KEYTABLE_H */
rrl.h000064400000014760150415243030005521 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_RRL_H
#define DNS_RRL_H 1

/*
 * Rate limit DNS responses.
 */

#include <inttypes.h>
#include <stdbool.h>

#include <isc/lang.h>

#include <dns/fixedname.h>
#include <dns/rdata.h>
#include <dns/types.h>

ISC_LANG_BEGINDECLS


/*
 * Memory allocation or other failures.
 */
#define DNS_RRL_LOG_FAIL	ISC_LOG_WARNING
/*
 * dropped or slipped responses.
 */
#define DNS_RRL_LOG_DROP	ISC_LOG_INFO
/*
 * Major events in dropping or slipping.
 */
#define DNS_RRL_LOG_DEBUG1	ISC_LOG_DEBUG(3)
/*
 * Limit computations.
 */
#define DNS_RRL_LOG_DEBUG2	ISC_LOG_DEBUG(4)
/*
 * Even less interesting.
 */
#define DNS_RRL_LOG_DEBUG3	ISC_LOG_DEBUG(9)


#define DNS_RRL_LOG_ERR_LEN	64
#define DNS_RRL_LOG_BUF_LEN	(sizeof("would continue limiting") +	\
				 DNS_RRL_LOG_ERR_LEN +			\
				 sizeof(" responses to ") +		\
				 ISC_NETADDR_FORMATSIZE +		\
				 sizeof("/128 for IN ") +		\
				 DNS_RDATATYPE_FORMATSIZE +		\
				 DNS_NAME_FORMATSIZE)


typedef struct dns_rrl_hash dns_rrl_hash_t;

/*
 * Response types.
 */
typedef enum {
	DNS_RRL_RTYPE_FREE = 0,
	DNS_RRL_RTYPE_QUERY,
	DNS_RRL_RTYPE_REFERRAL,
	DNS_RRL_RTYPE_NODATA,
	DNS_RRL_RTYPE_NXDOMAIN,
	DNS_RRL_RTYPE_ERROR,
	DNS_RRL_RTYPE_ALL,
	DNS_RRL_RTYPE_TCP,
} dns_rrl_rtype_t;

/*
 * A rate limit bucket key.
 * This should be small to limit the total size of the database.
 * The hash of the qname should be wide enough to make the probability
 * of collisions among requests from a single IP address block less than 50%.
 * We need a 32-bit hash value for 10000 qps (e.g. random qnames forged
 * by attacker) to collide with legitimate qnames from the target with
 * probability at most 1%.
 */
#define DNS_RRL_MAX_PREFIX  64
typedef union dns_rrl_key dns_rrl_key_t;
struct dns__rrl_key {
	uint32_t	    ip[DNS_RRL_MAX_PREFIX/32];
	uint32_t	    qname_hash;
	dns_rdatatype_t	    qtype;
	uint8_t         qclass;
	unsigned int	    rtype   :4; /* dns_rrl_rtype_t */
	unsigned int	    ipv6    :1;
};
union dns_rrl_key {
	struct dns__rrl_key s;
	uint16_t	w[sizeof(struct dns__rrl_key)/sizeof(uint16_t)];
};

/*
 * A rate-limit entry.
 * This should be small to limit the total size of the table of entries.
 */
typedef struct dns_rrl_entry dns_rrl_entry_t;
typedef ISC_LIST(dns_rrl_entry_t) dns_rrl_bin_t;
struct dns_rrl_entry {
	ISC_LINK(dns_rrl_entry_t) lru;
	ISC_LINK(dns_rrl_entry_t) hlink;
	dns_rrl_key_t	key;
# define DNS_RRL_RESPONSE_BITS	24
	signed int	responses   :DNS_RRL_RESPONSE_BITS;
# define DNS_RRL_QNAMES_BITS	8
	unsigned int	log_qname   :DNS_RRL_QNAMES_BITS;

# define DNS_RRL_TS_GEN_BITS	2
	unsigned int	ts_gen	    :DNS_RRL_TS_GEN_BITS;
	unsigned int	ts_valid    :1;
# define DNS_RRL_HASH_GEN_BITS	1
	unsigned int	hash_gen    :DNS_RRL_HASH_GEN_BITS;
	unsigned int	logged	    :1;
# define DNS_RRL_LOG_BITS	11
	unsigned int	log_secs    :DNS_RRL_LOG_BITS;

# define DNS_RRL_TS_BITS	12
	unsigned int	ts	    :DNS_RRL_TS_BITS;

# define DNS_RRL_MAX_SLIP	10
	unsigned int	slip_cnt    :4;
};

#define DNS_RRL_MAX_TIME_TRAVEL	5
#define DNS_RRL_FOREVER		(1<<DNS_RRL_TS_BITS)
#define DNS_RRL_MAX_TS		(DNS_RRL_FOREVER - 1)

#define DNS_RRL_MAX_RESPONSES	((1<<(DNS_RRL_RESPONSE_BITS-1))-1)
#define DNS_RRL_MAX_WINDOW	3600
#if DNS_RRL_MAX_WINDOW >= DNS_RRL_MAX_TS
#error "DNS_RRL_MAX_WINDOW is too large"
#endif
#define DNS_RRL_MAX_RATE	1000
#if DNS_RRL_MAX_RATE >= (DNS_RRL_MAX_RESPONSES / DNS_RRL_MAX_WINDOW)
#error "DNS_RRL_MAX_rate is too large"
#endif

#if (1<<DNS_RRL_LOG_BITS) >= DNS_RRL_FOREVER
#error DNS_RRL_LOG_BITS is too big
#endif
#define DNS_RRL_MAX_LOG_SECS	1800
#if DNS_RRL_MAX_LOG_SECS >= (1<<DNS_RRL_LOG_BITS)
#error "DNS_RRL_MAX_LOG_SECS is too large"
#endif
#define DNS_RRL_STOP_LOG_SECS	60
#if DNS_RRL_STOP_LOG_SECS >= (1<<DNS_RRL_LOG_BITS)
#error "DNS_RRL_STOP_LOG_SECS is too large"
#endif


/*
 * A hash table of rate-limit entries.
 */
struct dns_rrl_hash {
	isc_stdtime_t	check_time;
	unsigned int	gen	    :DNS_RRL_HASH_GEN_BITS;
	int		length;
	dns_rrl_bin_t	bins[1];
};

/*
 * A block of rate-limit entries.
 */
typedef struct dns_rrl_block dns_rrl_block_t;
struct dns_rrl_block {
	ISC_LINK(dns_rrl_block_t) link;
	int		size;
	dns_rrl_entry_t	entries[1];
};

/*
 * A rate limited qname buffer.
 */
typedef struct dns_rrl_qname_buf dns_rrl_qname_buf_t;
struct dns_rrl_qname_buf {
	ISC_LINK(dns_rrl_qname_buf_t) link;
	const dns_rrl_entry_t *e;
	unsigned int	    index;
	dns_fixedname_t	    qname;
};

typedef struct dns_rrl_rate dns_rrl_rate_t;
struct dns_rrl_rate {
	int	    r;
	int	    scaled;
	const char  *str;
};

/*
 * Per-view query rate limit parameters and a pointer to database.
 */
typedef struct dns_rrl dns_rrl_t;
struct dns_rrl {
	isc_mutex_t	lock;
	isc_mem_t	*mctx;

	bool	log_only;
	dns_rrl_rate_t	responses_per_second;
	dns_rrl_rate_t	referrals_per_second;
	dns_rrl_rate_t	nodata_per_second;
	dns_rrl_rate_t	nxdomains_per_second;
	dns_rrl_rate_t	errors_per_second;
	dns_rrl_rate_t	all_per_second;
	dns_rrl_rate_t	slip;
	int		window;
	double		qps_scale;
	int		max_entries;

	dns_acl_t	*exempt;

	int		num_entries;

	int		qps_responses;
	isc_stdtime_t	qps_time;
	double		qps;

	unsigned int	probes;
	unsigned int	searches;

	ISC_LIST(dns_rrl_block_t) blocks;
	ISC_LIST(dns_rrl_entry_t) lru;

	dns_rrl_hash_t	*hash;
	dns_rrl_hash_t	*old_hash;
	unsigned int	hash_gen;

	unsigned int	ts_gen;
# define DNS_RRL_TS_BASES   (1<<DNS_RRL_TS_GEN_BITS)
	isc_stdtime_t	ts_bases[DNS_RRL_TS_BASES];

	int		ipv4_prefixlen;
	uint32_t	ipv4_mask;
	int		ipv6_prefixlen;
	uint32_t	ipv6_mask[4];

	isc_stdtime_t	log_stops_time;
	dns_rrl_entry_t	*last_logged;
	int		num_logged;
	int		num_qnames;
	ISC_LIST(dns_rrl_qname_buf_t) qname_free;
# define DNS_RRL_QNAMES	    (1<<DNS_RRL_QNAMES_BITS)
	dns_rrl_qname_buf_t *qnames[DNS_RRL_QNAMES];
};

typedef enum {
	DNS_RRL_RESULT_OK,
	DNS_RRL_RESULT_DROP,
	DNS_RRL_RESULT_SLIP,
} dns_rrl_result_t;

dns_rrl_result_t
dns_rrl(dns_view_t *view,
	const isc_sockaddr_t *client_addr, bool is_tcp,
	dns_rdataclass_t rdclass, dns_rdatatype_t qtype,
	dns_name_t *qname, isc_result_t resp_result, isc_stdtime_t now,
	bool wouldlog, char *log_buf, unsigned int log_buf_len);

void
dns_rrl_view_destroy(dns_view_t *view);

isc_result_t
dns_rrl_init(dns_rrl_t **rrlp, dns_view_t *view, int min_entries);

ISC_LANG_ENDDECLS

#endif /* DNS_RRL_H */
dsdigest.h000064400000003272150415243030006524 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_DSDIGEST_H
#define DNS_DSDIGEST_H 1

/*! \file dns/dsdigest.h */

#include <isc/lang.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

isc_result_t
dns_dsdigest_fromtext(dns_dsdigest_t *dsdigestp, isc_textregion_t *source);
/*%<
 * Convert the text 'source' refers to into a DS/DLV digest type value.
 * The text may contain either a mnemonic digest name or a decimal
 * digest number.
 *
 * Requires:
 *\li	'dsdigestp' is a valid pointer.
 *
 *\li	'source' is a valid text region.
 *
 * Returns:
 *\li	ISC_R_SUCCESS			on success
 *\li	ISC_R_RANGE			numeric type is out of range
 *\li	DNS_R_UNKNOWN			mnemonic type is unknown
 */

isc_result_t
dns_dsdigest_totext(dns_dsdigest_t dsdigest, isc_buffer_t *target);
/*%<
 * Put a textual representation of the DS/DLV digest type 'dsdigest'
 * into 'target'.
 *
 * Requires:
 *\li	'dsdigest' is a valid dsdigest.
 *
 *\li	'target' is a valid text buffer.
 *
 * Ensures,
 *	if the result is success:
 *\li		The used space in 'target' is updated.
 *
 * Returns:
 *\li	ISC_R_SUCCESS			on success
 *\li	ISC_R_NOSPACE			target buffer is too small
 */

#define DNS_DSDIGEST_FORMATSIZE 20
void
dns_dsdigest_format(dns_dsdigest_t typ, char *cp, unsigned int size);
/*%<
 * Wrapper for dns_dsdigest_totext(), writing text into 'cp'
 */

ISC_LANG_ENDDECLS

#endif /* DNS_DSDIGEST_H */
request.h000064400000025624150415243030006413 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_REQUEST_H
#define DNS_REQUEST_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/request.h
 *
 * \brief
 * The request module provides simple request/response services useful for
 * sending SOA queries, DNS Notify messages, and dynamic update requests.
 *
 * MP:
 *\li	The module ensures appropriate synchronization of data structures it
 *	creates and manipulates.
 *
 * Resources:
 *\li	TBS
 *
 * Security:
 *\li	No anticipated impact.
 */

#include <stdbool.h>
#include <isc/lang.h>
#include <isc/event.h>

#include <dns/types.h>

#define DNS_REQUESTOPT_TCP 0x00000001U
#define DNS_REQUESTOPT_CASE 0x00000002U
#define DNS_REQUESTOPT_FIXEDID 0x00000004U
#define DNS_REQUESTOPT_SHARE 0x00000008U

typedef struct dns_requestevent {
	ISC_EVENT_COMMON(struct dns_requestevent);
	isc_result_t result;
	dns_request_t *request;
} dns_requestevent_t;

ISC_LANG_BEGINDECLS

isc_result_t
dns_requestmgr_create(isc_mem_t *mctx, isc_timermgr_t *timermgr,
		      isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr,
		      dns_dispatchmgr_t *dispatchmgr,
		      dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
		      dns_requestmgr_t **requestmgrp);
/*%<
 * Create a request manager.
 *
 * Requires:
 *
 *\li	'mctx' is a valid memory context.
 *
 *\li	'timermgr' is a valid timer manager.
 *
 *\li	'socketmgr' is a valid socket manager.
 *
 *\li	'taskmgr' is a valid task manager.
 *
 *\li	'dispatchv4' is a valid dispatcher with an IPv4 UDP socket, or is NULL.
 *
 *\li	'dispatchv6' is a valid dispatcher with an IPv6 UDP socket, or is NULL.
 *
 *\li	requestmgrp != NULL && *requestmgrp == NULL
 *
 * Ensures:
 *
 *\li	On success, *requestmgrp is a valid request manager.
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *
 *\li	Any other result indicates failure.
 */

void
dns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task,
			    isc_event_t **eventp);
/*%<
 * Send '*eventp' to 'task' when 'requestmgr' has completed shutdown.
 *
 * Notes:
 *
 *\li	It is not safe to detach the last reference to 'requestmgr' until
 *	shutdown is complete.
 *
 * Requires:
 *
 *\li	'requestmgr' is a valid request manager.
 *
 *\li	'task' is a valid task.
 *
 *\li	*eventp is a valid event.
 *
 * Ensures:
 *
 *\li	*eventp == NULL.
 */

void
dns_requestmgr_shutdown(dns_requestmgr_t *requestmgr);
/*%<
 * Start the shutdown process for 'requestmgr'.
 *
 * Notes:
 *
 *\li	This call has no effect if the request manager is already shutting
 *	down.
 *
 * Requires:
 *
 *\li	'requestmgr' is a valid requestmgr.
 */

void
dns_requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp);
/*%<
 *	Attach to the request manager.  dns_requestmgr_shutdown() must not
 *	have been called on 'source' prior to calling dns_requestmgr_attach().
 *
 * Requires:
 *
 *\li	'source' is a valid requestmgr.
 *
 *\li	'targetp' to be non NULL and '*targetp' to be NULL.
 */

void
dns_requestmgr_detach(dns_requestmgr_t **requestmgrp);
/*%<
 *	Detach from the given requestmgr.  If this is the final detach
 *	requestmgr will be destroyed.  dns_requestmgr_shutdown() must
 *	be called before the final detach.
 *
 * Requires:
 *
 *\li	'*requestmgrp' is a valid requestmgr.
 *
 * Ensures:
 *\li	'*requestmgrp' is NULL.
 */

isc_result_t
dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
		   isc_sockaddr_t *address, unsigned int options,
		   dns_tsigkey_t *key,
		   unsigned int timeout, isc_task_t *task,
		   isc_taskaction_t action, void *arg,
		   dns_request_t **requestp);
/*%<
 * Create and send a request.
 *
 * Notes:
 *
 *\li	'message' will be rendered and sent to 'address'.  If the
 *	#DNS_REQUESTOPT_TCP option is set, TCP will be used,
 *	#DNS_REQUESTOPT_SHARE option is set too, connecting TCP
 *	(vs. connected) will be shared too.  The request
 *	will timeout after 'timeout' seconds.
 *
 *\li	If the #DNS_REQUESTOPT_CASE option is set, use case sensitive
 *	compression.
 *
 *\li	When the request completes, successfully, due to a timeout, or
 *	because it was canceled, a completion event will be sent to 'task'.
 *
 * Requires:
 *
 *\li	'message' is a valid DNS message.
 *
 *\li	'address' is a valid sockaddr.
 *
 *\li	'timeout' > 0
 *
 *\li	'task' is a valid task.
 *
 *\li	requestp != NULL && *requestp == NULL
 */

/*% See dns_request_createvia4() */
isc_result_t
dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
		      isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
		      unsigned int options, dns_tsigkey_t *key,
		      unsigned int timeout, isc_task_t *task,
		      isc_taskaction_t action, void *arg,
		      dns_request_t **requestp);

/*% See dns_request_createvia4() */
isc_result_t
dns_request_createvia2(dns_requestmgr_t *requestmgr, dns_message_t *message,
		       isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
		       unsigned int options, dns_tsigkey_t *key,
		       unsigned int timeout, unsigned int udptimeout,
		       isc_task_t *task, isc_taskaction_t action, void *arg,
		       dns_request_t **requestp);

/*% See dns_request_createvia4() */
isc_result_t
dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
		       isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
		       unsigned int options, dns_tsigkey_t *key,
		       unsigned int timeout, unsigned int udptimeout,
		       unsigned int udpretries, isc_task_t *task,
		       isc_taskaction_t action, void *arg,
		       dns_request_t **requestp);

isc_result_t
dns_request_createvia4(dns_requestmgr_t *requestmgr, dns_message_t *message,
		       isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
		       isc_dscp_t dscp, unsigned int options,
		       dns_tsigkey_t *key, unsigned int timeout,
		       unsigned int udptimeout, unsigned int udpretries,
		       isc_task_t *task, isc_taskaction_t action, void *arg,
		       dns_request_t **requestp);
/*%<
 * Create and send a request.
 *
 * Notes:
 *
 *\li	'message' will be rendered and sent to 'address'.  If the
 *	#DNS_REQUESTOPT_TCP option is set, TCP will be used,
 *	#DNS_REQUESTOPT_SHARE option is set too, connecting TCP
 *	(vs. connected) will be shared too.  The request
 *	will timeout after 'timeout' seconds.  UDP requests will be resent
 *	at 'udptimeout' intervals if non-zero or 'udpretries' is non-zero.
 *
 *\li	If the #DNS_REQUESTOPT_CASE option is set, use case sensitive
 *	compression.
 *
 *\li	When the request completes, successfully, due to a timeout, or
 *	because it was canceled, a completion event will be sent to 'task'.
 *
 * Requires:
 *
 *\li	'message' is a valid DNS message.
 *
 *\li	'dstaddr' is a valid sockaddr.
 *
 *\li	'srcaddr' is a valid sockaddr or NULL.
 *
 *\li	'srcaddr' and 'dstaddr' are the same protocol family.
 *
 *\li	'timeout' > 0
 *
 *\li	'task' is a valid task.
 *
 *\li	requestp != NULL && *requestp == NULL
 */

/*% See dns_request_createraw4() */
isc_result_t
dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
		      isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
		      unsigned int options, unsigned int timeout,
		      isc_task_t *task, isc_taskaction_t action, void *arg,
		      dns_request_t **requestp);

/*% See dns_request_createraw4() */
isc_result_t
dns_request_createraw2(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
		       isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
		       unsigned int options, unsigned int timeout,
		       unsigned int udptimeout, isc_task_t *task,
		       isc_taskaction_t action, void *arg,
		       dns_request_t **requestp);

/*% See dns_request_createraw4() */
isc_result_t
dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
		       isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
		       unsigned int options, unsigned int timeout,
		       unsigned int udptimeout, unsigned int udpretries,
		       isc_task_t *task, isc_taskaction_t action, void *arg,
		       dns_request_t **requestp);

isc_result_t
dns_request_createraw4(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
		       isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
		       isc_dscp_t dscp, unsigned int options,
		       unsigned int timeout, unsigned int udptimeout,
		       unsigned int udpretries, isc_task_t *task,
		       isc_taskaction_t action, void *arg,
		       dns_request_t **requestp);
/*!<
 * \brief Create and send a request.
 *
 * Notes:
 *
 *\li	'msgbuf' will be sent to 'destaddr' after setting the id.  If the
 *	#DNS_REQUESTOPT_TCP option is set, TCP will be used,
 *	#DNS_REQUESTOPT_SHARE option is set too, connecting TCP
 *	(vs. connected) will be shared too.  The request
 *	will timeout after 'timeout' seconds.   UDP requests will be resent
 *	at 'udptimeout' intervals if non-zero or if 'udpretries' is not zero.
 *
 *\li	When the request completes, successfully, due to a timeout, or
 *	because it was canceled, a completion event will be sent to 'task'.
 *
 * Requires:
 *
 *\li	'msgbuf' is a valid DNS message in compressed wire format.
 *
 *\li	'destaddr' is a valid sockaddr.
 *
 *\li	'srcaddr' is a valid sockaddr or NULL.
 *
 *\li	'srcaddr' and 'dstaddr' are the same protocol family.
 *
 *\li	'timeout' > 0
 *
 *\li	'task' is a valid task.
 *
 *\li	requestp != NULL && *requestp == NULL
 */

void
dns_request_cancel(dns_request_t *request);
/*%<
 * Cancel 'request'.
 *
 * Requires:
 *
 *\li	'request' is a valid request.
 *
 * Ensures:
 *
 *\li	If the completion event for 'request' has not yet been sent, it
 *	will be sent, and the result code will be ISC_R_CANCELED.
 */

isc_result_t
dns_request_getresponse(dns_request_t *request, dns_message_t *message,
			unsigned int options);
/*%<
 * Get the response to 'request' by filling in 'message'.
 *
 * 'options' is passed to dns_message_parse().  See dns_message_parse()
 * for more details.
 *
 * Requires:
 *
 *\li	'request' is a valid request for which the caller has received the
 *	completion event.
 *
 *\li	The result code of the completion event was #ISC_R_SUCCESS.
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *
 *\li	Any result that dns_message_parse() can return.
 */

bool
dns_request_usedtcp(dns_request_t *request);
/*%<
 * Return whether this query used TCP or not.  Setting #DNS_REQUESTOPT_TCP
 * in the call to dns_request_create() will cause the function to return
 * #true, otherwise the result is based on the query message size.
 *
 * Requires:
 *\li	'request' is a valid request.
 *
 * Returns:
 *\li	true	if TCP was used.
 *\li	false	if UDP was used.
 */

void
dns_request_destroy(dns_request_t **requestp);
/*%<
 * Destroy 'request'.
 *
 * Requires:
 *
 *\li	'request' is a valid request for which the caller has received the
 *	completion event.
 *
 * Ensures:
 *
 *\li	*requestp == NULL
 */

ISC_LANG_ENDDECLS

#endif /* DNS_REQUEST_H */
cert.h000064400000002672150415243030005656 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_CERT_H
#define DNS_CERT_H 1

/*! \file dns/cert.h */

#include <isc/lang.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

isc_result_t
dns_cert_fromtext(dns_cert_t *certp, isc_textregion_t *source);
/*%<
 * Convert the text 'source' refers to into a certificate type.
 * The text may contain either a mnemonic type name or a decimal type number.
 *
 * Requires:
 *\li	'certp' is a valid pointer.
 *
 *\li	'source' is a valid text region.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS			on success
 *\li	#ISC_R_RANGE			numeric type is out of range
 *\li	#DNS_R_UNKNOWN			mnemonic type is unknown
 */

isc_result_t
dns_cert_totext(dns_cert_t cert, isc_buffer_t *target);
/*%<
 * Put a textual representation of certificate type 'cert' into 'target'.
 *
 * Requires:
 *\li	'cert' is a valid cert.
 *
 *\li	'target' is a valid text buffer.
 *
 * Ensures:
 *\li	If the result is success:
 *		The used space in 'target' is updated.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS			on success
 *\li	#ISC_R_NOSPACE			target buffer is too small
 */

ISC_LANG_ENDDECLS

#endif /* DNS_CERT_H */
nsec3.h000064400000017540150415243030005734 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_NSEC3_H
#define DNS_NSEC3_H 1

#include <stdbool.h>

#include <isc/lang.h>
#include <isc/iterated_hash.h>

#include <dns/db.h>
#include <dns/diff.h>
#include <dns/name.h>
#include <dns/rdatastruct.h>
#include <dns/types.h>

#define DNS_NSEC3_SALTSIZE	255
#define DNS_NSEC3_MAXITERATIONS 150U

/*
 * hash = 1, flags =1, iterations = 2, salt length = 1, salt = 255 (max)
 * hash length = 1, hash = 255 (max), bitmap = 8192 + 512 (max)
 */
#define DNS_NSEC3_BUFFERSIZE (6 + 255 + 255 + 8192 + 512)
/*
 * hash = 1, flags = 1, iterations = 2, salt length = 1, salt = 255 (max)
 */
#define DNS_NSEC3PARAM_BUFFERSIZE (5 + 255)

/*
 * Test "unknown" algorithm.  Is mapped to dns_hash_sha1.
 */
#define DNS_NSEC3_UNKNOWNALG ((dns_hash_t)245U)

ISC_LANG_BEGINDECLS

isc_result_t
dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
		     dns_dbnode_t *node, unsigned int hashalg,
		     unsigned int optin, unsigned int iterations,
		     const unsigned char *salt, size_t salt_length,
		     const unsigned char *nexthash, size_t hash_length,
		     unsigned char *buffer, dns_rdata_t *rdata);
/*%<
 * Build the rdata of a NSEC3 record for the data at 'node'.
 * Note: 'node' is not the node where the NSEC3 record will be stored.
 *
 * Requires:
 *	buffer	Points to a temporary buffer of at least
 * 		DNS_NSEC_BUFFERSIZE bytes.
 *	rdata	Points to an initialized dns_rdata_t.
 *
 * Ensures:
 *      *rdata	Contains a valid NSEC3 rdata.  The 'data' member refers
 *		to 'buffer'.
 */

bool
dns_nsec3_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type);
/*%<
 * Determine if a type is marked as present in an NSEC3 record.
 *
 * Requires:
 *	'nsec' points to a valid rdataset of type NSEC3
 */

isc_result_t
dns_nsec3_hashname(dns_fixedname_t *result,
		   unsigned char rethash[NSEC3_MAX_HASH_LENGTH],
		   size_t *hash_length, dns_name_t *name, dns_name_t *origin,
		   dns_hash_t hashalg, unsigned int iterations,
		   const unsigned char *salt, size_t saltlength);
/*%<
 * Make a hashed domain name from an unhashed one. If rethash is not NULL
 * the raw hash is stored there.
 */

unsigned int
dns_nsec3_hashlength(dns_hash_t hash);
/*%<
 * Return the length of the hash produced by the specified algorithm
 * or zero when unknown.
 */

bool
dns_nsec3_supportedhash(dns_hash_t hash);
/*%<
 * Return whether we support this hash algorithm or not.
 */

isc_result_t
dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
		   dns_name_t *name, const dns_rdata_nsec3param_t *nsec3param,
		   dns_ttl_t nsecttl, bool unsecure, dns_diff_t *diff);

isc_result_t
dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version,
		    dns_name_t *name, dns_ttl_t nsecttl,
		    bool unsecure, dns_diff_t *diff);

isc_result_t
dns_nsec3_addnsec3sx(dns_db_t *db, dns_dbversion_t *version,
		     dns_name_t *name, dns_ttl_t nsecttl,
		     bool unsecure, dns_rdatatype_t private,
		     dns_diff_t *diff);
/*%<
 * Add NSEC3 records for 'name', recording the change in 'diff'.
 * Adjust previous NSEC3 records, if any, to reflect the addition.
 * The existing NSEC3 records are removed.
 *
 * dns_nsec3_addnsec3() will only add records to the chain identified by
 * 'nsec3param'.
 *
 * 'unsecure' should be set to reflect if this is a potentially
 * unsecure delegation (no DS record).
 *
 * dns_nsec3_addnsec3s() will examine the NSEC3PARAM RRset to determine which
 * chains to be updated.  NSEC3PARAM records with the DNS_NSEC3FLAG_CREATE
 * will be preferentially chosen over NSEC3PARAM records without
 * DNS_NSEC3FLAG_CREATE set.  NSEC3PARAM records with DNS_NSEC3FLAG_REMOVE
 * set will be ignored by dns_nsec3_addnsec3s().  If DNS_NSEC3FLAG_CREATE
 * is set then the new NSEC3 will have OPTOUT set to match the that in the
 * NSEC3PARAM record otherwise OPTOUT will be inherited from the previous
 * record in the chain.
 *
 * dns_nsec3_addnsec3sx() is similar to dns_nsec3_addnsec3s() but 'private'
 * specifies the type of the private rdataset to be checked in addition to
 * the nsec3param rdataset at the zone apex.
 *
 * Requires:
 *	'db' to be valid.
 *	'version' to be valid or NULL.
 *	'name' to be valid.
 *	'nsec3param' to be valid.
 *	'diff' to be valid.
 */

isc_result_t
dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
		   const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff);

isc_result_t
dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
		    dns_diff_t *diff);

isc_result_t
dns_nsec3_delnsec3sx(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
		     dns_rdatatype_t private, dns_diff_t *diff);
/*%<
 * Remove NSEC3 records for 'name', recording the change in 'diff'.
 * Adjust previous NSEC3 records, if any, to reflect the removal.
 *
 * dns_nsec3_delnsec3() performs the above for the chain identified by
 * 'nsec3param'.
 *
 * dns_nsec3_delnsec3s() examines the NSEC3PARAM RRset in a similar manner
 * to dns_nsec3_addnsec3s().  Unlike dns_nsec3_addnsec3s() updated NSEC3
 * records have the OPTOUT flag preserved.
 *
 * dns_nsec3_delnsec3sx() is similar to dns_nsec3_delnsec3s() but 'private'
 * specifies the type of the private rdataset to be checked in addition to
 * the nsec3param rdataset at the zone apex.
 *
 * Requires:
 *	'db' to be valid.
 *	'version' to be valid or NULL.
 *	'name' to be valid.
 *	'nsec3param' to be valid.
 *	'diff' to be valid.
 */

isc_result_t
dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version,
		 bool complete, bool *answer);

isc_result_t
dns_nsec3_activex(dns_db_t *db, dns_dbversion_t *version,
		  bool complete, dns_rdatatype_t private,
		  bool *answer);
/*%<
 * Check if there are any complete/to be built NSEC3 chains.
 * If 'complete' is true only complete chains will be recognized.
 *
 * dns_nsec3_activex() is similar to dns_nsec3_active() but 'private'
 * specifies the type of the private rdataset to be checked in addition to
 * the nsec3param rdataset at the zone apex.
 *
 * Requires:
 *	'db' to be valid.
 *	'version' to be valid or NULL.
 *	'answer' to be non NULL.
 */

unsigned int
dns_nsec3_maxiterations(void);
/*%<
 * Return the maximum permissible number of NSEC3 iterations.
 */

bool
dns_nsec3param_fromprivate(dns_rdata_t *src, dns_rdata_t *target,
			   unsigned char *buf, size_t buflen);
/*%<
 * Convert a private rdata to a nsec3param rdata.
 *
 * Return true if 'src' could be successfully converted.
 *
 * 'buf' should be at least DNS_NSEC3PARAM_BUFFERSIZE in size.
 */

void
dns_nsec3param_toprivate(dns_rdata_t *src, dns_rdata_t *target,
			 dns_rdatatype_t privatetype,
			 unsigned char *buf, size_t buflen);
/*%<
 * Convert a nsec3param rdata to a private rdata.
 *
 * 'buf' should be at least src->length + 1 in size.
 */

isc_result_t
dns_nsec3param_salttotext(dns_rdata_nsec3param_t *nsec3param, char *dst,
			  size_t dstlen);
/*%<
 * Convert the salt of given NSEC3PARAM RDATA into hex-encoded, NULL-terminated
 * text stored at "dst".
 *
 * Requires:
 *
 *\li 	"dst" to have enough space (as indicated by "dstlen") to hold the
 * 	resulting text and its NULL-terminating byte.
 */

isc_result_t
dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver,
			    dns_zone_t *zone, bool nonsec,
			    dns_diff_t *diff);

/*%<
 * Mark NSEC3PARAM for deletion.
 */

isc_result_t
dns_nsec3_noexistnodata(dns_rdatatype_t type, dns_name_t* name,
			dns_name_t *nsec3name, dns_rdataset_t *nsec3set,
			dns_name_t *zonename, bool *exists,
			bool *data, bool *optout,
			bool *unknown, bool *setclosest,
			bool *setnearest, dns_name_t *closest,
			dns_name_t *nearest, dns_nseclog_t logit, void *arg);

ISC_LANG_ENDDECLS

#endif /* DNS_NSEC3_H */
order.h000064400000003717150415243030006035 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_ORDER_H
#define DNS_ORDER_H 1

/*! \file dns/order.h */

#include <isc/lang.h>
#include <isc/types.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

isc_result_t
dns_order_create(isc_mem_t *mctx, dns_order_t **orderp);
/*%<
 * Create a order object.
 *
 * Requires:
 * \li	'orderp' to be non NULL and '*orderp == NULL'.
 *\li	'mctx' to be valid.
 *
 * Returns:
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_NOMEMORY
 */

isc_result_t
dns_order_add(dns_order_t *order, dns_name_t *name,
	      dns_rdatatype_t rdtype, dns_rdataclass_t rdclass,
	      unsigned int mode);
/*%<
 * Add a entry to the end of the order list.
 *
 * Requires:
 * \li	'order' to be valid.
 *\li	'name' to be valid.
 *\li	'mode' to be one of #DNS_RDATASETATTR_RANDOMIZE,
 *		#DNS_RDATASETATTR_FIXEDORDER or zero (#DNS_RDATASETATTR_CYCLIC).
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 */

unsigned int
dns_order_find(dns_order_t *order, dns_name_t *name,
	       dns_rdatatype_t rdtype, dns_rdataclass_t rdclass);
/*%<
 * Find the first matching entry on the list.
 *
 * Requires:
 *\li	'order' to be valid.
 *\li	'name' to be valid.
 *
 * Returns the mode set by dns_order_add() or zero.
 */

void
dns_order_attach(dns_order_t *source, dns_order_t **target);
/*%<
 * Attach to the 'source' object.
 *
 * Requires:
 * \li	'source' to be valid.
 *\li	'target' to be non NULL and '*target == NULL'.
 */

void
dns_order_detach(dns_order_t **orderp);
/*%<
 * Detach from the object.  Clean up if last this was the last
 * reference.
 *
 * Requires:
 *\li	'*orderp' to be valid.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_ORDER_H */
clientinfo.h000064400000003726150415243030007054 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_CLIENTINFO_H
#define DNS_CLIENTINFO_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/clientinfo.h
 * \brief
 * The DNS clientinfo interface allows libdns to retrieve information
 * about the client from the caller.
 *
 * The clientinfo interface is used by the DNS DB and DLZ interfaces;
 * it allows databases to modify their answers on the basis of information
 * about the client, such as source IP address.
 *
 * dns_clientinfo_t contains a pointer to an opaque structure containing
 * client information in some form.  dns_clientinfomethods_t contains a
 * list of methods which operate on that opaque structure to return
 * potentially useful data.  Both structures also contain versioning
 * information.
 */

/*****
 ***** Imports
 *****/

#include <inttypes.h>

#include <isc/sockaddr.h>
#include <isc/types.h>

ISC_LANG_BEGINDECLS

/*****
 ***** Types
 *****/

#define DNS_CLIENTINFO_VERSION 2
typedef struct dns_clientinfo {
	uint16_t version;
	void *data;
	void *dbversion;
} dns_clientinfo_t;

typedef isc_result_t (*dns_clientinfo_sourceip_t)(dns_clientinfo_t *client,
						  isc_sockaddr_t **addrp);

#define DNS_CLIENTINFOMETHODS_VERSION 2
#define DNS_CLIENTINFOMETHODS_AGE 1

typedef struct dns_clientinfomethods {
	uint16_t version;
	uint16_t age;
	dns_clientinfo_sourceip_t sourceip;
} dns_clientinfomethods_t;

/*****
 ***** Methods
 *****/
void
dns_clientinfomethods_init(dns_clientinfomethods_t *methods,
			   dns_clientinfo_sourceip_t sourceip);

void
dns_clientinfo_init(dns_clientinfo_t *ci, void *data, void *versionp);

ISC_LANG_ENDDECLS

#endif /* DNS_CLIENTINFO_H */
update.h000064400000003165150415243030006201 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_UPDATE_H
#define DNS_UPDATE_H 1

/*! \file dns/update.h */

/***
 ***	Imports
 ***/

#include <inttypes.h>

#include <isc/lang.h>

#include <dns/types.h>
#include <dns/diff.h>

typedef struct {
	void (*func)(void *arg, dns_zone_t *zone, int level,
		     const char *message);
	void *arg;
} dns_update_log_t;

ISC_LANG_BEGINDECLS

/***
 ***	Functions
 ***/

uint32_t
dns_update_soaserial(uint32_t serial, dns_updatemethod_t method);
/*%<
 * Return the next serial number after 'serial', depending on the
 * update method 'method':
 *
 *\li	* dns_updatemethod_increment increments the serial number by one
 *\li	* dns_updatemethod_unixtime sets the serial number to the current
 *	  time (seconds since UNIX epoch) if possible, or increments by one
 *	  if not.
 */

isc_result_t
dns_update_signatures(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
		      dns_dbversion_t *oldver, dns_dbversion_t *newver,
		      dns_diff_t *diff, uint32_t sigvalidityinterval);

isc_result_t
dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
			 dns_dbversion_t *oldver, dns_dbversion_t *newver,
			 dns_diff_t *diff, uint32_t sigvalidityinterval,
			 dns_update_state_t **state);

ISC_LANG_ENDDECLS

#endif /* DNS_UPDATE_H */
types.h000064400000033516150415243030006066 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_TYPES_H
#define DNS_TYPES_H 1

/*! \file dns/types.h
 * \brief
 * Including this file gives you type declarations suitable for use in
 * .h files, which lets us avoid circular type reference problems.
 * \brief
 * To actually use a type or get declarations of its methods, you must
 * include the appropriate .h file too.
 */

#include <stdio.h>
#include <inttypes.h>
#include <stdbool.h>

#include <isc/types.h>

typedef struct dns_acache			dns_acache_t;
typedef struct dns_acacheentry			dns_acacheentry_t;
typedef struct dns_acachestats			dns_acachestats_t;
typedef struct dns_acl 				dns_acl_t;
typedef struct dns_aclelement 			dns_aclelement_t;
typedef struct dns_aclenv			dns_aclenv_t;
typedef struct dns_adb				dns_adb_t;
typedef struct dns_adbaddrinfo			dns_adbaddrinfo_t;
typedef ISC_LIST(dns_adbaddrinfo_t)		dns_adbaddrinfolist_t;
typedef struct dns_adbentry			dns_adbentry_t;
typedef struct dns_adbfind			dns_adbfind_t;
typedef ISC_LIST(dns_adbfind_t)			dns_adbfindlist_t;
typedef struct dns_badcache 			dns_badcache_t;
typedef struct dns_byaddr			dns_byaddr_t;
typedef struct dns_catz_zonemodmethods		dns_catz_zonemodmethods_t;
typedef struct dns_catz_entry_options		dns_catz_options_t;
typedef struct dns_catz_entry			dns_catz_entry_t;
typedef struct dns_catz_zone			dns_catz_zone_t;
typedef struct dns_catz_changed			dns_catz_changed_t;
typedef struct dns_catz_zones			dns_catz_zones_t;
typedef struct dns_client			dns_client_t;
typedef void					dns_clientrestrans_t;
typedef void					dns_clientreqtrans_t;
typedef void					dns_clientupdatetrans_t;
typedef struct dns_cache			dns_cache_t;
typedef uint16_t				dns_cert_t;
typedef struct dns_compress			dns_compress_t;
typedef struct dns_db				dns_db_t;
typedef struct dns_dbimplementation		dns_dbimplementation_t;
typedef struct dns_dbiterator			dns_dbiterator_t;
typedef void					dns_dbload_t;
typedef void					dns_dbnode_t;
typedef struct dns_dbonupdatelistener		dns_dbonupdatelistener_t;
typedef struct dns_dbtable			dns_dbtable_t;
typedef void					dns_dbversion_t;
typedef struct dns_dlzimplementation		dns_dlzimplementation_t;
typedef struct dns_dlzdb			dns_dlzdb_t;
typedef ISC_LIST(dns_dlzdb_t)			dns_dlzdblist_t;
typedef struct dns_dyndbctx			dns_dyndbctx_t;
typedef struct dns_sdlzimplementation		dns_sdlzimplementation_t;
typedef struct dns_decompress			dns_decompress_t;
typedef struct dns_dispatch			dns_dispatch_t;
typedef struct dns_dispatchevent		dns_dispatchevent_t;
typedef struct dns_dispatchlist			dns_dispatchlist_t;
typedef struct dns_dispatchset			dns_dispatchset_t;
typedef struct dns_dispatchmgr			dns_dispatchmgr_t;
typedef struct dns_dispentry			dns_dispentry_t;
typedef struct dns_dns64			dns_dns64_t;
typedef ISC_LIST(dns_dns64_t)			dns_dns64list_t;
typedef struct dns_dnsseckey			dns_dnsseckey_t;
typedef ISC_LIST(dns_dnsseckey_t)		dns_dnsseckeylist_t;
typedef uint8_t					dns_dsdigest_t;
typedef struct dns_dtdata			dns_dtdata_t;
typedef struct dns_dtenv			dns_dtenv_t;
typedef struct dns_dtmsg			dns_dtmsg_t;
typedef uint16_t 				dns_dtmsgtype_t;
typedef struct dns_dumpctx			dns_dumpctx_t;
typedef struct dns_ednsopt			dns_ednsopt_t;
typedef struct dns_fetch			dns_fetch_t;
typedef struct dns_fixedname			dns_fixedname_t;
typedef struct dns_forwarders			dns_forwarders_t;
typedef struct dns_forwarder			dns_forwarder_t;
typedef struct dns_fwdtable			dns_fwdtable_t;
typedef struct dns_geoip_databases		dns_geoip_databases_t;
typedef struct dns_iptable			dns_iptable_t;
typedef uint32_t				dns_iterations_t;
typedef uint16_t				dns_keyflags_t;
typedef struct dns_keynode			dns_keynode_t;
typedef ISC_LIST(dns_keynode_t)			dns_keynodelist_t;
typedef struct dns_keytable			dns_keytable_t;
typedef uint16_t				dns_keytag_t;
typedef struct dns_loadctx			dns_loadctx_t;
typedef struct dns_loadmgr			dns_loadmgr_t;
typedef struct dns_masterrawheader		dns_masterrawheader_t;
typedef uint64_t				dns_masterstyle_flags_t;
typedef struct dns_message			dns_message_t;
typedef uint16_t				dns_messageid_t;
typedef isc_region_t				dns_label_t;
typedef struct dns_lookup			dns_lookup_t;
typedef struct dns_name				dns_name_t;
typedef ISC_LIST(dns_name_t)			dns_namelist_t;
typedef struct dns_nta				dns_nta_t;
typedef struct dns_ntatable			dns_ntatable_t;
typedef uint16_t				dns_opcode_t;
typedef unsigned char				dns_offsets_t[128];
typedef struct dns_order			dns_order_t;
typedef struct dns_peer				dns_peer_t;
typedef struct dns_peerlist			dns_peerlist_t;
typedef struct dns_portlist			dns_portlist_t;
typedef struct dns_rbt				dns_rbt_t;
typedef uint16_t				dns_rcode_t;
typedef struct dns_rdata			dns_rdata_t;
typedef struct dns_rdatacallbacks		dns_rdatacallbacks_t;
typedef uint16_t				dns_rdataclass_t;
typedef struct dns_rdatalist			dns_rdatalist_t;
typedef struct dns_rdataset			dns_rdataset_t;
typedef ISC_LIST(dns_rdataset_t)		dns_rdatasetlist_t;
typedef struct dns_rdatasetiter			dns_rdatasetiter_t;
typedef uint16_t				dns_rdatatype_t;
typedef struct dns_request			dns_request_t;
typedef struct dns_requestmgr			dns_requestmgr_t;
typedef struct dns_resolver			dns_resolver_t;
typedef struct dns_sdbimplementation		dns_sdbimplementation_t;
typedef uint8_t					dns_secalg_t;
typedef uint8_t					dns_secproto_t;
typedef struct dns_signature			dns_signature_t;
typedef struct dns_ssurule			dns_ssurule_t;
typedef struct dns_ssutable			dns_ssutable_t;
typedef struct dns_stats			dns_stats_t;
typedef uint32_t				dns_rdatastatstype_t;
typedef struct dns_tkeyctx			dns_tkeyctx_t;
typedef uint16_t				dns_trust_t;
typedef struct dns_tsec				dns_tsec_t;
typedef struct dns_tsig_keyring			dns_tsig_keyring_t;
typedef struct dns_tsigkey			dns_tsigkey_t;
typedef uint32_t				dns_ttl_t;
typedef struct dns_update_state			dns_update_state_t;
typedef struct dns_validator			dns_validator_t;
typedef struct dns_view				dns_view_t;
typedef ISC_LIST(dns_view_t)			dns_viewlist_t;
typedef struct dns_zone				dns_zone_t;
typedef ISC_LIST(dns_zone_t)			dns_zonelist_t;
typedef struct dns_zonemgr			dns_zonemgr_t;
typedef struct dns_zt				dns_zt_t;
typedef struct dns_ipkeylist 			dns_ipkeylist_t;

/*
 * If we are not using GSSAPI, define the types we use as opaque types here.
 */
#ifndef GSSAPI
typedef struct not_defined_gss_cred_id *gss_cred_id_t;
typedef struct not_defined_gss_ctx *gss_ctx_id_t;
#endif
typedef struct dst_gssapi_signverifyctx dst_gssapi_signverifyctx_t;

typedef enum {
	dns_hash_sha1 = 1
} dns_hash_t;

typedef enum {
	dns_fwdpolicy_none = 0,
	dns_fwdpolicy_first = 1,
	dns_fwdpolicy_only = 2
} dns_fwdpolicy_t;

typedef enum {
	dns_namereln_none = 0,
	dns_namereln_contains = 1,
	dns_namereln_subdomain = 2,
	dns_namereln_equal = 3,
	dns_namereln_commonancestor = 4
} dns_namereln_t;

typedef enum {
	dns_one_answer, dns_many_answers
} dns_transfer_format_t;

typedef enum {
	dns_dbtype_zone = 0, dns_dbtype_cache = 1, dns_dbtype_stub = 3
} dns_dbtype_t;

typedef enum {
	dns_notifytype_no = 0,
	dns_notifytype_yes = 1,
	dns_notifytype_explicit = 2,
	dns_notifytype_masteronly = 3
} dns_notifytype_t;

typedef enum {
	dns_minimal_no = 0,
	dns_minimal_yes = 1,
	dns_minimal_noauth = 2,
	dns_minimal_noauthrec = 3
} dns_minimaltype_t;

typedef enum {
	dns_dialuptype_no = 0,
	dns_dialuptype_yes = 1,
	dns_dialuptype_notify = 2,
	dns_dialuptype_notifypassive = 3,
	dns_dialuptype_refresh = 4,
	dns_dialuptype_passive = 5
} dns_dialuptype_t;

typedef enum {
	dns_masterformat_none = 0,
	dns_masterformat_text = 1,
	dns_masterformat_raw  = 2,
	dns_masterformat_map = 3
} dns_masterformat_t;

typedef enum {
	dns_aaaa_ok = 0,
	dns_aaaa_filter = 1,
	dns_aaaa_break_dnssec = 2
} dns_aaaa_t;

/*
 * These are generated by gen.c.
 */
#include <dns/enumtype.h>	/* Provides dns_rdatatype_t. */
#include <dns/enumclass.h>	/* Provides dns_rdataclass_t. */

/*%
 * rcodes.
 */
enum {
	/*
	 * Standard rcodes.
	 */
	dns_rcode_noerror = 0,
#define dns_rcode_noerror		((dns_rcode_t)dns_rcode_noerror)
	dns_rcode_formerr = 1,
#define dns_rcode_formerr		((dns_rcode_t)dns_rcode_formerr)
	dns_rcode_servfail = 2,
#define dns_rcode_servfail		((dns_rcode_t)dns_rcode_servfail)
	dns_rcode_nxdomain = 3,
#define dns_rcode_nxdomain		((dns_rcode_t)dns_rcode_nxdomain)
	dns_rcode_notimp = 4,
#define dns_rcode_notimp		((dns_rcode_t)dns_rcode_notimp)
	dns_rcode_refused = 5,
#define dns_rcode_refused		((dns_rcode_t)dns_rcode_refused)
	dns_rcode_yxdomain = 6,
#define dns_rcode_yxdomain		((dns_rcode_t)dns_rcode_yxdomain)
	dns_rcode_yxrrset = 7,
#define dns_rcode_yxrrset		((dns_rcode_t)dns_rcode_yxrrset)
	dns_rcode_nxrrset = 8,
#define dns_rcode_nxrrset		((dns_rcode_t)dns_rcode_nxrrset)
	dns_rcode_notauth = 9,
#define dns_rcode_notauth		((dns_rcode_t)dns_rcode_notauth)
	dns_rcode_notzone = 10,
#define dns_rcode_notzone		((dns_rcode_t)dns_rcode_notzone)
	/*
	 * Extended rcodes.
	 */
	dns_rcode_badvers = 16,
#define dns_rcode_badvers		((dns_rcode_t)dns_rcode_badvers)
	dns_rcode_badcookie = 23
#define dns_rcode_badcookie		((dns_rcode_t)dns_rcode_badcookie)
	/*
	 * Update dns_rcodestats_create() and dns_rcodestats_increment()
	 * and this comment if a rcode > dns_rcode_badcookie is assigned.
	 */
	/* Private space [3841..4095] */
};

/*%
 * TSIG errors.
 */
enum {
	dns_tsigerror_badsig = 16,
	dns_tsigerror_badkey = 17,
	dns_tsigerror_badtime = 18,
	dns_tsigerror_badmode = 19,
	dns_tsigerror_badname = 20,
	dns_tsigerror_badalg = 21,
	dns_tsigerror_badtrunc = 22
};

/*%
 * Opcodes.
 */
enum {
	dns_opcode_query = 0,
#define dns_opcode_query		((dns_opcode_t)dns_opcode_query)
	dns_opcode_iquery = 1,
#define dns_opcode_iquery		((dns_opcode_t)dns_opcode_iquery)
	dns_opcode_status = 2,
#define dns_opcode_status		((dns_opcode_t)dns_opcode_status)
	dns_opcode_notify = 4,
#define dns_opcode_notify		((dns_opcode_t)dns_opcode_notify)
	dns_opcode_update = 5		/* dynamic update */
#define dns_opcode_update		((dns_opcode_t)dns_opcode_update)
};

/*%
 * Trust levels.  Must be kept in sync with trustnames[] in masterdump.c.
 */
enum {
	/* Sentinel value; no data should have this trust level. */
	dns_trust_none = 0,
#define dns_trust_none			((dns_trust_t)dns_trust_none)

	/*%
	 * Subject to DNSSEC validation but has not yet been validated
	 * dns_trust_pending_additional (from the additional section).
	 */
	dns_trust_pending_additional = 1,
#define dns_trust_pending_additional \
		 ((dns_trust_t)dns_trust_pending_additional)

	dns_trust_pending_answer = 2,
#define dns_trust_pending_answer	((dns_trust_t)dns_trust_pending_answer)

	/*% Received in the additional section of a response. */
	dns_trust_additional = 3,
#define dns_trust_additional		((dns_trust_t)dns_trust_additional)

	/* Received in a referral response. */
	dns_trust_glue = 4,
#define dns_trust_glue			((dns_trust_t)dns_trust_glue)

	/* Answer from a non-authoritative server */
	dns_trust_answer = 5,
#define dns_trust_answer		((dns_trust_t)dns_trust_answer)

	/*  Received in the authority section as part of an
	    authoritative response */
	dns_trust_authauthority = 6,
#define dns_trust_authauthority		((dns_trust_t)dns_trust_authauthority)

	/* Answer from an authoritative server */
	dns_trust_authanswer = 7,
#define dns_trust_authanswer		((dns_trust_t)dns_trust_authanswer)

	/* Successfully DNSSEC validated */
	dns_trust_secure = 8,
#define dns_trust_secure		((dns_trust_t)dns_trust_secure)

	/* This server is authoritative */
	dns_trust_ultimate = 9
#define dns_trust_ultimate		((dns_trust_t)dns_trust_ultimate)
};

#define DNS_TRUST_PENDING(x)		((x) == dns_trust_pending_answer || \
					 (x) == dns_trust_pending_additional)
#define DNS_TRUST_ADDITIONAL(x)		((x) == dns_trust_additional || \
					 (x) == dns_trust_pending_additional)
#define DNS_TRUST_GLUE(x)		((x) == dns_trust_glue)
#define DNS_TRUST_ANSWER(x)		((x) == dns_trust_answer)


/*%
 * Name checking severities.
 */
typedef enum {
	dns_severity_ignore,
	dns_severity_warn,
	dns_severity_fail
} dns_severity_t;

/*%
 * DNS Serial Number Update Method.
 *
 * \li	_none:		Keep the current serial.
 * \li	_increment:	Add one to the current serial, skipping 0.
 * \li	_unixtime:	Set to the seconds since 00:00 Jan 1, 1970,
 *			if possible.
 * \li	_date:		Set to today's date in YYYYMMDDVV format:
 *                      (Year, Month, Day, Version)
 */
typedef enum {
	dns_updatemethod_none = 0,
	dns_updatemethod_increment,
	dns_updatemethod_unixtime,
	dns_updatemethod_date
} dns_updatemethod_t;

typedef struct {
	const char *string;
	size_t      count;
} dns_indent_t;

typedef enum {
	dns_stale_answer_no,
	dns_stale_answer_yes,
	dns_stale_answer_conf
} dns_stale_answer_t;

/*
 * Functions.
 */
typedef void
(*dns_dumpdonefunc_t)(void *, isc_result_t);

typedef void
(*dns_loaddonefunc_t)(void *, isc_result_t);

typedef void
(*dns_rawdatafunc_t)(dns_zone_t *, dns_masterrawheader_t *);

typedef isc_result_t
(*dns_addrdatasetfunc_t)(void *, dns_name_t *, dns_rdataset_t *);

typedef isc_result_t
(*dns_additionaldatafunc_t)(void *, dns_name_t *, dns_rdatatype_t);

typedef isc_result_t
(*dns_digestfunc_t)(void *, isc_region_t *);

typedef void
(*dns_xfrindone_t)(dns_zone_t *, isc_result_t);

typedef void
(*dns_updatecallback_t)(void *, isc_result_t, dns_message_t *);

typedef int
(*dns_rdatasetorderfunc_t)(const dns_rdata_t *, const void *);

typedef bool
(*dns_checkmxfunc_t)(dns_zone_t *, dns_name_t *, dns_name_t *);

typedef bool
(*dns_checksrvfunc_t)(dns_zone_t *, dns_name_t *, dns_name_t *);

typedef bool
(*dns_checknsfunc_t)(dns_zone_t *, dns_name_t *, dns_name_t *,
		     dns_rdataset_t *, dns_rdataset_t *);

typedef bool
(*dns_isselffunc_t)(dns_view_t *, dns_tsigkey_t *, isc_sockaddr_t *,
		    isc_sockaddr_t *, dns_rdataclass_t, void *);

typedef isc_result_t
(*dns_deserializefunc_t)(void *, FILE *, off_t);

typedef void
(*dns_nseclog_t)(void *val, int , const char *, ...);

#endif /* DNS_TYPES_H */
dnstap.h000064400000022224150415243030006205 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef _DNSTAP_H
#define _DNSTAP_H

/*****
 ***** Module Info
 *****/

/*! \file
 * \brief
 * The dt (dnstap) module provides fast passive logging of DNS messages.
 * Protocol Buffers.  The protobuf schema for Dnstap messages is in the
 * file dnstap.proto, which is compiled to dnstap.pb-c.c and dnstap.pb-c.h.
 */

#include <inttypes.h>
#include <stdbool.h>

#ifdef HAVE_DNSTAP
#include <fstrm.h>
#include <protobuf-c/protobuf-c.h>
#else
struct fstrm_iothr_options;
#endif /* HAVE_DNSTAP */

#include <isc/region.h>
#include <isc/sockaddr.h>
#include <isc/time.h>
#include <isc/types.h>

#include <dns/name.h>
#include <dns/rdataclass.h>
#include <dns/rdatatype.h>
#include <dns/types.h>

/*%
 * Dnstap message types:
 *
 * STUB QUERY: SQ
 * STUB RESPONSE: SR
 * CLIENT QUERY: CQ
 * CLIENT RESPONSE: CR
 * AUTH QUERY: AQ
 * AUTH RESPONSE: AR
 * RESOLVER QUERY: RQ
 * RESOLVER RESPONSE: RR
 * FORWARDER QUERY: FQ
 * FORWARDER RESPONSE: FR
 */

#define DNS_DTTYPE_SQ 0x0001
#define DNS_DTTYPE_SR 0x0002
#define DNS_DTTYPE_CQ 0x0004
#define DNS_DTTYPE_CR 0x0008
#define DNS_DTTYPE_AQ 0x0010
#define DNS_DTTYPE_AR 0x0020
#define DNS_DTTYPE_RQ 0x0040
#define DNS_DTTYPE_RR 0x0080
#define DNS_DTTYPE_FQ 0x0100
#define DNS_DTTYPE_FR 0x0200
#define DNS_DTTYPE_TQ 0x0400
#define DNS_DTTYPE_TR 0x0800

#define DNS_DTTYPE_QUERY \
	(DNS_DTTYPE_SQ|DNS_DTTYPE_CQ|DNS_DTTYPE_AQ|\
	 DNS_DTTYPE_RQ|DNS_DTTYPE_FQ|DNS_DTTYPE_TQ)
#define DNS_DTTYPE_RESPONSE \
	(DNS_DTTYPE_SR|DNS_DTTYPE_CR|DNS_DTTYPE_AR|\
	 DNS_DTTYPE_RR|DNS_DTTYPE_FR|DNS_DTTYPE_TR)
#define DNS_DTTYPE_ALL \
	(DNS_DTTYPE_QUERY|DNS_DTTYPE_RESPONSE)

typedef enum {
	dns_dtmode_none = 0,
	dns_dtmode_file,
	dns_dtmode_unix
} dns_dtmode_t;

typedef struct dns_dthandle dns_dthandle_t;

#ifdef HAVE_DNSTAP
struct dns_dtdata {
	isc_mem_t *mctx;

	void *frame;

	bool query;
	bool tcp;
	dns_dtmsgtype_t type;

	isc_time_t qtime;
	isc_time_t rtime;

	isc_region_t qaddr;
	isc_region_t raddr;

	uint32_t qport;
	uint32_t rport;

	isc_region_t msgdata;
	dns_message_t *msg;

	char namebuf[DNS_NAME_FORMATSIZE];
	char typebuf[DNS_RDATATYPE_FORMATSIZE];
	char classbuf[DNS_RDATACLASS_FORMATSIZE];
};
#endif /* HAVE_DNSTAP */

isc_result_t
dns_dt_create(isc_mem_t *mctx, dns_dtmode_t mode, const char *path,
	      struct fstrm_iothr_options **foptp, dns_dtenv_t **envp);
/*%<
 * Create and initialize the dnstap environment.
 *
 * There should be a single global dnstap environment for the server;
 * copies of it will be attached to each view.
 *
 * Notes:
 *
 *\li	'path' refers to a UNIX domain socket by default. It may
 *	optionally be prepended with "socket:" or "file:". If prepended
 *	with "file:", then dnstap logs are sent to a file instead of a
 *	socket.
 *
 *\li	'*foptp' set the options for fstrm_iothr_init(). '*foptp' must have
 *	have had the number of input queues set and this should be set
 *	to the number of worker threads.  Additionally the queue model
 *	should also be set.  Other options may be set if desired.
 *	If dns_dt_create succeeds the *foptp is set to NULL.
 *
 * Requires:
 *
 *\li	'mctx' is a valid memory context.
 *
 *\li	'path' is a valid C string.
 *
 *\li	'fopt' is non NULL.
 *
 *\li	envp != NULL && *envp == NULL
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *
 *\li	Other errors are possible.
 */

isc_result_t
dns_dt_reopen(dns_dtenv_t *env, int roll);
/*%<
 * Reopens files established by dns_dt_create().
 *
 * If 'roll' is non-negative and 'env->mode' is dns_dtmode_file,
 * then the file is automatically rolled over before reopening.
 * The value of 'roll' indicates the number of backup log files to
 * keep.  If 'roll' is negative, or if 'env->mode' is dns_dtmode_unix,
 * then the channel is simply reopened.
 *
 * Note: dns_dt_reopen() must be called in task exclusive mode.
 *
 * Requires:
 *\li	'env' is a valid dnstap environment.
 */

isc_result_t
dns_dt_setidentity(dns_dtenv_t *env, const char *identity);
isc_result_t
dns_dt_setversion(dns_dtenv_t *env, const char *version);
/*%<
 * Set the "identity" and "version" strings to be sent in dnstap messages.
 *
 * Requires:
 *
 *\li	'env' is a valid dnstap environment.
 */

void
dns_dt_attach(dns_dtenv_t *source, dns_dtenv_t **destp);
/*%<
 * Attach '*destp' to 'source', incrementing the reference counter.
 *
 * Requires:
 *
 *\li	'source' is a valid dnstap environment.
 *
 *\li	'destp' is not NULL and '*destp' is NULL.
 *
 *\li	*destp is attached to source.
 */

void
dns_dt_detach(dns_dtenv_t **envp);
/*%<
 * Detach '*envp', decrementing the reference counter.
 *
 * Requires:
 *
 *\li	'*envp' is a valid dnstap environment.
 *
 * Ensures:
 *
 *\li	'*envp' will be destroyed when the number of references reaches zero.
 *
 *\li	'*envp' is NULL.
 */

isc_result_t
dns_dt_getstats(dns_dtenv_t *env, isc_stats_t **statsp);
/*%<
 * Attach to the stats struct if it exists.
 *
 * Requires:
 *
 *\li	'env' is a valid dnstap environment.
 *
 *\li	'statsp' is non NULL and '*statsp' is NULL.
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *
 *\li	ISC_R_NOTFOUND
 */

void
dns_dt_shutdown(void);
/*%<
 * Shuts down dnstap and frees global resources. This function must only
 * be called immediately before server shutdown.
 */

void
dns_dt_send(dns_view_t *view, dns_dtmsgtype_t msgtype,
	    isc_sockaddr_t *qaddr, isc_sockaddr_t *dstaddr,
	    bool tcp, isc_region_t *zone, isc_time_t *qtime,
	    isc_time_t *rtime, isc_buffer_t *buf);
/*%<
 * Sends a dnstap message to the log, if 'msgtype' is one of the message
 * types represented in 'view->dttypes'.
 *
 * Parameters are: 'qaddr' (query address, i.e, the address of the
 * query initiator); 'raddr' (response address, i.e., the address of
 * the query responder); 'tcp' (boolean indicating whether the transaction
 * was over TCP); 'zone' (the authoritative zone or bailiwick, in
 * uncompressed wire format), 'qtime' and 'rtime' (query and response
 * times; if NULL, they are set to the current time); and 'buf' (the
 * DNS message being logged, in wire format).
 *
 * Requires:
 *
 *\li	'view' is a valid view, and 'view->dtenv' is NULL or is a
 *	valid dnstap environment.
 */

isc_result_t
dns_dt_parse(isc_mem_t *mctx, isc_region_t *src, dns_dtdata_t **destp);
/*%<
 * Converts a raw dnstap frame in 'src' to a parsed dnstap data structure
 * in '*destp'.
 *
 * Requires:
 *\li	'src' is not NULL
 *
 *\li	'destp' is not NULL and '*destp' points to a valid buffer.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS on success
 *
 *\li	Other errors are possible.
 */

isc_result_t
dns_dt_datatotext(dns_dtdata_t *d, isc_buffer_t **dest);
/*%<
 * Converts a parsed dnstap data structure 'd' to text, storing
 * the result in the buffer 'dest'.  If 'dest' points to a dynamically
 * allocated buffer, then it may be reallocated as needed.
 *
 * (XXX: add a 'long_form' option to generate a detailed listing of
 * dnstap data instead * of a one-line summary.)
 *
 * Requires:
 *\li	'd' is not NULL
 *
 *\li	'dest' is not NULL and '*dest' points to a valid buffer.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS on success
 *\li	#ISC_R_NOSPACE if buffer is not dynamic and runs out of space
 *\li	#ISC_R_NOMEMORY if buffer is dynamic but memory could not be allocated
 *
 *\li	Other errors are possible.
 */

void
dns_dtdata_free(dns_dtdata_t **dp);
/*%<
 * Frees the specified dns_dtdata structure and all its members,
 * and sets *dp to NULL.
 */

isc_result_t
dns_dt_open(const char *filename, dns_dtmode_t mode,
	    isc_mem_t *mctx, dns_dthandle_t **handlep);
/*%<
 * Opens a dnstap framestream at 'filename' and stores a pointer to the
 * reader object in a dns_dthandle_t structure.
 *
 * The caller is responsible for allocating the handle structure.
 *
 * (XXX: Currently only file readers are supported, not unix-domain socket
 * readers.)
 *
 * Requires:
 *
 *\li	'filename' is not NULL.
 *
 *\li	'handlep' is not NULL and '*handlep' is NULL.
 *
 *\li	'*mctx' is not a valid memory context.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS on success
 *\li	#ISC_R_NOTIMPLEMENTED if 'mode' is not dns_dtmode_file. (XXX)
 *\li	#ISC_R_NOMEMORY if the fstrm library was unable to allocate a
 *      reader or options structure
 *\li	#ISC_R_FAILURE if 'filename' could not be opened.
 *\li	#DNS_R_BADDNSTAP if 'filename' does not contain a dnstap
 *      framestream.
 */

isc_result_t
dns_dt_getframe(dns_dthandle_t *handle, uint8_t **bufp, size_t *sizep);
/*%<
 * Read a dnstap frame from the framstream reader in 'handle', storing
 * a pointer to it in '*bufp' and its size in '*sizep'.
 *
 * Requires:
 *
 *\li	'handle' is not NULL
 *\li	'bufp' is not NULL
 *\li	'sizep' is not NULL
 *
 * Ensures:
 * \li	if returning ISC_R_SUCCESS then '*bufp' is not NULL
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS on success
 *\li	#ISC_R_NOMORE at the end of the frame stream
 *\li	#ISC_R_FAILURE for any other failure
 */

void
dns_dt_close(dns_dthandle_t **handlep);
/*%<
 * Closes the dnstap file referenced by 'handle'.
 *
 * Requires:
 *
 *\li	'*handlep' is not NULL
 */

#endif /* _DNSTAP_H */
dispatch.h000064400000040053150415243030006513 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_DISPATCH_H
#define DNS_DISPATCH_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/dispatch.h
 * \brief
 * DNS Dispatch Management
 * 	Shared UDP and single-use TCP dispatches for queries and responses.
 *
 * MP:
 *
 *\li     	All locking is performed internally to each dispatch.
 * 	Restrictions apply to dns_dispatch_removeresponse().
 *
 * Reliability:
 *
 * Resources:
 *
 * Security:
 *
 *\li	Depends on the isc_socket_t and dns_message_t for prevention of
 *	buffer overruns.
 *
 * Standards:
 *
 *\li	None.
 */

/***
 *** Imports
 ***/

#include <stdbool.h>

#include <isc/buffer.h>
#include <isc/lang.h>
#include <isc/mutex.h>
#include <isc/socket.h>
#include <isc/types.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

/*%
 * This event is sent to a task when a response comes in.
 * No part of this structure should ever be modified by the caller,
 * other than parts of the buffer.  The holy parts of the buffer are
 * the base and size of the buffer.  All other parts of the buffer may
 * be used.  On event delivery the used region contains the packet.
 *
 * "id" is the received message id,
 *
 * "addr" is the host that sent it to us,
 *
 * "buffer" holds state on the received data.
 *
 * The "free" routine for this event will clean up itself as well as
 * any buffer space allocated from common pools.
 */

struct dns_dispatchevent {
	ISC_EVENT_COMMON(dns_dispatchevent_t);	/*%< standard event common */
	isc_result_t		result;		/*%< result code */
	int32_t		id;		/*%< message id */
	isc_sockaddr_t		addr;		/*%< address recv'd from */
	struct in6_pktinfo	pktinfo;	/*%< reply info for v6 */
	isc_buffer_t	        buffer;		/*%< data buffer */
	uint32_t		attributes;	/*%< mirrored from socket.h */
};

/*%
 * This is a set of one or more dispatches which can be retrieved
 * round-robin fashion.
 */
struct dns_dispatchset {
	isc_mem_t		*mctx;
	dns_dispatch_t		**dispatches;
	int			ndisp;
	int			cur;
	isc_mutex_t		lock;
};

/*@{*/
/*%
 * Attributes for added dispatchers.
 *
 * Values with the mask 0xffff0000 are application defined.
 * Values with the mask 0x0000ffff are library defined.
 *
 * Insane values (like setting both TCP and UDP) are not caught.  Don't
 * do that.
 *
 * _PRIVATE
 *	The dispatcher cannot be shared.
 *
 * _TCP, _UDP
 *	The dispatcher is a TCP or UDP socket.
 *
 * _IPV4, _IPV6
 *	The dispatcher uses an IPv4 or IPv6 socket.
 *
 * _NOLISTEN
 *	The dispatcher should not listen on the socket.
 *
 * _MAKEQUERY
 *	The dispatcher can be used to issue queries to other servers, and
 *	accept replies from them.
 *
 * _RANDOMPORT
 *	Previously used to indicate that the port of a dispatch UDP must be
 *	chosen randomly.  This behavior now always applies and the attribute
 *	is obsoleted.
 *
 * _EXCLUSIVE
 *	A separate socket will be used on-demand for each transaction.
 */
#define DNS_DISPATCHATTR_PRIVATE	0x00000001U
#define DNS_DISPATCHATTR_TCP		0x00000002U
#define DNS_DISPATCHATTR_UDP		0x00000004U
#define DNS_DISPATCHATTR_IPV4		0x00000008U
#define DNS_DISPATCHATTR_IPV6		0x00000010U
#define DNS_DISPATCHATTR_NOLISTEN	0x00000020U
#define DNS_DISPATCHATTR_MAKEQUERY	0x00000040U
#define DNS_DISPATCHATTR_CONNECTED	0x00000080U
#define DNS_DISPATCHATTR_FIXEDID	0x00000100U
#define DNS_DISPATCHATTR_EXCLUSIVE	0x00000200U
/*@}*/

/*
 */
#define DNS_DISPATCHOPT_FIXEDID		0x00000001U

isc_result_t
dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
		       dns_dispatchmgr_t **mgrp);
/*%<
 * Creates a new dispatchmgr object.
 *
 * Requires:
 *\li	"mctx" be a valid memory context.
 *
 *\li	mgrp != NULL && *mgrp == NULL
 *
 *\li	"entropy" may be NULL, in which case an insecure random generator
 *	will be used.  If it is non-NULL, it must be a valid entropy
 *	source.
 *
 * Returns:
 *\li	ISC_R_SUCCESS	-- all ok
 *
 *\li	anything else	-- failure
 */


void
dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp);
/*%<
 * Destroys the dispatchmgr when it becomes empty.  This could be
 * immediately.
 *
 * Requires:
 *\li	mgrp != NULL && *mgrp is a valid dispatchmgr.
 */


void
dns_dispatchmgr_setblackhole(dns_dispatchmgr_t *mgr, dns_acl_t *blackhole);
/*%<
 * Sets the dispatcher's "blackhole list," a list of addresses that will
 * be ignored by all dispatchers created by the dispatchmgr.
 *
 * Requires:
 * \li	mgrp is a valid dispatchmgr
 * \li	blackhole is a valid acl
 */


dns_acl_t *
dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr);
/*%<
 * Gets a pointer to the dispatcher's current blackhole list,
 * without incrementing its reference count.
 *
 * Requires:
 *\li 	mgr is a valid dispatchmgr
 * Returns:
 *\li	A pointer to the current blackhole list, or NULL.
 */

void
dns_dispatchmgr_setblackportlist(dns_dispatchmgr_t *mgr,
				 dns_portlist_t *portlist);
/*%<
 * This function is deprecated.  Use dns_dispatchmgr_setavailports() instead.
 *
 * Requires:
 *\li	mgr is a valid dispatchmgr
 */

dns_portlist_t *
dns_dispatchmgr_getblackportlist(dns_dispatchmgr_t *mgr);
/*%<
 * This function is deprecated and always returns NULL.
 *
 * Requires:
 *\li	mgr is a valid dispatchmgr
 */

isc_result_t
dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
			      isc_portset_t *v6portset);
/*%<
 * Sets a list of UDP ports that can be used for outgoing UDP messages.
 *
 * Requires:
 *\li	mgr is a valid dispatchmgr
 *\li	v4portset is NULL or a valid port set
 *\li	v6portset is NULL or a valid port set
 */

void
dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats);
/*%<
 * Sets statistics counter for the dispatchmgr.  This function is expected to
 * be called only on zone creation (when necessary).
 * Once installed, it cannot be removed or replaced.  Also, there is no
 * interface to get the installed stats from the zone; the caller must keep the
 * stats to reference (e.g. dump) it later.
 *
 * Requires:
 *\li	mgr is a valid dispatchmgr with no managed dispatch.
 *\li	stats is a valid statistics supporting resolver statistics counters
 *	(see dns/stats.h).
 */

isc_result_t
dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
		    isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr,
		    unsigned int buffersize,
		    unsigned int maxbuffers, unsigned int maxrequests,
		    unsigned int buckets, unsigned int increment,
		    unsigned int attributes, unsigned int mask,
		    dns_dispatch_t **dispp);

isc_result_t
dns_dispatch_getudp_dup(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
		    isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr,
		    unsigned int buffersize,
		    unsigned int maxbuffers, unsigned int maxrequests,
		    unsigned int buckets, unsigned int increment,
		    unsigned int attributes, unsigned int mask,
		    dns_dispatch_t **dispp, dns_dispatch_t *dup);
/*%<
 * Attach to existing dns_dispatch_t if one is found with dns_dispatchmgr_find,
 * otherwise create a new UDP dispatch.
 *
 * Requires:
 *\li	All pointer parameters be valid for their respective types.
 *
 *\li	dispp != NULL && *disp == NULL
 *
 *\li	512 <= buffersize <= 64k
 *
 *\li	maxbuffers > 0
 *
 *\li	buckets < 2097169
 *
 *\li	increment > buckets
 *
 *\li	(attributes & DNS_DISPATCHATTR_TCP) == 0
 *
 * Returns:
 *\li	ISC_R_SUCCESS	-- success.
 *
 *\li	Anything else	-- failure.
 */

isc_result_t
dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
		       isc_taskmgr_t *taskmgr, unsigned int buffersize,
		       unsigned int maxbuffers, unsigned int maxrequests,
		       unsigned int buckets, unsigned int increment,
		       unsigned int attributes, dns_dispatch_t **dispp);
isc_result_t
dns_dispatch_createtcp2(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
			isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr,
			isc_sockaddr_t *destaddr, unsigned int buffersize,
			unsigned int maxbuffers, unsigned int maxrequests,
			unsigned int buckets, unsigned int increment,
			unsigned int attributes, dns_dispatch_t **dispp);
/*%<
 * Create a new dns_dispatch and attach it to the provided isc_socket_t.
 *
 * For all dispatches, "buffersize" is the maximum packet size we will
 * accept.
 *
 * "maxbuffers" and "maxrequests" control the number of buffers in the
 * overall system and the number of buffers which can be allocated to
 * requests.
 *
 * "buckets" is the number of buckets to use, and should be prime.
 *
 * "increment" is used in a collision avoidance function, and needs to be
 * a prime > buckets, and not 2.
 *
 * Requires:
 *
 *\li	mgr is a valid dispatch manager.
 *
 *\li	sock is a valid.
 *
 *\li	task is a valid task that can be used internally to this dispatcher.
 *
 * \li	512 <= buffersize <= 64k
 *
 *\li	maxbuffers > 0.
 *
 *\li	maxrequests <= maxbuffers.
 *
 *\li	buckets < 2097169 (the next prime after 65536 * 32)
 *
 *\li	increment > buckets (and prime).
 *
 *\li	attributes includes #DNS_DISPATCHATTR_TCP and does not include
 *	#DNS_DISPATCHATTR_UDP.
 *
 * Returns:
 *\li	ISC_R_SUCCESS	-- success.
 *
 *\li	Anything else	-- failure.
 */

void
dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp);
/*%<
 * Attach to a dispatch handle.
 *
 * Requires:
 *\li	disp is valid.
 *
 *\li	dispp != NULL && *dispp == NULL
 */

void
dns_dispatch_detach(dns_dispatch_t **dispp);
/*%<
 * Detaches from the dispatch.
 *
 * Requires:
 *\li	dispp != NULL and *dispp be a valid dispatch.
 */

void
dns_dispatch_starttcp(dns_dispatch_t *disp);
/*%<
 * Start processing of a TCP dispatch once the socket connects.
 *
 * Requires:
 *\li	'disp' is valid.
 */

isc_result_t
dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, isc_sockaddr_t *destaddr,
		    isc_sockaddr_t *localaddr, dns_dispatch_t **dispp);
isc_result_t
dns_dispatch_gettcp2(dns_dispatchmgr_t *mgr, isc_sockaddr_t *destaddr,
		     isc_sockaddr_t *localaddr, bool *connected,
		     dns_dispatch_t **dispp);
/*
 * Attempt to connect to a existing TCP connection (connection completed
 * for dns_dispatch_gettcp()).
 */


isc_result_t
dns_dispatch_addresponse3(dns_dispatch_t *disp, unsigned int options,
			  isc_sockaddr_t *dest, isc_task_t *task,
			  isc_taskaction_t action, void *arg,
			  uint16_t *idp, dns_dispentry_t **resp,
			  isc_socketmgr_t *sockmgr);

isc_result_t
dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
			  isc_task_t *task, isc_taskaction_t action, void *arg,
			  uint16_t *idp, dns_dispentry_t **resp,
			  isc_socketmgr_t *sockmgr);

isc_result_t
dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
			 isc_task_t *task, isc_taskaction_t action, void *arg,
			 uint16_t *idp, dns_dispentry_t **resp);
/*%<
 * Add a response entry for this dispatch.
 *
 * "*idp" is filled in with the assigned message ID, and *resp is filled in
 * to contain the magic token used to request event flow stop.
 *
 * Arranges for the given task to get a callback for response packets.  When
 * the event is delivered, it must be returned using dns_dispatch_freeevent()
 * or through dns_dispatch_removeresponse() for another to be delivered.
 *
 * Requires:
 *\li	"idp" be non-NULL.
 *
 *\li	"task" "action" and "arg" be set as appropriate.
 *
 *\li	"dest" be non-NULL and valid.
 *
 *\li	"resp" be non-NULL and *resp be NULL
 *
 *\li	"sockmgr" be NULL or a valid socket manager.  If 'disp' has
 *	the DNS_DISPATCHATTR_EXCLUSIVE attribute, this must not be NULL,
 *	which also means dns_dispatch_addresponse() cannot be used.
 *
 * Ensures:
 *
 *\li	&lt;id, dest> is a unique tuple.  That means incoming messages
 *	are identifiable.
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS		-- all is well.
 *\li	ISC_R_NOMEMORY		-- memory could not be allocated.
 *\li	ISC_R_NOMORE		-- no more message ids can be allocated
 *				   for this destination.
 */


void
dns_dispatch_removeresponse(dns_dispentry_t **resp,
			    dns_dispatchevent_t **sockevent);
/*%<
 * Stops the flow of responses for the provided id and destination.
 * If "sockevent" is non-NULL, the dispatch event and associated buffer is
 * also returned to the system.
 *
 * Requires:
 *\li	"resp" != NULL and "*resp" contain a value previously allocated
 *	by dns_dispatch_addresponse();
 *
 *\li	May only be called from within the task given as the 'task'
 * 	argument to dns_dispatch_addresponse() when allocating '*resp'.
 */

isc_socket_t *
dns_dispatch_getentrysocket(dns_dispentry_t *resp);

isc_socket_t *
dns_dispatch_getsocket(dns_dispatch_t *disp);
/*%<
 * Return the socket associated with this dispatcher.
 *
 * Requires:
 *\li	disp is valid.
 *
 * Returns:
 *\li	The socket the dispatcher is using.
 */

isc_result_t
dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp);
/*%<
 * Return the local address for this dispatch.
 * This currently only works for dispatches using UDP sockets.
 *
 * Requires:
 *\li	disp is valid.
 *\li	addrp to be non null.
 *
 * Returns:
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_NOTIMPLEMENTED
 */

void
dns_dispatch_cancel(dns_dispatch_t *disp);
/*%<
 * cancel outstanding clients
 *
 * Requires:
 *\li	disp is valid.
 */

unsigned int
dns_dispatch_getattributes(dns_dispatch_t *disp);
/*%<
 * Return the attributes (DNS_DISPATCHATTR_xxx) of this dispatch.  Only the
 * non-changeable attributes are expected to be referenced by the caller.
 *
 * Requires:
 *\li	disp is valid.
 */

void
dns_dispatch_changeattributes(dns_dispatch_t *disp,
			      unsigned int attributes, unsigned int mask);
/*%<
 * Set the bits described by "mask" to the corresponding values in
 * "attributes".
 *
 * That is:
 *
 * \code
 *	new = (old & ~mask) | (attributes & mask)
 * \endcode
 *
 * This function has a side effect when #DNS_DISPATCHATTR_NOLISTEN changes.
 * When the flag becomes off, the dispatch will start receiving on the
 * corresponding socket.  When the flag becomes on, receive events on the
 * corresponding socket will be canceled.
 *
 * Requires:
 *\li	disp is valid.
 *
 *\li	attributes are reasonable for the dispatch.  That is, setting the UDP
 *	attribute on a TCP socket isn't reasonable.
 */

void
dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event);
/*%<
 * Inform the dispatcher of a socket receive.  This is used for sockets
 * shared between dispatchers and clients.  If the dispatcher fails to copy
 * or send the event, nothing happens.
 *
 * If the attribute DNS_DISPATCHATTR_NOLISTEN is not set, then
 * the dispatch is already handling a recv; return immediately.
 *
 * Requires:
 *\li 	disp is valid, and the attribute DNS_DISPATCHATTR_NOLISTEN is set.
 * 	event != NULL
 */

dns_dispatch_t *
dns_dispatchset_get(dns_dispatchset_t *dset);
/*%<
 * Retrieve the next dispatch from dispatch set 'dset', and increment
 * the round-robin counter.
 *
 * Requires:
 *\li 	dset != NULL
 */

isc_result_t
dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr,
		       isc_taskmgr_t *taskmgr, dns_dispatch_t *source,
		       dns_dispatchset_t **dsetp, int n);
/*%<
 * Given a valid dispatch 'source', create a dispatch set containing
 * 'n' UDP dispatches, with the remainder filled out by clones of the
 * source.
 *
 * Requires:
 *\li 	source is a valid UDP dispatcher
 *\li 	dsetp != NULL, *dsetp == NULL
 */

void
dns_dispatchset_cancelall(dns_dispatchset_t *dset, isc_task_t *task);
/*%<
 * Cancel socket operations for the dispatches in 'dset'.
 */

void
dns_dispatchset_destroy(dns_dispatchset_t **dsetp);
/*%<
 * Dereference all the dispatches in '*dsetp', free the dispatchset
 * memory, and set *dsetp to NULL.
 *
 * Requires:
 *\li 	dset is valid
 */

void
dns_dispatch_setdscp(dns_dispatch_t *disp, isc_dscp_t dscp);
isc_dscp_t
dns_dispatch_getdscp(dns_dispatch_t *disp);
/*%<
 * Set/get the DSCP value to be used when sending responses to clients,
 * as defined in the "listen-on" or "listen-on-v6" statements.
 *
 * Requires:
 *\li	disp is valid.
 */

isc_result_t
dns_dispatch_getnext(dns_dispentry_t *resp, dns_dispatchevent_t **sockevent);
/*%<
 * Free the sockevent and trigger the sending of the next item off the
 * dispatch queue if present.
 *
 * Requires:
 *\li	resp is valid
 *\li	*sockevent to be valid
 */

ISC_LANG_ENDDECLS

#endif /* DNS_DISPATCH_H */
dyndb.h000064400000011343150415243030006014 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_DYNDB_H
#define DNS_DYNDB_H

#include <stdbool.h>

#include <isc/types.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

/*!
 * \brief
 * Context for initializing a dyndb module.
 *
 * This structure passes global server data to which a dyndb
 * module will need access -- the server memory context, hash
 * initializer, log context, etc.  The structure doesn't persist
 * beyond configuring the dyndb module. The module's register function
 * should attach to all reference-counted variables and its destroy
 * function should detach from them.
 */
struct dns_dyndbctx {
	unsigned int	magic;
	const void	*hashinit;
	isc_mem_t	*mctx;
	isc_log_t	*lctx;
	dns_view_t	*view;
	dns_zonemgr_t	*zmgr;
	isc_task_t	*task;
	isc_timermgr_t	*timermgr;
	bool	*refvar;
};

#define DNS_DYNDBCTX_MAGIC	ISC_MAGIC('D', 'd', 'b', 'c')
#define DNS_DYNDBCTX_VALID(d)	ISC_MAGIC_VALID(d, DNS_DYNDBCTX_MAGIC)

/*
 * API version
 *
 * When the API changes, increment DNS_DYNDB_VERSION. If the
 * change is backward-compatible (e.g., adding a new function call
 * but not changing or removing an old one), increment DNS_DYNDB_AGE;
 * if not, set DNS_DYNDB_AGE to 0.
 */
#ifndef DNS_DYNDB_VERSION
#define DNS_DYNDB_VERSION 1
#define DNS_DYNDB_AGE 0
#endif

typedef isc_result_t dns_dyndb_register_t(isc_mem_t *mctx,
					  const char *name,
					  const char *parameters,
					  const char *file,
					  unsigned long line,
					  const dns_dyndbctx_t *dctx,
					  void **instp);
/*%
 * Called when registering a new driver instance. 'name' must be unique.
 * 'parameters' contains the driver configuration text. 'dctx' is the
 * initialization context set up in dns_dyndb_createctx().
 *
 * '*instp' must be set to the driver instance handle if the function
 * is successful.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *\li	Other errors are possible
 */

typedef void dns_dyndb_destroy_t(void **instp);
/*%
 * Destroy a driver instance. Dereference any reference-counted
 * variables passed in 'dctx' and 'inst' in the register function.
 *
 * \c *instp must be set to \c NULL by the function before it returns.
 */

typedef int dns_dyndb_version_t(unsigned int *flags);
/*%
 * Return the API version number a dyndb module was compiled with.
 *
 * If the returned version number is no greater than than
 * DNS_DYNDB_VERSION, and no less than DNS_DYNDB_VERSION - DNS_DYNDB_AGE,
 * then the module is API-compatible with named.
 *
 * 'flags' is currently unused and may be NULL, but could be used in
 * the future to pass back driver capabilities or other information.
 */

isc_result_t
dns_dyndb_load(const char *libname, const char *name, const char *parameters,
	       const char *file, unsigned long line, isc_mem_t *mctx,
	       const dns_dyndbctx_t *dctx);
/*%
 * Load a dyndb module.
 *
 * This loads a dyndb module using dlopen() or equivalent, calls its register
 * function (see dns_dyndb_register_t above), and if successful, adds
 * the instance handle to a list of dyndb instances so it can be cleaned
 * up later.
 *
 * 'file' and 'line' can be used to indicate the name of the file and
 * the line number from which the parameters were taken, so that logged
 * error messages, if any, will display the correct locations.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *\li	Other errors are possible
 */

void
dns_dyndb_cleanup(bool exiting);
/*%
 * Shut down and destroy all running dyndb modules.
 *
 * 'exiting' indicates whether the server is shutting down,
 * as opposed to merely being reconfigured.
 */

isc_result_t
dns_dyndb_createctx(isc_mem_t *mctx, const void *hashinit, isc_log_t *lctx,
		    dns_view_t *view, dns_zonemgr_t *zmgr, isc_task_t *task,
		    isc_timermgr_t *tmgr, dns_dyndbctx_t **dctxp);
/*%
 * Create a dyndb initialization context structure, with
 * pointers to structures in the server that the dyndb module will
 * need to access (view, zone manager, memory context, hash initializer,
 * etc). This structure is expected to last only until all dyndb
 * modules have been loaded and initialized; after that it will be
 * destroyed with dns_dyndb_destroyctx().
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *\li	Other errors are possible
 */

void
dns_dyndb_destroyctx(dns_dyndbctx_t **dctxp);
/*%
 * Destroys a dyndb initialization context structure; all
 * reference-counted members are detached and the structure is freed.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_DYNDB_H */
acl.h000064400000016112150415243030005452 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_ACL_H
#define DNS_ACL_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/acl.h
 * \brief
 * Address match list handling.
 */

/***
 *** Imports
 ***/

#include <stdbool.h>

#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/netaddr.h>
#include <isc/refcount.h>

#if defined(HAVE_GEOIP) || defined(HAVE_GEOIP2)
#include <dns/geoip.h>
#endif
#include <dns/name.h>
#include <dns/types.h>
#include <dns/iptable.h>

/***
 *** Types
 ***/

typedef enum {
	dns_aclelementtype_ipprefix,
	dns_aclelementtype_keyname,
	dns_aclelementtype_nestedacl,
	dns_aclelementtype_localhost,
	dns_aclelementtype_localnets,
#if defined(HAVE_GEOIP) || defined(HAVE_GEOIP2)
	dns_aclelementtype_geoip,
#endif /* HAVE_GEOIP || HAVE_GEOIP2 */
	dns_aclelementtype_any
} dns_aclelementtype_t;

typedef struct dns_aclipprefix dns_aclipprefix_t;

struct dns_aclipprefix {
	isc_netaddr_t address; /* IP4/IP6 */
	unsigned int prefixlen;
};

struct dns_aclelement {
	dns_aclelementtype_t	type;
	bool		negative;
	dns_name_t		keyname;
#if defined(HAVE_GEOIP) || defined(HAVE_GEOIP2)
	dns_geoip_elem_t	geoip_elem;
#endif /* HAVE_GEOIP || HAVE_GEOIP2 */
	dns_acl_t		*nestedacl;
	int			node_num;
};

#define dns_acl_node_count(acl) acl->iptable->radix->num_added_node

struct dns_acl {
	unsigned int		magic;
	isc_mem_t		*mctx;
	isc_refcount_t		refcount;
	dns_iptable_t		*iptable;
	dns_aclelement_t	*elements;
	bool			has_negatives;
	unsigned int		alloc;		/*%< Elements allocated */
	unsigned int		length;		/*%< Elements initialized */
	char			*name;		/*%< Temporary use only */
	ISC_LINK(dns_acl_t)	nextincache;	/*%< Ditto */
};

struct dns_aclenv {
	dns_acl_t *localhost;
	dns_acl_t *localnets;
	bool match_mapped;
#if defined(HAVE_GEOIP) || defined(HAVE_GEOIP2)
	dns_geoip_databases_t *geoip;
	bool geoip_use_ecs;
#endif
};

#define DNS_ACL_MAGIC		ISC_MAGIC('D','a','c','l')
#define DNS_ACL_VALID(a)	ISC_MAGIC_VALID(a, DNS_ACL_MAGIC)

/***
 *** Functions
 ***/

ISC_LANG_BEGINDECLS

isc_result_t
dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target);
/*%<
 * Create a new ACL, including an IP table and an array with room
 * for 'n' ACL elements.  The elements are uninitialized and the
 * length is 0.
 */

isc_result_t
dns_acl_any(isc_mem_t *mctx, dns_acl_t **target);
/*%<
 * Create a new ACL that matches everything.
 */

isc_result_t
dns_acl_none(isc_mem_t *mctx, dns_acl_t **target);
/*%<
 * Create a new ACL that matches nothing.
 */

bool
dns_acl_isany(dns_acl_t *acl);
/*%<
 * Test whether ACL is set to "{ any; }"
 */

bool
dns_acl_isnone(dns_acl_t *acl);
/*%<
 * Test whether ACL is set to "{ none; }"
 */

isc_result_t
dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, bool pos);
/*%<
 * Merge the contents of one ACL into another.  Call dns_iptable_merge()
 * for the IP tables, then concatenate the element arrays.
 *
 * If pos is set to false, then the nested ACL is to be negated.  This
 * means reverse the sense of each *positive* element or IP table node,
 * but leave negatives alone, so as to prevent a double-negative causing
 * an unexpected positive match in the parent ACL.
 */

void
dns_acl_attach(dns_acl_t *source, dns_acl_t **target);
/*%<
 * Attach to acl 'source'.
 *
 * Requires:
 *\li	'source' to be a valid acl.
 *\li	'target' to be non NULL and '*target' to be NULL.
 */

void
dns_acl_detach(dns_acl_t **aclp);
/*%<
 * Detach the acl. On final detach the acl must not be linked on any
 * list.
 *
 * Requires:
 *\li	'*aclp' to be a valid acl.
 *
 * Insists:
 *\li	'*aclp' is not linked on final detach.
 */

bool
dns_acl_isinsecure(const dns_acl_t *a);
/*%<
 * Return #true iff the acl 'a' is considered insecure, that is,
 * if it contains IP addresses other than those of the local host.
 * This is intended for applications such as printing warning
 * messages for suspect ACLs; it is not intended for making access
 * control decisions.  We make no guarantee that an ACL for which
 * this function returns #false is safe.
 */

isc_result_t
dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env);
/*%<
 * Initialize ACL environment, setting up localhost and localnets ACLs
 */

void
dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s);

void
dns_aclenv_destroy(dns_aclenv_t *env);

isc_result_t
dns_acl_match(const isc_netaddr_t *reqaddr,
	      const dns_name_t *reqsigner,
	      const dns_acl_t *acl,
	      const dns_aclenv_t *env,
	      int *match,
	      const dns_aclelement_t **matchelt);

isc_result_t
dns_acl_match2(const isc_netaddr_t *reqaddr,
	       const dns_name_t *reqsigner,
	       const isc_netaddr_t *ecs,
	       uint8_t ecslen,
	       uint8_t *scope,
	       const dns_acl_t *acl,
	       const dns_aclenv_t *env,
	       int *match,
	       const dns_aclelement_t **matchelt);
/*%<
 * General, low-level ACL matching.  This is expected to
 * be useful even for weird stuff like the topology and sortlist statements.
 *
 * Match the address 'reqaddr', and optionally the key name 'reqsigner',
 * and optionally the client prefix 'ecs' of length 'ecslen'
 * (reported via EDNS client subnet option) against 'acl'.
 *
 * 'reqsigner' and 'ecs' may be NULL.  If an ACL matches against 'ecs'
 * and 'ecslen', then 'scope' will be set to indicate the netmask that
 * matched.
 *
 * If there is a match, '*match' will be set to an integer whose absolute
 * value corresponds to the order in which the matching value was inserted
 * into the ACL.  For a positive match, this value will be positive; for a
 * negative match, it will be negative.
 *
 * If there is no match, *match will be set to zero.
 *
 * If there is a match in the element list (either positive or negative)
 * and 'matchelt' is non-NULL, *matchelt will be pointed to the matching
 * element.
 *
 * 'env' points to the current ACL environment, including the
 * current values of localhost and localnets and (if applicable)
 * the GeoIP context.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		Always succeeds.
 */

bool
dns_aclelement_match(const isc_netaddr_t *reqaddr,
		     const dns_name_t *reqsigner,
		     const dns_aclelement_t *e,
		     const dns_aclenv_t *env,
		     const dns_aclelement_t **matchelt);

bool
dns_aclelement_match2(const isc_netaddr_t *reqaddr,
		      const dns_name_t *reqsigner,
		      const isc_netaddr_t *ecs,
		      uint8_t ecslen,
		      uint8_t *scope,
		      const dns_aclelement_t *e,
		      const dns_aclenv_t *env,
		      const dns_aclelement_t **matchelt);
/*%<
 * Like dns_acl_match, but matches against the single ACL element 'e'
 * rather than a complete ACL, and returns true iff it matched.
 *
 * To determine whether the match was positive or negative, the
 * caller should examine e->negative.  Since the element 'e' may be
 * a reference to a named ACL or a nested ACL, a matching element
 * returned through 'matchelt' is not necessarily 'e' itself.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_ACL_H */
rbt.h000064400000117252150415243030005511 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_RBT_H
#define DNS_RBT_H 1

/*! \file dns/rbt.h */

#include <inttypes.h>
#include <stdbool.h>

#include <isc/assertions.h>
#include <isc/crc64.h>
#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/refcount.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

#define DNS_RBT_USEHASH 1

/*@{*/
/*%
 * Option values for dns_rbt_findnode() and dns_rbt_findname().
 * These are used to form a bitmask.
 */
#define DNS_RBTFIND_NOOPTIONS                   0x00
#define DNS_RBTFIND_EMPTYDATA                   0x01
#define DNS_RBTFIND_NOEXACT                     0x02
#define DNS_RBTFIND_NOPREDECESSOR               0x04
/*@}*/

#ifndef DNS_RBT_USEISCREFCOUNT
#ifdef ISC_REFCOUNT_HAVEATOMIC
#define DNS_RBT_USEISCREFCOUNT 1
#endif
#endif

#define DNS_RBT_USEMAGIC 1

/*
 * These should add up to 30.
 */
#define DNS_RBT_LOCKLENGTH                      10
#define DNS_RBT_REFLENGTH                       20

#define DNS_RBTNODE_MAGIC               ISC_MAGIC('R','B','N','O')
#if DNS_RBT_USEMAGIC
#define DNS_RBTNODE_VALID(n)            ISC_MAGIC_VALID(n, DNS_RBTNODE_MAGIC)
#else
#define DNS_RBTNODE_VALID(n)            true
#endif

/*%
 * This is the structure that is used for each node in the red/black
 * tree of trees.  NOTE WELL:  the implementation manages this as a variable
 * length structure, with the actual wire-format name and other data
 * appended to this structure.  Allocating a contiguous block of memory for
 * multiple dns_rbtnode structures will not work.
 */
typedef struct dns_rbtnode dns_rbtnode_t;
enum {
	DNS_RBT_NSEC_NORMAL=0,      /* in main tree */
	DNS_RBT_NSEC_HAS_NSEC=1,    /* also has node in nsec tree */
	DNS_RBT_NSEC_NSEC=2,        /* in nsec tree */
	DNS_RBT_NSEC_NSEC3=3        /* in nsec3 tree */
};
struct dns_rbtnode {
#if DNS_RBT_USEMAGIC
	unsigned int magic;
#endif
	/*@{*/
	/*!
	 * The following bitfields add up to a total bitwidth of 32.
	 * The range of values necessary for each item is indicated,
	 * but in the case of "attributes" the field is wider to accommodate
	 * possible future expansion.
	 *
	 * In each case below the "range" indicated is what's _necessary_ for
	 * the bitfield to hold, not what it actually _can_ hold.
	 *
	 * Note: Tree lock must be held before modifying these
	 * bit-fields.
	 *
	 * Note: The two "unsigned int :0;" unnamed bitfields on either
	 * side of the bitfields below are scaffolding that border the
	 * set of bitfields which are accessed after acquiring the tree
	 * lock. Please don't insert any other bitfield members between
	 * the unnamed bitfields unless they should also be accessed
	 * after acquiring the tree lock.
	 */
	unsigned int :0;                /* start of bitfields c/o tree lock */
	unsigned int is_root : 1;       /*%< range is 0..1 */
	unsigned int color : 1;         /*%< range is 0..1 */
	unsigned int find_callback : 1; /*%< range is 0..1 */
	unsigned int attributes : 3;    /*%< range is 0..2 */
	unsigned int nsec : 2;          /*%< range is 0..3 */
	unsigned int namelen : 8;       /*%< range is 1..255 */
	unsigned int offsetlen : 8;     /*%< range is 1..128 */
	unsigned int oldnamelen : 8;    /*%< range is 1..255 */
	/*@}*/

	/* flags needed for serialization to file*/
	unsigned int is_mmapped : 1;
	unsigned int parent_is_relative : 1;
	unsigned int left_is_relative : 1;
	unsigned int right_is_relative : 1;
	unsigned int down_is_relative : 1;
	unsigned int data_is_relative : 1;

	/* node needs to be cleaned from rpz */
	unsigned int rpz : 1;
	unsigned int :0;                /* end of bitfields c/o tree lock */

#ifdef DNS_RBT_USEHASH
	unsigned int hashval;
	dns_rbtnode_t *uppernode;
	dns_rbtnode_t *hashnext;
#endif
	dns_rbtnode_t *parent;
	dns_rbtnode_t *left;
	dns_rbtnode_t *right;
	dns_rbtnode_t *down;

	/*%
	 * Used for LRU cache.  This linked list is used to mark nodes which
	 * have no data any longer, but we cannot unlink at that exact moment
	 * because we did not or could not obtain a write lock on the tree.
	 */
	ISC_LINK(dns_rbtnode_t) deadlink;

	/*@{*/
	/*!
	 * These values are used in the RBT DB implementation.  The appropriate
	 * node lock must be held before accessing them.
	 *
	 * Note: The two "unsigned int :0;" unnamed bitfields on either
	 * side of the bitfields below are scaffolding that border the
	 * set of bitfields which are accessed after acquiring the node
	 * lock. Please don't insert any other bitfield members between
	 * the unnamed bitfields unless they should also be accessed
	 * after acquiring the node lock.
	 *
	 * NOTE: Do not merge these fields into bitfields above, as
	 * they'll all be put in the same qword that could be accessed
	 * without the node lock as it shares the qword with other
	 * members. Leave these members here so that they occupy a
	 * separate region of memory.
	 */
	void *data;
	unsigned int locknum;
	unsigned int :0;                /* start of bitfields c/o node lock */
	unsigned int dirty:1;
	unsigned int wild:1;
#ifndef DNS_RBT_USEISCREFCOUNT
	unsigned int references:DNS_RBT_REFLENGTH;
#endif
	unsigned int :0;                /* end of bitfields c/o node lock */
#ifdef DNS_RBT_USEISCREFCOUNT
	isc_refcount_t references; /* note that this is not in the bitfield */
#endif
	/*@}*/
};

typedef isc_result_t (*dns_rbtfindcallback_t)(dns_rbtnode_t *node,
					      dns_name_t *name,
					      void *callback_arg);

typedef isc_result_t (*dns_rbtdatawriter_t)(FILE *file,
					    unsigned char *data,
					    void *arg,
					    uint64_t *crc);

typedef isc_result_t (*dns_rbtdatafixer_t)(dns_rbtnode_t *rbtnode,
					   void *base, size_t offset,
					   void *arg, uint64_t *crc);

typedef void (*dns_rbtdeleter_t)(void *, void *);

/*****
 *****  Chain Info
 *****/

/*!
 * A chain is used to keep track of the sequence of nodes to reach any given
 * node from the root of the tree.  Originally nodes did not have parent
 * pointers in them (for memory usage reasons) so there was no way to find
 * the path back to the root from any given node.  Now that nodes have parent
 * pointers, chains might be going away in a future release, though the
 * movement functionality would remain.
 *
 * Chains may be used to iterate over a tree of trees.  After setting up the
 * chain's structure using dns_rbtnodechain_init(), it needs to be initialized
 * to point to the lexically first or lexically last node in the tree of trees
 * using dns_rbtnodechain_first() or dns_rbtnodechain_last(), respectively.
 * Calling dns_rbtnodechain_next() or dns_rbtnodechain_prev() then moves the
 * chain over to the next or previous node, respectively.
 *
 * In any event, parent information, whether via parent pointers or chains, is
 * necessary information for iterating through the tree or for basic internal
 * tree maintenance issues (ie, the rotations that are done to rebalance the
 * tree when a node is added).  The obvious implication of this is that for a
 * chain to remain valid, the tree has to be locked down against writes for the
 * duration of the useful life of the chain, because additions or removals can
 * change the path from the root to the node the chain has targeted.
 *
 * The dns_rbtnodechain_ functions _first, _last, _prev and _next all take
 * dns_name_t parameters for the name and the origin, which can be NULL.  If
 * non-NULL, 'name' will end up pointing to the name data and offsets that are
 * stored at the node (and thus it will be read-only), so it should be a
 * regular dns_name_t that has been initialized with dns_name_init.  When
 * 'origin' is non-NULL, it will get the name of the origin stored in it, so it
 * needs to have its own buffer space and offsets, which is most easily
 * accomplished with a dns_fixedname_t.  It is _not_ necessary to reinitialize
 * either 'name' or 'origin' between calls to the chain functions.
 *
 * NOTE WELL: even though the name data at the root of the tree of trees will
 * be absolute (typically just "."), it will will be made into a relative name
 * with an origin of "." -- an empty name when the node is ".".  This is
 * because a common on operation on 'name' and 'origin' is to use
 * dns_name_concatenate() on them to generate the complete name.  An empty name
 * can be detected when dns_name_countlabels == 0, and is printed by
 * dns_name_totext()/dns_name_format() as "@", consistent with RFC1035's
 * definition of "@" as the current origin.
 *
 * dns_rbtnodechain_current is similar to the _first, _last, _prev and _next
 * functions but additionally can provide the node to which the chain points.
 */

/*%
 * The number of level blocks to allocate at a time.  Currently the maximum
 * number of levels is allocated directly in the structure, but future
 * revisions of this code might have a static initial block with dynamic
 * growth.  Allocating space for 256 levels when the tree is almost never that
 * deep is wasteful, but it's not clear that it matters, since the waste is
 * only 2MB for 1000 concurrently active chains on a system with 64-bit
 * pointers.
 */
#define DNS_RBT_LEVELBLOCK 254

typedef struct dns_rbtnodechain {
	unsigned int            magic;
	isc_mem_t *             mctx;
	/*%
	 * The terminal node of the chain.  It is not in levels[].
	 * This is ostensibly private ... but in a pinch it could be
	 * used tell that the chain points nowhere without needing to
	 * call dns_rbtnodechain_current().
	 */
	dns_rbtnode_t *         end;
	/*%
	 * The maximum number of labels in a name is 128; bitstrings mean
	 * a conceptually very large number (which I have not bothered to
	 * compute) of logical levels because splitting can potentially occur
	 * at each bit.  However, DNSSEC restricts the number of "logical"
	 * labels in a name to 255, meaning only 254 pointers are needed
	 * in the worst case.
	 */
	dns_rbtnode_t *         levels[DNS_RBT_LEVELBLOCK];
	/*%
	 * level_count indicates how deep the chain points into the
	 * tree of trees, and is the index into the levels[] array.
	 * Thus, levels[level_count - 1] is the last level node stored.
	 * A chain that points to the top level of the tree of trees has
	 * a level_count of 0, the first level has a level_count of 1, and
	 * so on.
	 */
	unsigned int            level_count;
	/*%
	 * level_matches tells how many levels matched above the node
	 * returned by dns_rbt_findnode().  A match (partial or exact) found
	 * in the first level thus results in level_matches being set to 1.
	 * This is used by the rbtdb to set the start point for a recursive
	 * search of superdomains until the RR it is looking for is found.
	 */
	unsigned int            level_matches;
} dns_rbtnodechain_t;

/*****
 ***** Public interfaces.
 *****/
isc_result_t
dns_rbt_create(isc_mem_t *mctx, dns_rbtdeleter_t deleter,
	       void *deleter_arg, dns_rbt_t **rbtp);
/*%<
 * Initialize a red-black tree of trees.
 *
 * Notes:
 *\li   The deleter argument, if non-null, points to a function that is
 *      responsible for cleaning up any memory associated with the data
 *      pointer of a node when the node is deleted.  It is passed the
 *      deleted node's data pointer as its first argument and deleter_arg
 *      as its second argument.
 *
 * Requires:
 * \li  mctx is a pointer to a valid memory context.
 *\li   rbtp != NULL && *rbtp == NULL
 *\li   arg == NULL iff deleter == NULL
 *
 * Ensures:
 *\li   If result is ISC_R_SUCCESS:
 *              *rbtp points to a valid red-black tree manager
 *
 *\li   If result is failure:
 *              *rbtp does not point to a valid red-black tree manager.
 *
 * Returns:
 *\li   #ISC_R_SUCCESS  Success
 *\li   #ISC_R_NOMEMORY Resource limit: Out of Memory
 */

isc_result_t
dns_rbt_addname(dns_rbt_t *rbt, dns_name_t *name, void *data);
/*%<
 * Add 'name' to the tree of trees, associated with 'data'.
 *
 * Notes:
 *\li   'data' is never required to be non-NULL, but specifying it
 *      when the name is added is faster than searching for 'name'
 *      again and then setting the data pointer.  The lack of a data pointer
 *      for a node also has other ramifications regarding whether
 *      dns_rbt_findname considers a node to exist, or dns_rbt_deletename
 *      joins nodes.
 *
 * Requires:
 *\li   rbt is a valid rbt manager.
 *\li   dns_name_isabsolute(name) == TRUE
 *
 * Ensures:
 *\li   'name' is not altered in any way.
 *
 *\li   Any external references to nodes in the tree are unaffected by
 *      node splits that are necessary to insert the new name.
 *
 *\li   If result is #ISC_R_SUCCESS:
 *              'name' is findable in the red/black tree of trees in O(log N).
 *              The data pointer of the node for 'name' is set to 'data'.
 *
 *\li   If result is #ISC_R_EXISTS or #ISC_R_NOSPACE:
 *              The tree of trees is unaltered.
 *
 *\li   If result is #ISC_R_NOMEMORY:
 *              No guarantees.
 *
 * Returns:
 *\li   #ISC_R_SUCCESS  Success
 *\li   #ISC_R_EXISTS   The name already exists with associated data.
 *\li   #ISC_R_NOSPACE  The name had more logical labels than are allowed.
 *\li   #ISC_R_NOMEMORY Resource Limit: Out of Memory
 */

isc_result_t
dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep);

/*%<
 * Just like dns_rbt_addname, but returns the address of the node.
 *
 * Requires:
 *\li   rbt is a valid rbt structure.
 *\li   dns_name_isabsolute(name) == TRUE
 *\li   nodep != NULL && *nodep == NULL
 *
 * Ensures:
 *\li   'name' is not altered in any way.
 *
 *\li   Any external references to nodes in the tree are unaffected by
 *      node splits that are necessary to insert the new name.
 *
 *\li   If result is ISC_R_SUCCESS:
 *              'name' is findable in the red/black tree of trees in O(log N).
 *              *nodep is the node that was added for 'name'.
 *
 *\li   If result is ISC_R_EXISTS:
 *              The tree of trees is unaltered.
 *              *nodep is the existing node for 'name'.
 *
 *\li   If result is ISC_R_NOMEMORY:
 *              No guarantees.
 *
 * Returns:
 *\li   #ISC_R_SUCCESS  Success
 *\li   #ISC_R_EXISTS   The name already exists, possibly without data.
 *\li   #ISC_R_NOMEMORY Resource Limit: Out of Memory
 */

isc_result_t
dns_rbt_findname(dns_rbt_t *rbt, const dns_name_t *name, unsigned int options,
		 dns_name_t *foundname, void **data);
/*%<
 * Get the data pointer associated with 'name'.
 *
 * Notes:
 *\li   When #DNS_RBTFIND_NOEXACT is set, the closest matching superdomain is
 *      returned (also subject to #DNS_RBTFIND_EMPTYDATA), even when there is
 *      an exact match in the tree.
 *
 *\li   A node that has no data is considered not to exist for this function,
 *      unless the #DNS_RBTFIND_EMPTYDATA option is set.
 *
 * Requires:
 *\li   rbt is a valid rbt manager.
 *\li   dns_name_isabsolute(name) == TRUE
 *\li   data != NULL && *data == NULL
 *
 * Ensures:
 *\li   'name' and the tree are not altered in any way.
 *
 *\li   If result is ISC_R_SUCCESS:
 *              *data is the data associated with 'name'.
 *
 *\li   If result is DNS_R_PARTIALMATCH:
 *              *data is the data associated with the deepest superdomain
 *              of 'name' which has data.
 *
 *\li   If result is ISC_R_NOTFOUND:
 *              Neither the name nor a superdomain was found with data.
 *
 * Returns:
 *\li   #ISC_R_SUCCESS          Success
 *\li   #DNS_R_PARTIALMATCH     Superdomain found with data
 *\li   #ISC_R_NOTFOUND         No match
 *\li   #ISC_R_NOSPACE          Concatenating nodes to form foundname failed
 */

isc_result_t
dns_rbt_findnode(dns_rbt_t *rbt, const dns_name_t *name, dns_name_t *foundname,
		 dns_rbtnode_t **node, dns_rbtnodechain_t *chain,
		 unsigned int options, dns_rbtfindcallback_t callback,
		 void *callback_arg);
/*%<
 * Find the node for 'name'.
 *
 * Notes:
 *\li   A node that has no data is considered not to exist for this function,
 *      unless the DNS_RBTFIND_EMPTYDATA option is set.  This applies to both
 *      exact matches and partial matches.
 *
 *\li   If the chain parameter is non-NULL, then the path through the tree
 *      to the DNSSEC predecessor of the searched for name is maintained,
 *      unless the DNS_RBTFIND_NOPREDECESSOR or DNS_RBTFIND_NOEXACT option
 *      is used. (For more details on those options, see below.)
 *
 *\li   If there is no predecessor, then the chain will point to nowhere, as
 *      indicated by chain->end being NULL or dns_rbtnodechain_current
 *      returning ISC_R_NOTFOUND.  Note that in a normal Internet DNS RBT
 *      there will always be a predecessor for all names except the root
 *      name, because '.' will exist and '.' is the predecessor of
 *      everything.  But you can certainly construct a trivial tree and a
 *      search for it that has no predecessor.
 *
 *\li   Within the chain structure, the 'levels' member of the structure holds
 *      the root node of each level except the first.
 *
 *\li   The 'level_count' of the chain indicates how deep the chain to the
 *      predecessor name is, as an index into the 'levels[]' array.  It does
 *      not count name elements, per se, but only levels of the tree of trees,
 *      the distinction arising because multiple labels from a name can be
 *      stored on only one level.  It is also does not include the level
 *      that has the node, since that level is not stored in levels[].
 *
 *\li   The chain's 'level_matches' is not directly related to the predecessor.
 *      It is the number of levels above the level of the found 'node',
 *      regardless of whether it was a partial match or exact match.  When
 *      the node is found in the top level tree, or no node is found at all,
 *      level_matches is 0.
 *
 *\li   When DNS_RBTFIND_NOEXACT is set, the closest matching superdomain is
 *      returned (also subject to DNS_RBTFIND_EMPTYDATA), even when
 *      there is an exact match in the tree.  In this case, the chain
 *      will not point to the DNSSEC predecessor, but will instead point
 *      to the exact match, if there was any.  Thus the preceding paragraphs
 *      should have "exact match" substituted for "predecessor" to describe
 *      how the various elements of the chain are set.  This was done to
 *      ensure that the chain's state was sane, and to prevent problems that
 *      occurred when running the predecessor location code under conditions
 *      it was not designed for.  It is not clear *where* the chain should
 *      point when DNS_RBTFIND_NOEXACT is set, so if you end up using a chain
 *      with this option because you want a particular node, let us know
 *      where you want the chain pointed, so this can be made more firm.
 *
 * Requires:
 *\li   rbt is a valid rbt manager.
 *\li   dns_name_isabsolute(name) == TRUE.
 *\li   node != NULL && *node == NULL.
 *\li   #DNS_RBTFIND_NOEXACT and DNS_RBTFIND_NOPREDECESSOR are mutually
 *              exclusive.
 *
 * Ensures:
 *\li   'name' and the tree are not altered in any way.
 *
 *\li   If result is ISC_R_SUCCESS:
 *\verbatim
 *              *node is the terminal node for 'name'.

 *              'foundname' and 'name' represent the same name (though not
 *              the same memory).

 *              'chain' points to the DNSSEC predecessor, if any, of 'name'.
 *
 *              chain->level_matches and chain->level_count are equal.
 *\endverbatim
 *
 *      If result is DNS_R_PARTIALMATCH:
 *\verbatim
 *              *node is the data associated with the deepest superdomain
 *              of 'name' which has data.
 *
 *              'foundname' is the name of deepest superdomain (which has
 *              data, unless the DNS_RBTFIND_EMPTYDATA option is set).
 *
 *              'chain' points to the DNSSEC predecessor, if any, of 'name'.
 *\endverbatim
 *
 *\li   If result is ISC_R_NOTFOUND:
 *\verbatim
 *              Neither the name nor a superdomain was found.  *node is NULL.
 *
 *              'chain' points to the DNSSEC predecessor, if any, of 'name'.
 *
 *              chain->level_matches is 0.
 *\endverbatim
 *
 * Returns:
 *\li   #ISC_R_SUCCESS          Success
 *\li   #DNS_R_PARTIALMATCH     Superdomain found with data
 *\li   #ISC_R_NOTFOUND         No match, or superdomain with no data
 *\li   #ISC_R_NOSPACE Concatenating nodes to form foundname failed
 */

isc_result_t
dns_rbt_deletename(dns_rbt_t *rbt, dns_name_t *name, bool recurse);
/*%<
 * Delete 'name' from the tree of trees.
 *
 * Notes:
 *\li   When 'name' is removed, if recurse is true then all of its
 *      subnames are removed too.
 *
 * Requires:
 *\li   rbt is a valid rbt manager.
 *\li   dns_name_isabsolute(name) == TRUE
 *
 * Ensures:
 *\li   'name' is not altered in any way.
 *
 *\li   Does NOT ensure that any external references to nodes in the tree
 *      are unaffected by node joins.
 *
 *\li   If result is ISC_R_SUCCESS:
 *              'name' does not appear in the tree with data; however,
 *              the node for the name might still exist which can be
 *              found with dns_rbt_findnode (but not dns_rbt_findname).
 *
 *\li   If result is ISC_R_NOTFOUND:
 *              'name' does not appear in the tree with data, because
 *              it did not appear in the tree before the function was called.
 *
 *\li   If result is something else:
 *              See result codes for dns_rbt_findnode (if it fails, the
 *              node is not deleted) or dns_rbt_deletenode (if it fails,
 *              the node is deleted, but the tree is not optimized when
 *              it could have been).
 *
 * Returns:
 *\li   #ISC_R_SUCCESS  Success
 *\li   #ISC_R_NOTFOUND No match
 *\li   something_else  Any return code from dns_rbt_findnode except
 *                      DNS_R_PARTIALMATCH (which causes ISC_R_NOTFOUND
 *                      to be returned instead), and any code from
 *                      dns_rbt_deletenode.
 */

isc_result_t
dns_rbt_deletenode(dns_rbt_t *rbt, dns_rbtnode_t *node, bool recurse);
/*%<
 * Delete 'node' from the tree of trees.
 *
 * Notes:
 *\li   When 'node' is removed, if recurse is true then all nodes
 *      in levels down from it are removed too.
 *
 * Requires:
 *\li   rbt is a valid rbt manager.
 *\li   node != NULL.
 *
 * Ensures:
 *\li   Does NOT ensure that any external references to nodes in the tree
 *      are unaffected by node joins.
 *
 *\li   If result is ISC_R_SUCCESS:
 *              'node' does not appear in the tree with data; however,
 *              the node might still exist if it serves as a pointer to
 *              a lower tree level as long as 'recurse' was false, hence
 *              the node could can be found with dns_rbt_findnode when
 *              that function's empty_data_ok parameter is true.
 *
 *\li   If result is ISC_R_NOMEMORY or ISC_R_NOSPACE:
 *              The node was deleted, but the tree structure was not
 *              optimized.
 *
 * Returns:
 *\li   #ISC_R_SUCCESS  Success
 *\li   #ISC_R_NOMEMORY Resource Limit: Out of Memory when joining nodes.
 *\li   #ISC_R_NOSPACE  dns_name_concatenate failed when joining nodes.
 */

void
dns_rbt_namefromnode(dns_rbtnode_t *node, dns_name_t *name);
/*%<
 * Convert the sequence of labels stored at 'node' into a 'name'.
 *
 * Notes:
 *\li   This function does not return the full name, from the root, but
 *      just the labels at the indicated node.
 *
 *\li   The name data pointed to by 'name' is the information stored
 *      in the node, not a copy.  Altering the data at this pointer
 *      will likely cause grief.
 *
 * Requires:
 * \li  name->offsets == NULL
 *
 * Ensures:
 * \li  'name' is DNS_NAMEATTR_READONLY.
 *
 * \li  'name' will point directly to the labels stored after the
 *      dns_rbtnode_t struct.
 *
 * \li  'name' will have offsets that also point to the information stored
 *      as part of the node.
 */

isc_result_t
dns_rbt_fullnamefromnode(dns_rbtnode_t *node, dns_name_t *name);
/*%<
 * Like dns_rbt_namefromnode, but returns the full name from the root.
 *
 * Notes:
 * \li  Unlike dns_rbt_namefromnode, the name will not point directly
 *      to node data.  Rather, dns_name_concatenate will be used to copy
 *      the name data from each node into the 'name' argument.
 *
 * Requires:
 * \li  name != NULL
 * \li  name has a dedicated buffer.
 *
 * Returns:
 * \li  ISC_R_SUCCESS
 * \li  ISC_R_NOSPACE           (possible via dns_name_concatenate)
 * \li  DNS_R_NAMETOOLONG       (possible via dns_name_concatenate)
 */

char *
dns_rbt_formatnodename(dns_rbtnode_t *node, char *printname,
		       unsigned int size);
/*%<
 * Format the full name of a node for printing, using dns_name_format().
 *
 * Notes:
 * \li  'size' is the length of the printname buffer.  This should be
 *      DNS_NAME_FORMATSIZE or larger.
 *
 * Requires:
 * \li  node and printname are not NULL.
 *
 * Returns:
 * \li  The 'printname' pointer.
 */

unsigned int
dns_rbt_nodecount(dns_rbt_t *rbt);
/*%<
 * Obtain the number of nodes in the tree of trees.
 *
 * Requires:
 * \li  rbt is a valid rbt manager.
 */

size_t
dns_rbt_hashsize(dns_rbt_t *rbt);
/*%<
 * Obtain the current number of buckets in the 'rbt' hash table.
 *
 * Requires:
 * \li  rbt is a valid rbt manager.
 */

void
dns_rbt_destroy(dns_rbt_t **rbtp);
isc_result_t
dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum);
/*%<
 * Stop working with a red-black tree of trees.
 * If 'quantum' is zero then the entire tree will be destroyed.
 * If 'quantum' is non zero then up to 'quantum' nodes will be destroyed
 * allowing the rbt to be incrementally destroyed by repeated calls to
 * dns_rbt_destroy2().  Once dns_rbt_destroy2() has been called no other
 * operations than dns_rbt_destroy()/dns_rbt_destroy2() should be
 * performed on the tree of trees.
 *
 * Requires:
 * \li  *rbt is a valid rbt manager.
 *
 * Ensures on ISC_R_SUCCESS:
 * \li  All space allocated by the RBT library has been returned.
 *
 * \li  *rbt is invalidated as an rbt manager.
 *
 * Returns:
 * \li  ISC_R_SUCCESS
 * \li  ISC_R_QUOTA if 'quantum' nodes have been destroyed.
 */

off_t
dns_rbt_serialize_align(off_t target);
/*%<
 * Align the provided integer to a pointer-size boundary.
 * This should be used if, during serialization of data to a will-be
 * mmap()ed file, a pointer alignment is needed for some data.
 */

isc_result_t
dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt,
		       dns_rbtdatawriter_t datawriter,
		       void *writer_arg, off_t *offset);
/*%<
 * Write out the RBT structure and its data to a file.
 *
 * Notes:
 * \li  The file must be an actual file which allows seek() calls, so it cannot
 *      be a stream.  Returns ISC_R_INVALIDFILE if not.
 */

isc_result_t
dns_rbt_deserialize_tree(void *base_address, size_t filesize,
			 off_t header_offset, isc_mem_t *mctx,
			 dns_rbtdeleter_t deleter, void *deleter_arg,
			 dns_rbtdatafixer_t datafixer, void *fixer_arg,
			 dns_rbtnode_t **originp, dns_rbt_t **rbtp);
/*%<
 * Read a RBT structure and its data from a file.
 *
 * If 'originp' is not NULL, then it is pointed to the root node of the RBT.
 *
 * Notes:
 * \li  The file must be an actual file which allows seek() calls, so it cannot
 *      be a stream.  This condition is not checked in the code.
 */

void
dns_rbt_printtext(dns_rbt_t *rbt,
		  void (*data_printer)(FILE *, void *), FILE *f);
/*%<
 * Print an ASCII representation of the internal structure of the red-black
 * tree of trees to the passed stream.
 *
 * data_printer is a callback function that is called to print the data
 * in a node. It should print it to the passed FILE stream.
 *
 * Notes:
 * \li  The name stored at each node, along with the node's color, is printed.
 *      Then the down pointer, left and right pointers are displayed
 *      recursively in turn.  NULL down pointers are silently omitted;
 *      NULL left and right pointers are printed.
 */

void
dns_rbt_printdot(dns_rbt_t *rbt, bool show_pointers, FILE *f);
/*%<
 * Print a GraphViz dot representation of the internal structure of the
 * red-black tree of trees to the passed stream.
 *
 * If show_pointers is TRUE, pointers are also included in the generated
 * graph.
 *
 * Notes:
 * \li	The name stored at each node, along with the node's color is displayed.
 *	Then the down pointer, left and right pointers are displayed
 *	recursively in turn.  NULL left, right and down pointers are
 *	silently omitted.
 */

void
dns_rbt_printnodeinfo(dns_rbtnode_t *n, FILE *f);
/*%<
 * Print out various information about a node
 *
 * Requires:
 *\li	'n' is a valid pointer.
 *
 *\li	'f' points to a valid open FILE structure that allows writing.
 */


size_t
dns__rbt_getheight(dns_rbt_t *rbt);
/*%<
 * Return the maximum height of sub-root nodes found in the red-black
 * forest.
 *
 * The height of a node is defined as the number of nodes in the longest
 * path from the node to a leaf. For each subtree in the forest, this
 * function determines the height of its root node. Then it returns the
 * maximum such height in the forest.
 *
 * Note: This function exists for testing purposes. Non-test code must
 * not use it.
 *
 * Requires:
 * \li  rbt is a valid rbt manager.
 */

bool
dns__rbt_checkproperties(dns_rbt_t *rbt);
/*%<
 * Check red-black properties of the forest.
 *
 * Note: This function exists for testing purposes. Non-test code must
 * not use it.
 *
 * Requires:
 * \li  rbt is a valid rbt manager.
 */

size_t
dns__rbtnode_getdistance(dns_rbtnode_t *node);
/*%<
 * Return the distance (in nodes) from the node to its upper node of its
 * subtree. The root node has a distance of 1. A child of the root node
 * has a distance of 2.
 */

/*****
 ***** Chain Functions
 *****/

void
dns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx);
/*%<
 * Initialize 'chain'.
 *
 * Requires:
 *\li   'chain' is a valid pointer.
 *
 *\li   'mctx' is a valid memory context.
 *
 * Ensures:
 *\li   'chain' is suitable for use.
 */

void
dns_rbtnodechain_reset(dns_rbtnodechain_t *chain);
/*%<
 * Free any dynamic storage associated with 'chain', and then reinitialize
 * 'chain'.
 *
 * Requires:
 *\li   'chain' is a valid pointer.
 *
 * Ensures:
 *\li   'chain' is suitable for use, and uses no dynamic storage.
 */

void
dns_rbtnodechain_invalidate(dns_rbtnodechain_t *chain);
/*%<
 * Free any dynamic storage associated with 'chain', and then invalidates it.
 *
 * Notes:
 *\li   Future calls to any dns_rbtnodechain_ function will need to call
 *      dns_rbtnodechain_init on the chain first (except, of course,
 *      dns_rbtnodechain_init itself).
 *
 * Requires:
 *\li   'chain' is a valid chain.
 *
 * Ensures:
 *\li   'chain' is no longer suitable for use, and uses no dynamic storage.
 */

isc_result_t
dns_rbtnodechain_current(dns_rbtnodechain_t *chain, dns_name_t *name,
			 dns_name_t *origin, dns_rbtnode_t **node);
/*%<
 * Provide the name, origin and node to which the chain is currently pointed.
 *
 * Notes:
 *\li   The tree need not have be locked against additions for the chain
 *      to remain valid, however there are no guarantees if any deletion
 *      has been made since the chain was established.
 *
 * Requires:
 *\li   'chain' is a valid chain.
 *
 * Ensures:
 *\li   'node', if non-NULL, is the node to which the chain was pointed
 *      by dns_rbt_findnode, dns_rbtnodechain_first or dns_rbtnodechain_last.
 *      If none were called for the chain since it was initialized or reset,
 *      or if the was no predecessor to the name searched for with
 *      dns_rbt_findnode, then '*node' is NULL and ISC_R_NOTFOUND is returned.
 *
 *\li   'name', if non-NULL, is the name stored at the terminal level of
 *      the chain.  This is typically a single label, like the "www" of
 *      "www.isc.org", but need not be so.  At the root of the tree of trees,
 *      if the node is "." then 'name' is ".", otherwise it is relative to ".".
 *      (Minimalist and atypical case:  if the tree has just the name
 *      "isc.org." then the root node's stored name is "isc.org." but 'name'
 *      will be "isc.org".)
 *
 *\li   'origin', if non-NULL, is the sequence of labels in the levels
 *      above the terminal level, such as "isc.org." in the above example.
 *      'origin' is always "." for the root node.
 *
 *
 * Returns:
 *\li   #ISC_R_SUCCESS          name, origin & node were successfully set.
 *\li   #ISC_R_NOTFOUND         The chain does not point to any node.
 *\li   &lt;something_else>     Any error return from dns_name_concatenate.
 */

isc_result_t
dns_rbtnodechain_first(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
		       dns_name_t *name, dns_name_t *origin);
/*%<
 * Set the chain to the lexically first node in the tree of trees.
 *
 * Notes:
 *\li   By the definition of ordering for DNS names, the root of the tree of
 *      trees is the very first node, since everything else in the megatree
 *      uses it as a common suffix.
 *
 * Requires:
 *\li   'chain' is a valid chain.
 *\li   'rbt' is a valid rbt manager.
 *
 * Ensures:
 *\li   The chain points to the very first node of the tree.
 *
 *\li   'name' and 'origin', if non-NULL, are set as described for
 *      dns_rbtnodechain_current.  Thus 'origin' will always be ".".
 *
 * Returns:
 *\li   #DNS_R_NEWORIGIN                The name & origin were successfully set.
 *\li   &lt;something_else>     Any error result from dns_rbtnodechain_current.
 */

isc_result_t
dns_rbtnodechain_last(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
		       dns_name_t *name, dns_name_t *origin);
/*%<
 * Set the chain to the lexically last node in the tree of trees.
 *
 * Requires:
 *\li   'chain' is a valid chain.
 *\li   'rbt' is a valid rbt manager.
 *
 * Ensures:
 *\li   The chain points to the very last node of the tree.
 *
 *\li   'name' and 'origin', if non-NULL, are set as described for
 *      dns_rbtnodechain_current.
 *
 * Returns:
 *\li   #DNS_R_NEWORIGIN                The name & origin were successfully set.
 *\li   #ISC_R_NOMEMORY         Resource Limit: Out of Memory building chain.
 *\li   &lt;something_else>     Any error result from dns_name_concatenate.
 */

isc_result_t
dns_rbtnodechain_prev(dns_rbtnodechain_t *chain, dns_name_t *name,
		      dns_name_t *origin);
/*%<
 * Adjusts chain to point the DNSSEC predecessor of the name to which it
 * is currently pointed.
 *
 * Requires:
 *\li   'chain' is a valid chain.
 *\li   'chain' has been pointed somewhere in the tree with dns_rbt_findnode,
 *      dns_rbtnodechain_first or dns_rbtnodechain_last -- and remember that
 *      dns_rbt_findnode is not guaranteed to point the chain somewhere,
 *      since there may have been no predecessor to the searched for name.
 *
 * Ensures:
 *\li   The chain is pointed to the predecessor of its current target.
 *
 *\li   'name' and 'origin', if non-NULL, are set as described for
 *      dns_rbtnodechain_current.
 *
 *\li   'origin' is only if a new origin was found.
 *
 * Returns:
 *\li   #ISC_R_SUCCESS          The predecessor was found and 'name' was set.
 *\li   #DNS_R_NEWORIGIN                The predecessor was found with a different
 *                              origin and 'name' and 'origin' were set.
 *\li   #ISC_R_NOMORE           There was no predecessor.
 *\li   &lt;something_else>     Any error result from dns_rbtnodechain_current.
 */

isc_result_t
dns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name,
		      dns_name_t *origin);
/*%<
 * Adjusts chain to point the DNSSEC successor of the name to which it
 * is currently pointed.
 *
 * Requires:
 *\li   'chain' is a valid chain.
 *\li   'chain' has been pointed somewhere in the tree with dns_rbt_findnode,
 *      dns_rbtnodechain_first or dns_rbtnodechain_last -- and remember that
 *      dns_rbt_findnode is not guaranteed to point the chain somewhere,
 *      since there may have been no predecessor to the searched for name.
 *
 * Ensures:
 *\li   The chain is pointed to the successor of its current target.
 *
 *\li   'name' and 'origin', if non-NULL, are set as described for
 *      dns_rbtnodechain_current.
 *
 *\li   'origin' is only if a new origin was found.
 *
 * Returns:
 *\li   #ISC_R_SUCCESS          The successor was found and 'name' was set.
 *\li   #DNS_R_NEWORIGIN                The successor was found with a different
 *                              origin and 'name' and 'origin' were set.
 *\li   #ISC_R_NOMORE           There was no successor.
 *\li   &lt;something_else>     Any error result from dns_name_concatenate.
 */

isc_result_t
dns_rbtnodechain_down(dns_rbtnodechain_t *chain, dns_name_t *name,
		      dns_name_t *origin);
/*%<
 * Descend down if possible.
 */

isc_result_t
dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name);
/*%<
 * Find the next node at the current depth in DNSSEC order.
 */

/*
 * Wrapper macros for manipulating the rbtnode reference counter:
 *   Since we selectively use isc_refcount_t for the reference counter of
 *   a rbtnode, operations on the counter depend on the actual type of it.
 *   The following macros provide a common interface to these operations,
 *   hiding the back-end.  The usage is the same as that of isc_refcount_xxx().
 */
#ifdef DNS_RBT_USEISCREFCOUNT
#define dns_rbtnode_refinit(node, n)                            \
	do {                                                    \
		isc_refcount_init(&(node)->references, (n));    \
	} while (0)
#define dns_rbtnode_refdestroy(node)                            \
	do {                                                    \
		isc_refcount_destroy(&(node)->references);      \
	} while (0)
#define dns_rbtnode_refcurrent(node)                            \
	isc_refcount_current(&(node)->references)
#define dns_rbtnode_refincrement0(node, refs)                   \
	do {                                                    \
		isc_refcount_increment0(&(node)->references, (refs)); \
	} while (0)
#define dns_rbtnode_refincrement(node, refs)                    \
	do {                                                    \
		isc_refcount_increment(&(node)->references, (refs)); \
	} while (0)
#define dns_rbtnode_refdecrement(node, refs)                    \
	do {                                                    \
		isc_refcount_decrement(&(node)->references, (refs)); \
	} while (0)
#else  /* DNS_RBT_USEISCREFCOUNT */
#define dns_rbtnode_refinit(node, n)    ((node)->references = (n))
#define dns_rbtnode_refdestroy(node)    ISC_REQUIRE((node)->references == 0)
#define dns_rbtnode_refcurrent(node)    ((node)->references)

#if (__STDC_VERSION__ + 0) >= 199901L || defined __GNUC__
static inline void
dns_rbtnode_refincrement0(dns_rbtnode_t *node, unsigned int *refs) {
	node->references++;
	if (refs != NULL)
		*refs = node->references;
}

static inline void
dns_rbtnode_refincrement(dns_rbtnode_t *node, unsigned int *refs) {
	ISC_REQUIRE(node->references > 0);
	node->references++;
	if (refs != NULL)
		*refs = node->references;
}

static inline void
dns_rbtnode_refdecrement(dns_rbtnode_t *node, unsigned int *refs) {
	ISC_REQUIRE(node->references > 0);
	node->references--;
	if (refs != NULL)
		*refs = node->references;
}
#else
#define dns_rbtnode_refincrement0(node, refs)                   \
	do {                                                    \
		unsigned int *_tmp = (unsigned int *)(refs);    \
		(node)->references++;                           \
		if ((_tmp) != NULL)                             \
			(*_tmp) = (node)->references;           \
	} while (0)
#define dns_rbtnode_refincrement(node, refs)                    \
	do {                                                    \
		ISC_REQUIRE((node)->references > 0);                \
		(node)->references++;                           \
		if ((refs) != NULL)                             \
			(*refs) = (node)->references;           \
	} while (0)
#define dns_rbtnode_refdecrement(node, refs)                    \
	do {                                                    \
		ISC_REQUIRE((node)->references > 0);                \
		(node)->references--;                           \
		if ((refs) != NULL)                             \
			(*refs) = (node)->references;           \
	} while (0)
#endif
#endif /* DNS_RBT_USEISCREFCOUNT */

void
dns_rbtnode_nodename(dns_rbtnode_t *node, dns_name_t *name);

dns_rbtnode_t *
dns_rbt_root(dns_rbt_t *rbt);

ISC_LANG_ENDDECLS

#endif /* DNS_RBT_H */
enumtype.h000064400000020154150415243030006562 0ustar00/*
 * Copyright (C) 1998-2025  Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

/***************
 ***************
 ***************   THIS FILE IS AUTOMATICALLY GENERATED BY gen.c.
 ***************   DO NOT EDIT!
 ***************
 ***************/

/*! \file */

#ifndef DNS_ENUMTYPE_H
#define DNS_ENUMTYPE_H 1

enum {
	dns_rdatatype_none = 0,
	dns_rdatatype_a = 1,
	dns_rdatatype_ns = 2,
	dns_rdatatype_md = 3,
	dns_rdatatype_mf = 4,
	dns_rdatatype_cname = 5,
	dns_rdatatype_soa = 6,
	dns_rdatatype_mb = 7,
	dns_rdatatype_mg = 8,
	dns_rdatatype_mr = 9,
	dns_rdatatype_null = 10,
	dns_rdatatype_wks = 11,
	dns_rdatatype_ptr = 12,
	dns_rdatatype_hinfo = 13,
	dns_rdatatype_minfo = 14,
	dns_rdatatype_mx = 15,
	dns_rdatatype_txt = 16,
	dns_rdatatype_rp = 17,
	dns_rdatatype_afsdb = 18,
	dns_rdatatype_x25 = 19,
	dns_rdatatype_isdn = 20,
	dns_rdatatype_rt = 21,
	dns_rdatatype_nsap = 22,
	dns_rdatatype_nsap_ptr = 23,
	dns_rdatatype_sig = 24,
	dns_rdatatype_key = 25,
	dns_rdatatype_px = 26,
	dns_rdatatype_gpos = 27,
	dns_rdatatype_aaaa = 28,
	dns_rdatatype_loc = 29,
	dns_rdatatype_nxt = 30,
	dns_rdatatype_eid = 31,
	dns_rdatatype_nimloc = 32,
	dns_rdatatype_srv = 33,
	dns_rdatatype_atma = 34,
	dns_rdatatype_naptr = 35,
	dns_rdatatype_kx = 36,
	dns_rdatatype_cert = 37,
	dns_rdatatype_a6 = 38,
	dns_rdatatype_dname = 39,
	dns_rdatatype_sink = 40,
	dns_rdatatype_opt = 41,
	dns_rdatatype_apl = 42,
	dns_rdatatype_ds = 43,
	dns_rdatatype_sshfp = 44,
	dns_rdatatype_ipseckey = 45,
	dns_rdatatype_rrsig = 46,
	dns_rdatatype_nsec = 47,
	dns_rdatatype_dnskey = 48,
	dns_rdatatype_dhcid = 49,
	dns_rdatatype_nsec3 = 50,
	dns_rdatatype_nsec3param = 51,
	dns_rdatatype_tlsa = 52,
	dns_rdatatype_smimea = 53,
	dns_rdatatype_hip = 55,
	dns_rdatatype_ninfo = 56,
	dns_rdatatype_rkey = 57,
	dns_rdatatype_talink = 58,
	dns_rdatatype_cds = 59,
	dns_rdatatype_cdnskey = 60,
	dns_rdatatype_openpgpkey = 61,
	dns_rdatatype_csync = 62,
	dns_rdatatype_zonemd = 63,
	dns_rdatatype_spf = 99,
	dns_rdatatype_nid = 104,
	dns_rdatatype_l32 = 105,
	dns_rdatatype_l64 = 106,
	dns_rdatatype_lp = 107,
	dns_rdatatype_eui48 = 108,
	dns_rdatatype_eui64 = 109,
	dns_rdatatype_tkey = 249,
	dns_rdatatype_tsig = 250,
	dns_rdatatype_uri = 256,
	dns_rdatatype_caa = 257,
	dns_rdatatype_avc = 258,
	dns_rdatatype_doa = 259,
	dns_rdatatype_amtrelay = 260,
	dns_rdatatype_ta = 32768,
	dns_rdatatype_dlv = 32769,
	dns_rdatatype_keydata = 65533,
	dns_rdatatype_ixfr = 251,
	dns_rdatatype_axfr = 252,
	dns_rdatatype_mailb = 253,
	dns_rdatatype_maila = 254,
	dns_rdatatype_any = 255
};

#define dns_rdatatype_none	((dns_rdatatype_t)dns_rdatatype_none)
#define dns_rdatatype_a		((dns_rdatatype_t)dns_rdatatype_a)
#define dns_rdatatype_ns	((dns_rdatatype_t)dns_rdatatype_ns)
#define dns_rdatatype_md	((dns_rdatatype_t)dns_rdatatype_md)
#define dns_rdatatype_mf	((dns_rdatatype_t)dns_rdatatype_mf)
#define dns_rdatatype_cname	((dns_rdatatype_t)dns_rdatatype_cname)
#define dns_rdatatype_soa	((dns_rdatatype_t)dns_rdatatype_soa)
#define dns_rdatatype_mb	((dns_rdatatype_t)dns_rdatatype_mb)
#define dns_rdatatype_mg	((dns_rdatatype_t)dns_rdatatype_mg)
#define dns_rdatatype_mr	((dns_rdatatype_t)dns_rdatatype_mr)
#define dns_rdatatype_null	((dns_rdatatype_t)dns_rdatatype_null)
#define dns_rdatatype_wks	((dns_rdatatype_t)dns_rdatatype_wks)
#define dns_rdatatype_ptr	((dns_rdatatype_t)dns_rdatatype_ptr)
#define dns_rdatatype_hinfo	((dns_rdatatype_t)dns_rdatatype_hinfo)
#define dns_rdatatype_minfo	((dns_rdatatype_t)dns_rdatatype_minfo)
#define dns_rdatatype_mx	((dns_rdatatype_t)dns_rdatatype_mx)
#define dns_rdatatype_txt	((dns_rdatatype_t)dns_rdatatype_txt)
#define dns_rdatatype_rp	((dns_rdatatype_t)dns_rdatatype_rp)
#define dns_rdatatype_afsdb	((dns_rdatatype_t)dns_rdatatype_afsdb)
#define dns_rdatatype_x25	((dns_rdatatype_t)dns_rdatatype_x25)
#define dns_rdatatype_isdn	((dns_rdatatype_t)dns_rdatatype_isdn)
#define dns_rdatatype_rt	((dns_rdatatype_t)dns_rdatatype_rt)
#define dns_rdatatype_nsap	((dns_rdatatype_t)dns_rdatatype_nsap)
#define dns_rdatatype_nsap_ptr	((dns_rdatatype_t)dns_rdatatype_nsap_ptr)
#define dns_rdatatype_sig	((dns_rdatatype_t)dns_rdatatype_sig)
#define dns_rdatatype_key	((dns_rdatatype_t)dns_rdatatype_key)
#define dns_rdatatype_px	((dns_rdatatype_t)dns_rdatatype_px)
#define dns_rdatatype_gpos	((dns_rdatatype_t)dns_rdatatype_gpos)
#define dns_rdatatype_aaaa	((dns_rdatatype_t)dns_rdatatype_aaaa)
#define dns_rdatatype_loc	((dns_rdatatype_t)dns_rdatatype_loc)
#define dns_rdatatype_nxt	((dns_rdatatype_t)dns_rdatatype_nxt)
#define dns_rdatatype_eid	((dns_rdatatype_t)dns_rdatatype_eid)
#define dns_rdatatype_nimloc	((dns_rdatatype_t)dns_rdatatype_nimloc)
#define dns_rdatatype_srv	((dns_rdatatype_t)dns_rdatatype_srv)
#define dns_rdatatype_atma	((dns_rdatatype_t)dns_rdatatype_atma)
#define dns_rdatatype_naptr	((dns_rdatatype_t)dns_rdatatype_naptr)
#define dns_rdatatype_kx	((dns_rdatatype_t)dns_rdatatype_kx)
#define dns_rdatatype_cert	((dns_rdatatype_t)dns_rdatatype_cert)
#define dns_rdatatype_a6	((dns_rdatatype_t)dns_rdatatype_a6)
#define dns_rdatatype_dname	((dns_rdatatype_t)dns_rdatatype_dname)
#define dns_rdatatype_sink	((dns_rdatatype_t)dns_rdatatype_sink)
#define dns_rdatatype_opt	((dns_rdatatype_t)dns_rdatatype_opt)
#define dns_rdatatype_apl	((dns_rdatatype_t)dns_rdatatype_apl)
#define dns_rdatatype_ds	((dns_rdatatype_t)dns_rdatatype_ds)
#define dns_rdatatype_sshfp	((dns_rdatatype_t)dns_rdatatype_sshfp)
#define dns_rdatatype_ipseckey	((dns_rdatatype_t)dns_rdatatype_ipseckey)
#define dns_rdatatype_rrsig	((dns_rdatatype_t)dns_rdatatype_rrsig)
#define dns_rdatatype_nsec	((dns_rdatatype_t)dns_rdatatype_nsec)
#define dns_rdatatype_dnskey	((dns_rdatatype_t)dns_rdatatype_dnskey)
#define dns_rdatatype_dhcid	((dns_rdatatype_t)dns_rdatatype_dhcid)
#define dns_rdatatype_nsec3	((dns_rdatatype_t)dns_rdatatype_nsec3)
#define dns_rdatatype_nsec3param	((dns_rdatatype_t)dns_rdatatype_nsec3param)
#define dns_rdatatype_tlsa	((dns_rdatatype_t)dns_rdatatype_tlsa)
#define dns_rdatatype_smimea	((dns_rdatatype_t)dns_rdatatype_smimea)
#define dns_rdatatype_hip	((dns_rdatatype_t)dns_rdatatype_hip)
#define dns_rdatatype_ninfo	((dns_rdatatype_t)dns_rdatatype_ninfo)
#define dns_rdatatype_rkey	((dns_rdatatype_t)dns_rdatatype_rkey)
#define dns_rdatatype_talink	((dns_rdatatype_t)dns_rdatatype_talink)
#define dns_rdatatype_cds	((dns_rdatatype_t)dns_rdatatype_cds)
#define dns_rdatatype_cdnskey	((dns_rdatatype_t)dns_rdatatype_cdnskey)
#define dns_rdatatype_openpgpkey	((dns_rdatatype_t)dns_rdatatype_openpgpkey)
#define dns_rdatatype_csync	((dns_rdatatype_t)dns_rdatatype_csync)
#define dns_rdatatype_zonemd	((dns_rdatatype_t)dns_rdatatype_zonemd)
#define dns_rdatatype_spf	((dns_rdatatype_t)dns_rdatatype_spf)
#define dns_rdatatype_nid	((dns_rdatatype_t)dns_rdatatype_nid)
#define dns_rdatatype_l32	((dns_rdatatype_t)dns_rdatatype_l32)
#define dns_rdatatype_l64	((dns_rdatatype_t)dns_rdatatype_l64)
#define dns_rdatatype_lp	((dns_rdatatype_t)dns_rdatatype_lp)
#define dns_rdatatype_eui48	((dns_rdatatype_t)dns_rdatatype_eui48)
#define dns_rdatatype_eui64	((dns_rdatatype_t)dns_rdatatype_eui64)
#define dns_rdatatype_tkey	((dns_rdatatype_t)dns_rdatatype_tkey)
#define dns_rdatatype_tsig	((dns_rdatatype_t)dns_rdatatype_tsig)
#define dns_rdatatype_uri	((dns_rdatatype_t)dns_rdatatype_uri)
#define dns_rdatatype_caa	((dns_rdatatype_t)dns_rdatatype_caa)
#define dns_rdatatype_avc	((dns_rdatatype_t)dns_rdatatype_avc)
#define dns_rdatatype_doa	((dns_rdatatype_t)dns_rdatatype_doa)
#define dns_rdatatype_amtrelay	((dns_rdatatype_t)dns_rdatatype_amtrelay)
#define dns_rdatatype_ta	((dns_rdatatype_t)dns_rdatatype_ta)
#define dns_rdatatype_dlv	((dns_rdatatype_t)dns_rdatatype_dlv)
#define dns_rdatatype_keydata	((dns_rdatatype_t)dns_rdatatype_keydata)
#define dns_rdatatype_ixfr	((dns_rdatatype_t)dns_rdatatype_ixfr)
#define dns_rdatatype_axfr	((dns_rdatatype_t)dns_rdatatype_axfr)
#define dns_rdatatype_mailb	((dns_rdatatype_t)dns_rdatatype_mailb)
#define dns_rdatatype_maila	((dns_rdatatype_t)dns_rdatatype_maila)
#define dns_rdatatype_any	((dns_rdatatype_t)dns_rdatatype_any)

#endif /* DNS_ENUMTYPE_H */
rdatasetiter.h000064400000007526150415243030007417 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_RDATASETITER_H
#define DNS_RDATASETITER_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/rdatasetiter.h
 * \brief
 * The DNS Rdataset Iterator interface allows iteration of all of the
 * rdatasets at a node.
 *
 * The dns_rdatasetiter_t type is like a "virtual class".  To actually use
 * it, an implementation of the class is required.  This implementation is
 * supplied by the database.
 *
 * It is the client's responsibility to call dns_rdataset_disassociate()
 * on all rdatasets returned.
 *
 * XXX more XXX
 *
 * MP:
 *\li	The iterator itself is not locked.  The caller must ensure
 *	synchronization.
 *
 *\li	The iterator methods ensure appropriate database locking.
 *
 * Reliability:
 *\li	No anticipated impact.
 *
 * Resources:
 *\li	TBS
 *
 * Security:
 *\li	No anticipated impact.
 *
 * Standards:
 *\li	None.
 */

/*****
 ***** Imports
 *****/

#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/stdtime.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

/*****
 ***** Types
 *****/

typedef struct dns_rdatasetitermethods {
	void		(*destroy)(dns_rdatasetiter_t **iteratorp);
	isc_result_t	(*first)(dns_rdatasetiter_t *iterator);
	isc_result_t	(*next)(dns_rdatasetiter_t *iterator);
	void		(*current)(dns_rdatasetiter_t *iterator,
				   dns_rdataset_t *rdataset);
} dns_rdatasetitermethods_t;

#define DNS_RDATASETITER_MAGIC	     ISC_MAGIC('D','N','S','i')
#define DNS_RDATASETITER_VALID(i)    ISC_MAGIC_VALID(i, DNS_RDATASETITER_MAGIC)

/*%
 * This structure is actually just the common prefix of a DNS db
 * implementation's version of a dns_rdatasetiter_t.
 * \brief
 * Direct use of this structure by clients is forbidden.  DB implementations
 * may change the structure.  'magic' must be #DNS_RDATASETITER_MAGIC for
 * any of the dns_rdatasetiter routines to work.  DB implementations must
 * maintain all DB rdataset iterator invariants.
 */
struct dns_rdatasetiter {
	/* Unlocked. */
	unsigned int			magic;
	dns_rdatasetitermethods_t *	methods;
	dns_db_t *			db;
	dns_dbnode_t *			node;
	dns_dbversion_t *		version;
	isc_stdtime_t			now;
};

void
dns_rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
/*%<
 * Destroy '*iteratorp'.
 *
 * Requires:
 *
 *\li	'*iteratorp' is a valid iterator.
 *
 * Ensures:
 *
 *\li	All resources used by the iterator are freed.
 *
 *\li	*iteratorp == NULL.
 */

isc_result_t
dns_rdatasetiter_first(dns_rdatasetiter_t *iterator);
/*%<
 * Move the rdataset cursor to the first rdataset at the node (if any).
 *
 * Requires:
 *\li	'iterator' is a valid iterator.
 *
 * Returns:
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_NOMORE			There are no rdatasets at the node.
 *
 *\li	Other results are possible, depending on the DB implementation.
 */

isc_result_t
dns_rdatasetiter_next(dns_rdatasetiter_t *iterator);
/*%<
 * Move the rdataset cursor to the next rdataset at the node (if any).
 *
 * Requires:
 *\li	'iterator' is a valid iterator.
 *
 * Returns:
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_NOMORE			There are no more rdatasets at the
 *					node.
 *
 *\li	Other results are possible, depending on the DB implementation.
 */

void
dns_rdatasetiter_current(dns_rdatasetiter_t *iterator,
			 dns_rdataset_t *rdataset);
/*%<
 * Return the current rdataset.
 *
 * Requires:
 *\li	'iterator' is a valid iterator.
 *
 *\li	'rdataset' is a valid, disassociated rdataset.
 *
 *\li	The rdataset cursor of 'iterator' is at a valid location (i.e. the
 *	result of last call to a cursor movement command was #ISC_R_SUCCESS).
 */

ISC_LANG_ENDDECLS

#endif /* DNS_RDATASETITER_H */
master.h000064400000026031150415243030006207 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_MASTER_H
#define DNS_MASTER_H 1

/*! \file dns/master.h */

/***
 ***	Imports
 ***/

#include <stdio.h>

#include <isc/lang.h>

#include <dns/types.h>

/*
 * Flags to be passed in the 'options' argument in the functions below.
 */
#define	DNS_MASTER_AGETTL 	0x00000001	/*%< Age the ttl based on $DATE. */
#define DNS_MASTER_MANYERRORS 	0x00000002	/*%< Continue processing on errors. */
#define DNS_MASTER_NOINCLUDE 	0x00000004	/*%< Disallow $INCLUDE directives. */
#define DNS_MASTER_ZONE 	0x00000008	/*%< Loading a zone master file. */
#define DNS_MASTER_HINT 	0x00000010	/*%< Loading a hint master file. */
#define DNS_MASTER_SLAVE 	0x00000020	/*%< Loading a slave master file. */
#define DNS_MASTER_CHECKNS 	0x00000040	/*%<
						 * Check NS records to see
						 * if they are an address
						 */
#define DNS_MASTER_FATALNS 	0x00000080	/*%<
						 * Treat DNS_MASTER_CHECKNS
						 * matches as fatal
						 */
#define DNS_MASTER_CHECKNAMES   0x00000100
#define DNS_MASTER_CHECKNAMESFAIL 0x00000200
#define DNS_MASTER_CHECKWILDCARD 0x00000400	/* Check for internal wildcards. */
#define DNS_MASTER_CHECKMX	0x00000800
#define DNS_MASTER_CHECKMXFAIL	0x00001000

#define DNS_MASTER_RESIGN	0x00002000
#define DNS_MASTER_KEY	 	0x00004000	/*%< Loading a key zone master file. */
#define DNS_MASTER_NOTTL	0x00008000	/*%< Don't require ttl. */
#define DNS_MASTER_CHECKTTL	0x00010000	/*%< Check max-zone-ttl */

ISC_LANG_BEGINDECLS

/*
 * Structures that implement the "raw" format for master dump.
 * These are provided for a reference purpose only; in the actual
 * encoding, we directly read/write each field so that the encoded data
 * is always "packed", regardless of the hardware architecture.
 */
#define DNS_RAWFORMAT_VERSION 1

/*
 * Flags to indicate the status of the data in the raw file header
 */
#define DNS_MASTERRAW_COMPAT 		0x01
#define DNS_MASTERRAW_SOURCESERIALSET	0x02
#define DNS_MASTERRAW_LASTXFRINSET	0x04

/* Common header */
struct dns_masterrawheader {
	uint32_t		format;		/* must be
						 * dns_masterformat_raw
						 * or
						 * dns_masterformat_map */
	uint32_t		version;	/* compatibility for future
						 * extensions */
	uint32_t		dumptime;	/* timestamp on creation
						 * (currently unused) */
	uint32_t		flags;		/* Flags */
	uint32_t		sourceserial;	/* Source serial number (used
						 * by inline-signing zones) */
	uint32_t		lastxfrin;	/* timestamp of last transfer
						 * (used by slave zones) */
};

/* The structure for each RRset */
typedef struct {
	uint32_t		totallen;	/* length of the data for this
						 * RRset, including the
						 * "header" part */
	dns_rdataclass_t	rdclass;	/* 16-bit class */
	dns_rdatatype_t		type;		/* 16-bit type */
	dns_rdatatype_t		covers;		/* same as type */
	dns_ttl_t		ttl;		/* 32-bit TTL */
	uint32_t		nrdata;		/* number of RRs in this set */
	/* followed by encoded owner name, and then rdata */
} dns_masterrawrdataset_t;

/*
 * Method prototype: a callback to register each include file as
 * it is encountered.
 */
typedef void
(*dns_masterincludecb_t)(const char *file, void *arg);

/***
 ***	Function
 ***/

isc_result_t
dns_master_loadfile(const char *master_file,
		    dns_name_t *top,
		    dns_name_t *origin,
		    dns_rdataclass_t zclass,
		    unsigned int options,
		    dns_rdatacallbacks_t *callbacks,
		    isc_mem_t *mctx);

isc_result_t
dns_master_loadfile2(const char *master_file,
		     dns_name_t *top,
		     dns_name_t *origin,
		     dns_rdataclass_t zclass,
		     unsigned int options,
		     dns_rdatacallbacks_t *callbacks,
		     isc_mem_t *mctx,
		     dns_masterformat_t format);

isc_result_t
dns_master_loadfile3(const char *master_file,
		     dns_name_t *top,
		     dns_name_t *origin,
		     dns_rdataclass_t zclass,
		     unsigned int options,
		     uint32_t resign,
		     dns_rdatacallbacks_t *callbacks,
		     isc_mem_t *mctx,
		     dns_masterformat_t format);

isc_result_t
dns_master_loadfile4(const char *master_file,
		     dns_name_t *top,
		     dns_name_t *origin,
		     dns_rdataclass_t zclass,
		     unsigned int options,
		     uint32_t resign,
		     dns_rdatacallbacks_t *callbacks,
		     dns_masterincludecb_t include_cb,
		     void *include_arg, isc_mem_t *mctx,
		     dns_masterformat_t format);

isc_result_t
dns_master_loadfile5(const char *master_file,
		     dns_name_t *top,
		     dns_name_t *origin,
		     dns_rdataclass_t zclass,
		     unsigned int options,
		     uint32_t resign,
		     dns_rdatacallbacks_t *callbacks,
		     dns_masterincludecb_t include_cb,
		     void *include_arg, isc_mem_t *mctx,
		     dns_masterformat_t format,
		     dns_ttl_t maxttl);

isc_result_t
dns_master_loadstream(FILE *stream,
		      dns_name_t *top,
		      dns_name_t *origin,
		      dns_rdataclass_t zclass,
		      unsigned int options,
		      dns_rdatacallbacks_t *callbacks,
		      isc_mem_t *mctx);

isc_result_t
dns_master_loadbuffer(isc_buffer_t *buffer,
		      dns_name_t *top,
		      dns_name_t *origin,
		      dns_rdataclass_t zclass,
		      unsigned int options,
		      dns_rdatacallbacks_t *callbacks,
		      isc_mem_t *mctx);

isc_result_t
dns_master_loadlexer(isc_lex_t *lex,
		     dns_name_t *top,
		     dns_name_t *origin,
		     dns_rdataclass_t zclass,
		     unsigned int options,
		     dns_rdatacallbacks_t *callbacks,
		     isc_mem_t *mctx);

isc_result_t
dns_master_loadfileinc(const char *master_file,
		       dns_name_t *top,
		       dns_name_t *origin,
		       dns_rdataclass_t zclass,
		       unsigned int options,
		       dns_rdatacallbacks_t *callbacks,
		       isc_task_t *task,
		       dns_loaddonefunc_t done, void *done_arg,
		       dns_loadctx_t **ctxp, isc_mem_t *mctx);

isc_result_t
dns_master_loadfileinc2(const char *master_file,
			dns_name_t *top,
			dns_name_t *origin,
			dns_rdataclass_t zclass,
			unsigned int options,
			dns_rdatacallbacks_t *callbacks,
			isc_task_t *task,
			dns_loaddonefunc_t done, void *done_arg,
			dns_loadctx_t **ctxp, isc_mem_t *mctx,
			dns_masterformat_t format);

isc_result_t
dns_master_loadfileinc3(const char *master_file,
			dns_name_t *top,
			dns_name_t *origin,
			dns_rdataclass_t zclass,
			unsigned int options,
			uint32_t resign,
			dns_rdatacallbacks_t *callbacks,
			isc_task_t *task,
			dns_loaddonefunc_t done, void *done_arg,
			dns_loadctx_t **ctxp, isc_mem_t *mctx,
			dns_masterformat_t format);

isc_result_t
dns_master_loadfileinc4(const char *master_file,
			dns_name_t *top,
			dns_name_t *origin,
			dns_rdataclass_t zclass,
			unsigned int options,
			uint32_t resign,
			dns_rdatacallbacks_t *callbacks,
			isc_task_t *task,
			dns_loaddonefunc_t done, void *done_arg,
			dns_loadctx_t **ctxp,
			dns_masterincludecb_t include_cb, void *include_arg,
			isc_mem_t *mctx, dns_masterformat_t format);

isc_result_t
dns_master_loadfileinc5(const char *master_file,
			dns_name_t *top,
			dns_name_t *origin,
			dns_rdataclass_t zclass,
			unsigned int options,
			uint32_t resign,
			dns_rdatacallbacks_t *callbacks,
			isc_task_t *task,
			dns_loaddonefunc_t done, void *done_arg,
			dns_loadctx_t **ctxp,
			dns_masterincludecb_t include_cb, void *include_arg,
			isc_mem_t *mctx, dns_masterformat_t format,
			uint32_t maxttl);

isc_result_t
dns_master_loadstreaminc(FILE *stream,
			 dns_name_t *top,
			 dns_name_t *origin,
			 dns_rdataclass_t zclass,
			 unsigned int options,
			 dns_rdatacallbacks_t *callbacks,
			 isc_task_t *task,
			 dns_loaddonefunc_t done, void *done_arg,
			 dns_loadctx_t **ctxp, isc_mem_t *mctx);

isc_result_t
dns_master_loadbufferinc(isc_buffer_t *buffer,
			 dns_name_t *top,
			 dns_name_t *origin,
			 dns_rdataclass_t zclass,
			 unsigned int options,
			 dns_rdatacallbacks_t *callbacks,
			 isc_task_t *task,
			 dns_loaddonefunc_t done, void *done_arg,
			 dns_loadctx_t **ctxp, isc_mem_t *mctx);

isc_result_t
dns_master_loadlexerinc(isc_lex_t *lex,
			dns_name_t *top,
			dns_name_t *origin,
			dns_rdataclass_t zclass,
			unsigned int options,
			dns_rdatacallbacks_t *callbacks,
			isc_task_t *task,
			dns_loaddonefunc_t done, void *done_arg,
			dns_loadctx_t **ctxp, isc_mem_t *mctx);

/*%<
 * Loads a RFC1305 master file from a file, stream, buffer, or existing
 * lexer into rdatasets and then calls 'callbacks->commit' to commit the
 * rdatasets.  Rdata memory belongs to dns_master_load and will be
 * reused / released when the callback completes.  dns_load_master will
 * abort if callbacks->commit returns any value other than ISC_R_SUCCESS.
 *
 * If 'DNS_MASTER_AGETTL' is set and the master file contains one or more
 * $DATE directives, the TTLs of the data will be aged accordingly.
 *
 * 'callbacks->commit' is assumed to call 'callbacks->error' or
 * 'callbacks->warn' to generate any error messages required.
 *
 * 'done' is called with 'done_arg' and a result code when the loading
 * is completed or has failed.  If the initial setup fails 'done' is
 * not called.
 *
 * 'resign' the number of seconds before a RRSIG expires that it should
 * be re-signed.  0 is used if not provided.
 *
 * Requires:
 *\li	'master_file' points to a valid string.
 *\li	'lexer' points to a valid lexer.
 *\li	'top' points to a valid name.
 *\li	'origin' points to a valid name.
 *\li	'callbacks->commit' points to a valid function.
 *\li	'callbacks->error' points to a valid function.
 *\li	'callbacks->warn' points to a valid function.
 *\li	'mctx' points to a valid memory context.
 *\li	'task' and 'done' to be valid.
 *\li	'lmgr' to be valid.
 *\li	'ctxp != NULL && ctxp == NULL'.
 *
 * Returns:
 *\li	ISC_R_SUCCESS upon successfully loading the master file.
 *\li	ISC_R_SEENINCLUDE upon successfully loading the master file with
 *		a $INCLUDE statement.
 *\li	ISC_R_NOMEMORY out of memory.
 *\li	ISC_R_UNEXPECTEDEND expected to be able to read a input token and
 *		there was not one.
 *\li	ISC_R_UNEXPECTED
 *\li	DNS_R_NOOWNER failed to specify a ownername.
 *\li	DNS_R_NOTTL failed to specify a ttl.
 *\li	DNS_R_BADCLASS record class did not match zone class.
 *\li	DNS_R_CONTINUE load still in progress (dns_master_load*inc() only).
 *\li	Any dns_rdata_fromtext() error code.
 *\li	Any error code from callbacks->commit().
 */

void
dns_loadctx_detach(dns_loadctx_t **ctxp);
/*%<
 * Detach from the load context.
 *
 * Requires:
 *\li	'*ctxp' to be valid.
 *
 * Ensures:
 *\li	'*ctxp == NULL'
 */

void
dns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target);
/*%<
 * Attach to the load context.
 *
 * Requires:
 *\li	'source' to be valid.
 *\li	'target != NULL && *target == NULL'.
 */

void
dns_loadctx_cancel(dns_loadctx_t *ctx);
/*%<
 * Cancel loading the zone file associated with this load context.
 *
 * Requires:
 *\li	'ctx' to be valid
 */

void
dns_master_initrawheader(dns_masterrawheader_t *header);
/*%<
 * Initializes the header for a raw master file, setting all
 * values to zero.
 */
ISC_LANG_ENDDECLS

#endif /* DNS_MASTER_H */
lib.h000064400000002250150415243030005457 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_LIB_H
#define DNS_LIB_H 1

/*! \file dns/lib.h */

#include <isc/types.h>
#include <isc/lang.h>

ISC_LANG_BEGINDECLS

/*%
 * Tuning: external query load in packets per seconds.
 */
LIBDNS_EXTERNAL_DATA extern unsigned int dns_pps;
LIBDNS_EXTERNAL_DATA extern isc_msgcat_t *dns_msgcat;

void
dns_lib_initmsgcat(void);
/*%<
 * Initialize the DNS library's message catalog, dns_msgcat, if it
 * has not already been initialized.
 */

isc_result_t
dns_lib_init(void);
/*%<
 * A set of initialization procedure used in the DNS library.  This function
 * is provided for an application that is not aware of the underlying ISC or
 * DNS libraries much.
 */

void
dns_lib_shutdown(void);
/*%<
 * Free temporary resources allocated in dns_lib_init().
 */

ISC_LANG_ENDDECLS

#endif /* DNS_LIB_H */
dlz.h000064400000024572150415243030005515 0ustar00/*
 * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/*
 * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the
 * above copyright notice and this permission notice appear in all
 * copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
 * USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
 * conceived and contributed by Rob Butler.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the
 * above copyright notice and this permission notice appear in all
 * copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
 * USE OR PERFORMANCE OF THIS SOFTWARE.
 */


/*! \file dns/dlz.h */

#ifndef DLZ_H
#define DLZ_H 1

/*****
 ***** Module Info
 *****/

/*
 * DLZ Interface
 *
 * The DLZ interface allows zones to be looked up using a driver instead of
 * Bind's default in memory zone table.
 *
 *
 * Reliability:
 *	No anticipated impact.
 *
 * Resources:
 *
 * Security:
 *	No anticipated impact.
 *
 * Standards:
 *	None.
 */

/*****
 ***** Imports
 *****/

#include <stdbool.h>

#include <dns/clientinfo.h>
#include <dns/name.h>
#include <dns/types.h>
#include <dns/view.h>
#include <dst/dst.h>

#include <isc/lang.h>

ISC_LANG_BEGINDECLS

/***
 *** Types
 ***/

#define DNS_DLZ_MAGIC		ISC_MAGIC('D','L','Z','D')
#define DNS_DLZ_VALID(dlz)	ISC_MAGIC_VALID(dlz, DNS_DLZ_MAGIC)

typedef isc_result_t
(*dns_dlzallowzonexfr_t)(void *driverarg, void *dbdata, isc_mem_t *mctx,
			 dns_rdataclass_t rdclass, dns_name_t *name,
			 isc_sockaddr_t *clientaddr,
			 dns_db_t **dbp);

/*%<
 * Method prototype.  Drivers implementing the DLZ interface MUST
 * supply an allow zone transfer method.  This method is called when
 * the DNS server is performing a zone transfer query.  The driver's
 * method should return ISC_R_SUCCESS and a database pointer to the
 * name server if the zone is supported by the database, and zone
 * transfer is allowed.  Otherwise it will return ISC_R_NOTFOUND if
 * the zone is not supported by the database, or ISC_R_NOPERM if zone
 * transfers are not allowed.  If an error occurs it should return a
 * result code indicating the type of error.
 */

typedef isc_result_t
(*dns_dlzcreate_t)(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
		   char *argv[], void *driverarg, void **dbdata);

/*%<
 * Method prototype.  Drivers implementing the DLZ interface MUST
 * supply a create method.  This method is called when the DNS server
 * is starting up and creating drivers for use later.
 */

typedef void
(*dns_dlzdestroy_t)(void *driverarg, void **dbdata);

/*%<
 * Method prototype.  Drivers implementing the DLZ interface MUST
 * supply a destroy method.  This method is called when the DNS server
 * is shutting down and no longer needs the driver.
 */

typedef isc_result_t
(*dns_dlzfindzone_t)(void *driverarg, void *dbdata, isc_mem_t *mctx,
		     dns_rdataclass_t rdclass, dns_name_t *name,
		     dns_clientinfomethods_t *methods,
		     dns_clientinfo_t *clientinfo,
		     dns_db_t **dbp);

/*%<
 * Method prototype.  Drivers implementing the DLZ interface MUST
 * supply a find zone method.  This method is called when the DNS
 * server is performing a query.  The find zone method will be called
 * with the longest possible name first, and continue to be called
 * with successively shorter domain names, until any of the following
 * occur:
 *
 * \li	1) a match is found, and the function returns (ISC_R_SUCCESS)
 *
 * \li	2) a problem occurs, and the functions returns anything other
 *	   than (ISC_R_NOTFOUND)
 * \li	3) we run out of domain name labels. I.E. we have tried the
 *	   shortest domain name
 * \li	4) the number of labels in the domain name is less than
 *	   min_labels for dns_dlzfindzone
 *
 * The driver's find zone method should return ISC_R_SUCCESS and a
 * database pointer to the name server if the zone is supported by the
 * database.  Otherwise it will return ISC_R_NOTFOUND, and a null
 * pointer if the zone is not supported.  If an error occurs it should
 * return a result code indicating the type of error.
 */


typedef isc_result_t
(*dns_dlzconfigure_t)(void *driverarg, void *dbdata,
		      dns_view_t *view, dns_dlzdb_t *dlzdb);
/*%<
 * Method prototype.  Drivers implementing the DLZ interface may
 * optionally supply a configure method. If supplied, this will be
 * called immediately after the create method is called. The driver
 * may call configuration functions during the configure call
 */


typedef bool (*dns_dlzssumatch_t)(dns_name_t *signer,
					   dns_name_t *name,
					   isc_netaddr_t *tcpaddr,
					   dns_rdatatype_t type,
					   const dst_key_t *key,
					   void *driverarg, void *dbdata);
/*%<
 * Method prototype.  Drivers implementing the DLZ interface may
 * optionally supply a ssumatch method. If supplied, this will be
 * called to authorize update requests
 */

/*% the methods supplied by a DLZ driver */
typedef struct dns_dlzmethods {
	dns_dlzcreate_t		create;
	dns_dlzdestroy_t	destroy;
	dns_dlzfindzone_t	findzone;
	dns_dlzallowzonexfr_t	allowzonexfr;
	dns_dlzconfigure_t	configure;
	dns_dlzssumatch_t	ssumatch;
} dns_dlzmethods_t;

/*% information about a DLZ driver */
struct dns_dlzimplementation {
	const char				*name;
	const dns_dlzmethods_t			*methods;
	isc_mem_t				*mctx;
	void					*driverarg;
	ISC_LINK(dns_dlzimplementation_t)	link;
};

typedef isc_result_t (*dlzconfigure_callback_t)(dns_view_t *, dns_dlzdb_t *,
						dns_zone_t *);

/*% An instance of a DLZ driver */
struct dns_dlzdb {
	unsigned int		magic;
	isc_mem_t		*mctx;
	dns_dlzimplementation_t	*implementation;
	void			*dbdata;
	dlzconfigure_callback_t configure_callback;
	bool		search;
	char			*dlzname;
	ISC_LINK(dns_dlzdb_t)	link;
	dns_ssutable_t 		*ssutable;
};


/***
 *** Method declarations
 ***/

isc_result_t
dns_dlzallowzonexfr(dns_view_t *view, dns_name_t *name,
		    isc_sockaddr_t *clientaddr, dns_db_t **dbp);

/*%<
 * This method is called when the DNS server is performing a zone
 * transfer query.  It will call the DLZ driver's allow zone transfer
 * method.
 */

isc_result_t
dns_dlzcreate(isc_mem_t *mctx, const char *dlzname,
	      const char *drivername, unsigned int argc,
	      char *argv[], dns_dlzdb_t **dbp);

/*%<
 * This method is called when the DNS server is starting up and
 * creating drivers for use later.  It will search the DLZ driver list
 * for 'drivername' and return a DLZ driver via dbp if a match is
 * found.  If the DLZ driver supplies a create method, this function
 * will call it.
 */

void
dns_dlzdestroy(dns_dlzdb_t **dbp);

/*%<
 * This method is called when the DNS server is shutting down and no
 * longer needs the driver.  If the DLZ driver supplies a destroy
 * methods, this function will call it.
 */

isc_result_t
dns_dlzregister(const char *drivername, const dns_dlzmethods_t *methods,
		 void *driverarg, isc_mem_t *mctx,
		dns_dlzimplementation_t **dlzimp);

/*%<
 * Register a dynamically loadable zones (DLZ) driver for the database
 * type 'drivername', implemented by the functions in '*methods'.
 *
 * dlzimp must point to a NULL dlz_implementation_t pointer.  That is,
 * dlzimp != NULL && *dlzimp == NULL.  It will be assigned a value that
 * will later be used to identify the driver when deregistering it.
 */

isc_result_t
dns_dlzstrtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp);

/*%<
 * This method is called when the name server is starting up to parse
 * the DLZ driver command line from named.conf.  Basically it splits
 * up a string into and argc / argv.  The primary difference of this
 * method is items between braces { } are considered only 1 word.  for
 * example the command line "this is { one grouped phrase } and this
 * isn't" would be parsed into:
 *
 * \li	argv[0]: "this"
 * \li	argv[1]: "is"
 * \li	argv{2]: " one grouped phrase "
 * \li	argv[3]: "and"
 * \li	argv[4]: "this"
 * \li	argv{5}: "isn't"
 *
 * braces should NOT be nested, more than one grouping in the command
 * line is allowed.  Notice, argv[2] has an extra space at the
 * beginning and end.  Extra spaces are not stripped between a
 * grouping.  You can do so in your driver if needed, or be sure not
 * to put extra spaces before / after the braces.
 */

void
dns_dlzunregister(dns_dlzimplementation_t **dlzimp);

/*%<
 * Removes the dlz driver from the list of registered dlz drivers.
 * There must be no active dlz drivers of this type when this function
 * is called.
 */


typedef isc_result_t dns_dlz_writeablezone_t(dns_view_t *view,
					     dns_dlzdb_t *dlzdb,
					     const char *zone_name);
dns_dlz_writeablezone_t dns_dlz_writeablezone;
/*%<
 * creates a writeable DLZ zone. Must be called from within the
 * configure() method of a DLZ driver.
 */


isc_result_t
dns_dlzconfigure(dns_view_t *view, dns_dlzdb_t *dlzdb,
		 dlzconfigure_callback_t callback);
/*%<
 * call a DLZ drivers configure method, if supplied
 */

bool
dns_dlz_ssumatch(dns_dlzdb_t *dlzdatabase,
		  dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr,
		  dns_rdatatype_t type, const dst_key_t *key);
/*%<
 * call a DLZ drivers ssumatch method, if supplied. Otherwise return false
 */

ISC_LANG_ENDDECLS

#endif /* DLZ_H */
xfrin.h000064400000005554150415243030006051 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_XFRIN_H
#define DNS_XFRIN_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/xfrin.h
 * \brief
 * Incoming zone transfers (AXFR + IXFR).
 */

/***
 *** Imports
 ***/

#include <isc/lang.h>

#include <dns/types.h>

/***
 *** Types
 ***/

/*%
 * A transfer in progress.  This is an opaque type.
 */
typedef struct dns_xfrin_ctx dns_xfrin_ctx_t;

/***
 *** Functions
 ***/

ISC_LANG_BEGINDECLS

/*% see dns_xfrin_create2() */
isc_result_t
dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
		 isc_sockaddr_t *masteraddr, dns_tsigkey_t *tsigkey,
		 isc_mem_t *mctx, isc_timermgr_t *timermgr,
		 isc_socketmgr_t *socketmgr, isc_task_t *task,
		 dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp);

isc_result_t
dns_xfrin_create2(dns_zone_t *zone, dns_rdatatype_t xfrtype,
		  isc_sockaddr_t *masteraddr, isc_sockaddr_t *sourceaddr,
		  dns_tsigkey_t *tsigkey, isc_mem_t *mctx,
		  isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
		  isc_task_t *task, dns_xfrindone_t done,
		  dns_xfrin_ctx_t **xfrp);

isc_result_t
dns_xfrin_create3(dns_zone_t *zone, dns_rdatatype_t xfrtype,
		  isc_sockaddr_t *masteraddr, isc_sockaddr_t *sourceaddr,
		  isc_dscp_t dscp, dns_tsigkey_t *tsigkey, isc_mem_t *mctx,
		  isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
		  isc_task_t *task, dns_xfrindone_t done,
		  dns_xfrin_ctx_t **xfrp);
/*%<
 * Attempt to start an incoming zone transfer of 'zone'
 * from 'masteraddr', creating a dns_xfrin_ctx_t object to
 * manage it.  Attach '*xfrp' to the newly created object.
 *
 * Iff ISC_R_SUCCESS is returned, '*done' is guaranteed to be
 * called in the context of 'task', with 'zone' and a result
 * code as arguments when the transfer finishes.
 *
 * Requires:
 *\li	'xfrtype' is dns_rdatatype_axfr, dns_rdatatype_ixfr
 *	or dns_rdatatype_soa (soa query followed by axfr if
 *	serial is greater than current serial).
 *
 *\li	If 'xfrtype' is dns_rdatatype_ixfr or dns_rdatatype_soa,
 *	the zone has a database.
 */

void
dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr);
/*%<
 * If the zone transfer 'xfr' has already finished,
 * do nothing.  Otherwise, abort it and cause it to call
 * its done callback with a status of ISC_R_CANCELED.
 */

void
dns_xfrin_detach(dns_xfrin_ctx_t **xfrp);
/*%<
 * Detach a reference to a zone transfer object.
 * Caller to maintain external locking if required.
 */

void
dns_xfrin_attach(dns_xfrin_ctx_t *source, dns_xfrin_ctx_t **target);
/*%<
 * Caller to maintain external locking if required.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_XFRIN_H */
tcpmsg.h000064400000006111150415243030006206 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_TCPMSG_H
#define DNS_TCPMSG_H 1

/*! \file dns/tcpmsg.h */

#include <inttypes.h>

#include <isc/buffer.h>
#include <isc/lang.h>
#include <isc/socket.h>

typedef struct dns_tcpmsg {
	/* private (don't touch!) */
	unsigned int		magic;
	uint16_t		size;
	isc_buffer_t		buffer;
	unsigned int		maxsize;
	isc_mem_t	       *mctx;
	isc_socket_t	       *sock;
	isc_task_t	       *task;
	isc_taskaction_t	action;
	void		       *arg;
	isc_event_t		event;
	/* public (read-only) */
	isc_result_t		result;
	isc_sockaddr_t		address;
} dns_tcpmsg_t;

ISC_LANG_BEGINDECLS

void
dns_tcpmsg_init(isc_mem_t *mctx, isc_socket_t *sock, dns_tcpmsg_t *tcpmsg);
/*%<
 * Associate a tcp message state with a given memory context and
 * TCP socket.
 *
 * Requires:
 *
 *\li	"mctx" and "sock" be non-NULL and valid types.
 *
 *\li	"sock" be a read/write TCP socket.
 *
 *\li	"tcpmsg" be non-NULL and an uninitialized or invalidated structure.
 *
 * Ensures:
 *
 *\li	"tcpmsg" is a valid structure.
 */

void
dns_tcpmsg_setmaxsize(dns_tcpmsg_t *tcpmsg, unsigned int maxsize);
/*%<
 * Set the maximum packet size to "maxsize"
 *
 * Requires:
 *
 *\li	"tcpmsg" be valid.
 *
 *\li	512 <= "maxsize" <= 65536
 */

isc_result_t
dns_tcpmsg_readmessage(dns_tcpmsg_t *tcpmsg,
		       isc_task_t *task, isc_taskaction_t action, void *arg);
/*%<
 * Schedule an event to be delivered when a DNS message is readable, or
 * when an error occurs on the socket.
 *
 * Requires:
 *
 *\li	"tcpmsg" be valid.
 *
 *\li	"task", "taskaction", and "arg" be valid.
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS		-- no error
 *\li	Anything that the isc_socket_recv() call can return.  XXXMLG
 *
 * Notes:
 *
 *\li	The event delivered is a fully generic event.  It will contain no
 *	actual data.  The sender will be a pointer to the dns_tcpmsg_t.
 *	The result code inside that structure should be checked to see
 *	what the final result was.
 */

void
dns_tcpmsg_cancelread(dns_tcpmsg_t *tcpmsg);
/*%<
 * Cancel a readmessage() call.  The event will still be posted with a
 * CANCELED result code.
 *
 * Requires:
 *
 *\li	"tcpmsg" be valid.
 */

void
dns_tcpmsg_keepbuffer(dns_tcpmsg_t *tcpmsg, isc_buffer_t *buffer);
/*%<
 * If a dns buffer is to be kept between calls, this function marks the
 * internal state-machine buffer as invalid, and copies all the contents
 * of the state into "buffer".
 *
 * Requires:
 *
 *\li	"tcpmsg" be valid.
 *
 *\li	"buffer" be non-NULL.
 */

void
dns_tcpmsg_invalidate(dns_tcpmsg_t *tcpmsg);
/*%<
 * Clean up all allocated state, and invalidate the structure.
 *
 * Requires:
 *
 *\li	"tcpmsg" be valid.
 *
 * Ensures:
 *
 *\li	"tcpmsg" is invalidated and disassociated with all memory contexts,
 *	sockets, etc.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_TCPMSG_H */
iptable.h000064400000003125150415243030006333 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_IPTABLE_H
#define DNS_IPTABLE_H 1

#include <stdbool.h>

#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/radix.h>

#include <dns/types.h>

struct dns_iptable {
	unsigned int		magic;
	isc_mem_t		*mctx;
	isc_refcount_t		refcount;
	isc_radix_tree_t	*radix;
	ISC_LINK(dns_iptable_t)	nextincache;
};

#define DNS_IPTABLE_MAGIC	ISC_MAGIC('T','a','b','l')
#define DNS_IPTABLE_VALID(a)	ISC_MAGIC_VALID(a, DNS_IPTABLE_MAGIC)

/***
 *** Functions
 ***/

ISC_LANG_BEGINDECLS

isc_result_t
dns_iptable_create(isc_mem_t *mctx, dns_iptable_t **target);
/*
 * Create a new IP table and the underlying radix structure
 */

isc_result_t
dns_iptable_addprefix(dns_iptable_t *tab, isc_netaddr_t *addr,
		      uint16_t bitlen, bool pos);
isc_result_t
dns_iptable_addprefix2(dns_iptable_t *tab, isc_netaddr_t *addr,
		       uint16_t bitlen, bool pos,
		       bool is_ecs);
/*
 * Add an IP prefix to an existing IP table
 */

isc_result_t
dns_iptable_merge(dns_iptable_t *tab, dns_iptable_t *source, bool pos);
/*
 * Merge one IP table into another one.
 */

void
dns_iptable_attach(dns_iptable_t *source, dns_iptable_t **target);

void
dns_iptable_detach(dns_iptable_t **tabp);

ISC_LANG_ENDDECLS

#endif /* DNS_IPTABLE_H */
sdb.h000064400000016070150415243040005467 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_SDB_H
#define DNS_SDB_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/sdb.h
 * \brief
 * Simple database API.
 */

/***
 *** Imports
 ***/

#include <inttypes.h>

#include <isc/lang.h>

#include <dns/clientinfo.h>
#include <dns/types.h>

/***
 *** Types
 ***/

/*%
 * A simple database.  This is an opaque type.
 */
typedef struct dns_sdb dns_sdb_t;

/*%
 * A simple database lookup in progress.  This is an opaque type.
 */
typedef struct dns_sdblookup dns_sdblookup_t;

/*%
 * A simple database traversal in progress.  This is an opaque type.
 */
typedef struct dns_sdballnodes dns_sdballnodes_t;

typedef isc_result_t
(*dns_sdblookupfunc_t)(const char *zone, const char *name, void *dbdata,
		       dns_sdblookup_t *lookup,
		       dns_clientinfomethods_t *methods,
		       dns_clientinfo_t *clientinfo);
typedef isc_result_t
(*dns_sdblookup2func_t)(const dns_name_t *zone, const dns_name_t *name,
			void *dbdata, dns_sdblookup_t *lookup,
			dns_clientinfomethods_t *methods,
			dns_clientinfo_t *clientinfo);

typedef isc_result_t
(*dns_sdbauthorityfunc_t)(const char *zone, void *dbdata, dns_sdblookup_t *);

typedef isc_result_t
(*dns_sdballnodesfunc_t)(const char *zone, void *dbdata,
			 dns_sdballnodes_t *allnodes);

typedef isc_result_t
(*dns_sdbcreatefunc_t)(const char *zone, int argc, char **argv,
		       void *driverdata, void **dbdata);

typedef void
(*dns_sdbdestroyfunc_t)(const char *zone, void *driverdata, void **dbdata);


typedef struct dns_sdbmethods {
	dns_sdblookupfunc_t	lookup;
	dns_sdbauthorityfunc_t	authority;
	dns_sdballnodesfunc_t	allnodes;
	dns_sdbcreatefunc_t	create;
	dns_sdbdestroyfunc_t	destroy;
	dns_sdblookup2func_t	lookup2;
} dns_sdbmethods_t;

/***
 *** Functions
 ***/

ISC_LANG_BEGINDECLS

#define DNS_SDBFLAG_RELATIVEOWNER 0x00000001U
#define DNS_SDBFLAG_RELATIVERDATA 0x00000002U
#define DNS_SDBFLAG_THREADSAFE 0x00000004U
#define DNS_SDBFLAG_DNS64 0x00000008U

isc_result_t
dns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
		 void *driverdata, unsigned int flags, isc_mem_t *mctx,
		 dns_sdbimplementation_t **sdbimp);
/*%<
 * Register a simple database driver for the database type 'drivername',
 * implemented by the functions in '*methods'.
 *
 * sdbimp must point to a NULL dns_sdbimplementation_t pointer.  That is,
 * sdbimp != NULL && *sdbimp == NULL.  It will be assigned a value that
 * will later be used to identify the driver when deregistering it.
 *
 * The name server will perform lookups in the database by calling the
 * function 'lookup', passing it a printable zone name 'zone', a printable
 * domain name 'name', and a copy of the argument 'dbdata' that
 * was potentially returned by the create function.  The 'dns_sdblookup_t'
 * argument to 'lookup' and 'authority' is an opaque pointer to be passed to
 * ns_sdb_putrr().
 *
 * The lookup function returns the lookup results to the name server
 * by calling ns_sdb_putrr() once for each record found.  On success,
 * the return value of the lookup function should be ISC_R_SUCCESS.
 * If the domain name 'name' does not exist, the lookup function should
 * ISC_R_NOTFOUND.  Any other return value is treated as an error.
 *
 * Lookups at the zone apex will cause the server to also call the
 * function 'authority' (if non-NULL), which must provide an SOA record
 * and NS records for the zone by calling ns_sdb_putrr() once for each of
 * these records.  The 'authority' function may be NULL if invoking
 * the 'lookup' function on the zone apex will return SOA and NS records.
 *
 * The allnodes function, if non-NULL, fills in an opaque structure to be
 * used by a database iterator.  This allows the zone to be transferred.
 * This may use a considerable amount of memory for large zones, and the
 * zone transfer may not be fully RFC1035 compliant if the zone is
 * frequently changed.
 *
 * The create function will be called for each zone configured
 * into the name server using this database type.  It can be used
 * to create a "database object" containing zone specific data,
 * which can make use of the database arguments specified in the
 * name server configuration.
 *
 * The destroy function will be called to free the database object
 * when its zone is destroyed.
 *
 * The create and destroy functions may be NULL.
 *
 * If flags includes DNS_SDBFLAG_RELATIVEOWNER, the lookup and authority
 * functions will be called with relative names rather than absolute names.
 * The string "@" represents the zone apex in this case.
 *
 * If flags includes DNS_SDBFLAG_RELATIVERDATA, the rdata strings may
 * include relative names.  Otherwise, all names in the rdata string must
 * be absolute.  Be aware that if relative names are allowed, any
 * absolute names must contain a trailing dot.
 *
 * If flags includes DNS_SDBFLAG_THREADSAFE, the driver must be able to
 * handle multiple lookups in parallel.  Otherwise, calls into the driver
 * are serialized.
 */

void
dns_sdb_unregister(dns_sdbimplementation_t **sdbimp);
/*%<
 * Removes the simple database driver from the list of registered database
 * types.  There must be no active databases of this type when this function
 * is called.
 */

/*% See dns_sdb_putradata() */
isc_result_t
dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
	      const char *data);
isc_result_t
dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t type, dns_ttl_t ttl,
		 const unsigned char *rdata, unsigned int rdlen);
/*%<
 * Add a single resource record to the lookup structure to be
 * returned in the query response.  dns_sdb_putrr() takes the
 * resource record in master file text format as a null-terminated
 * string, and dns_sdb_putrdata() takes the raw RDATA in
 * uncompressed wire format.
 */

/*% See dns_sdb_putnamerdata() */
isc_result_t
dns_sdb_putnamedrr(dns_sdballnodes_t *allnodes, const char *name,
		   const char *type, dns_ttl_t ttl, const char *data);
isc_result_t
dns_sdb_putnamedrdata(dns_sdballnodes_t *allnodes, const char *name,
		      dns_rdatatype_t type, dns_ttl_t ttl,
		      const void *rdata, unsigned int rdlen);
/*%<
 * Add a single resource record to the allnodes structure to be
 * included in a zone transfer response, in text or wire
 * format as above.
 */

isc_result_t
dns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname,
	       uint32_t serial);
/*%<
 * This function may optionally be called from the 'authority' callback
 * to simplify construction of the SOA record for 'zone'.  It will
 * provide a SOA listing 'mname' as as the master server and 'rname' as
 * the responsible person mailbox.  It is the responsibility of the
 * driver to increment the serial number between responses if necessary.
 * All other SOA fields will have reasonable default values.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_SDB_H */
message.h000064400000113660150415243040006346 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_MESSAGE_H
#define DNS_MESSAGE_H 1

/***
 ***	Imports
 ***/

#include <inttypes.h>
#include <stdbool.h>

#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/refcount.h>

#include <dns/compress.h>
#include <dns/masterdump.h>
#include <dns/types.h>

#include <dst/dst.h>

/*! \file dns/message.h
 * \brief Message Handling Module
 *
 * How this beast works:
 *
 * When a dns message is received in a buffer, dns_message_parse() is called
 * on the memory region.  Various items are checked including the format
 * of the message (if counts are right, if counts consume the entire sections,
 * and if sections consume the entire message) and known pseudo-RRs in the
 * additional data section are analyzed and removed.
 *
 * TSIG checking is also done at this layer, and any DNSSEC transaction
 * signatures should also be checked here.
 *
 * Notes on using the gettemp*() and puttemp*() functions:
 *
 * These functions return items (names, rdatasets, etc) allocated from some
 * internal state of the dns_message_t.
 *
 * Names and rdatasets must be put back into the dns_message_t in
 * one of two ways.  Assume a name was allocated via
 * dns_message_gettempname():
 *
 *\li	(1) insert it into a section, using dns_message_addname().
 *
 *\li	(2) return it to the message using dns_message_puttempname().
 *
 * The same applies to rdatasets.
 *
 * On the other hand, offsets, rdatalists and rdatas allocated using
 * dns_message_gettemp*() will always be freed automatically
 * when the message is reset or destroyed; calling dns_message_puttemp*()
 * on rdatalists and rdatas is optional and serves only to enable the item
 * to be reused multiple times during the lifetime of the message; offsets
 * cannot be reused.
 *
 * Buffers allocated using isc_buffer_allocate() can be automatically freed
 * as well by giving the buffer to the message using dns_message_takebuffer().
 * Doing this will cause the buffer to be freed using isc_buffer_free()
 * when the section lists are cleared, such as in a reset or in a destroy.
 * Since the buffer itself exists until the message is destroyed, this sort
 * of code can be written:
 *
 * \code
 *	buffer = isc_buffer_allocate(mctx, 512);
 *	name = NULL;
 *	name = dns_message_gettempname(message, &name);
 *	dns_name_init(name, NULL);
 *	result = dns_name_fromtext(name, &source, dns_rootname, 0, buffer);
 *	dns_message_takebuffer(message, &buffer);
 * \endcode
 *
 *
 * TODO:
 *
 * XXX Needed:  ways to set and retrieve EDNS information, add rdata to a
 * section, move rdata from one section to another, remove rdata, etc.
 */

#define DNS_MESSAGEFLAG_QR		0x8000U
#define DNS_MESSAGEFLAG_AA		0x0400U
#define DNS_MESSAGEFLAG_TC		0x0200U
#define DNS_MESSAGEFLAG_RD		0x0100U
#define DNS_MESSAGEFLAG_RA		0x0080U
#define DNS_MESSAGEFLAG_AD		0x0020U
#define DNS_MESSAGEFLAG_CD		0x0010U

/*%< EDNS0 extended message flags */
#define DNS_MESSAGEEXTFLAG_DO		0x8000U

/*%< EDNS0 extended OPT codes */
#define DNS_OPT_LLQ	      1	 /*%< LLQ opt code */
#define DNS_OPT_NSID	      3	 /*%< NSID opt code */
#define DNS_OPT_CLIENT_SUBNET 8	 /*%< client subnet opt code */
#define DNS_OPT_EXPIRE	      9	 /*%< EXPIRE opt code */
#define DNS_OPT_COOKIE	      10 /*%< COOKIE opt code */
#define DNS_OPT_TCP_KEEPALIVE 11 /*%< TCP keepalive opt code */
#define DNS_OPT_PAD	      12 /*%< PAD opt code */
#define DNS_OPT_KEY_TAG	      14 /*%< Key tag opt code */
#define DNS_OPT_EDE	      15 /*%< Extended DNS Error opt code */
#define DNS_OPT_CLIENT_TAG    16 /*%< Client tag opt code */
#define DNS_OPT_SERVER_TAG    17 /*%< Server tag opt code */

/*%< Experimental options [65001...65534] as per RFC6891 */

/*%< The number of EDNS options we know about. */
#define DNS_EDNSOPTIONS	5

#define DNS_MESSAGE_REPLYPRESERVE	(DNS_MESSAGEFLAG_RD|DNS_MESSAGEFLAG_CD)
#define DNS_MESSAGEEXTFLAG_REPLYPRESERVE (DNS_MESSAGEEXTFLAG_DO)

#define DNS_MESSAGE_HEADERLEN		12 /*%< 6 uint16_t's */

#define DNS_MESSAGE_MAGIC		ISC_MAGIC('M','S','G','@')
#define DNS_MESSAGE_VALID(msg)		ISC_MAGIC_VALID(msg, DNS_MESSAGE_MAGIC)

/*
 * Ordering here matters.  DNS_SECTION_ANY must be the lowest and negative,
 * and DNS_SECTION_MAX must be one greater than the last used section.
 */
typedef int dns_section_t;
#define DNS_SECTION_ANY			(-1)
#define DNS_SECTION_QUESTION		0
#define DNS_SECTION_ANSWER		1
#define DNS_SECTION_AUTHORITY		2
#define DNS_SECTION_ADDITIONAL		3
#define DNS_SECTION_MAX			4

typedef int dns_pseudosection_t;
#define DNS_PSEUDOSECTION_ANY		(-1)
#define DNS_PSEUDOSECTION_OPT           0
#define DNS_PSEUDOSECTION_TSIG          1
#define DNS_PSEUDOSECTION_SIG0          2
#define DNS_PSEUDOSECTION_MAX           3

typedef int dns_messagetextflag_t;
#define DNS_MESSAGETEXTFLAG_NOCOMMENTS	0x0001
#define DNS_MESSAGETEXTFLAG_NOHEADERS	0x0002
#define DNS_MESSAGETEXTFLAG_ONESOA	0x0004
#define DNS_MESSAGETEXTFLAG_OMITSOA	0x0008

/*
 * Dynamic update names for these sections.
 */
#define DNS_SECTION_ZONE		DNS_SECTION_QUESTION
#define DNS_SECTION_PREREQUISITE	DNS_SECTION_ANSWER
#define DNS_SECTION_UPDATE		DNS_SECTION_AUTHORITY

/*
 * These tell the message library how the created dns_message_t will be used.
 */
#define DNS_MESSAGE_INTENTUNKNOWN	0 /*%< internal use only */
#define DNS_MESSAGE_INTENTPARSE		1 /*%< parsing messages */
#define DNS_MESSAGE_INTENTRENDER	2 /*%< rendering */

/*
 * Control behavior of parsing
 */
#define DNS_MESSAGEPARSE_PRESERVEORDER	0x0001	/*%< preserve rdata order */
#define DNS_MESSAGEPARSE_BESTEFFORT	0x0002	/*%< return a message if a
						   recoverable parse error
						   occurs */
#define DNS_MESSAGEPARSE_CLONEBUFFER	0x0004	/*%< save a copy of the
						   source buffer */
#define DNS_MESSAGEPARSE_IGNORETRUNCATION 0x0008 /*%< truncation errors are
						  * not fatal. */

/*
 * Control behavior of rendering
 */
#define DNS_MESSAGERENDER_ORDERED	0x0001	/*%< don't change order */
#define DNS_MESSAGERENDER_PARTIAL	0x0002	/*%< allow a partial rdataset */
#define DNS_MESSAGERENDER_OMITDNSSEC	0x0004	/*%< omit DNSSEC records */
#define DNS_MESSAGERENDER_PREFER_A	0x0008	/*%< prefer A records in
						     additional section. */
#define DNS_MESSAGERENDER_PREFER_AAAA	0x0010	/*%< prefer AAAA records in
						  additional section. */
#ifdef ALLOW_FILTER_AAAA
#define DNS_MESSAGERENDER_FILTER_AAAA	0x0020	/*%< filter AAAA records */
#endif

typedef struct dns_msgblock dns_msgblock_t;

struct dns_message {
	/* public from here down */
	unsigned int			magic;
	isc_refcount_t			refcount;

	dns_messageid_t			id;
	unsigned int			flags;
	dns_rcode_t			rcode;
	dns_opcode_t			opcode;
	dns_rdataclass_t		rdclass;

	/* 4 real, 1 pseudo */
	unsigned int			counts[DNS_SECTION_MAX];

	/* private from here down */
	dns_namelist_t			sections[DNS_SECTION_MAX];
	dns_name_t		       *cursors[DNS_SECTION_MAX];
	dns_rdataset_t		       *opt;
	dns_rdataset_t		       *sig0;
	dns_rdataset_t		       *tsig;

	int				state;
	unsigned int			from_to_wire : 2;
	unsigned int			header_ok : 1;
	unsigned int			question_ok : 1;
	unsigned int			tcp_continuation : 1;
	unsigned int			verified_sig : 1;
	unsigned int			verify_attempted : 1;
	unsigned int			free_query : 1;
	unsigned int			free_saved : 1;
	unsigned int			cc_ok : 1;
	unsigned int			cc_bad : 1;
	unsigned int			tkey : 1;
	unsigned int			rdclass_set : 1;

	unsigned int			opt_reserved;
	unsigned int			sig_reserved;
	unsigned int			reserved; /* reserved space (render) */

	isc_buffer_t		       *buffer;
	dns_compress_t		       *cctx;

	isc_mem_t		       *mctx;
	isc_mempool_t		       *namepool;
	isc_mempool_t		       *rdspool;

	isc_bufferlist_t		scratchpad;
	isc_bufferlist_t		cleanup;

	ISC_LIST(dns_msgblock_t)	rdatas;
	ISC_LIST(dns_msgblock_t)	rdatalists;
	ISC_LIST(dns_msgblock_t)	offsets;

	ISC_LIST(dns_rdata_t)		freerdata;
	ISC_LIST(dns_rdatalist_t)	freerdatalist;

	dns_rcode_t			tsigstatus;
	dns_rcode_t			querytsigstatus;
	dns_name_t		       *tsigname; /* Owner name of TSIG, if any */
	dns_rdataset_t		       *querytsig;
	dns_tsigkey_t		       *tsigkey;
	dst_context_t		       *tsigctx;
	int				sigstart;
	int				timeadjust;

	dns_name_t		       *sig0name; /* Owner name of SIG0, if any */
	dst_key_t		       *sig0key;
	dns_rcode_t			sig0status;
	isc_region_t			query;
	isc_region_t			saved;

	dns_rdatasetorderfunc_t		order;
	const void *			order_arg;

	dns_indent_t			indent;
};

struct dns_ednsopt {
	uint16_t			code;
	uint16_t			length;
	unsigned char			*value;
};

/***
 *** Functions
 ***/

ISC_LANG_BEGINDECLS

isc_result_t
dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp);

/*%<
 * Create msg structure.
 *
 * This function will allocate some internal blocks of memory that are
 * expected to be needed for parsing or rendering nearly any type of message.
 *
 * Requires:
 *\li	'mctx' be a valid memory context.
 *
 *\li	'msgp' be non-null and '*msg' be NULL.
 *
 *\li	'intent' must be one of DNS_MESSAGE_INTENTPARSE or
 *	#DNS_MESSAGE_INTENTRENDER.
 *
 * Ensures:
 *\li	The data in "*msg" is set to indicate an unused and empty msg
 *	structure.
 *
 * Returns:
 *\li	#ISC_R_NOMEMORY		-- out of memory
 *\li	#ISC_R_SUCCESS		-- success
 */

void
dns_message_reset(dns_message_t *msg, unsigned int intent);
/*%<
 * Reset a message structure to default state.  All internal lists are freed
 * or reset to a default state as well.  This is simply a more efficient
 * way to call dns_message_detach() (assuming last reference is hold),
 * followed by dns_message_create(), since it avoid many memory allocations.
 *
 * If any data loanouts (buffers, names, rdatas, etc) were requested,
 * the caller must no longer use them after this call.
 *
 * The intended next use of the message will be 'intent'.
 *
 * Requires:
 *
 *\li	'msg' be valid.
 *
 *\li	'intent' is DNS_MESSAGE_INTENTPARSE or DNS_MESSAGE_INTENTRENDER
 */

void
dns_message_attach(dns_message_t *source, dns_message_t **target);
/*%<
 * Attach to message 'source'.
 *
 * Requires:
 *\li	'source' to be a valid message.
 *\li	'target' to be non NULL and '*target' to be NULL.
 */

void
dns_message_detach(dns_message_t **messagep);
/*%<
 * Detach *messagep from its message.
 * list.
 *
 * Requires:
 *\li	'*messagep' to be a valid message.
 */

isc_result_t
dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
			  const dns_master_style_t *style,
			  dns_messagetextflag_t flags,
			  isc_buffer_t *target);

isc_result_t
dns_message_pseudosectiontotext(dns_message_t *msg,
				dns_pseudosection_t section,
				const dns_master_style_t *style,
				dns_messagetextflag_t flags,
				isc_buffer_t *target);
/*%<
 * Convert section 'section' or 'pseudosection' of message 'msg' to
 * a cleartext representation
 *
 * Notes:
 *     \li See dns_message_totext for meanings of flags.
 *
 * Requires:
 *
 *\li	'msg' is a valid message.
 *
 *\li	'style' is a valid master dump style.
 *
 *\li	'target' is a valid buffer.
 *
 *\li	'section' is a valid section label.
 *
 * Ensures:
 *
 *\li	If the result is success:
 *		The used space in 'target' is updated.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOSPACE
 *\li	#ISC_R_NOMORE
 *
 *\li	Note: On error return, *target may be partially filled with data.
*/

isc_result_t
dns_message_totext(dns_message_t *msg, const dns_master_style_t *style,
		   dns_messagetextflag_t flags, isc_buffer_t *target);
/*%<
 * Convert all sections of message 'msg' to a cleartext representation
 *
 * Notes on flags:
 *\li	If #DNS_MESSAGETEXTFLAG_NOCOMMENTS is cleared, lines beginning with
 * 	";;" will be emitted indicating section name.
 *\li	If #DNS_MESSAGETEXTFLAG_NOHEADERS is cleared, header lines will be
 * 	emitted.
 *\li   If #DNS_MESSAGETEXTFLAG_ONESOA is set then only print the first
 *	SOA record in the answer section.
 *\li	If *#DNS_MESSAGETEXTFLAG_OMITSOA is set don't print any SOA records
 *	in the answer section.
 *
 * The SOA flags are useful for suppressing the display of the second
 * SOA record in an AXFR by setting #DNS_MESSAGETEXTFLAG_ONESOA on the
 * first message in an AXFR stream and #DNS_MESSAGETEXTFLAG_OMITSOA on
 * subsequent messages.
 *
 * Requires:
 *
 *\li	'msg' is a valid message.
 *
 *\li	'style' is a valid master dump style.
 *
 *\li	'target' is a valid buffer.
 *
 * Ensures:
 *
 *\li	If the result is success:
 *		The used space in 'target' is updated.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOSPACE
 *\li	#ISC_R_NOMORE
 *
 *\li	Note: On error return, *target may be partially filled with data.
 */

isc_result_t
dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
		  unsigned int options);
/*%<
 * Parse raw wire data in 'source' as a DNS message.
 *
 * OPT records are detected and stored in the pseudo-section "opt".
 * TSIGs are detected and stored in the pseudo-section "tsig".
 *
 * If #DNS_MESSAGEPARSE_PRESERVEORDER is set, or if the opcode of the message
 * is UPDATE, a separate dns_name_t object will be created for each RR in the
 * message.  Each such dns_name_t will have a single rdataset containing the
 * single RR, and the order of the RRs in the message is preserved.
 * Otherwise, only one dns_name_t object will be created for each unique
 * owner name in the section, and each such dns_name_t will have a list
 * of rdatasets.  To access the names and their data, use
 * dns_message_firstname() and dns_message_nextname().
 *
 * If #DNS_MESSAGEPARSE_BESTEFFORT is set, errors in message content will
 * not be considered FORMERRs.  If the entire message can be parsed, it
 * will be returned and DNS_R_RECOVERABLE will be returned.
 *
 * If #DNS_MESSAGEPARSE_IGNORETRUNCATION is set then return as many complete
 * RR's as possible, DNS_R_RECOVERABLE will be returned.
 *
 * OPT and TSIG records are always handled specially, regardless of the
 * 'preserve_order' setting.
 *
 * Requires:
 *\li	"msg" be valid.
 *
 *\li	"buffer" be a wire format buffer.
 *
 * Ensures:
 *\li	The buffer's data format is correct.
 *
 *\li	The buffer's contents verify as correct regarding header bits, buffer
 * 	and rdata sizes, etc.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		-- all is well
 *\li	#ISC_R_NOMEMORY		-- no memory
 *\li	#DNS_R_RECOVERABLE	-- the message parsed properly, but contained
 *				   errors.
 *\li	Many other errors possible XXXMLG
 */

isc_result_t
dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx,
			isc_buffer_t *buffer);
/*%<
 * Begin rendering on a message.  Only one call can be made to this function
 * per message.
 *
 * The compression context is "owned" by the message library until
 * dns_message_renderend() is called.  It must be invalidated by the caller.
 *
 * The buffer is "owned" by the message library until dns_message_renderend()
 * is called.
 *
 * Requires:
 *
 *\li	'msg' be valid.
 *
 *\li	'cctx' be valid.
 *
 *\li	'buffer' is a valid buffer.
 *
 * Side Effects:
 *
 *\li	The buffer is cleared before it is used.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		-- all is well
 *\li	#ISC_R_NOSPACE		-- output buffer is too small
 */

isc_result_t
dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer);
/*%<
 * Reset the buffer.  This can be used after growing the old buffer
 * on a ISC_R_NOSPACE return from most of the render functions.
 *
 * On successful completion, the old buffer is no longer used by the
 * library.  The new buffer is owned by the library until
 * dns_message_renderend() is called.
 *
 * Requires:
 *
 *\li	'msg' be valid.
 *
 *\li	dns_message_renderbegin() was called.
 *
 *\li	buffer != NULL.
 *
 * Returns:
 *\li	#ISC_R_NOSPACE		-- new buffer is too small
 *\li	#ISC_R_SUCCESS		-- all is well.
 */

isc_result_t
dns_message_renderreserve(dns_message_t *msg, unsigned int space);
/*%<
 * XXXMLG should use size_t rather than unsigned int once the buffer
 * API is cleaned up
 *
 * Reserve "space" bytes in the given buffer.
 *
 * Requires:
 *
 *\li	'msg' be valid.
 *
 *\li	dns_message_renderbegin() was called.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		-- all is well.
 *\li	#ISC_R_NOSPACE		-- not enough free space in the buffer.
 */

void
dns_message_renderrelease(dns_message_t *msg, unsigned int space);
/*%<
 * XXXMLG should use size_t rather than unsigned int once the buffer
 * API is cleaned up
 *
 * Release "space" bytes in the given buffer that was previously reserved.
 *
 * Requires:
 *
 *\li	'msg' be valid.
 *
 *\li	'space' is less than or equal to the total amount of space reserved
 *	via prior calls to dns_message_renderreserve().
 *
 *\li	dns_message_renderbegin() was called.
 */

isc_result_t
dns_message_rendersection(dns_message_t *msg, dns_section_t section,
			  unsigned int options);
/*%<
 * Render all names, rdatalists, etc from the given section at the
 * specified priority or higher.
 *
 * Requires:
 *\li	'msg' be valid.
 *
 *\li	'section' be a valid section.
 *
 *\li	dns_message_renderbegin() was called.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		-- all records were written, and there are
 *				   no more records for this section.
 *\li	#ISC_R_NOSPACE		-- Not enough room in the buffer to write
 *				   all records requested.
 *\li	#DNS_R_MOREDATA		-- All requested records written, and there
 *				   are records remaining for this section.
 */

void
dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target);
/*%<
 * Render the message header.  This is implicitly called by
 * dns_message_renderend().
 *
 * Requires:
 *
 *\li	'msg' be a valid message.
 *
 *\li	dns_message_renderbegin() was called.
 *
 *\li	'target' is a valid buffer with enough space to hold a message header
 */

isc_result_t
dns_message_renderend(dns_message_t *msg);
/*%<
 * Finish rendering to the buffer.  Note that more data can be in the
 * 'msg' structure.  Destroying the structure will free this, or in a multi-
 * part EDNS1 message this data can be rendered to another buffer later.
 *
 * Requires:
 *
 *\li	'msg' be a valid message.
 *
 *\li	dns_message_renderbegin() was called.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		-- all is well.
 */

void
dns_message_renderreset(dns_message_t *msg);
/*%<
 * Reset the message so that it may be rendered again.
 *
 * Notes:
 *
 *\li	If dns_message_renderbegin() has been called, dns_message_renderend()
 *	must be called before calling this function.
 *
 * Requires:
 *
 *\li	'msg' be a valid message with rendering intent.
 */

isc_result_t
dns_message_firstname(dns_message_t *msg, dns_section_t section);
/*%<
 * Set internal per-section name pointer to the beginning of the section.
 *
 * The functions dns_message_firstname() and dns_message_nextname() may
 * be used for iterating over the owner names in a section.
 *
 * Requires:
 *
 *\li   	'msg' be valid.
 *
 *\li	'section' be a valid section.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		-- All is well.
 *\li	#ISC_R_NOMORE		-- No names on given section.
 */

isc_result_t
dns_message_nextname(dns_message_t *msg, dns_section_t section);
/*%<
 * Sets the internal per-section name pointer to point to the next name
 * in that section.
 *
 * Requires:
 *
 * \li  	'msg' be valid.
 *
 *\li	'section' be a valid section.
 *
 *\li	dns_message_firstname() must have been called on this section,
 *	and the result was ISC_R_SUCCESS.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		-- All is well.
 *\li	#ISC_R_NOMORE		-- No more names in given section.
 */

void
dns_message_currentname(dns_message_t *msg, dns_section_t section,
			dns_name_t **name);
/*%<
 * Sets 'name' to point to the name where the per-section internal name
 * pointer is currently set.
 *
 * This function returns the name in the database, so any data associated
 * with it (via the name's "list" member) contains the actual rdatasets.
 *
 * Requires:
 *
 *\li	'msg' be valid.
 *
 *\li	'name' be non-NULL, and *name be NULL.
 *
 *\li	'section' be a valid section.
 *
 *\li	dns_message_firstname() must have been called on this section,
 *	and the result of it and any dns_message_nextname() calls was
 *	#ISC_R_SUCCESS.
 */

isc_result_t
dns_message_findname(dns_message_t *msg, dns_section_t section,
		     dns_name_t *target, dns_rdatatype_t type,
		     dns_rdatatype_t covers, dns_name_t **foundname,
		     dns_rdataset_t **rdataset);
/*%<
 * Search for a name in the specified section.  If it is found, *name is
 * set to point to the name, and *rdataset is set to point to the found
 * rdataset (if type is specified as other than dns_rdatatype_any).
 *
 * Requires:
 *\li	'msg' be valid.
 *
 *\li	'section' be a valid section.
 *
 *\li	If a pointer to the name is desired, 'foundname' should be non-NULL.
 *	If it is non-NULL, '*foundname' MUST be NULL.
 *
 *\li	If a type other than dns_datatype_any is searched for, 'rdataset'
 *	may be non-NULL, '*rdataset' be NULL, and will point at the found
 *	rdataset.  If the type is dns_datatype_any, 'rdataset' must be NULL.
 *
 *\li	'target' be a valid name.
 *
 *\li	'type' be a valid type.
 *
 *\li	If 'type' is dns_rdatatype_rrsig, 'covers' must be a valid type.
 *	Otherwise it should be 0.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		-- all is well.
 *\li	#DNS_R_NXDOMAIN		-- name does not exist in that section.
 *\li	#DNS_R_NXRRSET		-- The name does exist, but the desired
 *				   type does not.
 */

isc_result_t
dns_message_findtype(dns_name_t *name, dns_rdatatype_t type,
		     dns_rdatatype_t covers, dns_rdataset_t **rdataset);
/*%<
 * Search the name for the specified type.  If it is found, *rdataset is
 * filled in with a pointer to that rdataset.
 *
 * Requires:
 *\li	if '**rdataset' is non-NULL, *rdataset needs to be NULL.
 *
 *\li	'type' be a valid type, and NOT dns_rdatatype_any.
 *
 *\li	If 'type' is dns_rdatatype_rrsig, 'covers' must be a valid type.
 *	Otherwise it should be 0.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		-- all is well.
 *\li	#ISC_R_NOTFOUND		-- the desired type does not exist.
 */

void
dns_message_addname(dns_message_t *msg, dns_name_t *name,
		    dns_section_t section);
/*%<
 * Adds the name to the given section.
 *
 * It is the caller's responsibility to enforce any unique name requirements
 * in a section.
 *
 * Requires:
 *
 *\li	'msg' be valid, and be a renderable message.
 *
 *\li	'name' be a valid absolute name.
 *
 *\li	'section' be a named section.
 */

void
dns_message_removename(dns_message_t *msg, dns_name_t *name,
		       dns_section_t section);
/*%<
 * Remove a existing name from a given section.
 *
 * It is the caller's responsibility to ensure the name is part of the
 * given section.
 *
 * Requires:
 *
 *\li	'msg' be valid, and be a renderable message.
 *
 *\li	'name' be a valid absolute name.
 *
 *\li	'section' be a named section.
 */


/*
 * LOANOUT FUNCTIONS
 *
 * Each of these functions loan a particular type of data to the caller.
 * The storage for these will vanish when the message is destroyed or
 * reset, and must NOT be used after these operations.
 */

isc_result_t
dns_message_gettempname(dns_message_t *msg, dns_name_t **item);
/*%<
 * Return a name that can be used for any temporary purpose, including
 * inserting into the message's linked lists.  The name must be returned
 * to the message code using dns_message_puttempname() or inserted into
 * one of the message's sections before the message is destroyed.
 *
 * It is the caller's responsibility to initialize this name.
 *
 * Requires:
 *\li	msg be a valid message
 *
 *\li	item != NULL && *item == NULL
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		-- All is well.
 *\li	#ISC_R_NOMEMORY		-- No item can be allocated.
 */

isc_result_t
dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item);
/*%<
 * Return an offsets array that can be used for any temporary purpose,
 * such as attaching to a temporary name.  The offsets will be freed
 * when the message is destroyed or reset.
 *
 * Requires:
 *\li	msg be a valid message
 *
 *\li	item != NULL && *item == NULL
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		-- All is well.
 *\li	#ISC_R_NOMEMORY		-- No item can be allocated.
 */

isc_result_t
dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item);
/*%<
 * Return a rdata that can be used for any temporary purpose, including
 * inserting into the message's linked lists.  The rdata will be freed
 * when the message is destroyed or reset.
 *
 * Requires:
 *\li	msg be a valid message
 *
 *\li	item != NULL && *item == NULL
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		-- All is well.
 *\li	#ISC_R_NOMEMORY		-- No item can be allocated.
 */

isc_result_t
dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item);
/*%<
 * Return a rdataset that can be used for any temporary purpose, including
 * inserting into the message's linked lists. The name must be returned
 * to the message code using dns_message_puttempname() or inserted into
 * one of the message's sections before the message is destroyed.
 *
 * Requires:
 *\li	msg be a valid message
 *
 *\li	item != NULL && *item == NULL
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		-- All is well.
 *\li	#ISC_R_NOMEMORY		-- No item can be allocated.
 */

isc_result_t
dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item);
/*%<
 * Return a rdatalist that can be used for any temporary purpose, including
 * inserting into the message's linked lists.  The rdatalist will be
 * destroyed when the message is destroyed or reset.
 *
 * Requires:
 *\li	msg be a valid message
 *
 *\li	item != NULL && *item == NULL
 *
 * Returns:
 *\li	#ISC_R_SUCCESS		-- All is well.
 *\li	#ISC_R_NOMEMORY		-- No item can be allocated.
 */

void
dns_message_puttempname(dns_message_t *msg, dns_name_t **item);
/*%<
 * Return a borrowed name to the message's name free list.
 *
 * Requires:
 *\li	msg be a valid message
 *
 *\li	item != NULL && *item point to a name returned by
 *	dns_message_gettempname()
 *
 * Ensures:
 *\li	*item == NULL
 */

void
dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item);
/*%<
 * Return a borrowed rdata to the message's rdata free list.
 *
 * Requires:
 *\li	msg be a valid message
 *
 *\li	item != NULL && *item point to a rdata returned by
 *	dns_message_gettemprdata()
 *
 * Ensures:
 *\li	*item == NULL
 */

void
dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item);
/*%<
 * Return a borrowed rdataset to the message's rdataset free list.
 *
 * Requires:
 *\li	msg be a valid message
 *
 *\li	item != NULL && *item point to a rdataset returned by
 *	dns_message_gettemprdataset()
 *
 * Ensures:
 *\li	*item == NULL
 */

void
dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item);
/*%<
 * Return a borrowed rdatalist to the message's rdatalist free list.
 *
 * Requires:
 *\li	msg be a valid message
 *
 *\li	item != NULL && *item point to a rdatalist returned by
 *	dns_message_gettemprdatalist()
 *
 * Ensures:
 *\li	*item == NULL
 */

isc_result_t
dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp,
		       unsigned int *flagsp);
/*%<
 * Assume the remaining region of "source" is a DNS message.  Peek into
 * it and fill in "*idp" with the message id, and "*flagsp" with the flags.
 *
 * Requires:
 *
 *\li	source != NULL
 *
 * Ensures:
 *
 *\li	if (idp != NULL) *idp == message id.
 *
 *\li	if (flagsp != NULL) *flagsp == message flags.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS		-- all is well.
 *
 *\li	#ISC_R_UNEXPECTEDEND	-- buffer doesn't contain enough for a header.
 */

isc_result_t
dns_message_reply(dns_message_t *msg, bool want_question_section);
/*%<
 * Start formatting a reply to the query in 'msg'.
 *
 * Requires:
 *
 *\li	'msg' is a valid message with parsing intent, and contains a query.
 *
 * Ensures:
 *
 *\li	The message will have a rendering intent.  If 'want_question_section'
 *	is true, the message opcode is query or notify, and the question
 *	section is present and properly formatted, then the question section
 *	will be included in the reply.  All other sections will be cleared.
 *	The QR flag will be set, the RD flag will be preserved, and all other
 *	flags will be cleared.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS		-- all is well.
 *
 *\li	#DNS_R_FORMERR		-- the header or question section of the
 *				   message is invalid, replying is impossible.
 *				   If DNS_R_FORMERR is returned when
 *				   want_question_section is false, then
 *				   it's the header section that's bad;
 *				   otherwise either of the header or question
 *				   sections may be bad.
 */

dns_rdataset_t *
dns_message_getopt(dns_message_t *msg);
/*%<
 * Get the OPT record for 'msg'.
 *
 * Requires:
 *
 *\li	'msg' is a valid message.
 *
 * Returns:
 *
 *\li	The OPT rdataset of 'msg', or NULL if there isn't one.
 */

isc_result_t
dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt);
/*%<
 * Set the OPT record for 'msg'.
 *
 * Requires:
 *
 *\li	'msg' is a valid message with rendering intent
 *	and no sections have been rendered.
 *
 *\li	'opt' is a valid OPT record.
 *
 * Ensures:
 *
 *\li	The OPT record has either been freed or ownership of it has
 *	been transferred to the message.
 *
 *\li	If ISC_R_SUCCESS was returned, the OPT record will be rendered
 *	when dns_message_renderend() is called.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS		-- all is well.
 *
 *\li	#ISC_R_NOSPACE		-- there is no space for the OPT record.
 */

dns_rdataset_t *
dns_message_gettsig(dns_message_t *msg, dns_name_t **owner);
/*%<
 * Get the TSIG record and owner for 'msg'.
 *
 * Requires:
 *
 *\li	'msg' is a valid message.
 *\li	'owner' is NULL or *owner is NULL.
 *
 * Returns:
 *
 *\li	The TSIG rdataset of 'msg', or NULL if there isn't one.
 *
 * Ensures:
 *
 * \li	If 'owner' is not NULL, it will point to the owner name.
 */

isc_result_t
dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key);
/*%<
 * Set the tsig key for 'msg'.  This is only necessary for when rendering a
 * query or parsing a response.  The key (if non-NULL) is attached to, and
 * will be detached when the message is destroyed.
 *
 * Requires:
 *
 *\li	'msg' is a valid message with rendering intent,
 *	dns_message_renderbegin() has been called, and no sections have been
 *	rendered.
 *\li	'key' is a valid tsig key or NULL.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS		-- all is well.
 *
 *\li	#ISC_R_NOSPACE		-- there is no space for the TSIG record.
 */

dns_tsigkey_t *
dns_message_gettsigkey(dns_message_t *msg);
/*%<
 * Gets the tsig key for 'msg'.
 *
 * Requires:
 *
 *\li	'msg' is a valid message
 */

isc_result_t
dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig);
/*%<
 * Indicates that 'querytsig' is the TSIG from the signed query for which
 * 'msg' is the response.  This is also used for chained TSIGs in TCP
 * responses.
 *
 * Requires:
 *
 *\li	'querytsig' is a valid buffer as returned by dns_message_getquerytsig()
 *	or NULL
 *
 *\li	'msg' is a valid message
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 */

isc_result_t
dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx,
			 isc_buffer_t **querytsig);
/*%<
 * Gets the tsig from the TSIG from the signed query 'msg'.  This is also used
 * for chained TSIGs in TCP responses.  Unlike dns_message_gettsig, this makes
 * a copy of the data, so can be used if the message is destroyed.
 *
 * Requires:
 *
 *\li	'msg' is a valid signed message
 *\li	'mctx' is a valid memory context
 *\li	querytsig != NULL && *querytsig == NULL
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *
 * Ensures:
 *\li 	'tsig' points to NULL or an allocated buffer which must be freed
 * 	by the caller.
 */

dns_rdataset_t *
dns_message_getsig0(dns_message_t *msg, dns_name_t **owner);
/*%<
 * Get the SIG(0) record and owner for 'msg'.
 *
 * Requires:
 *
 *\li	'msg' is a valid message.
 *\li	'owner' is NULL or *owner is NULL.
 *
 * Returns:
 *
 *\li	The SIG(0) rdataset of 'msg', or NULL if there isn't one.
 *
 * Ensures:
 *
 * \li	If 'owner' is not NULL, it will point to the owner name.
 */

isc_result_t
dns_message_setsig0key(dns_message_t *msg, dst_key_t *key);
/*%<
 * Set the SIG(0) key for 'msg'.
 *
 * Requires:
 *
 *\li	'msg' is a valid message with rendering intent,
 *	dns_message_renderbegin() has been called, and no sections have been
 *	rendered.
 *\li	'key' is a valid sig key or NULL.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS		-- all is well.
 *
 *\li	#ISC_R_NOSPACE		-- there is no space for the SIG(0) record.
 */

dst_key_t *
dns_message_getsig0key(dns_message_t *msg);
/*%<
 * Gets the SIG(0) key for 'msg'.
 *
 * Requires:
 *
 *\li	'msg' is a valid message
 */

void
dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer);
/*%<
 * Give the *buffer to the message code to clean up when it is no
 * longer needed.  This is usually when the message is reset or
 * destroyed.
 *
 * Requires:
 *
 *\li	msg be a valid message.
 *
 *\li	buffer != NULL && *buffer is a valid isc_buffer_t, which was
 *	dynamically allocated via isc_buffer_allocate().
 */

isc_result_t
dns_message_signer(dns_message_t *msg, dns_name_t *signer);
/*%<
 * If this message was signed, return the identity of the signer.
 * Unless ISC_R_NOTFOUND is returned, signer will reflect the name of the
 * key that signed the message.
 *
 * Requires:
 *
 *\li	msg is a valid parsed message.
 *\li	signer is a valid name
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS		- the message was signed, and *signer
 *				  contains the signing identity
 *
 *\li	#ISC_R_NOTFOUND		- no TSIG or SIG(0) record is present in the
 *				  message
 *
 *\li	#DNS_R_TSIGVERIFYFAILURE	- the message was signed by a TSIG, but the
 *				  signature failed to verify
 *
 *\li	#DNS_R_TSIGERRORSET	- the message was signed by a TSIG and
 *				  verified, but the query was rejected by
 *				  the server
 *
 *\li	#DNS_R_NOIDENTITY	- the message was signed by a TSIG and
 *				  verified, but the key has no identity since
 *				  it was generated by an unsigned TKEY process
 *
 *\li	#DNS_R_SIGINVALID	- the message was signed by a SIG(0), but
 *				  the signature failed to verify
 *
 *\li	#DNS_R_NOTVERIFIEDYET	- the message was signed by a TSIG or SIG(0),
 *				  but the signature has not been verified yet
 */

isc_result_t
dns_message_checksig(dns_message_t *msg, dns_view_t *view);
/*%<
 * If this message was signed, verify the signature.
 *
 * Requires:
 *
 *\li	msg is a valid parsed message.
 *\li	view is a valid view or NULL
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS		- the message was unsigned, or the message
 *				  was signed correctly.
 *
 *\li	#DNS_R_EXPECTEDTSIG	- A TSIG was expected, but not seen
 *\li	#DNS_R_UNEXPECTEDTSIG	- A TSIG was seen but not expected
 *\li	#DNS_R_TSIGVERIFYFAILURE - The TSIG failed to verify
 */

isc_result_t
dns_message_rechecksig(dns_message_t *msg, dns_view_t *view);
/*%<
 * Reset the signature state and then if the message was signed,
 * verify the message.
 *
 * Requires:
 *
 *\li	msg is a valid parsed message.
 *\li	view is a valid view or NULL
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS		- the message was unsigned, or the message
 *				  was signed correctly.
 *
 *\li	#DNS_R_EXPECTEDTSIG	- A TSIG was expected, but not seen
 *\li	#DNS_R_UNEXPECTEDTSIG	- A TSIG was seen but not expected
 *\li	#DNS_R_TSIGVERIFYFAILURE - The TSIG failed to verify
 */

void
dns_message_resetsig(dns_message_t *msg);
/*%<
 * Reset the signature state.
 *
 * Requires:
 *\li	'msg' is a valid parsed message.
 */

isc_region_t *
dns_message_getrawmessage(dns_message_t *msg);
/*%<
 * Retrieve the raw message in compressed wire format.  The message must
 * have been successfully parsed for it to have been saved.
 *
 * Requires:
 *\li	msg is a valid parsed message.
 *
 * Returns:
 *\li	NULL	if there is no saved message.
 *	a pointer to a region which refers the dns message.
 */

void
dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
			 const void *order_arg);
/*%<
 * Define the order in which RR sets get rendered by
 * dns_message_rendersection() to be the ascending order
 * defined by the integer value returned by 'order' when
 * given each RR and 'arg' as arguments.  If 'order' and
 * 'order_arg' are NULL, a default order is used.
 *
 * Requires:
 *\li	msg be a valid message.
 *\li	order_arg is NULL if and only if order is NULL.
 */

void
dns_message_settimeadjust(dns_message_t *msg, int timeadjust);
/*%<
 * Adjust the time used to sign/verify a message by timeadjust.
 * Currently only TSIG.
 *
 * Requires:
 *\li	msg be a valid message.
 */

int
dns_message_gettimeadjust(dns_message_t *msg);
/*%<
 * Return the current time adjustment.
 *
 * Requires:
 *\li	msg be a valid message.
 */

void
dns_message_logpacket(dns_message_t *message, const char *description,
		      isc_logcategory_t *category, isc_logmodule_t *module,
		      int level, isc_mem_t *mctx);
void
dns_message_logpacket2(dns_message_t *message,
		       const char *description, isc_sockaddr_t *address,
		       isc_logcategory_t *category, isc_logmodule_t *module,
		       int level, isc_mem_t *mctx);
void
dns_message_logfmtpacket(dns_message_t *message, const char *description,
			 isc_logcategory_t *category, isc_logmodule_t *module,
			 const dns_master_style_t *style, int level,
			 isc_mem_t *mctx);
void
dns_message_logfmtpacket2(dns_message_t *message,
			  const char *description, isc_sockaddr_t *address,
			  isc_logcategory_t *category, isc_logmodule_t *module,
			  const dns_master_style_t *style, int level,
			  isc_mem_t *mctx);
/*%<
 * Log 'message' at the specified logging parameters.
 *
 * For dns_message_logpacket and dns_message_logfmtpacket expect the
 * 'description' to end in a newline.
 *
 * For dns_message_logpacket2 and dns_message_logfmtpacket2
 * 'description' will be emitted at the start of the message followed
 * by the formatted address and a newline.
 *
 * Requires:
 * \li   message be a valid.
 * \li   description to be non NULL.
 * \li   address to be non NULL.
 * \li   category to be valid.
 * \li   module to be valid.
 * \li   style to be valid.
 * \li   mctx to be a valid.
 */

isc_result_t
dns_message_buildopt(dns_message_t *msg, dns_rdataset_t **opt,
		     unsigned int version, uint16_t udpsize,
		     unsigned int flags, dns_ednsopt_t *ednsopts, size_t count);
/*%<
 * Built a opt record.
 *
 * Requires:
 * \li   msg be a valid message.
 * \li   opt to be a non NULL and *opt to be NULL.
 *
 * Returns:
 * \li	 ISC_R_SUCCESS on success.
 * \li	 ISC_R_NOMEMORY
 * \li	 ISC_R_NOSPACE
 * \li	 other.
 */

void
dns_message_setclass(dns_message_t *msg, dns_rdataclass_t rdclass);
/*%<
 * Set the expected class of records in the response.
 *
 * Requires:
 * \li   msg be a valid message with parsing intent.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_MESSAGE_H */
edns.h000064400000001322150415243040005642 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_EDNS_H
#define DNS_EDNS_H 1

/*%
 * The maximum version on EDNS supported by this build.
 */
#define DNS_EDNS_VERSION 0
#ifdef DRAFT_ANDREWS_EDNS1
#undef DNS_EDNS_VERSION
/*
 * Warning: this currently disables sending COOKIE requests in resolver.c
 */
#define DNS_EDNS_VERSION 1 /* draft-andrews-edns1 */
#endif

#endif
catz.h000064400000027071150415243040005663 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_CATZ_H
#define DNS_CATZ_H 1

#include <inttypes.h>
#include <stdbool.h>

#include <isc/ht.h>
#include <isc/lang.h>
#include <isc/rwlock.h>
#include <isc/time.h>
#include <isc/timer.h>

#include <dns/db.h>
#include <dns/fixedname.h>
#include <dns/ipkeylist.h>
#include <dns/rdata.h>
#include <dns/types.h>

ISC_LANG_BEGINDECLS

#define DNS_CATZ_ERROR_LEVEL	ISC_LOG_WARNING
#define DNS_CATZ_INFO_LEVEL	ISC_LOG_INFO
#define DNS_CATZ_DEBUG_LEVEL1	ISC_LOG_DEBUG(1)
#define DNS_CATZ_DEBUG_LEVEL2	ISC_LOG_DEBUG(2)
#define DNS_CATZ_DEBUG_LEVEL3	ISC_LOG_DEBUG(3)
#define DNS_CATZ_DEBUG_QUIET	(DNS_CATZ_DEBUG_LEVEL3+1)

/*
 * Catalog Zones functions and structures.
 */

/*
 * Options for a member zone in a catalog
 */
struct dns_catz_entry_options {
	/*
	 * Options that can be overridden in catalog zone
	 */
	/* default-masters definition */
	dns_ipkeylist_t masters;

	/* both as text in config format, NULL if none */
	isc_buffer_t *allow_query;
	isc_buffer_t *allow_transfer;

	/*
	 * Options that are only set in named.conf
	 */
	/* zone-directory definition */
	char *zonedir;

	/* zone should not be stored on disk (no 'file' statement in def */
	bool in_memory;
	/*
	 * Minimal interval between catalog zone updates, if a new version
	 * of catalog zone is received before this time the update will be
	 * postponed. This is a global option for the whole catalog zone.
	 */
	uint32_t min_update_interval;
};

void
dns_catz_options_init(dns_catz_options_t *options);
/*%<
 * Initialize 'options' to NULL values.
 *
 * Requires:
 * \li	'options' to be non NULL.
 */

void
dns_catz_options_free(dns_catz_options_t *options, isc_mem_t *mctx);
/*%<
 * Free 'options' contents into 'mctx'. ('options' itself is not freed.)
 *
 * Requires:
 * \li	'options' to be non NULL.
 * \li	'mctx' to be a valid memory context.
 */

isc_result_t
dns_catz_options_copy(isc_mem_t *mctx, const dns_catz_options_t *opts,
		      dns_catz_options_t *nopts);
/*%<
 * Duplicate 'opts' into 'nopts', allocating space from 'mctx'.
 *
 * Requires:
 * \li	'mctx' to be a valid memory context.
 * \li	'options' to be non NULL and valid options.
 * \li	'nopts' to be non NULL.
 */

isc_result_t
dns_catz_options_setdefault(isc_mem_t *mctx, const dns_catz_options_t *defaults,
			    dns_catz_options_t *opts);
/*%<
 * Replace empty values in 'opts' with values from 'defaults'
 *
 * Requires:
 * \li	'mctx' to be a valid memory context.
 * \li	'defaults' to be non NULL and valid options.
 * \li	'opts' to be non NULL.
 */

dns_name_t *
dns_catz_entry_getname(dns_catz_entry_t *entry);
/*%<
 * Get domain name for 'entry'
 *
 * Requires:
 * \li	'entry' to be non NULL.
 *
 * Returns:
 * \li	domain name for entry.
 */

isc_result_t
dns_catz_entry_new(isc_mem_t *mctx, const dns_name_t *domain,
		   dns_catz_entry_t **nentryp);
/*%<
 * Allocate a new catz_entry on 'mctx', with the name 'domain'
 *
 * Requires:
 * \li	'mctx' to be a valid memory context.
 * \li	'domain' to be valid dns_name or NULL.
 * \li	'nentryp' to be non NULL, *nentryp to be NULL.
 *
 * Returns:
 * \li	ISC_R_SUCCESS on success
 * \li	ISC_R_NOMEMORY on allocation failure
 */

isc_result_t
dns_catz_entry_copy(dns_catz_zone_t *zone, const dns_catz_entry_t *entry,
		    dns_catz_entry_t **nentryp);
/*%<
 * Allocate a new catz_entry and deep copy 'entry' into 'nentryp'.
 *
 * Requires:
 * \li	'mctx' to be a valid memory context.
 * \li	'entry' to be non NULL.
 * \li	'nentryp' to be non NULL, *nentryp to be NULL.
 *
 * Returns:
 * \li	ISC_R_SUCCESS on success
 * \li	ISC_R_NOMEMORY on allocation failure
 */

void
dns_catz_entry_attach(dns_catz_entry_t *entry, dns_catz_entry_t **entryp);
/*%<
 * Attach an entry
 *
 * Requires:
 * \li	'entry' is a valid dns_catz_entry_t.
 * \li	'entryp' is not NULL and '*entryp' is NULL.
 */

void
dns_catz_entry_detach(dns_catz_zone_t *zone, dns_catz_entry_t **entryp);
/*%<
 * Detach an entry, free if no further references
 *
 * Requires:
 * \li	'zone' is a valid dns_catz_zone_t.
 * \li	'entryp' is not NULL and '*entryp' is not NULL.
 */

bool
dns_catz_entry_validate(const dns_catz_entry_t *entry);
/*%<
 * Validate whether entry is correct.
 * (NOT YET IMPLEMENTED: always returns true)
 *
 * Requires:
 *\li	'entry' is a valid dns_catz_entry_t.
 */

bool
dns_catz_entry_cmp(const dns_catz_entry_t *ea, const dns_catz_entry_t *eb);
/*%<
 * Deep compare two entries
 *
 * Requires:
 * \li	'ea' is a valid dns_catz_entry_t.
 * \li	'eb' is a valid dns_catz_entry_t.
 *
 * Returns:
 * \li 'true' if entries are the same.
 * \li 'false' if the entries differ.
 */

void
dns_catz_zone_attach(dns_catz_zone_t *zone, dns_catz_zone_t **zonep);
/*%<
 * Attach a catzone
 *
 * Requires:
 * \li	'zone' is a valid dns_catz_zone_t.
 * \li	'zonep' is not NULL and '*zonep' is NULL.
 */

void
dns_catz_zone_detach(dns_catz_zone_t** zonep);
/*%<
 * Detach a zone, free if no further references
 *
 * Requires:
 * \li	'zonep' is not NULL and '*zonep' is not NULL.
 */

isc_result_t
dns_catz_new_zone(dns_catz_zones_t *catzs, dns_catz_zone_t **zonep,
		const dns_name_t *name);
/*%<
 * Allocate a new catz zone on catzs mctx
 *
 * Requires:
 * \li	'catzs' is a valid dns_catz_zones_t.
 * \li	'zonep' is not NULL and '*zonep' is NULL.
 * \li	'name' is a valid dns_name_t.
 *
 */

dns_name_t *
dns_catz_zone_getname(dns_catz_zone_t *zone);
/*%<
 * Get catalog zone name
 *
 * Requires:
 * \li	'zone' is a valid dns_catz_zone_t.
 */

dns_catz_options_t *
dns_catz_zone_getdefoptions(dns_catz_zone_t *zone);
/*%<
 * Get default member zone options for catalog zone 'zone'
 *
 * Requires:
 * \li	'zone' is a valid dns_catz_zone_t.
 */

void
dns_catz_zone_resetdefoptions(dns_catz_zone_t *zone);
/*%<
 * Reset the default member zone options for catalog zone 'zone' to
 * the default values.
 *
 * Requires:
 * \li	'zone' is a valid dns_catz_zone_t.
 */

isc_result_t
dns_catz_zones_merge(dns_catz_zone_t *target, dns_catz_zone_t *newzone);
/*%<
 * Merge 'newzone' into 'target', calling addzone/delzone/modzone
 * (from zone->catzs->zmm) for appropriate member zones.
 *
 * Requires:
 * \li	'orig' is a valid dns_catz_zone_t.
 * \li	'newzone' is not NULL and '*newzone' is not NULL.
 *
 */

isc_result_t
dns_catz_update_process(dns_catz_zones_t *catzs, dns_catz_zone_t *zone,
			 dns_name_t *src_name, dns_rdataset_t *rdataset);
/*%<
 * Process a single rdataset from a catalog zone 'zone' update, src_name is the
 * record name.
 *
 * Requires:
 * \li	'catzs' is a valid dns_catz_zones_t.
 * \li	'zone' is a valid dns_catz_zone_t.
 * \li	'src_name' is a valid dns_name_t.
 * \li	'rdataset' is valid rdataset.
 */

isc_result_t
dns_catz_generate_masterfilename(dns_catz_zone_t *zone, dns_catz_entry_t *entry,
				 isc_buffer_t **buffer);
/*%<
 * Generate master file name and put it into *buffer (might be reallocated).
 * The general format of the file name is:
 * __catz__catalog.zone.name__member_zone_name.db
 * But if it's too long it's shortened to:
 * __catz__unique_hash_generated_from_the_above.db
 *
 * Requires:
 * \li	'zone' is a valid dns_catz_zone_t.
 * \li	'entry' is a valid dns_catz_entry_t.
 * \li	'buffer' is not NULL and '*buffer' is not NULL.
 */

isc_result_t
dns_catz_generate_zonecfg(dns_catz_zone_t *zone, dns_catz_entry_t *entry,
			  isc_buffer_t **buf);
/*%<
 * Generate a zone config entry (in text form) from dns_catz_entry and puts
 * it into *buf. buf might be reallocated.
 *
 * Requires:
 * \li	'zone' is a valid dns_catz_zone_t.
 * \li	'entry' is a valid dns_catz_entry_t.
 * \li	'buf' is not NULL and '*buf' is NULL.
 *
 */


/* Methods provided by named to dynamically modify the member zones */
/* xxxwpk TODO config! */
typedef isc_result_t (*dns_catz_zoneop_fn_t)(dns_catz_entry_t *entry,
					     dns_catz_zone_t *origin,
					     dns_view_t *view,
					     isc_taskmgr_t *taskmgr,
					     void *udata);
struct dns_catz_zonemodmethods {
	dns_catz_zoneop_fn_t addzone;
	dns_catz_zoneop_fn_t modzone;
	dns_catz_zoneop_fn_t delzone;
	void *udata;
};


isc_result_t
dns_catz_new_zones(dns_catz_zones_t **catzsp, dns_catz_zonemodmethods_t *zmm,
		   isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
		   isc_timermgr_t *timermgr);
/*%<
 * Allocate a new catz_zones object, a collection storing all catalog zones
 * for a view.
 *
 * Requires:
 * \li 'catzsp' is not NULL and '*catzsp' is NULL.
 * \li 'zmm' is not NULL.
 *
 */

isc_result_t
dns_catz_add_zone(dns_catz_zones_t *catzs, const dns_name_t *name,
		  dns_catz_zone_t **catzp);
/*%<
 * Allocate a new catz named 'name' and put it in 'catzs' collection.
 *
 * Requires:
 * \li	'catzs' is a valid dns_catz_zones_t.
 * \li	'name' is a valid dns_name_t.
 * \li	'zonep' is not NULL and *zonep is NULL.
 *
 */

dns_catz_zone_t *
dns_catz_get_zone(dns_catz_zones_t *catzs, const dns_name_t *name);
/*%<
 * Returns a zone named 'name' from collection 'catzs'
 *
 * Requires:
 * \li	'catzs' is a valid dns_catz_zones_t.
 * \li	'name' is a valid dns_name_t.
 */

void
dns_catz_catzs_attach(dns_catz_zones_t *catzs, dns_catz_zones_t **catzsp);
/*%<
 * Attach 'catzs' to 'catzsp'.
 *
 * Requires:
 * \li	'catzs' is a valid dns_catz_zones_t.
 * \li	'catzsp' is not NULL and *catzsp is NULL.
 */

void
dns_catz_catzs_detach(dns_catz_zones_t **catzsp);
/*%<
 * Detach 'catzsp', free if no further references.
 *
 * Requires:
 * \li	'catzsp' is not NULL and *catzsp is not NULL.
 */

void
dns_catz_catzs_set_view(dns_catz_zones_t *catzs, dns_view_t *view);
/*%<
 * Set a view for 'catzs'.
 *
 * Requires:
 * \li	'catzs' is a valid dns_catz_zones_t.
 * \li	'catzs->view' is NULL or 'catzs->view' == 'view'.
 */


isc_result_t
dns_catz_dbupdate_callback(dns_db_t *db, void *fn_arg);
/*%<
 * Callback for update of catalog zone database.
 * If there was no catalog zone update recently it launches an
 * update_taskaction immediately.
 * If there was an update recently it schedules update_taskaction for some time
 * in the future.
 * If there is an update scheduled it replaces old db version with a new one.
 *
 * Requires:
 * \li	'db' is a valid database.
 * \li	'fn_arg' is not NULL (casted to dns_catz_zones_t*).
 */

void
dns_catz_update_taskaction(isc_task_t *task, isc_event_t *event);
/*%<
 * Task that launches dns_catz_update_from_db.
 *
 * Requires:
 * \li	'event' is not NULL.
 */

void
dns_catz_update_from_db(dns_db_t *db, dns_catz_zones_t *catzs);
/*%<
 * Process an updated database for a catalog zone.
 * It creates a new catz, iterates over database to fill it with content, and
 * then merges new catz into old catz.
 *
 * Requires:
 * \li	'db' is a valid DB.
 * \li	'catzs' is a valid dns_catz_zones_t.
 *
 */

void
dns_catz_prereconfig(dns_catz_zones_t *catzs);
/*%<
 * Called before reconfig, clears 'active' flag on all the zones in set
 *
 * Requires:
 * \li	'catzs' is a valid dns_catz_zones_t.
 *
 */

void
dns_catz_postreconfig(dns_catz_zones_t *catzs);
/*%<
 * Called after reconfig, walks through all zones in set, removes those
 * inactive and force reload of those with changed configuration.
 *
 * Requires:
 * \li	'catzs' is a valid dns_catz_zones_t.
 */

isc_result_t
dns_catz_get_iterator(dns_catz_zone_t *catz, isc_ht_iter_t **itp);
/*%<
 * Get the hashtable iterator on catalog zone members, point '*itp' to it.
 *
 * Requires:
 * \li	'catzs' is a valid dns_catz_zones_t.
 * \li	'itp' is not NULL and '*itp' is NULL.
 *
 * Returns:
 * \li #ISC_R_SUCCESS		-- success
 * \li Any other value		-- failure
 */

ISC_LANG_ENDDECLS

#endif /* DNS_CATZ_H_ */
fixedname.h000064400000003177150415243040006663 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_FIXEDNAME_H
#define DNS_FIXEDNAME_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/fixedname.h
 * \brief
 * Fixed-size Names
 *
 * dns_fixedname_t is a convenience type containing a name, an offsets
 * table, and a dedicated buffer big enough for the longest possible
 * name. This is typically used for stack-allocated names.
 *
 * MP:
 *\li	The caller must ensure any required synchronization.
 *
 * Reliability:
 *\li	No anticipated impact.
 *
 * Resources:
 *\li	Per dns_fixedname_t:
 *\code
 *		sizeof(dns_name_t) + sizeof(dns_offsets_t) +
 *		sizeof(isc_buffer_t) + 255 bytes + structure padding
 *\endcode
 *
 * Security:
 *\li	No anticipated impact.
 *
 * Standards:
 *\li	None.
 */

/*****
 ***** Imports
 *****/

#include <isc/buffer.h>
#include <isc/lang.h>

#include <dns/name.h>

/*****
 ***** Types
 *****/

struct dns_fixedname {
	dns_name_t			name;
	dns_offsets_t			offsets;
	isc_buffer_t			buffer;
	unsigned char			data[DNS_NAME_MAXWIRE];
};

ISC_LANG_BEGINDECLS

void
dns_fixedname_init(dns_fixedname_t *fixed);

void
dns_fixedname_invalidate(dns_fixedname_t *fixed);

dns_name_t *
dns_fixedname_name(dns_fixedname_t *fixed);

dns_name_t *
dns_fixedname_initname(dns_fixedname_t *fixed);

ISC_LANG_ENDDECLS

#endif /* DNS_FIXEDNAME_H */
rdataslab.h000064400000010440150415243040006647 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_RDATASLAB_H
#define DNS_RDATASLAB_H 1

/*! \file dns/rdataslab.h
 * \brief
 * Implements storage of rdatasets into slabs of memory.
 *
 * MP:
 *\li	Clients of this module must impose any required synchronization.
 *
 * Reliability:
 *\li	This module deals with low-level byte streams.  Errors in any of
 *	the functions are likely to crash the server or corrupt memory.
 *
 *\li	If the caller passes invalid memory references, these functions are
 *	likely to crash the server or corrupt memory.
 *
 * Resources:
 *\li	None.
 *
 * Security:
 *\li	None.
 *
 * Standards:
 *\li	None.
 */

/***
 *** Imports
 ***/

#include <stdbool.h>

#include <isc/lang.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

#define DNS_RDATASLAB_FORCE 0x1
#define DNS_RDATASLAB_EXACT 0x2

#define DNS_RDATASLAB_OFFLINE 0x01 	/* RRSIG is for offline DNSKEY */
#define DNS_RDATASLAB_WARNMASK 0x0E	/*%< RRSIG(DNSKEY) expired
					 * warnings number mask. */
#define DNS_RDATASLAB_WARNSHIFT 1	/*%< How many bits to shift to find
					 * remaining expired warning number. */


/***
 *** Functions
 ***/

isc_result_t
dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
			   isc_region_t *region, unsigned int reservelen);
/*%<
 * Slabify a rdataset.  The slab area will be allocated and returned
 * in 'region'.
 *
 * Requires:
 *\li	'rdataset' is valid.
 *
 * Ensures:
 *\li	'region' will have base pointing to the start of allocated memory,
 *	with the slabified region beginning at region->base + reservelen.
 *	region->length contains the total length allocated.
 *
 * Returns:
 *\li	ISC_R_SUCCESS		- successful completion
 *\li	ISC_R_NOMEMORY		- no memory.
 *\li	XXX others
 */

void
dns_rdataslab_tordataset(unsigned char *slab, unsigned int reservelen,
			 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
			 dns_rdatatype_t covers, dns_ttl_t ttl,
			 dns_rdataset_t *rdataset);
/*%<
 * Construct an rdataset from a slab.
 *
 * Requires:
 *\li	'slab' points to a slab.
 *\li	'rdataset' is disassociated.
 *
 * Ensures:
 *\li	'rdataset' is associated and points to a valid rdataest.
 */

unsigned int
dns_rdataslab_size(unsigned char *slab, unsigned int reservelen);
/*%<
 * Return the total size of an rdataslab.
 *
 * Requires:
 *\li	'slab' points to a slab.
 *
 * Returns:
 *\li	The number of bytes in the slab, including the reservelen.
 */

unsigned int
dns_rdataslab_count(unsigned char *slab, unsigned int reservelen);
/*%<
 * Return the number of records in the rdataslab
 *
 * Requires:
 *\li	'slab' points to a slab.
 *
 * Returns:
 *\li	The number of records in the slab.
 */

isc_result_t
dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
		    unsigned int reservelen, isc_mem_t *mctx,
		    dns_rdataclass_t rdclass, dns_rdatatype_t type,
		    unsigned int flags, unsigned char **tslabp);
/*%<
 * Merge 'oslab' and 'nslab'.
 */

isc_result_t
dns_rdataslab_subtract(unsigned char *mslab, unsigned char *sslab,
		       unsigned int reservelen, isc_mem_t *mctx,
		       dns_rdataclass_t rdclass, dns_rdatatype_t type,
		       unsigned int flags, unsigned char **tslabp);
/*%<
 * Subtract 'sslab' from 'mslab'.  If 'exact' is true then all elements
 * of 'sslab' must exist in 'mslab'.
 *
 * XXX
 * valid flags are DNS_RDATASLAB_EXACT
 */

bool
dns_rdataslab_equal(unsigned char *slab1, unsigned char *slab2,
		    unsigned int reservelen);
/*%<
 * Compare two rdataslabs for equality.  This does _not_ do a full
 * DNSSEC comparison.
 *
 * Requires:
 *\li	'slab1' and 'slab2' point to slabs.
 *
 * Returns:
 *\li	true if the slabs are equal, false otherwise.
 */
bool
dns_rdataslab_equalx(unsigned char *slab1, unsigned char *slab2,
		     unsigned int reservelen, dns_rdataclass_t rdclass,
		     dns_rdatatype_t type);
/*%<
 * Compare two rdataslabs for DNSSEC equality.
 *
 * Requires:
 *\li	'slab1' and 'slab2' point to slabs.
 *
 * Returns:
 *\li	true if the slabs are equal, #false otherwise.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_RDATASLAB_H */
opcode.h000064400000001757150415243040006176 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_OPCODE_H
#define DNS_OPCODE_H 1

/*! \file dns/opcode.h */

#include <isc/lang.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

isc_result_t dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target);
/*%<
 * Put a textual representation of error 'opcode' into 'target'.
 *
 * Requires:
 *\li	'opcode' is a valid opcode.
 *
 *\li	'target' is a valid text buffer.
 *
 * Ensures:
 *\li	If the result is success:
 *		The used space in 'target' is updated.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS			on success
 *\li	#ISC_R_NOSPACE			target buffer is too small
 */

ISC_LANG_ENDDECLS

#endif /* DNS_OPCODE_H */
rriterator.h000064400000010206150415243040007107 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_RRITERATOR_H
#define DNS_RRITERATOR_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/rriterator.h
 * \brief
 * Functions for "walking" a zone database, visiting each RR or RRset in turn.
 */

/*****
 ***** Imports
 *****/

#include <inttypes.h>

#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/ondestroy.h>
#include <isc/stdtime.h>

#include <dns/db.h>
#include <dns/dbiterator.h>
#include <dns/fixedname.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdataset.h>
#include <dns/rdatasetiter.h>
#include <dns/types.h>

ISC_LANG_BEGINDECLS

/*****
 ***** Types
 *****/

/*%
 * A dns_rriterator_t is an iterator that iterates over an entire database,
 * returning one RR at a time, in some arbitrary order.
 */

typedef struct dns_rriterator {
	unsigned int		magic;
	isc_result_t		result;
	dns_db_t		*db;
	dns_dbiterator_t 	*dbit;
	dns_dbversion_t 	*ver;
	isc_stdtime_t		now;
	dns_dbnode_t		*node;
	dns_fixedname_t		fixedname;
	dns_rdatasetiter_t 	*rdatasetit;
	dns_rdataset_t 		rdataset;
	dns_rdata_t		rdata;
} dns_rriterator_t;

#define RRITERATOR_MAGIC		ISC_MAGIC('R', 'R', 'I', 't')
#define VALID_RRITERATOR(m)		ISC_MAGIC_VALID(m, RRITERATOR_MAGIC)

isc_result_t
dns_rriterator_init(dns_rriterator_t *it, dns_db_t *db,
		       dns_dbversion_t *ver, isc_stdtime_t now);
/*%
 * Initialize an rriterator; sets the cursor to the origin node
 * of the database.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * Returns:
 *
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOMEMORY
 */

isc_result_t
dns_rriterator_first(dns_rriterator_t *it);
/*%<
 * Move the rriterator cursor to the first rdata in the database.
 *
 * Requires:
 *\li	'it' is a valid, initialized rriterator
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMORE			There are no rdata in the set.
 */

isc_result_t
dns_rriterator_nextrrset(dns_rriterator_t *it);
/*%<
 * Move the rriterator cursor to the next rrset in the database,
 * skipping over any remaining records that have the same rdatatype
 * as the current one.
 *
 * Requires:
 *\li	'it' is a valid, initialized rriterator
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMORE			No more rrsets in the database
 */

isc_result_t
dns_rriterator_next(dns_rriterator_t *it);
/*%<
 * Move the rriterator cursor to the next rrset in the database,
 * skipping over any remaining records that have the same rdatatype
 * as the current one.
 *
 * Requires:
 *\li	'it' is a valid, initialized rriterator
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMORE			No more records in the database
 */

void
dns_rriterator_current(dns_rriterator_t *it, dns_name_t **name,
			  uint32_t *ttl, dns_rdataset_t **rdataset,
			  dns_rdata_t **rdata);
/*%<
 * Make '*name' refer to the current name.  If 'rdataset' is not NULL,
 * make '*rdataset' refer to the current * rdataset.  If '*rdata' is not
 * NULL, make '*rdata' refer to the current record.
 *
 * Requires:
 *\li	'*name' is a valid name object
 *\li	'rdataset' is NULL or '*rdataset' is NULL
 *\li	'rdata' is NULL or '*rdata' is NULL
 *
 * Ensures:
 *\li	'rdata' refers to the rdata at the rdata cursor location of
 *\li	'rdataset'.
 */

void
dns_rriterator_pause(dns_rriterator_t *it);
/*%<
 * Pause rriterator.  Frees any locks held by the database iterator.
 * Callers should use this routine any time they are not going to
 * execute another rriterator method in the immediate future.
 *
 * Requires:
 *\li	'it' is a valid iterator.
 *
 * Ensures:
 *\li	Any database locks being held for efficiency of iterator access are
 *	released.
 */

void
dns_rriterator_destroy(dns_rriterator_t *it);
/*%<
 * Shut down and free resources in rriterator 'it'.
 *
 * Requires:
 *
 *\li	'it' is a valid iterator.
 *
 * Ensures:
 *
 *\li	All resources used by the rriterator are freed.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_RRITERATOR_H */
events.h000064400000007733150415243040006231 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_EVENTS_H
#define DNS_EVENTS_H 1

#include <isc/eventclass.h>

/*! \file dns/events.h
 * \brief
 * Registry of DNS event numbers.
 */

#define DNS_EVENT_FETCHCONTROL			(ISC_EVENTCLASS_DNS + 0)
#define DNS_EVENT_FETCHDONE			(ISC_EVENTCLASS_DNS + 1)
#define DNS_EVENT_VIEWRESSHUTDOWN		(ISC_EVENTCLASS_DNS + 2)
#define DNS_EVENT_VIEWADBSHUTDOWN		(ISC_EVENTCLASS_DNS + 3)
#define DNS_EVENT_UPDATE			(ISC_EVENTCLASS_DNS + 4)
#define DNS_EVENT_UPDATEDONE			(ISC_EVENTCLASS_DNS + 5)
#define DNS_EVENT_DISPATCH			(ISC_EVENTCLASS_DNS + 6)
#define DNS_EVENT_TCPMSG			(ISC_EVENTCLASS_DNS + 7)
#define DNS_EVENT_ADBMOREADDRESSES		(ISC_EVENTCLASS_DNS + 8)
#define DNS_EVENT_ADBNOMOREADDRESSES		(ISC_EVENTCLASS_DNS + 9)
#define DNS_EVENT_ADBCANCELED			(ISC_EVENTCLASS_DNS + 10)
#define DNS_EVENT_ADBNAMEDELETED		(ISC_EVENTCLASS_DNS + 11)
#define DNS_EVENT_ADBSHUTDOWN			(ISC_EVENTCLASS_DNS + 12)
#define DNS_EVENT_ADBEXPIRED			(ISC_EVENTCLASS_DNS + 13)
#define DNS_EVENT_ADBCONTROL			(ISC_EVENTCLASS_DNS + 14)
#define DNS_EVENT_CACHECLEAN			(ISC_EVENTCLASS_DNS + 15)
#define DNS_EVENT_BYADDRDONE			(ISC_EVENTCLASS_DNS + 16)
#define DNS_EVENT_ZONECONTROL			(ISC_EVENTCLASS_DNS + 17)
#define DNS_EVENT_DBDESTROYED			(ISC_EVENTCLASS_DNS + 18)
#define DNS_EVENT_VALIDATORDONE			(ISC_EVENTCLASS_DNS + 19)
#define DNS_EVENT_REQUESTDONE			(ISC_EVENTCLASS_DNS + 20)
#define DNS_EVENT_VALIDATORSTART		(ISC_EVENTCLASS_DNS + 21)
#define DNS_EVENT_VIEWREQSHUTDOWN		(ISC_EVENTCLASS_DNS + 22)
#define DNS_EVENT_NOTIFYSENDTOADDR		(ISC_EVENTCLASS_DNS + 23)
#define DNS_EVENT_ZONE				(ISC_EVENTCLASS_DNS + 24)
#define DNS_EVENT_ZONESTARTXFRIN		(ISC_EVENTCLASS_DNS + 25)
#define DNS_EVENT_MASTERQUANTUM			(ISC_EVENTCLASS_DNS + 26)
#define DNS_EVENT_CACHEOVERMEM			(ISC_EVENTCLASS_DNS + 27)
#define DNS_EVENT_MASTERNEXTZONE		(ISC_EVENTCLASS_DNS + 28)
#define DNS_EVENT_IOREADY			(ISC_EVENTCLASS_DNS + 29)
#define DNS_EVENT_LOOKUPDONE			(ISC_EVENTCLASS_DNS + 30)
#define DNS_EVENT_RBTDEADNODES			(ISC_EVENTCLASS_DNS + 31)
#define DNS_EVENT_DISPATCHCONTROL		(ISC_EVENTCLASS_DNS + 32)
#define DNS_EVENT_REQUESTCONTROL		(ISC_EVENTCLASS_DNS + 33)
#define DNS_EVENT_DUMPQUANTUM			(ISC_EVENTCLASS_DNS + 34)
#define DNS_EVENT_IMPORTRECVDONE		(ISC_EVENTCLASS_DNS + 35)
#define DNS_EVENT_FREESTORAGE			(ISC_EVENTCLASS_DNS + 36)
#define DNS_EVENT_VIEWACACHESHUTDOWN		(ISC_EVENTCLASS_DNS + 37)
#define DNS_EVENT_ACACHECONTROL			(ISC_EVENTCLASS_DNS + 38)
#define DNS_EVENT_ACACHECLEAN			(ISC_EVENTCLASS_DNS + 39)
#define DNS_EVENT_ACACHEOVERMEM			(ISC_EVENTCLASS_DNS + 40)
#define DNS_EVENT_RBTPRUNE			(ISC_EVENTCLASS_DNS + 41)
#define DNS_EVENT_MANAGEKEYS			(ISC_EVENTCLASS_DNS + 42)
#define DNS_EVENT_CLIENTRESDONE			(ISC_EVENTCLASS_DNS + 43)
#define DNS_EVENT_CLIENTREQDONE			(ISC_EVENTCLASS_DNS + 44)
#define DNS_EVENT_ADBGROWENTRIES		(ISC_EVENTCLASS_DNS + 45)
#define DNS_EVENT_ADBGROWNAMES			(ISC_EVENTCLASS_DNS + 46)
#define DNS_EVENT_ZONESECURESERIAL		(ISC_EVENTCLASS_DNS + 47)
#define DNS_EVENT_ZONESECUREDB			(ISC_EVENTCLASS_DNS + 48)
#define DNS_EVENT_ZONELOAD			(ISC_EVENTCLASS_DNS + 49)
#define DNS_EVENT_KEYDONE			(ISC_EVENTCLASS_DNS + 50)
#define DNS_EVENT_SETNSEC3PARAM			(ISC_EVENTCLASS_DNS + 51)
#define DNS_EVENT_SETSERIAL			(ISC_EVENTCLASS_DNS + 52)
#define DNS_EVENT_CATZUPDATED			(ISC_EVENTCLASS_DNS + 53)
#define DNS_EVENT_CATZADDZONE			(ISC_EVENTCLASS_DNS + 54)
#define DNS_EVENT_CATZMODZONE			(ISC_EVENTCLASS_DNS + 55)
#define DNS_EVENT_CATZDELZONE			(ISC_EVENTCLASS_DNS + 56)
#define DNS_EVENT_STARTUPDATE			(ISC_EVENTCLASS_DNS + 58)

#define DNS_EVENT_FIRSTEVENT			(ISC_EVENTCLASS_DNS + 0)
#define DNS_EVENT_LASTEVENT			(ISC_EVENTCLASS_DNS + 65535)

#endif /* DNS_EVENTS_H */
compress.h000064400000014766150415243040006564 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_COMPRESS_H
#define DNS_COMPRESS_H 1

#include <inttypes.h>
#include <stdbool.h>

#include <isc/lang.h>
#include <isc/region.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

/*! \file dns/compress.h
 * Direct manipulation of the structures is strongly discouraged.
 *
 * A name compression context handles compression of multiple DNS names
 * in relation to a single DNS message. The context can be used to
 * selectively turn on/off compression for specific names (depending on
 * the RR type) by using \c dns_compress_setmethods(). Alternately,
 * compression can be disabled completely using \c
 * dns_compress_disable().
 *
 * \c dns_compress_setmethods() is intended for use by RDATA towire()
 * implementations, whereas \c dns_compress_disable() is intended to be
 * used by a nameserver's configuration manager.
 */

#define DNS_COMPRESS_NONE		0x00	/*%< no compression */
#define DNS_COMPRESS_GLOBAL14		0x01	/*%< "normal" compression. */
#define DNS_COMPRESS_ALL		0x01	/*%< all compression. */
#define DNS_COMPRESS_CASESENSITIVE	0x02	/*%< case sensitive compression. */
#define DNS_COMPRESS_ENABLED		0x04

#define DNS_COMPRESS_READY		0x80000000

#define DNS_COMPRESS_TABLESIZE 64
#define DNS_COMPRESS_INITIALNODES 16

typedef struct dns_compressnode dns_compressnode_t;

struct dns_compressnode {
	isc_region_t		r;
	uint16_t		offset;
	uint16_t		count;
	uint8_t			labels;
	dns_compressnode_t	*next;
};

struct dns_compress {
	unsigned int		magic;		/*%< Magic number. */
	unsigned int		allowed;	/*%< Allowed methods. */
	int			edns;		/*%< Edns version or -1. */
	/*% Global compression table. */
	dns_compressnode_t	*table[DNS_COMPRESS_TABLESIZE];
	/*% Preallocated nodes for the table. */
	dns_compressnode_t	initialnodes[DNS_COMPRESS_INITIALNODES];
	uint16_t		count;		/*%< Number of nodes. */
	isc_mem_t		*mctx;		/*%< Memory context. */
};

typedef enum {
	DNS_DECOMPRESS_ANY,			/*%< Any compression */
	DNS_DECOMPRESS_STRICT,			/*%< Allowed compression */
	DNS_DECOMPRESS_NONE			/*%< No compression */
} dns_decompresstype_t;

struct dns_decompress {
	unsigned int		magic;		/*%< Magic number. */
	unsigned int		allowed;	/*%< Allowed methods. */
	int			edns;		/*%< Edns version or -1. */
	dns_decompresstype_t	type;		/*%< Strict checking */
};

isc_result_t
dns_compress_init(dns_compress_t *cctx, int edns, isc_mem_t *mctx);
/*%<
 *	Initialise the compression context structure pointed to by
 *	'cctx'. A freshly initialized context has name compression
 *	enabled, but no methods are set. Please use \c
 *	dns_compress_setmethods() to set a compression method.
 *
 *	Requires:
 *	\li	'cctx' is a valid dns_compress_t structure.
 *	\li	'mctx' is an initialized memory context.
 *	Ensures:
 *	\li	cctx->global is initialized.
 *
 *	Returns:
 *	\li	#ISC_R_SUCCESS
 */

void
dns_compress_invalidate(dns_compress_t *cctx);

/*%<
 *	Invalidate the compression structure pointed to by cctx.
 *
 *	Requires:
 *\li		'cctx' to be initialized.
 */

void
dns_compress_setmethods(dns_compress_t *cctx, unsigned int allowed);

/*%<
 *	Sets allowed compression methods.
 *
 *	Requires:
 *\li		'cctx' to be initialized.
 */

unsigned int
dns_compress_getmethods(dns_compress_t *cctx);

/*%<
 *	Gets allowed compression methods.
 *
 *	Requires:
 *\li		'cctx' to be initialized.
 *
 *	Returns:
 *\li		allowed compression bitmap.
 */

void
dns_compress_disable(dns_compress_t *cctx);
/*%<
 *	Disables all name compression in the context. Once disabled,
 *	name compression cannot currently be re-enabled.
 *
 *	Requires:
 *\li		'cctx' to be initialized.
 *
 */

void
dns_compress_setsensitive(dns_compress_t *cctx, bool sensitive);

/*
 *	Preserve the case of compressed domain names.
 *
 *	Requires:
 *		'cctx' to be initialized.
 */

bool
dns_compress_getsensitive(dns_compress_t *cctx);
/*
 *	Return whether case is to be preserved when compressing
 *	domain names.
 *
 *	Requires:
 *		'cctx' to be initialized.
 */

int
dns_compress_getedns(dns_compress_t *cctx);

/*%<
 *	Gets edns value.
 *
 *	Requires:
 *\li		'cctx' to be initialized.
 *
 *	Returns:
 *\li		-1 .. 255
 */

bool
dns_compress_findglobal(dns_compress_t *cctx, const dns_name_t *name,
			dns_name_t *prefix, uint16_t *offset);
/*%<
 *	Finds longest possible match of 'name' in the global compression table.
 *
 *	Requires:
 *\li		'cctx' to be initialized.
 *\li		'name' to be a absolute name.
 *\li		'prefix' to be initialized.
 *\li		'offset' to point to an uint16_t.
 *
 *	Ensures:
 *\li		'prefix' and 'offset' are valid if true is 	returned.
 *
 *	Returns:
 *\li		#true / #false
 */

void
dns_compress_add(dns_compress_t *cctx, const dns_name_t *name,
		 const dns_name_t *prefix, uint16_t offset);
/*%<
 *	Add compression pointers for 'name' to the compression table,
 *	not replacing existing pointers.
 *
 *	Requires:
 *\li		'cctx' initialized
 *
 *\li		'name' must be initialized and absolute, and must remain
 *		valid until the message compression is complete.
 *
 *\li		'prefix' must be a prefix returned by
 *		dns_compress_findglobal(), or the same as 'name'.
 */

void
dns_compress_rollback(dns_compress_t *cctx, uint16_t offset);

/*%<
 *	Remove any compression pointers from global table >= offset.
 *
 *	Requires:
 *\li		'cctx' is initialized.
 */

void
dns_decompress_init(dns_decompress_t *dctx, int edns,
		    dns_decompresstype_t type);

/*%<
 *	Initializes 'dctx'.
 *	Records 'edns' and 'type' into the structure.
 *
 *	Requires:
 *\li		'dctx' to be a valid pointer.
 */

void
dns_decompress_invalidate(dns_decompress_t *dctx);

/*%<
 *	Invalidates 'dctx'.
 *
 *	Requires:
 *\li		'dctx' to be initialized
 */

void
dns_decompress_setmethods(dns_decompress_t *dctx, unsigned int allowed);

/*%<
 *	Sets 'dctx->allowed' to 'allowed'.
 *
 *	Requires:
 *\li		'dctx' to be initialized
 */

unsigned int
dns_decompress_getmethods(dns_decompress_t *dctx);

/*%<
 *	Returns 'dctx->allowed'
 *
 *	Requires:
 *\li		'dctx' to be initialized
 */

int
dns_decompress_edns(dns_decompress_t *dctx);

/*%<
 *	Returns 'dctx->edns'
 *
 *	Requires:
 *\li		'dctx' to be initialized
 */

dns_decompresstype_t
dns_decompress_type(dns_decompress_t *dctx);

/*%<
 *	Returns 'dctx->type'
 *
 *	Requires:
 *\li		'dctx' to be initialized
 */

ISC_LANG_ENDDECLS

#endif /* DNS_COMPRESS_H */
rpz.h000064400000024137150415243040005535 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_RPZ_H
#define DNS_RPZ_H 1

#include <stdbool.h>

#include <isc/deprecated.h>
#include <isc/event.h>
#include <isc/ht.h>
#include <isc/lang.h>
#include <isc/refcount.h>
#include <isc/rwlock.h>

#include <dns/fixedname.h>
#include <dns/rdata.h>
#include <dns/types.h>

ISC_LANG_BEGINDECLS

#define DNS_RPZ_PREFIX		"rpz-"
/*
 * Sub-zones of various trigger types.
 */
#define DNS_RPZ_CLIENT_IP_ZONE	DNS_RPZ_PREFIX"client-ip"
#define DNS_RPZ_IP_ZONE		DNS_RPZ_PREFIX"ip"
#define DNS_RPZ_NSIP_ZONE	DNS_RPZ_PREFIX"nsip"
#define DNS_RPZ_NSDNAME_ZONE	DNS_RPZ_PREFIX"nsdname"
/*
 * Special policies.
 */
#define DNS_RPZ_PASSTHRU_NAME	DNS_RPZ_PREFIX"passthru"
#define DNS_RPZ_DROP_NAME	DNS_RPZ_PREFIX"drop"
#define DNS_RPZ_TCP_ONLY_NAME	DNS_RPZ_PREFIX"tcp-only"


typedef uint8_t		dns_rpz_prefix_t;

typedef enum {
	DNS_RPZ_TYPE_BAD,
	DNS_RPZ_TYPE_CLIENT_IP,
	DNS_RPZ_TYPE_QNAME,
	DNS_RPZ_TYPE_IP,
	DNS_RPZ_TYPE_NSDNAME,
	DNS_RPZ_TYPE_NSIP
} dns_rpz_type_t;

/*
 * Require DNS_RPZ_POLICY_PASSTHRU < DNS_RPZ_POLICY_DROP
 * < DNS_RPZ_POLICY_TCP_ONLY DNS_RPZ_POLICY_NXDOMAIN < DNS_RPZ_POLICY_NODATA
 * < DNS_RPZ_POLICY_CNAME to choose among competing policies.
 */
typedef enum {
	DNS_RPZ_POLICY_GIVEN = 0,	/* 'given': what policy record says */
	DNS_RPZ_POLICY_DISABLED = 1,	/* log what would have happened */
	DNS_RPZ_POLICY_PASSTHRU = 2,	/* 'passthru': do not rewrite */
	DNS_RPZ_POLICY_DROP = 3,	/* 'drop': do not respond */
	DNS_RPZ_POLICY_TCP_ONLY = 4,	/* 'tcp-only': answer UDP with TC=1 */
	DNS_RPZ_POLICY_NXDOMAIN = 5,	/* 'nxdomain': answer with NXDOMAIN */
	DNS_RPZ_POLICY_NODATA = 6,	/* 'nodata': answer with ANCOUNT=0 */
	DNS_RPZ_POLICY_CNAME = 7,	/* 'cname x': answer with x's rrsets */
	DNS_RPZ_POLICY_DNS64,		/* Apply DN64 to the A rewrite */
	DNS_RPZ_POLICY_RECORD,
	DNS_RPZ_POLICY_WILDCNAME,
	DNS_RPZ_POLICY_MISS,
	DNS_RPZ_POLICY_ERROR
} dns_rpz_policy_t;

typedef uint8_t	    dns_rpz_num_t;

#define DNS_RPZ_MAX_ZONES   32
#if DNS_RPZ_MAX_ZONES > 32
# if DNS_RPZ_MAX_ZONES > 64
#  error "rpz zone bit masks must fit in a word"
# endif
typedef uint64_t	    dns_rpz_zbits_t;
#else
typedef uint32_t	    dns_rpz_zbits_t;
#endif

#define DNS_RPZ_ALL_ZBITS   ((dns_rpz_zbits_t)-1)

#define DNS_RPZ_INVALID_NUM DNS_RPZ_MAX_ZONES

#define DNS_RPZ_ZBIT(n)	    (((dns_rpz_zbits_t)1) << (dns_rpz_num_t)(n))

/*
 * Mask of the specified and higher numbered policy zones
 * Avoid hassles with (1<<33) or (1<<65)
 */
#define DNS_RPZ_ZMASK(n)    ((dns_rpz_zbits_t)((((n) >= DNS_RPZ_MAX_ZONES-1) ? \
						0 : (1<<((n)+1))) -1))

/*
 * The trigger counter type.
 */
typedef size_t dns_rpz_trigger_counter_t;

/*
 * The number of triggers of each type in a response policy zone.
 */
typedef struct dns_rpz_triggers dns_rpz_triggers_t;
struct dns_rpz_triggers {
	dns_rpz_trigger_counter_t	client_ipv4;
	dns_rpz_trigger_counter_t	client_ipv6;
	dns_rpz_trigger_counter_t	qname;
	dns_rpz_trigger_counter_t	ipv4;
	dns_rpz_trigger_counter_t	ipv6;
	dns_rpz_trigger_counter_t	nsdname;
	dns_rpz_trigger_counter_t	nsipv4;
	dns_rpz_trigger_counter_t	nsipv6;
};

/*
 * A single response policy zone.
 */
typedef struct dns_rpz_zone dns_rpz_zone_t;
struct dns_rpz_zone {
	isc_refcount_t	refs;
	dns_rpz_num_t	num;		/* ordinal in list of policy zones */
	dns_name_t	origin;		/* Policy zone name */
	dns_name_t	client_ip;	/* DNS_RPZ_CLIENT_IP_ZONE.origin. */
	dns_name_t	ip;		/* DNS_RPZ_IP_ZONE.origin. */
	dns_name_t	nsdname;	/* DNS_RPZ_NSDNAME_ZONE.origin */
	dns_name_t	nsip;		/* DNS_RPZ_NSIP_ZONE.origin. */
	dns_name_t	passthru;	/* DNS_RPZ_PASSTHRU_NAME. */
	dns_name_t	drop;		/* DNS_RPZ_DROP_NAME. */
	dns_name_t	tcp_only;	/* DNS_RPZ_TCP_ONLY_NAME. */
	dns_name_t	cname;		/* override value for ..._CNAME */
	dns_ttl_t	max_policy_ttl;
	dns_rpz_policy_t policy;	/* DNS_RPZ_POLICY_GIVEN or override */
};

/*
 * Radix tree node for response policy IP addresses
 */
typedef struct dns_rpz_cidr_node dns_rpz_cidr_node_t;

/*
 * Bitfields indicating which policy zones have policies of
 * which type.
 */
typedef struct dns_rpz_have dns_rpz_have_t;
struct dns_rpz_have {
	dns_rpz_zbits_t	    client_ipv4;
	dns_rpz_zbits_t	    client_ipv6;
	dns_rpz_zbits_t	    client_ip;
	dns_rpz_zbits_t	    qname;
	dns_rpz_zbits_t	    ipv4;
	dns_rpz_zbits_t	    ipv6;
	dns_rpz_zbits_t	    ip;
	dns_rpz_zbits_t	    nsdname;
	dns_rpz_zbits_t	    nsipv4;
	dns_rpz_zbits_t	    nsipv6;
	dns_rpz_zbits_t	    nsip;
	dns_rpz_zbits_t	    qname_skip_recurse;
};

/*
 * Policy options
 */
typedef struct dns_rpz_popt dns_rpz_popt_t;
struct dns_rpz_popt {
	dns_rpz_zbits_t	    no_rd_ok;
	dns_rpz_zbits_t	    no_log;
	bool	    break_dnssec;
	bool	    qname_wait_recurse;
	bool	    nsip_wait_recurse;
	unsigned int	    min_ns_labels;
	dns_rpz_num_t	    num_zones;
};

/*
 * Response policy zones known to a view.
 */
typedef struct dns_rpz_zones dns_rpz_zones_t;
struct dns_rpz_zones {
	dns_rpz_popt_t		p;
	dns_rpz_zone_t		*zones[DNS_RPZ_MAX_ZONES];
	dns_rpz_triggers_t	triggers[DNS_RPZ_MAX_ZONES];

	/*
	 * RPZ policy version number (initially 0, increases whenever
	 * the server is reconfigured with new zones or policy)
	 */
	int			rpz_ver;

	dns_rpz_zbits_t		defined;

	/*
	 * The set of records for a policy zone are in one of these states:
	 *	never loaded		    load_begun=0  have=0
	 *	during initial loading	    load_begun=1  have=0
	 *				and rbtdb->rpzsp == rbtdb->load_rpzsp
	 *	after good load		    load_begun=1  have!=0
	 *	after failed initial load   load_begun=1  have=0
	 *				and rbtdb->load_rpzsp == NULL
	 *	reloading after failure	    load_begun=1  have=0
	 *	reloading after success
	 *		main rpzs	    load_begun=1  have!=0
	 *		load rpzs	    load_begun=1  have=0
	 */
	dns_rpz_zbits_t		load_begun;
	dns_rpz_have_t		have;

	/*
	 * total_triggers maintains the total number of triggers in all
	 * policy zones in the view. It is only used to print summary
	 * statistics after a zone load of how the trigger counts
	 * changed.
	 */
	dns_rpz_triggers_t	total_triggers;

	isc_mem_t		*mctx;
	isc_refcount_t		refs;
	/*
	 * One lock for short term read-only search that guarantees the
	 * consistency of the pointers.
	 * A second lock for maintenance that guarantees no other thread
	 * is adding or deleting nodes.
	 */
	isc_rwlock_t		search_lock;
	isc_mutex_t		maint_lock;

	dns_rpz_cidr_node_t	*cidr;
	dns_rbt_t		*rbt;
};


/*
 * context for finding the best policy
 */
typedef struct {
	unsigned int		state;
# define DNS_RPZ_REWRITTEN	0x0001
# define DNS_RPZ_DONE_CLIENT_IP	0x0002	/* client IP address checked */
# define DNS_RPZ_DONE_QNAME	0x0004	/* qname checked */
# define DNS_RPZ_DONE_QNAME_IP	0x0008	/* IP addresses of qname checked */
# define DNS_RPZ_DONE_NSDNAME	0x0010	/* NS name missed; checking addresses */
# define DNS_RPZ_DONE_IPv4	0x0020
# define DNS_RPZ_RECURSING	0x0040
# define DNS_RPZ_ACTIVE		0x0080
	/*
	 * Best match so far.
	 */
	struct {
		dns_rpz_type_t		type;
		dns_rpz_zone_t		*rpz;
		dns_rpz_prefix_t	prefix;
		dns_rpz_policy_t	policy;
		dns_ttl_t		ttl;
		isc_result_t		result;
		dns_zone_t		*zone;
		dns_db_t		*db;
		dns_dbversion_t		*version;
		dns_dbnode_t		*node;
		dns_rdataset_t		*rdataset;
	} m;
	/*
	 * State for chasing IP addresses and NS names including recursion.
	 */
	struct {
		unsigned int		label;
		dns_db_t		*db;
		dns_rdataset_t		*ns_rdataset;
		dns_rdatatype_t		r_type;
		isc_result_t		r_result;
		dns_rdataset_t		*r_rdataset;
	} r;

	/*
	 * State of real query while recursing for NSIP or NSDNAME.
	 */
	struct {
		isc_result_t		result;
		bool		is_zone;
		bool		authoritative;
		dns_zone_t		*zone;
		dns_db_t		*db;
		dns_dbnode_t		*node;
		dns_rdataset_t		*rdataset;
		dns_rdataset_t		*sigrdataset;
		dns_rdatatype_t		qtype;
	} q;

	/*
	 * A copy of the 'have' and 'p' structures and the RPZ
	 * policy version as of the beginning of RPZ processing,
	 * used to avoid problems when policy is updated while
	 * RPZ recursion is ongoing.
	 */
	dns_rpz_have_t		have;
	dns_rpz_popt_t		popt;
	int			rpz_ver;

	/*
	 * p_name: current policy owner name
	 * r_name: recursing for this name to possible policy triggers
	 * f_name: saved found name from before recursion
	 */
	dns_name_t		*p_name;
	dns_name_t		*r_name;
	dns_name_t		*fname;
	dns_fixedname_t		_p_namef;
	dns_fixedname_t		_r_namef;
	dns_fixedname_t		_fnamef;
} dns_rpz_st_t;

#define DNS_RPZ_TTL_DEFAULT		5
#define DNS_RPZ_MAX_TTL_DEFAULT		DNS_RPZ_TTL_DEFAULT

/*
 * So various response policy zone messages can be turned up or down.
 */
#define DNS_RPZ_ERROR_LEVEL	ISC_LOG_WARNING
#define DNS_RPZ_INFO_LEVEL	ISC_LOG_INFO
#define DNS_RPZ_DEBUG_LEVEL1	ISC_LOG_DEBUG(1)
#define DNS_RPZ_DEBUG_LEVEL2	ISC_LOG_DEBUG(2)
#define DNS_RPZ_DEBUG_LEVEL3	ISC_LOG_DEBUG(3)
#define DNS_RPZ_DEBUG_QUIET	(DNS_RPZ_DEBUG_LEVEL3+1)

const char *
dns_rpz_type2str(dns_rpz_type_t type);

dns_rpz_policy_t
dns_rpz_str2policy(const char *str);

const char *
dns_rpz_policy2str(dns_rpz_policy_t policy);

dns_rpz_policy_t
dns_rpz_decode_cname(dns_rpz_zone_t *rpz, dns_rdataset_t *rdataset,
		     dns_name_t *selfname);

isc_result_t
dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, isc_mem_t *mctx);

void
dns_rpz_attach_rpzs(dns_rpz_zones_t *source, dns_rpz_zones_t **target);

void
dns_rpz_detach_rpzs(dns_rpz_zones_t **rpzsp);

isc_result_t
dns_rpz_beginload(dns_rpz_zones_t **load_rpzsp,
		  dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num);

isc_result_t
dns_rpz_ready(dns_rpz_zones_t *rpzs,
	      dns_rpz_zones_t **load_rpzsp, dns_rpz_num_t rpz_num);

isc_result_t
dns_rpz_add(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, dns_name_t *name);

void
dns_rpz_delete(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, dns_name_t *name);

dns_rpz_num_t
dns_rpz_find_ip(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type,
		dns_rpz_zbits_t zbits, const isc_netaddr_t *netaddr,
		dns_name_t *ip_name, dns_rpz_prefix_t *prefixp);

dns_rpz_zbits_t
dns_rpz_find_name(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type,
		  dns_rpz_zbits_t zbits, dns_name_t *trig_name);

ISC_LANG_ENDDECLS

#endif /* DNS_RPZ_H */
rdatalist.h000064400000005011150415243040006677 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_RDATALIST_H
#define DNS_RDATALIST_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/rdatalist.h
 * \brief
 * A DNS rdatalist is a list of rdata of a common type and class.
 *
 * MP:
 *\li	Clients of this module must impose any required synchronization.
 *
 * Reliability:
 *\li	No anticipated impact.
 *
 * Resources:
 *\li	TBS
 *
 * Security:
 *\li	No anticipated impact.
 *
 * Standards:
 *\li	None.
 */

#include <isc/lang.h>

#include <dns/types.h>

/*%
 * Clients may use this type directly.
 */
struct dns_rdatalist {
	dns_rdataclass_t		rdclass;
	dns_rdatatype_t			type;
	dns_rdatatype_t			covers;
	dns_ttl_t			ttl;
	ISC_LIST(dns_rdata_t)		rdata;
	ISC_LINK(dns_rdatalist_t)	link;
	/*%<
	 * Case vector.  If the bit is set then the corresponding
	 * character in the owner name needs to be AND'd with 0x20,
	 * rendering that character upper case.
	 */
	unsigned char			upper[32];
};

ISC_LANG_BEGINDECLS

void
dns_rdatalist_init(dns_rdatalist_t *rdatalist);
/*%<
 * Initialize rdatalist.
 *
 * Ensures:
 *\li	All fields of rdatalist have been initialized to their default
 *	values.
 */

isc_result_t
dns_rdatalist_tordataset(dns_rdatalist_t *rdatalist,
			 dns_rdataset_t *rdataset);
/*%<
 * Make 'rdataset' refer to the rdata in 'rdatalist'.
 *
 * Note:
 *\li	The caller must ensure that 'rdatalist' remains valid and unchanged
 *	while 'rdataset' is associated with it.
 *
 * Requires:
 *
 *\li	'rdatalist' is a valid rdatalist.
 *
 *\li	'rdataset' is a valid rdataset that is not currently associated with
 *	any rdata.
 *
 * Ensures,
 *	on success,
 *
 *\li		'rdataset' is associated with the rdata in rdatalist.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 */

isc_result_t
dns_rdatalist_fromrdataset(dns_rdataset_t *rdataset,
			   dns_rdatalist_t **rdatalist);
/*%<
 * Point 'rdatalist' to the rdatalist in 'rdataset'.
 *
 * Requires:
 *
 *\li	'rdatalist' is a pointer to a NULL dns_rdatalist_t pointer.
 *
 *\li	'rdataset' is a valid rdataset associated with an rdatalist.
 *
 * Ensures,
 *	on success,
 *
 *\li		'rdatalist' is pointed to the rdatalist in rdataset.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 */

ISC_LANG_ENDDECLS

#endif /* DNS_RDATALIST_H */
rdataclass.h000064400000004321150415243040007034 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_RDATACLASS_H
#define DNS_RDATACLASS_H 1

/*! \file dns/rdataclass.h */

#include <isc/lang.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

isc_result_t
dns_rdataclass_fromtext(dns_rdataclass_t *classp, isc_textregion_t *source);
/*%<
 * Convert the text 'source' refers to into a DNS class.
 *
 * Requires:
 *\li	'classp' is a valid pointer.
 *
 *\li	'source' is a valid text region.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS			on success
 *\li	#DNS_R_UNKNOWN			class is unknown
 */

isc_result_t
dns_rdataclass_totext(dns_rdataclass_t rdclass, isc_buffer_t *target);
/*%<
 * Put a textual representation of class 'rdclass' into 'target'.
 *
 * Requires:
 *\li	'rdclass' is a valid class.
 *
 *\li	'target' is a valid text buffer.
 *
 * Ensures,
 *	if the result is success:
 *\li		The used space in 'target' is updated.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS			on success
 *\li	#ISC_R_NOSPACE			target buffer is too small
 */

isc_result_t
dns_rdataclass_tounknowntext(dns_rdataclass_t rdclass, isc_buffer_t *target);
/*%<
 * Put textual RFC3597 CLASSXXXX representation of class 'rdclass' into
 * 'target'.
 *
 * Requires:
 *\li	'rdclass' is a valid class.
 *
 *\li	'target' is a valid text buffer.
 *
 * Ensures,
 *	if the result is success:
 *\li		The used space in 'target' is updated.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS			on success
 *\li	#ISC_R_NOSPACE			target buffer is too small
 */

void
dns_rdataclass_format(dns_rdataclass_t rdclass,
		      char *array, unsigned int size);
/*%<
 * Format a human-readable representation of the class 'rdclass'
 * into the character array 'array', which is of size 'size'.
 * The resulting string is guaranteed to be null-terminated.
 */

#define DNS_RDATACLASS_FORMATSIZE sizeof("CLASS65535")
/*%<
 * Minimum size of array to pass to dns_rdataclass_format().
 */

ISC_LANG_ENDDECLS

#endif /* DNS_RDATACLASS_H */
time.h000064400000003237150415243040005656 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_TIME_H
#define DNS_TIME_H 1

/*! \file dns/time.h */

/***
 ***	Imports
 ***/

#include <inttypes.h>

#include <isc/buffer.h>
#include <isc/lang.h>

ISC_LANG_BEGINDECLS

/***
 ***	Functions
 ***/

isc_result_t
dns_time64_fromtext(const char *source, int64_t *target);
/*%<
 * Convert a date and time in YYYYMMDDHHMMSS text format at 'source'
 * into to a 64-bit count of seconds since Jan 1 1970 0:00 GMT.
 * Store the count at 'target'.
 */

isc_result_t
dns_time32_fromtext(const char *source, uint32_t *target);
/*%<
 * Like dns_time64_fromtext, but returns the second count modulo 2^32
 * as per RFC2535.
 */


isc_result_t
dns_time64_totext(int64_t value, isc_buffer_t *target);
/*%<
 * Convert a 64-bit count of seconds since Jan 1 1970 0:00 GMT into
 * a YYYYMMDDHHMMSS text representation and append it to 'target'.
 */

isc_result_t
dns_time32_totext(uint32_t value, isc_buffer_t *target);
/*%<
 * Like dns_time64_totext, but for a 32-bit cyclic time value.
 * Of those dates whose counts of seconds since Jan 1 1970 0:00 GMT
 * are congruent with 'value' modulo 2^32, the one closest to the
 * current date is chosen.
 */

int64_t
dns_time64_from32(uint32_t value);
/*%<
 * Covert a 32-bit cyclic time value into a 64 bit time stamp.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_TIME_H */
callbacks.h000064400000004337150415243040006641 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_CALLBACKS_H
#define DNS_CALLBACKS_H 1

/*! \file dns/callbacks.h */

/***
 ***	Imports
 ***/

#include <isc/lang.h>
#include <isc/magic.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

/***
 ***	Types
 ***/

#define DNS_CALLBACK_MAGIC	ISC_MAGIC('C','L','L','B')
#define DNS_CALLBACK_VALID(cb)	ISC_MAGIC_VALID(cb, DNS_CALLBACK_MAGIC)

struct dns_rdatacallbacks {
	unsigned int magic;

	/*%
	 * dns_load_master calls this when it has rdatasets to commit.
	 */
	dns_addrdatasetfunc_t add;

	/*%
	 * This is called when reading in a database image from a 'map'
	 * format zone file.
	 */
	dns_deserializefunc_t deserialize;

	/*%
	 * dns_master_load*() call this when loading a raw zonefile,
	 * to pass back information obtained from the file header
	 */
	dns_rawdatafunc_t rawdata;
	dns_zone_t *zone;

	/*%
	 * dns_load_master / dns_rdata_fromtext call this to issue a error.
	 */
	void	(*error)(struct dns_rdatacallbacks *, const char *, ...);
	/*%
	 * dns_load_master / dns_rdata_fromtext call this to issue a warning.
	 */
	void	(*warn)(struct dns_rdatacallbacks *, const char *, ...);
	/*%
	 * Private data handles for use by the above callback functions.
	 */
	void	*add_private;
	void	*deserialize_private;
	void	*error_private;
	void	*warn_private;
};

/***
 ***	Initialization
 ***/

void
dns_rdatacallbacks_init(dns_rdatacallbacks_t *callbacks);
/*%<
 * Initialize 'callbacks'.
 *
 * \li	'magic' is set to DNS_CALLBACK_MAGIC
 *
 * \li	'error' and 'warn' are set to default callbacks that print the
 *	error message through the DNS library log context.
 *
 *\li	All other elements are initialized to NULL.
 *
 * Requires:
 *  \li    'callbacks' is a valid dns_rdatacallbacks_t,
 */

void
dns_rdatacallbacks_init_stdio(dns_rdatacallbacks_t *callbacks);
/*%<
 * Like dns_rdatacallbacks_init, but logs to stdio.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_CALLBACKS_H */
rdatastruct.h000064400000170220150415243040007255 0ustar00/*
 * Copyright (C) 1998-2025  Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

/***************
 ***************
 ***************   THIS FILE IS AUTOMATICALLY GENERATED BY gen.c.
 ***************   DO NOT EDIT!
 ***************
 ***************/

/*! \file */

/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_RDATASTRUCT_H
#define DNS_RDATASTRUCT_H 1

#include <isc/lang.h>
#include <isc/sockaddr.h>

#include <dns/name.h>
#include <dns/types.h>

ISC_LANG_BEGINDECLS

typedef struct dns_rdatacommon {
	dns_rdataclass_t			rdclass;
	dns_rdatatype_t				rdtype;
	ISC_LINK(struct dns_rdatacommon)	link;
} dns_rdatacommon_t;

#define DNS_RDATACOMMON_INIT(_data, _rdtype, _rdclass) \
	do { \
		(_data)->common.rdtype = (_rdtype); \
		(_data)->common.rdclass = (_rdclass); \
		ISC_LINK_INIT(&(_data)->common, link); \
	} while (0)
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef IN_1_A_1_H
#define IN_1_A_1_H 1


typedef struct dns_rdata_in_a {
	dns_rdatacommon_t	common;
	struct in_addr          in_addr;
} dns_rdata_in_a_t;

#endif /* IN_1_A_1_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


/* by Bjorn.Victor@it.uu.se, 2005-05-07 */
/* Based on generic/mx_15.h */

#ifndef CH_3_A_1_H
#define CH_3_A_1_H 1

typedef uint16_t ch_addr_t;

typedef struct dns_rdata_ch_a {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_name_t		ch_addr_dom; /* ch-addr domain for back mapping */
	ch_addr_t		ch_addr; /* chaos address (16 bit) network order */
} dns_rdata_ch_a_t;

#endif /* CH_3_A_1_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef HS_4_A_1_H
#define HS_4_A_1_H 1


typedef struct dns_rdata_hs_a {
	dns_rdatacommon_t	common;
	struct in_addr          in_addr;
} dns_rdata_hs_a_t;

#endif /* HS_4_A_1_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_NS_2_H
#define GENERIC_NS_2_H 1


typedef struct dns_rdata_ns {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_name_t		name;
} dns_rdata_ns_t;


#endif /* GENERIC_NS_2_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_MD_3_H
#define GENERIC_MD_3_H 1


typedef struct dns_rdata_md {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_name_t		md;
} dns_rdata_md_t;


#endif /* GENERIC_MD_3_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_MF_4_H
#define GENERIC_MF_4_H 1


typedef struct dns_rdata_mf {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_name_t		mf;
} dns_rdata_mf_t;

#endif /* GENERIC_MF_4_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef GENERIC_CNAME_5_H
#define GENERIC_CNAME_5_H 1

typedef struct dns_rdata_cname {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_name_t		cname;
} dns_rdata_cname_t;

#endif /* GENERIC_CNAME_5_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_SOA_6_H
#define GENERIC_SOA_6_H 1


typedef struct dns_rdata_soa {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_name_t		origin;
	dns_name_t		contact;
	uint32_t		serial;		/*%< host order */
	uint32_t		refresh;	/*%< host order */
	uint32_t		retry;		/*%< host order */
	uint32_t		expire;		/*%< host order */
	uint32_t		minimum;	/*%< host order */
} dns_rdata_soa_t;


#endif /* GENERIC_SOA_6_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_MB_7_H
#define GENERIC_MB_7_H 1


typedef struct dns_rdata_mb {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_name_t		mb;
} dns_rdata_mb_t;

#endif /* GENERIC_MB_7_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_MG_8_H
#define GENERIC_MG_8_H 1


typedef struct dns_rdata_mg {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_name_t		mg;
} dns_rdata_mg_t;

#endif /* GENERIC_MG_8_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_MR_9_H
#define GENERIC_MR_9_H 1


typedef struct dns_rdata_mr {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_name_t		mr;
} dns_rdata_mr_t;

#endif /* GENERIC_MR_9_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_NULL_10_H
#define GENERIC_NULL_10_H 1


typedef struct dns_rdata_null {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	uint16_t		length;
	unsigned char		*data;
} dns_rdata_null_t;


#endif /* GENERIC_NULL_10_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef IN_1_WKS_11_H
#define IN_1_WKS_11_H 1


typedef	struct dns_rdata_in_wks {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	struct in_addr		in_addr;
	uint16_t		protocol;
	unsigned char		*map;
	uint16_t		map_len;
} dns_rdata_in_wks_t;

#endif /* IN_1_WKS_11_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_PTR_12_H
#define GENERIC_PTR_12_H 1


typedef struct dns_rdata_ptr {
	dns_rdatacommon_t       common;
	isc_mem_t               *mctx;
	dns_name_t              ptr;
} dns_rdata_ptr_t;

#endif /* GENERIC_PTR_12_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_HINFO_13_H
#define GENERIC_HINFO_13_H 1


typedef struct dns_rdata_hinfo {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	char			*cpu;
	char			*os;
	uint8_t		cpu_len;
	uint8_t		os_len;
} dns_rdata_hinfo_t;

#endif /* GENERIC_HINFO_13_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_MINFO_14_H
#define GENERIC_MINFO_14_H 1


typedef struct dns_rdata_minfo {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_name_t		rmailbox;
	dns_name_t		emailbox;
} dns_rdata_minfo_t;

#endif /* GENERIC_MINFO_14_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_MX_15_H
#define GENERIC_MX_15_H 1


typedef struct dns_rdata_mx {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	uint16_t		pref;
	dns_name_t		mx;
} dns_rdata_mx_t;

#endif /* GENERIC_MX_15_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_TXT_16_H
#define GENERIC_TXT_16_H 1


typedef struct dns_rdata_txt_string {
		uint8_t    length;
		unsigned char   *data;
} dns_rdata_txt_string_t;

typedef struct dns_rdata_txt {
	dns_rdatacommon_t       common;
	isc_mem_t               *mctx;
	unsigned char           *txt;
	uint16_t            txt_len;
	/* private */
	uint16_t            offset;
} dns_rdata_txt_t;

/*
 * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done
 * via rdatastructpre.h and rdatastructsuf.h.
 */

isc_result_t
dns_rdata_txt_first(dns_rdata_txt_t *);

isc_result_t
dns_rdata_txt_next(dns_rdata_txt_t *);

isc_result_t
dns_rdata_txt_current(dns_rdata_txt_t *, dns_rdata_txt_string_t *);

#endif /* GENERIC_TXT_16_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_RP_17_H
#define GENERIC_RP_17_H 1


/*!
 *  \brief Per RFC1183 */

typedef struct dns_rdata_rp {
	dns_rdatacommon_t       common;
	isc_mem_t               *mctx;
	dns_name_t              mail;
	dns_name_t              text;
} dns_rdata_rp_t;


#endif /* GENERIC_RP_17_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_AFSDB_18_H
#define GENERIC_AFSDB_18_H 1


/*!
 *  \brief Per RFC1183 */

typedef struct dns_rdata_afsdb {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	uint16_t		subtype;
	dns_name_t		server;
} dns_rdata_afsdb_t;

#endif /* GENERIC_AFSDB_18_H */

/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_X25_19_H
#define GENERIC_X25_19_H 1


/*!
 *  \brief Per RFC1183 */

typedef struct dns_rdata_x25 {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	unsigned char		*x25;
	uint8_t		x25_len;
} dns_rdata_x25_t;

#endif /* GENERIC_X25_19_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_ISDN_20_H
#define GENERIC_ISDN_20_H 1


/*!
 * \brief Per RFC1183 */

typedef struct dns_rdata_isdn {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	char			*isdn;
	char			*subaddress;
	uint8_t		isdn_len;
	uint8_t		subaddress_len;
} dns_rdata_isdn_t;

#endif /* GENERIC_ISDN_20_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_RT_21_H
#define GENERIC_RT_21_H 1


/*!
 *  \brief Per RFC1183 */

typedef struct dns_rdata_rt {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	uint16_t		preference;
	dns_name_t		host;
} dns_rdata_rt_t;

#endif /* GENERIC_RT_21_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef IN_1_NSAP_22_H
#define IN_1_NSAP_22_H 1


/*!
 *  \brief Per RFC1706 */

typedef struct dns_rdata_in_nsap {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	unsigned char		*nsap;
	uint16_t		nsap_len;
} dns_rdata_in_nsap_t;

#endif /* IN_1_NSAP_22_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef IN_1_NSAP_PTR_23_H
#define IN_1_NSAP_PTR_23_H 1


/*!
 *  \brief Per RFC1348.  Obsoleted in RFC 1706 - use PTR instead. */

typedef struct dns_rdata_in_nsap_ptr {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_name_t		owner;
} dns_rdata_in_nsap_ptr_t;

#endif /* IN_1_NSAP_PTR_23_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_SIG_24_H
#define GENERIC_SIG_24_H 1


/*!
 *  \brief Per RFC2535 */

typedef struct dns_rdata_sig_t {
	dns_rdatacommon_t	common;
	isc_mem_t *		mctx;
	dns_rdatatype_t		covered;
	dns_secalg_t		algorithm;
	uint8_t		labels;
	uint32_t		originalttl;
	uint32_t		timeexpire;
	uint32_t		timesigned;
	uint16_t		keyid;
	dns_name_t		signer;
	uint16_t		siglen;
	unsigned char *		signature;
} dns_rdata_sig_t;


#endif /* GENERIC_SIG_24_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_KEY_25_H
#define GENERIC_KEY_25_H 1


/*!
 * \brief Per RFC2535 */

typedef struct dns_rdata_key {
	dns_rdatacommon_t	common;
	isc_mem_t *		mctx;
	uint16_t		flags;
	dns_secproto_t		protocol;
	dns_secalg_t		algorithm;
	uint16_t		datalen;
	unsigned char *		data;
} dns_rdata_key_t;


#endif /* GENERIC_KEY_25_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef IN_1_PX_26_H
#define IN_1_PX_26_H 1


/*!
 *  \brief Per RFC2163 */

typedef struct dns_rdata_in_px {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	uint16_t		preference;
	dns_name_t		map822;
	dns_name_t		mapx400;
} dns_rdata_in_px_t;

#endif /* IN_1_PX_26_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_GPOS_27_H
#define GENERIC_GPOS_27_H 1


/*!
 *  \brief per RFC1712 */

typedef struct dns_rdata_gpos {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	char			*longitude;
	char			*latitude;
	char			*altitude;
	uint8_t		long_len;
	uint8_t		lat_len;
	uint8_t		alt_len;
} dns_rdata_gpos_t;

#endif /* GENERIC_GPOS_27_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef IN_1_AAAA_28_H
#define IN_1_AAAA_28_H 1


/*!
 *  \brief Per RFC1886 */

typedef struct dns_rdata_in_aaaa {
	dns_rdatacommon_t	common;
	struct in6_addr		in6_addr;
} dns_rdata_in_aaaa_t;

#endif /* IN_1_AAAA_28_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_LOC_29_H
#define GENERIC_LOC_29_H 1


/*!
 * \brief Per RFC1876 */

typedef struct dns_rdata_loc_0 {
	uint8_t	version;	/* must be first and zero */
	uint8_t	size;
	uint8_t	horizontal;
	uint8_t	vertical;
	uint32_t	latitude;
	uint32_t	longitude;
	uint32_t	altitude;
} dns_rdata_loc_0_t;

typedef struct dns_rdata_loc {
	dns_rdatacommon_t	common;
	union {
		dns_rdata_loc_0_t v0;
	} v;
} dns_rdata_loc_t;

#endif /* GENERIC_LOC_29_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_NXT_30_H
#define GENERIC_NXT_30_H 1


/*!
 *  \brief RFC2535 */

typedef struct dns_rdata_nxt {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_name_t		next;
	unsigned char		*typebits;
	uint16_t		len;
} dns_rdata_nxt_t;

#endif /* GENERIC_NXT_30_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef IN_1_EID_31_H
#define IN_1_EID_31_H 1


/*!
 *  \brief http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt
 */

typedef struct dns_rdata_in_eid {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	unsigned char		*eid;
	uint16_t		eid_len;
} dns_rdata_in_eid_t;

#endif /* IN_1_EID_31_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef IN_1_NIMLOC_32_H
#define IN_1_NIMLOC_32_H 1


/*!
 *  \brief http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt
 */

typedef struct dns_rdata_in_nimloc {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	unsigned char		*nimloc;
	uint16_t		nimloc_len;
} dns_rdata_in_nimloc_t;

#endif /* IN_1_NIMLOC_32_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef IN_1_SRV_33_H
#define IN_1_SRV_33_H 1

/*!
 *  \brief Per RFC2782 */

typedef struct dns_rdata_in_srv {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	uint16_t		priority;
	uint16_t		weight;
	uint16_t		port;
	dns_name_t		target;
} dns_rdata_in_srv_t;

#endif /* IN_1_SRV_33_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef IN_1_ATMA_22_H
#define IN_1_ATMA_22_H 1


/*!
 *  \brief Per RFC1706 */

typedef struct dns_rdata_in_atma {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	unsigned char		format;
	unsigned char		*atma;
	uint16_t		atma_len;
} dns_rdata_in_atma_t;

#endif /* IN_1_ATMA_22_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_NAPTR_35_H
#define GENERIC_NAPTR_35_H 1


/*!
 *  \brief Per RFC2915 */

typedef struct dns_rdata_naptr {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	uint16_t		order;
	uint16_t		preference;
	char			*flags;
	uint8_t		flags_len;
	char			*service;
	uint8_t		service_len;
	char			*regexp;
	uint8_t		regexp_len;
	dns_name_t		replacement;
} dns_rdata_naptr_t;

#endif /* GENERIC_NAPTR_35_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef IN_1_KX_36_H
#define IN_1_KX_36_H 1


/*!
 *  \brief Per RFC2230 */

typedef struct dns_rdata_in_kx {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	uint16_t		preference;
	dns_name_t		exchange;
} dns_rdata_in_kx_t;

#endif /* IN_1_KX_36_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef GENERIC_CERT_37_H
#define GENERIC_CERT_37_H 1

/*% RFC2538 */
typedef struct dns_rdata_cert {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	uint16_t		type;
	uint16_t		key_tag;
	uint8_t		algorithm;
	uint16_t		length;
	unsigned char		*certificate;
} dns_rdata_cert_t;

#endif /* GENERIC_CERT_37_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef IN_1_A6_38_H
#define IN_1_A6_38_H 1


/*!
 *  \brief Per RFC2874 */

typedef struct dns_rdata_in_a6 {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_name_t		prefix;
	uint8_t		prefixlen;
	struct in6_addr		in6_addr;
} dns_rdata_in_a6_t;

#endif /* IN_1_A6_38_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_DNAME_39_H
#define GENERIC_DNAME_39_H 1


/*!
 *  \brief per RFC2672 */

typedef struct dns_rdata_dname {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_name_t		dname;
} dns_rdata_dname_t;

#endif /* GENERIC_DNAME_39_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_SINK_40_H
#define GENERIC_SINK_40_H 1

typedef struct dns_rdata_sink_t {
	dns_rdatacommon_t	common;
	isc_mem_t *		mctx;
	uint8_t		meaning;
	uint8_t		coding;
	uint8_t		subcoding;
	uint16_t		datalen;
	unsigned char *		data;
} dns_rdata_sink_t;

#endif /* GENERIC_SINK_40_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_OPT_41_H
#define GENERIC_OPT_41_H 1


/*!
 *  \brief Per RFC2671 */

typedef struct dns_rdata_opt_opcode {
		uint16_t	opcode;
		uint16_t	length;
		unsigned char	*data;
} dns_rdata_opt_opcode_t;

typedef struct dns_rdata_opt {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	unsigned char		*options;
	uint16_t		length;
	/* private */
	uint16_t		offset;
} dns_rdata_opt_t;

/*
 * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done
 * via rdatastructpre.h and rdatastructsuf.h.
 */

isc_result_t
dns_rdata_opt_first(dns_rdata_opt_t *);

isc_result_t
dns_rdata_opt_next(dns_rdata_opt_t *);

isc_result_t
dns_rdata_opt_current(dns_rdata_opt_t *, dns_rdata_opt_opcode_t *);

#endif /* GENERIC_OPT_41_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef IN_1_APL_42_H
#define IN_1_APL_42_H 1


typedef struct dns_rdata_apl_ent {
	bool	negative;
	uint16_t	family;
	uint8_t	prefix;
	uint8_t	length;
	unsigned char	*data;
} dns_rdata_apl_ent_t;

typedef struct dns_rdata_in_apl {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	/* type & class specific elements */
	unsigned char           *apl;
	uint16_t            apl_len;
	/* private */
	uint16_t            offset;
} dns_rdata_in_apl_t;

/*
 * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done
 * via rdatastructpre.h and rdatastructsuf.h.
 */

isc_result_t
dns_rdata_apl_first(dns_rdata_in_apl_t *);

isc_result_t
dns_rdata_apl_next(dns_rdata_in_apl_t *);

isc_result_t
dns_rdata_apl_current(dns_rdata_in_apl_t *, dns_rdata_apl_ent_t *);

unsigned int
dns_rdata_apl_count(const dns_rdata_in_apl_t *apl);

#endif /* IN_1_APL_42_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef GENERIC_DS_43_H
#define GENERIC_DS_43_H 1

/*!
 *  \brief per draft-ietf-dnsext-delegation-signer-05.txt */
typedef struct dns_rdata_ds {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	uint16_t		key_tag;
	dns_secalg_t		algorithm;
	dns_dsdigest_t		digest_type;
	uint16_t		length;
	unsigned char		*digest;
} dns_rdata_ds_t;

#endif /* GENERIC_DS_43_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


/*!
 *  \brief Per RFC 4255 */

#ifndef GENERIC_SSHFP_44_H
#define GENERIC_SSHFP_44_H 1

typedef struct dns_rdata_sshfp {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	uint8_t		algorithm;
	uint8_t		digest_type;
	uint16_t		length;
	unsigned char		*digest;
} dns_rdata_sshfp_t;

#endif /* GENERIC_SSHFP_44_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef GENERIC_IPSECKEY_45_H
#define GENERIC_IPSECKEY_45_H 1

typedef struct dns_rdata_ipseckey {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	uint8_t		precedence;
	uint8_t		gateway_type;
	uint8_t		algorithm;
	struct in_addr		in_addr;	/* gateway type 1 */
	struct in6_addr		in6_addr;	/* gateway type 2 */
	dns_name_t		gateway;	/* gateway type 3 */
	unsigned char		*key;
	uint16_t		keylength;
} dns_rdata_ipseckey_t;

#endif /* GENERIC_IPSECKEY_45_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_DNSSIG_46_H
#define GENERIC_DNSSIG_46_H 1


/*!
 *  \brief Per RFC2535 */
typedef struct dns_rdata_rrsig {
	dns_rdatacommon_t	common;
	isc_mem_t *		mctx;
	dns_rdatatype_t		covered;
	dns_secalg_t		algorithm;
	uint8_t		labels;
	uint32_t		originalttl;
	uint32_t		timeexpire;
	uint32_t		timesigned;
	uint16_t		keyid;
	dns_name_t		signer;
	uint16_t		siglen;
	unsigned char *		signature;
} dns_rdata_rrsig_t;


#endif /* GENERIC_DNSSIG_46_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_NSEC_47_H
#define GENERIC_NSEC_47_H 1


/*!
 * \brief Per RFC 3845 */

typedef struct dns_rdata_nsec {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_name_t		next;
	unsigned char		*typebits;
	uint16_t		len;
} dns_rdata_nsec_t;

#endif /* GENERIC_NSEC_47_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_DNSKEY_48_H
#define GENERIC_DNSKEY_48_H 1

/*!
 *  \brief per RFC2535
 */

typedef struct dns_rdata_key dns_rdata_dnskey_t;

#endif /* GENERIC_DNSKEY_48_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef IN_1_DHCID_49_H
#define IN_1_DHCID_49_H 1


typedef struct dns_rdata_in_dhcid {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	unsigned char		*dhcid;
	unsigned int		length;
} dns_rdata_in_dhcid_t;

#endif /* IN_1_DHCID_49_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef GENERIC_NSEC3_50_H
#define GENERIC_NSEC3_50_H 1


/*!
 * \brief Per RFC 5155 */

#include <isc/iterated_hash.h>

typedef struct dns_rdata_nsec3 {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_hash_t		hash;
	unsigned char		flags;
	dns_iterations_t	iterations;
	unsigned char		salt_length;
	unsigned char		next_length;
	uint16_t		len;
	unsigned char		*salt;
	unsigned char		*next;
	unsigned char		*typebits;
} dns_rdata_nsec3_t;

/*
 * The corresponding NSEC3 interval is OPTOUT indicating possible
 * insecure delegations.
 */
#define DNS_NSEC3FLAG_OPTOUT 0x01U

/*%
 * The following flags are used in the private-type record (implemented in
 * lib/dns/private.c) which is used to store NSEC3PARAM data during the
 * time when it is not legal to have an actual NSEC3PARAM record in the
 * zone.  They are defined here because the private-type record uses the
 * same flags field for the OPTOUT flag above and for the private flags
 * below.  XXX: This should be considered for refactoring.
 */

/*%
 * Non-standard, private type only.
 *
 * Create a corresponding NSEC3 chain.
 * Once the NSEC3 chain is complete this flag will be removed to signal
 * that there is a complete chain.
 *
 * This flag is automatically set when a NSEC3PARAM record is added to
 * the zone via UPDATE.
 *
 * NSEC3PARAM records containing this flag should never be published,
 * but if they are, they should be ignored by RFC 5155 compliant
 * nameservers.
 */
#define DNS_NSEC3FLAG_CREATE 0x80U

/*%
 * Non-standard, private type only.
 *
 * The corresponding NSEC3 set is to be removed once the NSEC chain
 * has been generated.
 *
 * This flag is automatically set when the last active NSEC3PARAM record
 * is removed from the zone via UPDATE.
 *
 * NSEC3PARAM records containing this flag should never be published,
 * but if they are, they should be ignored by RFC 5155 compliant
 * nameservers.
 */
#define DNS_NSEC3FLAG_REMOVE 0x40U

/*%
 * Non-standard, private type only.
 *
 * When set with the CREATE flag, a corresponding NSEC3 chain will be
 * created when the zone becomes capable of supporting one (i.e., when it
 * has a DNSKEY RRset containing at least one NSEC3-capable algorithm).
 * Without this flag, NSEC3 chain creation would be attempted immediately,
 * fail, and the private type record would be removed.  With it, the NSEC3
 * parameters are stored until they can be used.  When the zone has the
 * necessary prerequisites for NSEC3, then the INITIAL flag can be cleared,
 * and the record will be cleaned up normally.
 *
 * NSEC3PARAM records containing this flag should never be published, but
 * if they are, they should be ignored by RFC 5155 compliant nameservers.
 */
#define DNS_NSEC3FLAG_INITIAL 0x20U

/*%
 * Non-standard, private type only.
 *
 * Prevent the creation of a NSEC chain before the last NSEC3 chain
 * is removed.  This will normally only be set when the zone is
 * transitioning from secure with NSEC3 chains to insecure.
 *
 * NSEC3PARAM records containing this flag should never be published,
 * but if they are, they should be ignored by RFC 5155 compliant
 * nameservers.
 */
#define DNS_NSEC3FLAG_NONSEC 0x10U

#endif /* GENERIC_NSEC3_50_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef GENERIC_NSEC3PARAM_51_H
#define GENERIC_NSEC3PARAM_51_H 1


/*!
 * \brief Per RFC 5155 */

#include <isc/iterated_hash.h>

typedef struct dns_rdata_nsec3param {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_hash_t		hash;
	unsigned char		flags;		/* DNS_NSEC3FLAG_* */
	dns_iterations_t	iterations;
	unsigned char		salt_length;
	unsigned char		*salt;
} dns_rdata_nsec3param_t;

#endif /* GENERIC_NSEC3PARAM_51_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef GENERIC_TLSA_52_H
#define GENERIC_TLSA_52_H 1

/*!
 *  \brief per rfc6698.txt
 */
typedef struct dns_rdata_tlsa {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	uint8_t		usage;
	uint8_t		selector;
	uint8_t		match;
	uint16_t		length;
	unsigned char		*data;
} dns_rdata_tlsa_t;

#endif /* GENERIC_TLSA_52_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_SMIMEA_53_H
#define GENERIC_SMIMEA_53_H 1

typedef struct dns_rdata_tlsa dns_rdata_smimea_t;

#endif /* GENERIC_SMIMEA_53_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef GENERIC_HIP_5_H
#define GENERIC_HIP_5_H 1

/* RFC 5205 */

typedef struct dns_rdata_hip {
	dns_rdatacommon_t	common;
	isc_mem_t *		mctx;
	unsigned char *		hit;
	unsigned char *		key;
	unsigned char *		servers;
	uint8_t		algorithm;
	uint8_t		hit_len;
	uint16_t		key_len;
	uint16_t		servers_len;
	/* Private */
	uint16_t		offset;
} dns_rdata_hip_t;

isc_result_t
dns_rdata_hip_first(dns_rdata_hip_t *);

isc_result_t
dns_rdata_hip_next(dns_rdata_hip_t *);

void
dns_rdata_hip_current(dns_rdata_hip_t *, dns_name_t *);

#endif /* GENERIC_HIP_5_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_NINFO_56_H
#define GENERIC_NINFO_56_H 1

typedef struct dns_rdata_txt_string dns_rdata_ninfo_string_t;

typedef struct dns_rdata_txt dns_rdata_ninfo_t;

/*
 * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done
 * via rdatastructpre.h and rdatastructsuf.h.
 */

isc_result_t
dns_rdata_ninfo_first(dns_rdata_ninfo_t *);

isc_result_t
dns_rdata_ninfo_next(dns_rdata_ninfo_t *);

isc_result_t
dns_rdata_ninfo_current(dns_rdata_ninfo_t *, dns_rdata_ninfo_string_t *);

#endif /* GENERIC_NINFO_16_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_RKEY_57_H
#define GENERIC_RKEY_57_H 1

typedef struct dns_rdata_key dns_rdata_rkey_t;

#endif /* GENERIC_RKEY_57_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* http://www.iana.org/assignments/dns-parameters/TALINK/talink-completed-template */

#ifndef GENERIC_TALINK_58_H
#define GENERIC_TALINK_58_H 1

typedef struct dns_rdata_talink {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	dns_name_t		prev;
	dns_name_t		next;
} dns_rdata_talink_t;

#endif /* GENERIC_TALINK_58_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_CDS_59_H
#define GENERIC_CDS_59_H 1

/* CDS records have the same RDATA fields as DS records. */
typedef struct dns_rdata_ds dns_rdata_cds_t;

#endif /* GENERIC_CDS_59_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_CDNSKEY_60_H
#define GENERIC_CDNSKEY_60_H 1

/* CDNSKEY records have the same RDATA fields as DNSKEY records. */
typedef struct dns_rdata_key dns_rdata_cdnskey_t;

#endif /* GENERIC_CDNSKEY_60_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_OPENPGPKEY_61_H
#define GENERIC_OPENPGPKEY_61_H 1

typedef struct dns_rdata_openpgpkey {
	dns_rdatacommon_t	common;
	isc_mem_t *		mctx;
	uint16_t		length;
	unsigned char *		keyring;
} dns_rdata_openpgpkey_t;

#endif /* GENERIC_OPENPGPKEY_61_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_CSYNC_62_H
#define GENERIC_CSYNC_62_H 1

/*!
 * \brief Per RFC 7477
 */

typedef struct dns_rdata_csync {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	uint32_t		serial;
	uint16_t		flags;
	unsigned char		*typebits;
	uint16_t		len;
} dns_rdata_csync_t;

#endif /* GENERIC_CSYNC_62_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_ZONEMD_63_H
#define GENERIC_ZONEMD_63_H 1

/* Known digest type(s). */
#define DNS_ZONEMD_DIGEST_SHA384 (1)
#define DNS_ZONEMD_DIGEST_SHA512 (2)

/*
 *  \brief per RFC 8976
 */
typedef struct dns_rdata_zonemd {
	dns_rdatacommon_t common;
	isc_mem_t *mctx;
	uint32_t serial;
	uint8_t scheme;
	uint8_t digest_type;
	unsigned char *digest;
	uint16_t length;
} dns_rdata_zonemd_t;

#endif /* GENERIC_ZONEMD_63_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_SPF_99_H
#define GENERIC_SPF_99_H 1


typedef struct dns_rdata_spf_string {
		uint8_t    length;
		unsigned char   *data;
} dns_rdata_spf_string_t;

typedef struct dns_rdata_spf {
	dns_rdatacommon_t       common;
	isc_mem_t               *mctx;
	unsigned char           *txt;
	uint16_t            txt_len;
	/* private */
	uint16_t            offset;
} dns_rdata_spf_t;

/*
 * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done
 * via rdatastructpre.h and rdatastructsuf.h.
 */
#endif /* GENERIC_SPF_99_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_NID_104_H
#define GENERIC_NID_104_H 1

typedef struct dns_rdata_nid {
	dns_rdatacommon_t	common;
	uint16_t		pref;
	unsigned char		nid[8];
} dns_rdata_nid_t;

#endif /* GENERIC_NID_104_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_L32_105_H
#define GENERIC_L32_105_H 1

typedef struct dns_rdata_l32 {
	dns_rdatacommon_t	common;
	uint16_t		pref;
	struct in_addr		l32;
} dns_rdata_l32_t;

#endif /* GENERIC_L32_105_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_L64_106_H
#define GENERIC_L64_106_H 1

typedef struct dns_rdata_l64 {
	dns_rdatacommon_t	common;
	uint16_t		pref;
	unsigned char		l64[8];
} dns_rdata_l64_t;

#endif /* GENERIC_L64_106_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_LP_107_H
#define GENERIC_LP_107_H 1

typedef struct dns_rdata_lp {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	uint16_t		pref;
	dns_name_t		lp;
} dns_rdata_lp_t;

#endif /* GENERIC_LP_107_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_EUI48_108_H
#define GENERIC_EUI48_108_H 1

typedef struct dns_rdata_eui48 {
	dns_rdatacommon_t	common;
	unsigned char		eui48[6];
} dns_rdata_eui48_t;

#endif /* GENERIC_EUI48_10k_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/* */
#ifndef GENERIC_EUI64_109_H
#define GENERIC_EUI64_109_H 1

typedef struct dns_rdata_eui64 {
	dns_rdatacommon_t	common;
	unsigned char		eui64[8];
} dns_rdata_eui64_t;

#endif /* GENERIC_EUI64_10k_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_TKEY_249_H
#define GENERIC_TKEY_249_H 1


/*!
 *  \brief Per draft-ietf-dnsind-tkey-00.txt */

typedef struct dns_rdata_tkey {
	dns_rdatacommon_t	common;
	isc_mem_t *		mctx;
	dns_name_t		algorithm;
	uint32_t		inception;
	uint32_t		expire;
	uint16_t		mode;
	uint16_t		error;
	uint16_t		keylen;
	unsigned char *		key;
	uint16_t		otherlen;
	unsigned char *		other;
} dns_rdata_tkey_t;


#endif /* GENERIC_TKEY_249_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef ANY_255_TSIG_250_H
#define ANY_255_TSIG_250_H 1

/*% RFC2845 */
typedef struct dns_rdata_any_tsig {
	dns_rdatacommon_t	common;
	isc_mem_t *		mctx;
	dns_name_t		algorithm;
	uint64_t		timesigned;
	uint16_t		fudge;
	uint16_t		siglen;
	unsigned char *		signature;
	uint16_t		originalid;
	uint16_t		error;
	uint16_t		otherlen;
	unsigned char *		other;
} dns_rdata_any_tsig_t;

#endif /* ANY_255_TSIG_250_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_URI_256_H
#define GENERIC_URI_256_H 1


typedef struct dns_rdata_uri {
	dns_rdatacommon_t	common;
	isc_mem_t *		mctx;
	uint16_t		priority;
	uint16_t		weight;
	unsigned char *		target;
	uint16_t		tgt_len;
} dns_rdata_uri_t;

#endif /* GENERIC_URI_256_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_CAA_257_H
#define GENERIC_CAA_257_H 1


typedef struct dns_rdata_caa {
	dns_rdatacommon_t	common;
	isc_mem_t *		mctx;
	uint8_t		flags;
	unsigned char *		tag;
	uint8_t		tag_len;
	unsigned char		*value;
	uint16_t		value_len;
} dns_rdata_caa_t;

#endif /* GENERIC_CAA_257_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_AVC_258_H
#define GENERIC_AVC_258_H 1

typedef dns_rdata_txt_string_t dns_rdata_avc_string_t;

typedef struct dns_rdata_avc {
	dns_rdatacommon_t       common;
	isc_mem_t               *mctx;
	unsigned char           *data;
	uint16_t            length;
	/* private */
	uint16_t            offset;
} dns_rdata_avc_t;

/*
 * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done
 * via rdatastructpre.h and rdatastructsuf.h.
 */
#endif /* GENERIC_AVC_258_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_DOA_259_H
#define GENERIC_DOA_259_H 1

typedef struct dns_rdata_doa {
	dns_rdatacommon_t	common;
	isc_mem_t *		mctx;
	unsigned char *		mediatype;
	unsigned char *		data;
	uint32_t		enterprise;
	uint32_t		type;
	uint16_t		data_len;
	uint8_t		location;
	uint8_t		mediatype_len;
} dns_rdata_doa_t;

#endif /* GENERIC_DOA_259_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef GENERIC_AMTRELAY_260_H
#define GENERIC_AMTRELAY_260_H 1

typedef struct dns_rdata_amtrelay {
	dns_rdatacommon_t	common;
	isc_mem_t		*mctx;
	uint8_t			precedence;
	bool			discovery;
	uint8_t			gateway_type;
	struct in_addr		in_addr;	/* gateway type 1 */
	struct in6_addr		in6_addr;	/* gateway type 2 */
	dns_name_t		gateway;	/* gateway type 3 */
	unsigned char		*data;		/* gateway type > 3 */
	uint16_t		length;
} dns_rdata_amtrelay_t;

#endif /* GENERIC_AMTRELAY_260_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_TA_32768_H
#define GENERIC_TA_32768_H 1

/*
 * TA records are identical to DS records.
 */
typedef struct dns_rdata_ds dns_rdata_ta_t;

#endif /* GENERIC_TA_32768_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


/* draft-ietf-dnsext-delegation-signer-05.txt */
#ifndef GENERIC_DLV_32769_H
#define GENERIC_DLV_32769_H 1

typedef struct dns_rdata_ds dns_rdata_dlv_t;

#endif /* GENERIC_DLV_32769_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef GENERIC_KEYDATA_65533_H
#define GENERIC_KEYDATA_65533_H 1


typedef struct dns_rdata_keydata {
	dns_rdatacommon_t	common;
	isc_mem_t *		mctx;
	uint32_t		refresh;      /* Timer for refreshing data */
	uint32_t		addhd;	      /* Hold-down timer for adding */
	uint32_t		removehd;     /* Hold-down timer for removing */
	uint16_t		flags;	      /* Copy of DNSKEY_48 */
	dns_secproto_t		protocol;
	dns_secalg_t		algorithm;
	uint16_t		datalen;
	unsigned char *		data;
} dns_rdata_keydata_t;

#endif /* GENERIC_KEYDATA_65533_H */
/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


ISC_LANG_ENDDECLS

#endif /* DNS_RDATASTRUCT_H */
peer.h000064400000013516150415243040005654 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_PEER_H
#define DNS_PEER_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/peer.h
 * \brief
 * Data structures for peers (e.g. a 'server' config file statement)
 */

/***
 *** Imports
 ***/

#include <inttypes.h>
#include <stdbool.h>

#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/netaddr.h>

#include <dns/types.h>

#define DNS_PEERLIST_MAGIC	ISC_MAGIC('s','e','R','L')
#define DNS_PEER_MAGIC		ISC_MAGIC('S','E','r','v')

#define DNS_PEERLIST_VALID(ptr)	ISC_MAGIC_VALID(ptr, DNS_PEERLIST_MAGIC)
#define DNS_PEER_VALID(ptr)	ISC_MAGIC_VALID(ptr, DNS_PEER_MAGIC)

/***
 *** Types
 ***/

struct dns_peerlist {
	unsigned int		magic;
	uint32_t		refs;

	isc_mem_t	       *mem;

	ISC_LIST(dns_peer_t) elements;
};

struct dns_peer {
	unsigned int		magic;
	uint32_t		refs;

	isc_mem_t	       *mem;

	isc_netaddr_t		address;
	unsigned int		prefixlen;
	bool		bogus;
	dns_transfer_format_t	transfer_format;
	uint32_t		transfers;
	bool		support_ixfr;
	bool		provide_ixfr;
	bool		request_ixfr;
	bool		support_edns;
	bool		request_nsid;
	bool		send_cookie;
	bool		request_expire;
	bool		force_tcp;
	dns_name_t	       *key;
	isc_sockaddr_t	       *transfer_source;
	isc_dscp_t		transfer_dscp;
	isc_sockaddr_t	       *notify_source;
	isc_dscp_t		notify_dscp;
	isc_sockaddr_t	       *query_source;
	isc_dscp_t		query_dscp;
	uint16_t		udpsize;		/* receive size */
	uint16_t		maxudp;			/* transmit size */
	uint8_t			ednsversion;		/* edns version */

	uint32_t		bitflags;

	ISC_LINK(dns_peer_t)	next;
};

/***
 *** Functions
 ***/

ISC_LANG_BEGINDECLS

isc_result_t
dns_peerlist_new(isc_mem_t *mem, dns_peerlist_t **list);

void
dns_peerlist_attach(dns_peerlist_t *source, dns_peerlist_t **target);

void
dns_peerlist_detach(dns_peerlist_t **list);

/*
 * After return caller still holds a reference to peer.
 */
void
dns_peerlist_addpeer(dns_peerlist_t *peers, dns_peer_t *peer);

/*
 * Ditto. */
isc_result_t
dns_peerlist_peerbyaddr(dns_peerlist_t *peers, isc_netaddr_t *addr,
			dns_peer_t **retval);

/*
 * What he said.
 */
isc_result_t
dns_peerlist_currpeer(dns_peerlist_t *peers, dns_peer_t **retval);

isc_result_t
dns_peer_new(isc_mem_t *mem, isc_netaddr_t *ipaddr, dns_peer_t **peer);

isc_result_t
dns_peer_newprefix(isc_mem_t *mem, isc_netaddr_t *ipaddr,
		   unsigned int prefixlen, dns_peer_t **peer);

void
dns_peer_attach(dns_peer_t *source, dns_peer_t **target);

void
dns_peer_detach(dns_peer_t **list);

isc_result_t
dns_peer_setbogus(dns_peer_t *peer, bool newval);

isc_result_t
dns_peer_getbogus(dns_peer_t *peer, bool *retval);

isc_result_t
dns_peer_setrequestixfr(dns_peer_t *peer, bool newval);

isc_result_t
dns_peer_getrequestixfr(dns_peer_t *peer, bool *retval);

isc_result_t
dns_peer_setprovideixfr(dns_peer_t *peer, bool newval);

isc_result_t
dns_peer_getprovideixfr(dns_peer_t *peer, bool *retval);

isc_result_t
dns_peer_setrequestnsid(dns_peer_t *peer, bool newval);

isc_result_t
dns_peer_getrequestnsid(dns_peer_t *peer, bool *retval);

isc_result_t
dns_peer_setsendcookie(dns_peer_t *peer, bool newval);

isc_result_t
dns_peer_getsendcookie(dns_peer_t *peer, bool *retval);

isc_result_t
dns_peer_setrequestexpire(dns_peer_t *peer, bool newval);

isc_result_t
dns_peer_getrequestexpire(dns_peer_t *peer, bool *retval);

isc_result_t
dns_peer_setsupportedns(dns_peer_t *peer, bool newval);

isc_result_t
dns_peer_getforcetcp(dns_peer_t *peer, bool *retval);

isc_result_t
dns_peer_setforcetcp(dns_peer_t *peer, bool newval);

isc_result_t
dns_peer_getsupportedns(dns_peer_t *peer, bool *retval);

isc_result_t
dns_peer_settransfers(dns_peer_t *peer, uint32_t newval);

isc_result_t
dns_peer_gettransfers(dns_peer_t *peer, uint32_t *retval);

isc_result_t
dns_peer_settransferformat(dns_peer_t *peer, dns_transfer_format_t newval);

isc_result_t
dns_peer_gettransferformat(dns_peer_t *peer, dns_transfer_format_t *retval);

isc_result_t
dns_peer_setkeybycharp(dns_peer_t *peer, const char *keyval);

isc_result_t
dns_peer_getkey(dns_peer_t *peer, dns_name_t **retval);

isc_result_t
dns_peer_setkey(dns_peer_t *peer, dns_name_t **keyval);

isc_result_t
dns_peer_settransfersource(dns_peer_t *peer,
			   const isc_sockaddr_t *transfer_source);

isc_result_t
dns_peer_gettransfersource(dns_peer_t *peer, isc_sockaddr_t *transfer_source);

isc_result_t
dns_peer_setudpsize(dns_peer_t *peer, uint16_t udpsize);

isc_result_t
dns_peer_getudpsize(dns_peer_t *peer, uint16_t *udpsize);

isc_result_t
dns_peer_setmaxudp(dns_peer_t *peer, uint16_t maxudp);

isc_result_t
dns_peer_getmaxudp(dns_peer_t *peer, uint16_t *maxudp);

isc_result_t
dns_peer_setnotifysource(dns_peer_t *peer, const isc_sockaddr_t *notify_source);

isc_result_t
dns_peer_getnotifysource(dns_peer_t *peer, isc_sockaddr_t *notify_source);

isc_result_t
dns_peer_setquerysource(dns_peer_t *peer, const isc_sockaddr_t *query_source);

isc_result_t
dns_peer_getquerysource(dns_peer_t *peer, isc_sockaddr_t *query_source);

isc_result_t
dns_peer_setnotifydscp(dns_peer_t *peer, isc_dscp_t dscp);

isc_result_t
dns_peer_getnotifydscp(dns_peer_t *peer, isc_dscp_t *dscpp);

isc_result_t
dns_peer_settransferdscp(dns_peer_t *peer, isc_dscp_t dscp);

isc_result_t
dns_peer_gettransferdscp(dns_peer_t *peer, isc_dscp_t *dscpp);

isc_result_t
dns_peer_setquerydscp(dns_peer_t *peer, isc_dscp_t dscp);

isc_result_t
dns_peer_getquerydscp(dns_peer_t *peer, isc_dscp_t *dscpp);

isc_result_t
dns_peer_setednsversion(dns_peer_t *peer, uint8_t ednsversion);

isc_result_t
dns_peer_getednsversion(dns_peer_t *peer, uint8_t *ednsversion);
ISC_LANG_ENDDECLS

#endif /* DNS_PEER_H */
client.h000064400000053032150415243040006174 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_CLIENT_H
#define DNS_CLIENT_H 1

/*****
 ***** Module Info
 *****/

/*! \file
 *
 * \brief
 * The DNS client module provides convenient programming interfaces to various
 * DNS services, such as name resolution with or without DNSSEC validation or
 * dynamic DNS update.  This module is primarily expected to be used by other
 * applications than BIND9-related ones that need such advanced DNS features.
 *
 * MP:
 *\li	In the typical usage of this module, application threads will not share
 *	the same data structures created and manipulated in this module.
 *	However, the module still ensures appropriate synchronization of such
 *	data structures.
 *
 * Resources:
 *\li	TBS
 *
 * Security:
 *\li	This module does not handle any low-level data directly, and so no
 *	security issue specific to this module is anticipated.
 */

#include <isc/event.h>
#include <isc/sockaddr.h>

#include <dns/tsig.h>
#include <dns/types.h>

#include <dst/dst.h>

typedef enum {
	updateop_none = 0,
	updateop_add = 1,
	updateop_delete = 2,
	updateop_exist = 3,
	updateop_notexist = 4,
	updateop_max = 5
} dns_client_updateop_t;

ISC_LANG_BEGINDECLS

/***
 *** Types
 ***/

/*%
 * Optional flags for dns_client_create(x).
 */
/*%< Enable caching resolution results (experimental). */
#define DNS_CLIENTCREATEOPT_USECACHE	0x8000

/*%
 * Optional flags for dns_client_(start)resolve.
 */
/*%< Do not return DNSSEC data (e.g. RRSIGS) with response. */
#define DNS_CLIENTRESOPT_NODNSSEC	0x01
/*%< Allow running external context. */
#define DNS_CLIENTRESOPT_ALLOWRUN	0x02
/*%< Don't validate responses. */
#define DNS_CLIENTRESOPT_NOVALIDATE	0x04
/*%< Don't set the CD flag on upstream queries. */
#define DNS_CLIENTRESOPT_NOCDFLAG	0x08
/*%< Use TCP transport. */
#define DNS_CLIENTRESOPT_TCP		0x10

/*%
 * Optional flags for dns_client_(start)request.
 */
/*%< Allow running external context. */
#define DNS_CLIENTREQOPT_ALLOWRUN	0x01
/*%< Use TCP transport. */
#define DNS_CLIENTREQOPT_TCP		0x02

/*%
 * Optional flags for dns_client_(start)update.
 */
/*%< Allow running external context. */
#define DNS_CLIENTUPDOPT_ALLOWRUN	0x01
/*%< Use TCP transport. */
#define DNS_CLIENTUPDOPT_TCP		0x02

/*%
 * A dns_clientresevent_t is sent when name resolution performed by a client
 * completes.  'result' stores the result code of the entire resolution
 * procedure.  'vresult' specifically stores the result code of DNSSEC
 * validation if it is performed.  When name resolution successfully completes,
 * 'answerlist' is typically non empty, containing answer names along with
 * RRsets.  It is the receiver's responsibility to free this list by calling
 * dns_client_freeresanswer() before freeing the event structure.
 */
typedef struct dns_clientresevent {
	ISC_EVENT_COMMON(struct dns_clientresevent);
	isc_result_t	result;
	isc_result_t	vresult;
	dns_namelist_t	answerlist;
} dns_clientresevent_t;		/* too long? */

/*%
 * Status of a dynamic update procedure.
 */
typedef enum {
	dns_clientupdatestate_prepare,	/*%< no updates have been sent */
	dns_clientupdatestate_sent,	/*%< updates were sent, no response */
	dns_clientupdatestate_done	/*%< update was sent and succeeded */
} dns_clientupdatestate_t;

/*%
 * A dns_clientreqevent_t is sent when a DNS request is completed by a client.
 * 'result' stores the result code of the entire transaction.
 * If the transaction is successfully completed but the response packet cannot
 * be parsed, 'result' will store the result code of dns_message_parse().
 * If the response packet is received, 'rmessage' will contain the response
 * message, whether it is successfully parsed or not.
 */
typedef struct dns_clientreqevent {
	ISC_EVENT_COMMON(struct dns_clientreqevent);
	isc_result_t	result;
	dns_message_t	*rmessage;
} dns_clientreqevent_t;		/* too long? */

/*%
 * A dns_clientupdateevent_t is sent when dynamic update performed by a client
 * completes.  'result' stores the result code of the entire update procedure.
 * 'state' specifies the status of the update procedure when this event is
 * sent.  This can be used as a hint by the receiver to determine whether
 * the update attempt was ever made.  In particular, if the state is
 * dns_clientupdatestate_prepare, the receiver can be sure that the requested
 * update was not applied.
 */
typedef struct dns_clientupdateevent {
	ISC_EVENT_COMMON(struct dns_clientupdateevent);
	isc_result_t		result;
	dns_clientupdatestate_t	state;
} dns_clientupdateevent_t;	/* too long? */

isc_result_t
dns_client_create(dns_client_t **clientp, unsigned int options);

isc_result_t
dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr,
		   isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr,
		   unsigned int options, dns_client_t **clientp);

isc_result_t
dns_client_createx2(isc_mem_t *mctx, isc_appctx_t *actx,
	   isc_taskmgr_t *taskmgr, isc_socketmgr_t *socketmgr,
	   isc_timermgr_t *timermgr, unsigned int options,
	   dns_client_t **clientp,
	   isc_sockaddr_t *localaddr4, isc_sockaddr_t *localaddr6);
/*%<
 * Create a DNS client.  These functions create a new client object with
 * minimal internal resources such as the default 'view' for the IN class and
 * IPv4/IPv6 dispatches for the view.
 *
 * dns_client_createx() takes 'manager' arguments so that the caller can
 * control the behavior of the client through the underlying event framework.
 * On the other hand, dns_client_create() simplifies the interface and creates
 * the managers internally.  A DNS client object created via
 * dns_client_create() is expected to be used by an application that only needs
 * simple synchronous services or by a thread-based application.
 *
 * dns_client_createx2 takes two additional parameters, 'localaddr4' and
 * 'localaddr6', to specify the local address to use for each family. If
 * both are set to NULL, then wildcard addresses will be used for both
 * families. If only one is NULL, then the other address will be used
 * as the local address, and the other protocol family will not be used.
 *
 * If the DNS_CLIENTCREATEOPT_USECACHE flag is set in 'options',
 * dns_client_create(x) will create a cache database with the view.
 *
 * Requires:
 *
 *\li	'mctx' is a valid memory context.
 *
 *\li	'actx' is a valid application context.
 *
 *\li	'taskmgr' is a valid task manager.
 *
 *\li	'socketmgr' is a valid socket manager.
 *
 *\li	'timermgr' is a valid timer manager.
 *
 *\li	clientp != NULL && *clientp == NULL.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS				On success.
 *
 *\li	Anything else				Failure.
 */

void
dns_client_destroy(dns_client_t **clientp);
/*%<
 * Destroy 'client'.
 *
 * Requires:
 *
 *\li	'*clientp' is a valid client.
 *
 * Ensures:
 *
 *\li	*clientp == NULL.
 */

isc_result_t
dns_client_setservers(dns_client_t *client, dns_rdataclass_t rdclass,
		      dns_name_t *name_space, isc_sockaddrlist_t *addrs);
/*%<
 * Specify a list of addresses of recursive name servers that the client will
 * use for name resolution.  A view for the 'rdclass' class must be created
 * beforehand.  If 'name_space' is non NULL, the specified server will be used
 * if and only if the query name is a subdomain of 'name_space'.  When servers
 * for multiple 'name_space's are provided, and a query name is covered by
 * more than one 'name_space', the servers for the best (longest) matching
 * name_space will be used.  If 'name_space' is NULL, it works as if
 * dns_rootname (.) were specified.
 *
 * Requires:
 *
 *\li	'client' is a valid client.
 *
 *\li	'name_space' is NULL or a valid name.
 *
 *\li	'addrs' != NULL.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS				On success.
 *
 *\li	Anything else				Failure.
 */

isc_result_t
dns_client_clearservers(dns_client_t *client, dns_rdataclass_t rdclass,
			dns_name_t *name_space);
/*%<
 * Remove configured recursive name servers for the 'rdclass' and 'name_space'
 * from the client.  See the description of dns_client_setservers() for
 * the requirements about 'rdclass' and 'name_space'.
 *
 * Requires:
 *
 *\li	'client' is a valid client.
 *
 *\li	'name_space' is NULL or a valid name.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS				On success.
 *
 *\li	Anything else				Failure.
 */

isc_result_t
dns_client_setdlv(dns_client_t *client, dns_rdataclass_t rdclass,
		  const char *dlvname);
/*%<
 * Specify a name to use for DNSSEC lookaside validation.
 * If a trusted key has been added for that name, then DLV will be
 * used during validation.  If 'dlvname' is NULL, then DLV will no
 * longer be used for this client.
 *
 * Requires:
 *
 *\li	'client' is a valid client.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS				On success.
 *
 *\li	Anything else				Failure.
 */

isc_result_t
dns_client_resolve(dns_client_t *client, dns_name_t *name,
		   dns_rdataclass_t rdclass, dns_rdatatype_t type,
		   unsigned int options, dns_namelist_t *namelist);

isc_result_t
dns_client_startresolve(dns_client_t *client, dns_name_t *name,
			dns_rdataclass_t rdclass, dns_rdatatype_t type,
			unsigned int options, isc_task_t *task,
			isc_taskaction_t action, void *arg,
			dns_clientrestrans_t **transp);
/*%<
 * Perform name resolution for 'name', 'rdclass', and 'type'.
 *
 * If any trusted keys are configured and the query name is considered to
 * belong to a secure zone, these functions also validate the responses
 * using DNSSEC by default.  If the DNS_CLIENTRESOPT_NOVALIDATE flag is set
 * in 'options', DNSSEC validation is disabled regardless of the configured
 * trusted keys or the query name. With DNS_CLIENTRESOPT_NODNSSEC
 * DNSSEC data is not returned with response. DNS_CLIENTRESOPT_NOCDFLAG
 * disables the CD flag on queries, DNS_CLIENTRESOPT_TCP switches to
 * the TCP (vs. UDP) transport.
 *
 * dns_client_resolve() provides a synchronous service.  This function starts
 * name resolution internally and blocks until it completes.  On success,
 * 'namelist' will contain a list of answer names, each of which has
 * corresponding RRsets.  The caller must provide a valid empty list, and
 * is responsible for freeing the list content via dns_client_freeresanswer().
 * If the name resolution fails due to an error in DNSSEC validation,
 * dns_client_resolve() returns the result code indicating the validation
 * error. Otherwise, it returns the result code of the entire resolution
 * process, either success or failure.
 *
 * It is typically expected that the client object passed to
 * dns_client_resolve() was created via dns_client_create() and has its own
 * managers and contexts.  However, if the DNS_CLIENTRESOPT_ALLOWRUN flag is
 * set in 'options', this function performs the synchronous service even if
 * it does not have its own manager and context structures.
 *
 * dns_client_startresolve() is an asynchronous version of dns_client_resolve()
 * and does not block.  When name resolution is completed, 'action' will be
 * called with the argument of a 'dns_clientresevent_t' object, which contains
 * the resulting list of answer names (on success).  On return, '*transp' is
 * set to an opaque transaction ID so that the caller can cancel this
 * resolution process.
 *
 * Requires:
 *
 *\li	'client' is a valid client.
 *
 *\li	'addrs' != NULL.
 *
 *\li	'name' is a valid name.
 *
 *\li	'namelist' != NULL and is not empty.
 *
 *\li	'task' is a valid task.
 *
 *\li	'transp' != NULL && *transp == NULL;
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS				On success.
 *
 *\li	Anything else				Failure.
 */

void
dns_client_cancelresolve(dns_clientrestrans_t *trans);
/*%<
 * Cancel an ongoing resolution procedure started via
 * dns_client_startresolve().
 *
 * Notes:
 *
 *\li	If the resolution procedure has not completed, post its CLIENTRESDONE
 *	event with a result code of #ISC_R_CANCELED.
 *
 * Requires:
 *
 *\li	'trans' is a valid transaction ID.
 */

void
dns_client_destroyrestrans(dns_clientrestrans_t **transp);
/*%<
 * Destroy name resolution transaction state identified by '*transp'.
 *
 * Requires:
 *
 *\li	'*transp' is a valid transaction ID.
 *
 *\li	The caller has received the CLIENTRESDONE event (either because the
 *	resolution completed or because dns_client_cancelresolve() was called).
 *
 * Ensures:
 *
 *\li	*transp == NULL.
 */

void
dns_client_freeresanswer(dns_client_t *client, dns_namelist_t *namelist);
/*%<
 * Free resources allocated for the content of 'namelist'.
 *
 * Requires:
 *
 *\li	'client' is a valid client.
 *
 *\li	'namelist' != NULL.
 */

isc_result_t
dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
			 dns_name_t *keyname, isc_buffer_t *keydatabuf);
/*%<
 * Add a DNSSEC trusted key for the 'rdclass' class.  A view for the 'rdclass'
 * class must be created beforehand.  'keyname' is the DNS name of the key,
 * and 'keydatabuf' stores the resource data of the key.
 *
 * Requires:
 *
 *\li	'client' is a valid client.
 *
 *\li	'keyname' is a valid name.
 *
 *\li	'keydatabuf' is a valid buffer.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS				On success.
 *
 *\li	Anything else				Failure.
 */

isc_result_t
dns_client_request(dns_client_t *client, dns_message_t *qmessage,
		   dns_message_t *rmessage, isc_sockaddr_t *server,
		   unsigned int options, unsigned int parseoptions,
		   dns_tsec_t *tsec, unsigned int timeout,
		   unsigned int udptimeout, unsigned int udpretries);

isc_result_t
dns_client_startrequest(dns_client_t *client, dns_message_t *qmessage,
			dns_message_t *rmessage, isc_sockaddr_t *server,
			unsigned int options, unsigned int parseoptions,
			dns_tsec_t *tsec, unsigned int timeout,
			unsigned int udptimeout, unsigned int udpretries,
			isc_task_t *task, isc_taskaction_t action, void *arg,
			dns_clientreqtrans_t **transp);

/*%<
 * Send a DNS request containing a query message 'query' to 'server'.
 *
 * 'parseoptions' will be used when the response packet is parsed, and will be
 * passed to dns_message_parse() via dns_request_getresponse().  See
 * dns_message_parse() for more details.
 *
 * 'tsec' is a transaction security object containing, e.g. a TSIG key for
 * authenticating the request/response transaction.  This is optional and can
 * be NULL, in which case this library performs the transaction  without any
 * transaction authentication.
 *
 * 'timeout', 'udptimeout', and 'udpretries' are passed to
 * dns_request_createvia3().  See dns_request_createvia3() for more details.
 *
 * dns_client_request() provides a synchronous service.  This function sends
 * the request and blocks until a response is received.  On success,
 * 'rmessage' will contain the response message.  The caller must provide a
 * valid initialized message.
 *
 * It is usually expected that the client object passed to
 * dns_client_request() was created via dns_client_create() and has its own
 * managers and contexts.  However, if the DNS_CLIENTREQOPT_ALLOWRUN flag is
 * set in 'options', this function performs the synchronous service even if
 * it does not have its own manager and context structures.
 *
 * dns_client_startrequest() is an asynchronous version of dns_client_request()
 * and does not block.  When the transaction is completed, 'action' will be
 * called with the argument of a 'dns_clientreqevent_t' object, which contains
 * the response message (on success).  On return, '*transp' is set to an opaque
 * transaction ID so that the caller can cancel this request.
 *
 * DNS_CLIENTREQOPT_TCP switches to the TCP (vs. UDP) transport.
 *
 * Requires:
 *
 *\li	'client' is a valid client.
 *
 *\li	'qmessage' and 'rmessage' are valid initialized message.
 *
 *\li	'server' is a valid socket address structure.
 *
 *\li	'task' is a valid task.
 *
 *\li	'transp' != NULL && *transp == NULL;
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS				On success.
 *
 *\li	Anything else				Failure.
 *
 *\li	Any result that dns_message_parse() can return.
 */

void
dns_client_cancelrequest(dns_clientreqtrans_t *transp);
/*%<
 * Cancel an ongoing DNS request procedure started via
 * dns_client_startrequest().
 *
 * Notes:
 *
 *\li	If the request procedure has not completed, post its CLIENTREQDONE
 *	event with a result code of #ISC_R_CANCELED.
 *
 * Requires:
 *
 *\li	'trans' is a valid transaction ID.
 */

void
dns_client_destroyreqtrans(dns_clientreqtrans_t **transp);
/*%
 * Destroy DNS request transaction state identified by '*transp'.
 *
 * Requires:
 *
 *\li	'*transp' is a valid transaction ID.
 *
 *\li	The caller has received the CLIENTREQDONE event (either because the
 *	request completed or because dns_client_cancelrequest() was called).
 *
 * Ensures:
 *
 *\li	*transp == NULL.
 */

isc_result_t
dns_client_update(dns_client_t *client, dns_rdataclass_t rdclass,
		  dns_name_t *zonename, dns_namelist_t *prerequisites,
		  dns_namelist_t *updates, isc_sockaddrlist_t *servers,
		  dns_tsec_t *tsec, unsigned int options);

isc_result_t
dns_client_startupdate(dns_client_t *client, dns_rdataclass_t rdclass,
		       dns_name_t *zonename, dns_namelist_t *prerequisites,
		       dns_namelist_t *updates, isc_sockaddrlist_t *servers,
		       dns_tsec_t *tsec, unsigned int options,
		       isc_task_t *task, isc_taskaction_t action, void *arg,
		       dns_clientupdatetrans_t **transp);
/*%<
 * Perform DNS dynamic update for 'updates' of the 'rdclass' class with
 * optional 'prerequisites'.
 *
 * 'updates' are a list of names with associated RRsets to be updated.
 *
 * 'prerequisites' are a list of names with associated RRsets corresponding to
 * the prerequisites of the updates.  This is optional and can be NULL, in
 * which case the prerequisite section of the update message will be empty.
 *
 * Both 'updates' and 'prerequisites' must be constructed as specified in
 * RFC2136.
 *
 * 'zonename' is the name of the zone in which the updated names exist.
 * This is optional and can be NULL.  In this case, these functions internally
 * identify the appropriate zone through some queries for the SOA RR starting
 * with the first name in prerequisites or updates.
 *
 * 'servers' is a list of authoritative servers to which the update message
 * should be sent.  This is optional and can be NULL.  In this case, these
 * functions internally identify the appropriate primary server name and its
 * addresses through some queries for the SOA RR (like the case of zonename)
 * and supplemental A/AAAA queries for the server name.
 * Note: The client module generally assumes the given addresses are of the
 * primary server of the corresponding zone.  It will work even if a secondary
 * server address is specified as long as the server allows update forwarding,
 * it is generally discouraged to include secondary server addresses unless
 * there's strong reason to do so.
 *
 * 'tsec' is a transaction security object containing, e.g. a TSIG key for
 * authenticating the update transaction (and the supplemental query/response
 * transactions if the server is specified).  This is optional and can be
 * NULL, in which case the library tries the update without any transaction
 * authentication.
 *
 * It is typically expected that the client object passed to
 * dns_client_update() was created via dns_client_create() and has its own
 * managers and contexts.  However, if the DNS_CLIENTUPDOPT_ALLOWRUN flag is
 * set in 'options', this function performs the synchronous service even if
 * it does not have its own manager and context structures.
 *
 * dns_client_update() provides a synchronous service.  This function blocks
 * until the entire update procedure completes, including the additional
 * queries when necessary.
 *
 * dns_client_startupdate() is an asynchronous version of dns_client_update().
 * It immediately returns (typically with *transp being set to a non-NULL
 * pointer), and performs the update procedure through a set of internal
 * events.  All transactions including the additional query exchanges are
 * performed as a separate event, so none of these events cause blocking
 * operation.  When the update procedure completes, the specified function
 * 'action' will be called with the argument of a 'dns_clientupdateevent_t'
 * structure.  On return, '*transp' is set to an opaque transaction ID so that
 * the caller can cancel this update process.
 *
 * DNS_CLIENTUPDOPT_TCP switches to the TCP (vs. UDP) transport.
 *
 * Requires:
 *
 *\li	'client' is a valid client.
 *
 *\li	'updates' != NULL.
 *
 *\li	'task' is a valid task.
 *
 *\li	'transp' != NULL && *transp == NULL;
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS				On success.
 *
 *\li	Anything else				Failure.
 */

void
dns_client_cancelupdate(dns_clientupdatetrans_t *trans);
/*%<
 * Cancel an ongoing dynamic update procedure started via
 * dns_client_startupdate().
 *
 * Notes:
 *
 *\li	If the update procedure has not completed, post its UPDATEDONE
 *	event with a result code of #ISC_R_CANCELED.
 *
 * Requires:
 *
 *\li	'trans' is a valid transaction ID.
 */

void
dns_client_destroyupdatetrans(dns_clientupdatetrans_t **transp);
/*%<
 * Destroy dynamic update transaction identified by '*transp'.
 *
 * Requires:
 *
 *\li	'*transp' is a valid transaction ID.
 *
 *\li	The caller has received the UPDATEDONE event (either because the
 *	update completed or because dns_client_cancelupdate() was called).
 *
 * Ensures:
 *
 *\li	*transp == NULL.
 */

isc_result_t
dns_client_updaterec(dns_client_updateop_t op, dns_name_t *owner,
		     dns_rdatatype_t type, dns_rdata_t *source,
		     dns_ttl_t ttl, dns_name_t *target,
		     dns_rdataset_t *rdataset, dns_rdatalist_t *rdatalist,
		     dns_rdata_t *rdata, isc_mem_t *mctx);
/*%<
 * TBD
 */

void
dns_client_freeupdate(dns_name_t **namep);
/*%<
 * TBD
 */

isc_mem_t *
dns_client_mctx(dns_client_t *client);

ISC_LANG_ENDDECLS

#endif /* DNS_CLIENT_H */
soa.h000064400000004212150415243040005474 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_SOA_H
#define DNS_SOA_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/soa.h
 * \brief
 * SOA utilities.
 */

/***
 *** Imports
 ***/

#include <inttypes.h>

#include <isc/lang.h>
#include <isc/types.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

#define DNS_SOA_BUFFERSIZE      ((2 * DNS_NAME_MAXWIRE) + (4 * 5))

isc_result_t
dns_soa_buildrdata(dns_name_t *origin, dns_name_t *contact,
		   dns_rdataclass_t rdclass,
		   uint32_t serial, uint32_t refresh,
		   uint32_t retry, uint32_t expire,
		   uint32_t minimum, unsigned char *buffer,
		   dns_rdata_t *rdata);
/*%<
 * Build the rdata of an SOA record.
 *
 * Requires:
 *\li   buffer  Points to a temporary buffer of at least
 *              DNS_SOA_BUFFERSIZE bytes.
 *\li   rdata   Points to an initialized dns_rdata_t.
 *
 * Ensures:
 *  \li    *rdata       Contains a valid SOA rdata.  The 'data' member
 *  			refers to 'buffer'.
 */

uint32_t
dns_soa_getserial(dns_rdata_t *rdata);
uint32_t
dns_soa_getrefresh(dns_rdata_t *rdata);
uint32_t
dns_soa_getretry(dns_rdata_t *rdata);
uint32_t
dns_soa_getexpire(dns_rdata_t *rdata);
uint32_t
dns_soa_getminimum(dns_rdata_t *rdata);
/*
 * Extract an integer field from the rdata of a SOA record.
 *
 * Requires:
 *	rdata refers to the rdata of a well-formed SOA record.
 */

void
dns_soa_setserial(uint32_t val, dns_rdata_t *rdata);
void
dns_soa_setrefresh(uint32_t val, dns_rdata_t *rdata);
void
dns_soa_setretry(uint32_t val, dns_rdata_t *rdata);
void
dns_soa_setexpire(uint32_t val, dns_rdata_t *rdata);
void
dns_soa_setminimum(uint32_t val, dns_rdata_t *rdata);
/*
 * Change an integer field of a SOA record by modifying the
 * rdata in-place.
 *
 * Requires:
 *	rdata refers to the rdata of a well-formed SOA record.
 */


ISC_LANG_ENDDECLS

#endif /* DNS_SOA_H */
tsig.h000064400000020300150415243040005654 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_TSIG_H
#define DNS_TSIG_H 1

/*! \file dns/tsig.h */

#include <stdbool.h>

#include <isc/lang.h>
#include <isc/refcount.h>
#include <isc/rwlock.h>
#include <isc/stdio.h>
#include <isc/stdtime.h>

#include <pk11/site.h>

#include <dns/types.h>
#include <dns/name.h>

#include <dst/dst.h>

/*
 * Algorithms.
 */
#ifndef PK11_MD5_DISABLE
LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_hmacmd5_name;
#define DNS_TSIG_HMACMD5_NAME		dns_tsig_hmacmd5_name
#endif
LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_gssapi_name;
#define DNS_TSIG_GSSAPI_NAME		dns_tsig_gssapi_name
LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_gssapims_name;
#define DNS_TSIG_GSSAPIMS_NAME		dns_tsig_gssapims_name
LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_hmacsha1_name;
#define DNS_TSIG_HMACSHA1_NAME		dns_tsig_hmacsha1_name
LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_hmacsha224_name;
#define DNS_TSIG_HMACSHA224_NAME	dns_tsig_hmacsha224_name
LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_hmacsha256_name;
#define DNS_TSIG_HMACSHA256_NAME	dns_tsig_hmacsha256_name
LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_hmacsha384_name;
#define DNS_TSIG_HMACSHA384_NAME	dns_tsig_hmacsha384_name
LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_hmacsha512_name;
#define DNS_TSIG_HMACSHA512_NAME	dns_tsig_hmacsha512_name

/*%
 * Default fudge value.
 */
#define DNS_TSIG_FUDGE			300

struct dns_tsig_keyring {
	dns_rbt_t *keys;
	unsigned int writecount;
	isc_rwlock_t lock;
	isc_mem_t *mctx;
	/*
	 * LRU list of generated key along with a count of the keys on the
	 * list and a maximum size.
	 */
	unsigned int generated;
	unsigned int maxgenerated;
	ISC_LIST(dns_tsigkey_t) lru;
	isc_refcount_t references;
};

struct dns_tsigkey {
	/* Unlocked */
	unsigned int		magic;		/*%< Magic number. */
	isc_mem_t		*mctx;
	dst_key_t		*key;		/*%< Key */
	dns_name_t		name;		/*%< Key name */
	dns_name_t		*algorithm;	/*%< Algorithm name */
	dns_name_t		*creator;	/*%< name that created secret */
	bool		generated;	/*%< was this generated? */
	isc_stdtime_t		inception;	/*%< start of validity period */
	isc_stdtime_t		expire;		/*%< end of validity period */
	dns_tsig_keyring_t	*ring;		/*%< the enclosing keyring */
	isc_refcount_t		refs;		/*%< reference counter */
	ISC_LINK(dns_tsigkey_t) link;
};

ISC_LANG_BEGINDECLS

const dns_name_t *
dns_tsigkey_identity(const dns_tsigkey_t *tsigkey);
/*%<
 *	Returns the identity of the provided TSIG key.
 *
 *	Requires:
 *\li		'tsigkey' is a valid TSIG key or NULL
 *
 *	Returns:
 *\li		NULL if 'tsigkey' was NULL
 *\li		identity of the provided TSIG key
 */

isc_result_t
dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
		   unsigned char *secret, int length, bool generated,
		   dns_name_t *creator, isc_stdtime_t inception,
		   isc_stdtime_t expire, isc_mem_t *mctx,
		   dns_tsig_keyring_t *ring, dns_tsigkey_t **key);

isc_result_t
dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
			  dst_key_t *dstkey, bool generated,
			  dns_name_t *creator, isc_stdtime_t inception,
			  isc_stdtime_t expire, isc_mem_t *mctx,
			  dns_tsig_keyring_t *ring, dns_tsigkey_t **key);
/*%<
 *	Creates a tsig key structure and saves it in the keyring.  If key is
 *	not NULL, *key will contain a copy of the key.  The keys validity
 *	period is specified by (inception, expire), and will not expire if
 *	inception == expire.  If the key was generated, the creating identity,
 *	if there is one, should be in the creator parameter.  Specifying an
 *	unimplemented algorithm will cause failure only if dstkey != NULL; this
 *	allows a transient key with an invalid algorithm to exist long enough
 *	to generate a BADKEY response.
 *
 *	If dns_tsigkey_createfromkey is successful a new reference to 'dstkey'
 *	will have been made.
 *
 *	Requires:
 *\li		'name' is a valid dns_name_t
 *\li		'algorithm' is a valid dns_name_t
 *\li		'secret' is a valid pointer
 *\li		'length' is an integer >= 0
 *\li		'dstkey' is a valid dst key or NULL
 *\li		'creator' points to a valid dns_name_t or is NULL
 *\li		'mctx' is a valid memory context
 *\li		'ring' is a valid TSIG keyring or NULL
 *\li		'key' or '*key' must be NULL
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS
 *\li		#ISC_R_EXISTS - a key with this name already exists
 *\li		#ISC_R_NOTIMPLEMENTED - algorithm is not implemented
 *\li		#ISC_R_NOMEMORY
 */

void
dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp);
/*%<
 *	Attach '*targetp' to 'source'.
 *
 *	Requires:
 *\li		'key' is a valid TSIG key
 *
 *	Ensures:
 *\li		*targetp is attached to source.
 */

void
dns_tsigkey_detach(dns_tsigkey_t **keyp);
/*%<
 *	Detaches from the tsig key structure pointed to by '*key'.
 *
 *	Requires:
 *\li		'keyp' is not NULL and '*keyp' is a valid TSIG key
 *
 *	Ensures:
 *\li		'keyp' points to NULL
 */

void
dns_tsigkey_setdeleted(dns_tsigkey_t *key);
/*%<
 *	Prevents this key from being used again.  It will be deleted when
 *	no references exist.
 *
 *	Requires:
 *\li		'key' is a valid TSIG key on a keyring
 */

isc_result_t
dns_tsig_sign(dns_message_t *msg);
/*%<
 *	Generates a TSIG record for this message
 *
 *	Requires:
 *\li		'msg' is a valid message
 *\li		'msg->tsigkey' is a valid TSIG key
 *\li		'msg->tsig' is NULL
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS
 *\li		#ISC_R_NOMEMORY
 *\li		#ISC_R_NOSPACE
 *\li		#DNS_R_EXPECTEDTSIG
 *			- this is a response & msg->querytsig is NULL
 */

isc_result_t
dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
		dns_tsig_keyring_t *ring1, dns_tsig_keyring_t *ring2);
/*%<
 *	Verifies the TSIG record in this message
 *
 *	Requires:
 *\li		'source' is a valid buffer containing the unparsed message
 *\li		'msg' is a valid message
 *\li		'msg->tsigkey' is a valid TSIG key if this is a response
 *\li		'msg->tsig' is NULL
 *\li		'msg->querytsig' is not NULL if this is a response
 *\li		'ring1' and 'ring2' are each either a valid keyring or NULL
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS
 *\li		#ISC_R_NOMEMORY
 *\li		#DNS_R_EXPECTEDTSIG - A TSIG was expected but not seen
 *\li		#DNS_R_UNEXPECTEDTSIG - A TSIG was seen but not expected
 *\li		#DNS_R_TSIGERRORSET - the TSIG verified but ->error was set
 *				     and this is a query
 *\li		#DNS_R_CLOCKSKEW - the TSIG failed to verify because of
 *				  the time was out of the allowed range.
 *\li		#DNS_R_TSIGVERIFYFAILURE - the TSIG failed to verify
 *\li		#DNS_R_EXPECTEDRESPONSE - the message was set over TCP and
 *					 should have been a response,
 *					 but was not.
 */

isc_result_t
dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
		 dns_name_t *algorithm, dns_tsig_keyring_t *ring);
/*%<
 *	Returns the TSIG key corresponding to this name and (possibly)
 *	algorithm.  Also increments the key's reference counter.
 *
 *	Requires:
 *\li		'tsigkey' is not NULL
 *\li		'*tsigkey' is NULL
 *\li		'name' is a valid dns_name_t
 *\li		'algorithm' is a valid dns_name_t or NULL
 *\li		'ring' is a valid keyring
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS
 *\li		#ISC_R_NOTFOUND
 */


isc_result_t
dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp);
/*%<
 *	Create an empty TSIG key ring.
 *
 *	Requires:
 *\li		'mctx' is not NULL
 *\li		'ringp' is not NULL, and '*ringp' is NULL
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS
 *\li		#ISC_R_NOMEMORY
 */

isc_result_t
dns_tsigkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
		    dns_tsigkey_t *tkey);
/*%<
 *      Place a TSIG key onto a key ring.
 *
 *	Requires:
 *\li		'ring', 'name' and 'tkey' are not NULL
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS
 *\li		Any other value indicates failure.
 */


void
dns_tsigkeyring_attach(dns_tsig_keyring_t *source, dns_tsig_keyring_t **target);

void
dns_tsigkeyring_detach(dns_tsig_keyring_t **ringp);

isc_result_t
dns_tsigkeyring_dumpanddetach(dns_tsig_keyring_t **ringp, FILE *fp);

/*%<
 *	Destroy a TSIG key ring.
 *
 *	Requires:
 *\li		'ringp' is not NULL
 */

void
dns_keyring_restore(dns_tsig_keyring_t *ring, FILE *fp);

ISC_LANG_ENDDECLS

#endif /* DNS_TSIG_H */
tkey.h000064400000016717150415243040005703 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_TKEY_H
#define DNS_TKEY_H 1

/*! \file dns/tkey.h */

#include <inttypes.h>
#include <stdbool.h>

#include <isc/lang.h>

#include <dns/types.h>

#include <dst/dst.h>
#include <dst/gssapi.h>

ISC_LANG_BEGINDECLS

/* Key agreement modes */
#define DNS_TKEYMODE_SERVERASSIGNED		1
#define DNS_TKEYMODE_DIFFIEHELLMAN		2
#define DNS_TKEYMODE_GSSAPI			3
#define DNS_TKEYMODE_RESOLVERASSIGNED		4
#define DNS_TKEYMODE_DELETE			5

struct dns_tkeyctx {
	dst_key_t *dhkey;
	dns_name_t *domain;
	gss_cred_id_t gsscred;
	isc_mem_t *mctx;
	isc_entropy_t *ectx;
	char *gssapi_keytab;
};

isc_result_t
dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx,
		   dns_tkeyctx_t **tctxp);
/*%<
 *	Create an empty TKEY context.
 *
 * 	Requires:
 *\li		'mctx' is not NULL
 *\li		'tctx' is not NULL
 *\li		'*tctx' is NULL
 *
 *	Returns
 *\li		#ISC_R_SUCCESS
 *\li		#ISC_R_NOMEMORY
 *\li		return codes from dns_name_fromtext()
 */

void
dns_tkeyctx_destroy(dns_tkeyctx_t **tctxp);
/*%<
 *      Frees all data associated with the TKEY context
 *
 * 	Requires:
 *\li		'tctx' is not NULL
 *\li		'*tctx' is not NULL
 */

isc_result_t
dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
		      dns_tsig_keyring_t *ring);
/*%<
 *	Processes a query containing a TKEY record, adding or deleting TSIG
 *	keys if necessary, and modifies the message to contain the response.
 *
 *	Requires:
 *\li		'msg' is a valid message
 *\li		'tctx' is a valid TKEY context
 *\li		'ring' is a valid TSIG keyring
 *
 *	Returns
 *\li		#ISC_R_SUCCESS	msg was updated (the TKEY operation succeeded,
 *				or msg now includes a TKEY with an error set)
 *		DNS_R_FORMERR	the packet was malformed (missing a TKEY
 *				or KEY).
 *\li		other		An error occurred while processing the message
 */

isc_result_t
dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name,
		      dns_name_t *algorithm, isc_buffer_t *nonce,
		      uint32_t lifetime);
/*%<
 *	Builds a query containing a TKEY that will generate a shared
 *	secret using a Diffie-Hellman key exchange.  The shared key
 *	will be of the specified algorithm (only DNS_TSIG_HMACMD5_NAME
 *	is supported), and will be named either 'name',
 *	'name' + server chosen domain, or random data + server chosen domain
 *	if 'name' == dns_rootname.  If nonce is not NULL, it supplies
 *	random data used in the shared secret computation.  The key is
 *	requested to have the specified lifetime (in seconds)
 *
 *
 *	Requires:
 *\li		'msg' is a valid message
 *\li		'key' is a valid Diffie Hellman dst key
 *\li		'name' is a valid name
 *\li		'algorithm' is a valid name
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS	msg was successfully updated to include the
 *				query to be sent
 *\li		other		an error occurred while building the message
 */

isc_result_t
dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname,
		       isc_buffer_t *intoken, uint32_t lifetime,
		       gss_ctx_id_t *context, bool win2k,
		       isc_mem_t *mctx, char **err_message);
/*%<
 *	Builds a query containing a TKEY that will generate a GSSAPI context.
 *	The key is requested to have the specified lifetime (in seconds).
 *
 *	Requires:
 *\li		'msg'	  is a valid message
 *\li		'name'	  is a valid name
 *\li		'gname'	  is a valid name
 *\li		'context' is a pointer to a valid gss_ctx_id_t
 *			  (which may have the value GSS_C_NO_CONTEXT)
 *\li		'win2k'   when true says to turn on some hacks to work
 *			  with the non-standard GSS-TSIG of Windows 2000
 *
 *	Returns:
 *\li		ISC_R_SUCCESS	msg was successfully updated to include the
 *				query to be sent
 *\li		other		an error occurred while building the message
 *\li		*err_message	optional error message
 */


isc_result_t
dns_tkey_builddeletequery(dns_message_t *msg, dns_tsigkey_t *key);
/*%<
 *	Builds a query containing a TKEY record that will delete the
 *	specified shared secret from the server.
 *
 *	Requires:
 *\li		'msg' is a valid message
 *\li		'key' is a valid TSIG key
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS	msg was successfully updated to include the
 *				query to be sent
 *\li		other		an error occurred while building the message
 */

isc_result_t
dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
			   dst_key_t *key, isc_buffer_t *nonce,
			   dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring);
/*%<
 *	Processes a response to a query containing a TKEY that was
 *	designed to generate a shared secret using a Diffie-Hellman key
 *	exchange.  If the query was successful, a new shared key
 *	is created and added to the list of shared keys.
 *
 *	Requires:
 *\li		'qmsg' is a valid message (the query)
 *\li		'rmsg' is a valid message (the response)
 *\li		'key' is a valid Diffie Hellman dst key
 *\li		'outkey' is either NULL or a pointer to NULL
 *\li		'ring' is a valid keyring or NULL
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS	the shared key was successfully added
 *\li		#ISC_R_NOTFOUND	an error occurred while looking for a
 *				component of the query or response
 */

isc_result_t
dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
			    dns_name_t *gname, gss_ctx_id_t *context,
			    isc_buffer_t *outtoken, dns_tsigkey_t **outkey,
			    dns_tsig_keyring_t *ring, char **err_message);
/*%<
 * XXX
 */

isc_result_t
dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
			       dns_tsig_keyring_t *ring);
/*%<
 *	Processes a response to a query containing a TKEY that was
 *	designed to delete a shared secret.  If the query was successful,
 *	the shared key is deleted from the list of shared keys.
 *
 *	Requires:
 *\li		'qmsg' is a valid message (the query)
 *\li		'rmsg' is a valid message (the response)
 *\li		'ring' is not NULL
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS	the shared key was successfully deleted
 *\li		#ISC_R_NOTFOUND	an error occurred while looking for a
 *				component of the query or response
 */

isc_result_t
dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
		      dns_name_t *server, gss_ctx_id_t *context,
		      dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring,
		      bool win2k, char **err_message);

/*
 *	Client side negotiation of GSS-TSIG.  Process the response
 *	to a TKEY, and establish a TSIG key if negotiation was successful.
 *	Build a response to the input TKEY message.  Can take multiple
 *	calls to successfully establish the context.
 *
 *	Requires:
 *		'qmsg'    is a valid message, the original TKEY request;
 *			     it will be filled with the new message to send
 *		'rmsg'    is a valid message, the incoming TKEY message
 *		'server'  is the server name
 *		'context' is the input context handle
 *		'outkey'  receives the established key, if non-NULL;
 *			      if non-NULL must point to NULL
 *		'ring'	  is the keyring in which to establish the key,
 *			      or NULL
 *		'win2k'   when true says to turn on some hacks to work
 *			      with the non-standard GSS-TSIG of Windows 2000
 *
 *	Returns:
 *		ISC_R_SUCCESS	context was successfully established
 *		ISC_R_NOTFOUND  couldn't find a needed part of the query
 *					or response
 *		DNS_R_CONTINUE  additional context negotiation is required;
 *					send the new qmsg to the server
 */

ISC_LANG_ENDDECLS

#endif /* DNS_TKEY_H */
sdlz.h000064400000033606150415243050005700 0ustar00/*
 * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/*
 * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the
 * above copyright notice and this permission notice appear in all
 * copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
 * USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
 * conceived and contributed by Rob Butler.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the
 * above copyright notice and this permission notice appear in all
 * copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
 * USE OR PERFORMANCE OF THIS SOFTWARE.
 */


/*! \file dns/sdlz.h */

#ifndef SDLZ_H
#define SDLZ_H 1

#include <inttypes.h>
#include <stdbool.h>

#include <dns/clientinfo.h>
#include <dns/dlz.h>

ISC_LANG_BEGINDECLS

#define DNS_SDLZFLAG_THREADSAFE		0x00000001U
#define DNS_SDLZFLAG_RELATIVEOWNER	0x00000002U
#define DNS_SDLZFLAG_RELATIVERDATA	0x00000004U

 /* A simple DLZ database. */
typedef struct dns_sdlz_db dns_sdlz_db_t;

 /* A simple DLZ database lookup in progress. */
typedef struct dns_sdlzlookup dns_sdlzlookup_t;

 /* A simple DLZ database traversal in progress. */
typedef struct dns_sdlzallnodes dns_sdlzallnodes_t;

typedef isc_result_t (*dns_sdlzallnodesfunc_t)(const char *zone,
					       void *driverarg,
					       void *dbdata,
					       dns_sdlzallnodes_t *allnodes);
/*%<
 * Method prototype.  Drivers implementing the SDLZ interface may
 * supply an all nodes method.  This method is called when the DNS
 * server is performing a zone transfer query, after the allow zone
 * transfer method has been called.  This method is only called if the
 * allow zone transfer method returned ISC_R_SUCCESS.  This method and
 * the allow zone transfer method are both required for zone transfers
 * to be supported.  If the driver generates data dynamically (instead
 * of searching in a database for it) it should not implement this
 * function as a zone transfer would be meaningless.  A SDLZ driver
 * does not have to implement an all nodes method.
 */

typedef isc_result_t (*dns_sdlzallowzonexfr_t)(void *driverarg,
					       void *dbdata, const char *name,
					       const char *client);

/*%<
 * Method prototype.  Drivers implementing the SDLZ interface may
 * supply an allow zone transfer method.  This method is called when
 * the DNS server is performing a zone transfer query, before the all
 * nodes method can be called.  This method and the all node method
 * are both required for zone transfers to be supported.  If the
 * driver generates data dynamically (instead of searching in a
 * database for it) it should not implement this function as a zone
 * transfer would be meaningless.  A SDLZ driver does not have to
 * implement an allow zone transfer method.
 *
 * This method should return ISC_R_SUCCESS if the zone is supported by
 * the database and a zone transfer is allowed for the specified
 * client.  If the zone is supported by the database, but zone
 * transfers are not allowed for the specified client this method
 * should return ISC_R_NOPERM..  Lastly the method should return
 * ISC_R_NOTFOUND if the zone is not supported by the database.  If an
 * error occurs it should return a result code indicating the type of
 * error.
 */

typedef isc_result_t (*dns_sdlzauthorityfunc_t)(const char *zone,
						void *driverarg, void *dbdata,
						dns_sdlzlookup_t *lookup);

/*%<
 * Method prototype.  Drivers implementing the SDLZ interface may
 * supply an authority method.  This method is called when the DNS
 * server is performing a query, after both the find zone and lookup
 * methods have been called.  This method is required if the lookup
 * function does not supply authority information for the dns
 * record. A SDLZ driver does not have to implement an authority
 * method.
 */

typedef isc_result_t (*dns_sdlzcreate_t)(const char *dlzname,
					 unsigned int argc, char *argv[],
					 void *driverarg, void **dbdata);

/*%<
 * Method prototype.  Drivers implementing the SDLZ interface may
 * supply a create method.  This method is called when the DNS server
 * is starting up and creating drivers for use later. A SDLZ driver
 * does not have to implement a create method.
 */

typedef void (*dns_sdlzdestroy_t)(void *driverarg, void *dbdata);

/*%<
 * Method prototype.  Drivers implementing the SDLZ interface may
 * supply a destroy method.  This method is called when the DNS server
 * is shutting down and no longer needs the driver.  A SDLZ driver does
 * not have to implement a destroy method.
 */

typedef isc_result_t
(*dns_sdlzfindzone_t)(void *driverarg, void *dbdata, const char *name,
		      dns_clientinfomethods_t *methods,
		      dns_clientinfo_t *clientinfo);
/*%<
 * Method prototype.  Drivers implementing the SDLZ interface MUST
 * supply a find zone method.  This method is called when the DNS
 * server is performing a query to to determine if 'name' is a
 * supported dns zone.  The find zone method will be called with the
 * longest possible name first, and continue to be called with
 * successively shorter domain names, until any of the following
 * occur:
 *
 * \li	1) the function returns (ISC_R_SUCCESS) indicating a zone name
 *	   match.
 *
 * \li	2) a problem occurs, and the functions returns anything other than
 *	   (ISC_R_NOTFOUND)
 *
 * \li	3) we run out of domain name labels. I.E. we have tried the
 *	   shortest domain name
 *
 * \li	4) the number of labels in the domain name is less than min_labels
 *	   for dns_dlzfindzone
 *
 * The driver's find zone method should return ISC_R_SUCCESS if the
 * zone is supported by the database.  Otherwise it should return
 * ISC_R_NOTFOUND, if the zone is not supported.  If an error occurs
 * it should return a result code indicating the type of error.
 */

typedef isc_result_t
(*dns_sdlzlookupfunc_t)(const char *zone, const char *name, void *driverarg,
			void *dbdata, dns_sdlzlookup_t *lookup,
			dns_clientinfomethods_t *methods,
			dns_clientinfo_t *clientinfo);

/*%<
 * Method prototype.  Drivers implementing the SDLZ interface MUST
 * supply a lookup method.  This method is called when the
 * DNS server is performing a query, after the find zone and before any
 * other methods have been called.  This function returns DNS record
 * information using the dns_sdlz_putrr and dns_sdlz_putsoa functions.
 * If this function supplies authority information for the DNS record
 * the authority method is not required.  If it does not, the
 * authority function is required.
 *
 * The 'methods' and 'clientinfo' args allow an SDLZ driver to retrieve
 * information about the querying client (such as source IP address)
 * from the caller.
 */

typedef isc_result_t (*dns_sdlznewversion_t)(const char *zone,
					     void *driverarg, void *dbdata,
					     void **versionp);
/*%<
 * Method prototype.  Drivers implementing the SDLZ interface may
 * supply a newversion method.  This method is called to start a
 * write transaction on a zone and should only be implemented by
 * writeable backends.
 * When implemented, the driver should create a new transaction, and
 * fill *versionp with a pointer to the transaction state. The
 * closeversion function will be called to close the transaction.
 */

typedef void (*dns_sdlzcloseversion_t)(const char *zone, bool commit,
				       void *driverarg, void *dbdata,
				       void **versionp);
/*%<
 * Method prototype.  Drivers implementing the SDLZ interface must
 * supply a closeversion method if they supply a newversion method.
 * When implemented, the driver should close the given transaction,
 * committing changes if 'commit' is true. If 'commit' is not true
 * then all changes should be discarded and the database rolled back.
 * If the call is successful then *versionp should be set to NULL
 */

typedef isc_result_t (*dns_sdlzconfigure_t)(dns_view_t *view,
					    dns_dlzdb_t *dlzdb,
					    void *driverarg, void *dbdata);
/*%<
 * Method prototype.  Drivers implementing the SDLZ interface may
 * supply a configure method. When supplied, it will be called
 * immediately after the create method to give the driver a chance
 * to configure writeable zones
 */


typedef bool (*dns_sdlzssumatch_t)(const char *signer,
					    const char *name,
					    const char *tcpaddr,
					    const char *type,
					    const char *key,
					    uint32_t keydatalen,
					    unsigned char *keydata,
					    void *driverarg,
					    void *dbdata);

/*%<
 * Method prototype.  Drivers implementing the SDLZ interface may
 * supply a ssumatch method. If supplied, then ssumatch will be
 * called to authorize any zone updates. The driver should return
 * true to allow the update, and false to deny it. For a DLZ
 * controlled zone, this is the only access control on updates.
 */


typedef isc_result_t (*dns_sdlzmodrdataset_t)(const char *name,
					      const char *rdatastr,
					      void *driverarg, void *dbdata,
					      void *version);
/*%<
 * Method prototype.  Drivers implementing the SDLZ interface may
 * supply addrdataset and subtractrdataset methods. If supplied, then these
 * will be called when rdatasets are added/subtracted during
 * updates. The version parameter comes from a call to the sdlz
 * newversion() method from the driver. The rdataset parameter is a
 * linearise string representation of the rdataset change. The format
 * is the same as used by dig when displaying records. The fields are
 * tab delimited.
 */

typedef isc_result_t (*dns_sdlzdelrdataset_t)(const char *name,
					      const char *type,
					      void *driverarg, void *dbdata,
					      void *version);
/*%<
 * Method prototype.  Drivers implementing the SDLZ interface may
 * supply a delrdataset method. If supplied, then this
 * function will be called when rdatasets are deleted during
 * updates. The call should remove all rdatasets of the given type for
 * the specified name.
 */

typedef struct dns_sdlzmethods {
	dns_sdlzcreate_t	create;
	dns_sdlzdestroy_t	destroy;
	dns_sdlzfindzone_t	findzone;
	dns_sdlzlookupfunc_t	lookup;
	dns_sdlzauthorityfunc_t	authority;
	dns_sdlzallnodesfunc_t	allnodes;
	dns_sdlzallowzonexfr_t	allowzonexfr;
	dns_sdlznewversion_t    newversion;
	dns_sdlzcloseversion_t  closeversion;
	dns_sdlzconfigure_t	configure;
	dns_sdlzssumatch_t	ssumatch;
	dns_sdlzmodrdataset_t	addrdataset;
	dns_sdlzmodrdataset_t	subtractrdataset;
	dns_sdlzdelrdataset_t	delrdataset;
} dns_sdlzmethods_t;

isc_result_t
dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
		 void *driverarg, unsigned int flags, isc_mem_t *mctx,
		 dns_sdlzimplementation_t **sdlzimp);
/*%<
 * Register a dynamically loadable zones (dlz) driver for the database
 * type 'drivername', implemented by the functions in '*methods'.
 *
 * sdlzimp must point to a NULL dns_sdlzimplementation_t pointer.
 * That is, sdlzimp != NULL && *sdlzimp == NULL.  It will be assigned
 * a value that will later be used to identify the driver when
 * deregistering it.
 */

void
dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp);

/*%<
 * Removes the sdlz driver from the list of registered sdlz drivers.
 * There must be no active sdlz drivers of this type when this
 * function is called.
 */

typedef isc_result_t dns_sdlz_putnamedrr_t(dns_sdlzallnodes_t *allnodes,
					   const char *name,
					   const char *type,
					   dns_ttl_t ttl,
					   const char *data);
dns_sdlz_putnamedrr_t dns_sdlz_putnamedrr;

/*%<
 * Add a single resource record to the allnodes structure to be later
 * parsed into a zone transfer response.
 */

typedef isc_result_t dns_sdlz_putrr_t(dns_sdlzlookup_t *lookup,
				      const char *type,
				      dns_ttl_t ttl,
				      const char *data);
dns_sdlz_putrr_t dns_sdlz_putrr;
/*%<
 * Add a single resource record to the lookup structure to be later
 * parsed into a query response.
 */

typedef isc_result_t dns_sdlz_putsoa_t(dns_sdlzlookup_t *lookup,
				       const char *mname,
				       const char *rname,
				       uint32_t serial);
dns_sdlz_putsoa_t dns_sdlz_putsoa;
/*%<
 * This function may optionally be called from the 'authority'
 * callback to simplify construction of the SOA record for 'zone'.  It
 * will provide a SOA listing 'mname' as as the master server and
 * 'rname' as the responsible person mailbox.  It is the
 * responsibility of the driver to increment the serial number between
 * responses if necessary.  All other SOA fields will have reasonable
 * default values.
 */


typedef isc_result_t dns_sdlz_setdb_t(dns_dlzdb_t *dlzdatabase,
				      dns_rdataclass_t rdclass,
				      dns_name_t *name,
				      dns_db_t **dbp);
dns_sdlz_setdb_t dns_sdlz_setdb;
/*%<
 * Create the database pointers for a writeable SDLZ zone
 */


ISC_LANG_ENDDECLS

#endif /* SDLZ_H */
zone.h000064400000166700150415243050005701 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_ZONE_H
#define DNS_ZONE_H 1

/*! \file dns/zone.h */

/***
 ***	Imports
 ***/

#include <stdio.h>
#include <stdbool.h>

#include <isc/formatcheck.h>
#include <isc/lang.h>
#include <isc/rwlock.h>

#include <dns/catz.h>
#include <dns/master.h>
#include <dns/masterdump.h>
#include <dns/rdatastruct.h>
#include <dns/rpz.h>
#include <dns/types.h>
#include <dns/zt.h>

typedef enum {
	dns_zone_none,
	dns_zone_master,
	dns_zone_slave,
	dns_zone_stub,
	dns_zone_staticstub,
	dns_zone_key,
	dns_zone_dlz,
	dns_zone_redirect
} dns_zonetype_t;

typedef enum {
	dns_zonestat_none = 0,
	dns_zonestat_terse,
	dns_zonestat_full
} dns_zonestat_level_t;

#define DNS_ZONEOPT_SERVERS	  0x00000001U	/*%< perform server checks */
#define DNS_ZONEOPT_PARENTS	  0x00000002U	/*%< perform parent checks */
#define DNS_ZONEOPT_CHILDREN	  0x00000004U	/*%< perform child checks */
#define DNS_ZONEOPT_NOTIFY	  0x00000008U	/*%< perform NOTIFY */
#define DNS_ZONEOPT_MANYERRORS	  0x00000010U	/*%< return many errors on load */
#define DNS_ZONEOPT_IXFRFROMDIFFS 0x00000020U	/*%< calculate differences */
#define DNS_ZONEOPT_NOMERGE	  0x00000040U	/*%< don't merge journal */
#define DNS_ZONEOPT_CHECKNS	  0x00000080U	/*%< check if NS's are addresses */
#define DNS_ZONEOPT_FATALNS	  0x00000100U	/*%< DNS_ZONEOPT_CHECKNS is fatal */
#define DNS_ZONEOPT_MULTIMASTER	  0x00000200U	/*%< this zone has multiple masters */
#define DNS_ZONEOPT_USEALTXFRSRC  0x00000400U	/*%< use alternate transfer sources */
#define DNS_ZONEOPT_CHECKNAMES	  0x00000800U	/*%< check-names */
#define DNS_ZONEOPT_CHECKNAMESFAIL 0x00001000U	/*%< fatal check-name failures */
#define DNS_ZONEOPT_CHECKWILDCARD 0x00002000U	/*%< check for internal wildcards */
#define DNS_ZONEOPT_CHECKMX	  0x00004000U	/*%< check-mx */
#define DNS_ZONEOPT_CHECKMXFAIL   0x00008000U	/*%< fatal check-mx failures */
#define DNS_ZONEOPT_CHECKINTEGRITY 0x00010000U	/*%< perform integrity checks */
#define DNS_ZONEOPT_CHECKSIBLING  0x00020000U	/*%< perform sibling glue checks */
#define DNS_ZONEOPT_NOCHECKNS	  0x00040000U	/*%< disable IN NS address checks */
#define DNS_ZONEOPT_WARNMXCNAME	  0x00080000U	/*%< warn on MX CNAME check */
#define DNS_ZONEOPT_IGNOREMXCNAME 0x00100000U	/*%< ignore MX CNAME check */
#define DNS_ZONEOPT_WARNSRVCNAME  0x00200000U	/*%< warn on SRV CNAME check */
#define DNS_ZONEOPT_IGNORESRVCNAME 0x00400000U	/*%< ignore SRV CNAME check */
#define DNS_ZONEOPT_UPDATECHECKKSK 0x00800000U	/*%< check dnskey KSK flag */
#define DNS_ZONEOPT_TRYTCPREFRESH 0x01000000U	/*%< try tcp refresh on udp failure */
#define DNS_ZONEOPT_NOTIFYTOSOA	  0x02000000U	/*%< Notify the SOA MNAME */
#define DNS_ZONEOPT_NSEC3TESTZONE 0x04000000U	/*%< nsec3-test-zone */
#define DNS_ZONEOPT_SECURETOINSECURE 0x08000000U /*%< dnssec-secure-to-insecure */
#define DNS_ZONEOPT_DNSKEYKSKONLY 0x10000000U	/*%< dnssec-dnskey-kskonly */
#define DNS_ZONEOPT_CHECKDUPRR	  0x20000000U   /*%< check-dup-records */
#define DNS_ZONEOPT_CHECKDUPRRFAIL 0x40000000U	/*%< fatal check-dup-records failures */
#define DNS_ZONEOPT_CHECKSPF	  0x80000000U	/*%< check SPF records */

/*
 * The following zone options are shifted left into the
 * higher-order 32 bits of the options.
 */
#define DNS_ZONEOPT2_CHECKTTL	  0x00000001U	/*%< check max-zone-ttl */
#define DNS_ZONEOPT2_AUTOEMPTY	  0x00000002U	/*%< automatic empty zone */

#ifndef NOMINUM_PUBLIC
/*
 * Nominum specific options build down.
 */
#define DNS_ZONEOPT_NOTIFYFORWARD 0x80000000U	/* forward notify to master */
#endif /* NOMINUM_PUBLIC */

/*
 * Zone key maintenance options
 */
#define DNS_ZONEKEY_ALLOW	0x00000001U	/*%< fetch keys on command */
#define DNS_ZONEKEY_MAINTAIN	0x00000002U	/*%< publish/sign on schedule */
#define DNS_ZONEKEY_CREATE	0x00000004U	/*%< make keys when needed */
#define DNS_ZONEKEY_FULLSIGN    0x00000008U     /*%< roll to new keys immediately */
#define DNS_ZONEKEY_NORESIGN	0x00000010U	/*%< no automatic resigning */

#ifndef DNS_ZONE_MINREFRESH
#define DNS_ZONE_MINREFRESH		    300	/*%< 5 minutes */
#endif
#ifndef DNS_ZONE_MAXREFRESH
#define DNS_ZONE_MAXREFRESH		2419200	/*%< 4 weeks */
#endif
#ifndef DNS_ZONE_DEFAULTREFRESH
#define DNS_ZONE_DEFAULTREFRESH		   3600	/*%< 1 hour */
#endif
#ifndef DNS_ZONE_MINRETRY
#define DNS_ZONE_MINRETRY		    300	/*%< 5 minutes */
#endif
#ifndef DNS_ZONE_MAXRETRY
#define DNS_ZONE_MAXRETRY		1209600	/*%< 2 weeks */
#endif
#ifndef DNS_ZONE_DEFAULTRETRY
#define DNS_ZONE_DEFAULTRETRY		     60	/*%< 1 minute, subject to
						   exponential backoff */
#endif

#define DNS_ZONESTATE_XFERRUNNING	1
#define DNS_ZONESTATE_XFERDEFERRED	2
#define DNS_ZONESTATE_SOAQUERY		3
#define DNS_ZONESTATE_ANY		4
#define DNS_ZONESTATE_AUTOMATIC		5

ISC_LANG_BEGINDECLS

/***
 ***	Functions
 ***/

isc_result_t
dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx);
/*%<
 *	Creates a new empty zone and attach '*zonep' to it.
 *
 * Requires:
 *\li	'zonep' to point to a NULL pointer.
 *\li	'mctx' to be a valid memory context.
 *
 * Ensures:
 *\li	'*zonep' refers to a valid zone.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *\li	#ISC_R_UNEXPECTED
 */

void
dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass);
/*%<
 *	Sets the class of a zone.  This operation can only be performed
 *	once on a zone.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	dns_zone_setclass() not to have been called since the zone was
 *	created.
 *\li	'rdclass' != dns_rdataclass_none.
 */

dns_rdataclass_t
dns_zone_getclass(dns_zone_t *zone);
/*%<
 *	Returns the current zone class.
 *
 * Requires:
 *\li	'zone' to be a valid zone.
 */

isc_result_t
dns_zone_getserial2(dns_zone_t *zone, uint32_t *serialp);

uint32_t
dns_zone_getserial(dns_zone_t *zone);
/*%<
 *	Returns the current serial number of the zone.  On success, the SOA
 *	serial of the zone will be copied into '*serialp'.
 *	dns_zone_getserial() cannot catch failure cases and is deprecated by
 *	dns_zone_getserial2().
 *
 * Requires:
 *\li	'zone' to be a valid zone.
 *\li	'serialp' to be non NULL
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#DNS_R_NOTLOADED	zone DB is not loaded
 */

void
dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type);
/*%<
 *	Sets the zone type. This operation can only be performed once on
 *	a zone.
 *
 * Requires:
 *\li	'zone' to be a valid zone.
 *\li	dns_zone_settype() not to have been called since the zone was
 *	created.
 *\li	'type' != dns_zone_none
 */

void
dns_zone_setview(dns_zone_t *zone, dns_view_t *view);
/*%<
 *	Associate the zone with a view.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

dns_view_t *
dns_zone_getview(dns_zone_t *zone);
/*%<
 *	Returns the zone's associated view.
 *
 * Requires:
 *\li	'zone' to be a valid zone.
 */

void
dns_zone_setviewcommit(dns_zone_t *zone);
/*%<
 *	Commit the previous view saved internally via dns_zone_setview().
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

void
dns_zone_setviewrevert(dns_zone_t *zone);
/*%<
 *	Revert the most recent dns_zone_setview() on this zone,
 *	restoring the previous view.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */


isc_result_t
dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin);
/*%<
 *	Sets the zones origin to 'origin'.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'origin' to be non NULL.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li 	#ISC_R_NOMEMORY
 */

dns_name_t *
dns_zone_getorigin(dns_zone_t *zone);
/*%<
 *	Returns the value of the origin.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

isc_result_t
dns_zone_setfile(dns_zone_t *zone, const char *file);

isc_result_t
dns_zone_setfile2(dns_zone_t *zone, const char *file,
		  dns_masterformat_t format);
isc_result_t
dns_zone_setfile3(dns_zone_t *zone, const char *file,
		  dns_masterformat_t format, const dns_master_style_t *style);
/*%<
 *    Sets the name of the master file in the format of 'format' from which
 *    the zone loads its database to 'file'.
 *
 *    For zones that have no associated master file, 'file' will be NULL.
 *
 *	For zones with persistent databases, the file name
 *	setting is ignored.
 *
 *    dns_zone_setfile() is a backward-compatible form of
 *    dns_zone_setfile2(), which always specifies the
 *    dns_masterformat_text (RFC1035) format.
 *
 *    dns_zone_setfile2() is a backward-compatible form of
 *    dns_zone_setfile3(), which also specifies the style
 *    that should be used if a zone using the 'text'
 *    masterformat is ever dumped.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *
 * Returns:
 *\li	#ISC_R_NOMEMORY
 *\li	#ISC_R_SUCCESS
 */

const char *
dns_zone_getfile(dns_zone_t *zone);
/*%<
 * 	Gets the name of the zone's master file, if any.
 *
 * Requires:
 *\li	'zone' to be valid initialised zone.
 *
 * Returns:
 *\li	Pointer to null-terminated file name, or NULL.
 */

void
dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t records);
/*%<
 * 	Sets the maximum number of records permitted in a zone.
 *	0 implies unlimited.
 *
 * Requires:
 *\li	'zone' to be valid initialised zone.
 *
 * Returns:
 *\li	void
 */

uint32_t
dns_zone_getmaxrecords(dns_zone_t *zone);
/*%<
 * 	Gets the maximum number of records permitted in a zone.
 *	0 implies unlimited.
 *
 * Requires:
 *\li	'zone' to be valid initialised zone.
 *
 * Returns:
 *\li	uint32_t maxrecords.
 */

void
dns_zone_setmaxttl(dns_zone_t *zone, uint32_t maxttl);
/*%<
 * 	Sets the max ttl of the zone.
 *
 * Requires:
 *\li	'zone' to be valid initialised zone.
 *
 * Returns:
 *\li	void
 */

dns_ttl_t
dns_zone_getmaxttl(dns_zone_t *zone);
/*%<
 * 	Gets the max ttl of the zone.
 *
 * Requires:
 *\li	'zone' to be valid initialised zone.
 *
 * Returns:
 *\li	dns_ttl_t maxttl.
 */

isc_result_t
dns_zone_load(dns_zone_t *zone);

isc_result_t
dns_zone_loadnew(dns_zone_t *zone);

isc_result_t
dns_zone_loadandthaw(dns_zone_t *zone);

/*%<
 *	Cause the database to be loaded from its backing store.
 *	Confirm that the minimum requirements for the zone type are
 *	met, otherwise DNS_R_BADZONE is returned.
 *
 *	dns_zone_loadnew() only loads zones that are not yet loaded.
 *	dns_zone_load() also loads zones that are already loaded and
 *	and whose master file has changed since the last load.
 *	dns_zone_loadandthaw() is similar to dns_zone_load() but will
 *	also re-enable DNS UPDATEs when the load completes.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *
 * Returns:
 *\li	#ISC_R_UNEXPECTED
 *\li	#ISC_R_SUCCESS
 *\li	DNS_R_CONTINUE	  Incremental load has been queued.
 *\li	DNS_R_UPTODATE	  The zone has already been loaded based on
 *			  file system timestamps.
 *\li	DNS_R_BADZONE
 *\li	Any result value from dns_db_load().
 */

isc_result_t
dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg);

isc_result_t
dns_zone_asyncload2(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg,
		    bool newonly);
/*%<
 * Cause the database to be loaded from its backing store asynchronously.
 * Other zone maintenance functions are suspended until this is complete.
 * When finished, 'done' is called to inform the caller, with 'arg' as
 * its first argument and 'zone' as its second.  (Normally, 'arg' is
 * expected to point to the zone table but is left undefined for testing
 * purposes.)
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *
 * Returns:
 *\li	#ISC_R_ALREADYRUNNING
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_FAILURE
 *\li	#ISC_R_NOMEMORY
 */

bool
dns__zone_loadpending(dns_zone_t *zone);
/*%<
 * Indicates whether the zone is waiting to be loaded asynchronously.
 * (Not currently intended for use outside of this module and associated
 * tests.)
 */

void
dns_zone_attach(dns_zone_t *source, dns_zone_t **target);
/*%<
 *	Attach '*target' to 'source' incrementing its external
 * 	reference count.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'target' to be non NULL and '*target' to be NULL.
 */

void
dns_zone_detach(dns_zone_t **zonep);
/*%<
 *	Detach from a zone decrementing its external reference count.
 *	If this was the last external reference to the zone it will be
 * 	shut down and eventually freed.
 *
 * Require:
 *\li	'zonep' to point to a valid zone.
 */

void
dns_zone_iattach(dns_zone_t *source, dns_zone_t **target);
/*%<
 *	Attach '*target' to 'source' incrementing its internal
 * 	reference count.  This is intended for use by operations
 * 	such as zone transfers that need to prevent the zone
 * 	object from being freed but not from shutting down.
 *
 * Require:
 *\li	The caller is running in the context of the zone's task.
 *\li	'zone' to be a valid zone.
 *\li	'target' to be non NULL and '*target' to be NULL.
 */

void
dns_zone_idetach(dns_zone_t **zonep);
/*%<
 *	Detach from a zone decrementing its internal reference count.
 *	If there are no more internal or external references to the
 * 	zone, it will be freed.
 *
 * Require:
 *\li	The caller is running in the context of the zone's task.
 *\li	'zonep' to point to a valid zone.
 */

void
dns_zone_setflag(dns_zone_t *zone, unsigned int flags, bool value);
/*%<
 *	Sets ('value' == 'true') / clears ('value' == 'IS_FALSE')
 *	zone flags.  Valid flag bits are DNS_ZONE_F_*.
 *
 * Requires
 *\li	'zone' to be a valid zone.
 */

isc_result_t
dns_zone_getdb(dns_zone_t *zone, dns_db_t **dbp);
/*%<
 * 	Attach '*dbp' to the database to if it exists otherwise
 *	return DNS_R_NOTLOADED.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'dbp' to be != NULL && '*dbp' == NULL.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	DNS_R_NOTLOADED
 */

void
dns_zone_setdb(dns_zone_t *zone, dns_db_t *db);
/*%<
 *	Sets the zone database to 'db'.
 *
 *	This function is expected to be used to configure a zone with a
 *	database which is not loaded from a file or zone transfer.
 *	It can be used for a general purpose zone, but right now its use
 *	is limited to static-stub zones to avoid possible undiscovered
 *	problems in the general cases.
 *
 * Require:
 *\li	'zone' to be a valid zone of static-stub.
 *\li	zone doesn't have a database.
 */

isc_result_t
dns_zone_setdbtype(dns_zone_t *zone,
		   unsigned int dbargc, const char * const *dbargv);
/*%<
 *	Sets the database type to dbargv[0] and database arguments
 *	to subsequent dbargv elements.
 *	'db_type' is not checked to see if it is a valid database type.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'database' to be non NULL.
 *\li	'dbargc' to be >= 1
 *\li	'dbargv' to point to dbargc NULL-terminated strings
 *
 * Returns:
 *\li	#ISC_R_NOMEMORY
 *\li	#ISC_R_SUCCESS
 */

isc_result_t
dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx);
/*%<
 *	Returns the current dbtype.  isc_mem_free() should be used
 * 	to free 'argv' after use.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'argv' to be non NULL and *argv to be NULL.
 *\li	'mctx' to be valid.
 *
 * Returns:
 *\li	#ISC_R_NOMEMORY
 *\li	#ISC_R_SUCCESS
 */

void
dns_zone_markdirty(dns_zone_t *zone);
/*%<
 *	Mark a zone as 'dirty'.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

void
dns_zone_expire(dns_zone_t *zone);
/*%<
 *	Mark the zone as expired.  If the zone requires dumping cause it to
 *	be initiated.  Set the refresh and retry intervals to there default
 *	values and unload the zone.
 *
 * Require
 *\li	'zone' to be a valid zone.
 */

void
dns_zone_refresh(dns_zone_t *zone);
/*%<
 *	Initiate zone up to date checks.  The zone must already be being
 *	managed.
 *
 * Require
 *\li	'zone' to be a valid zone.
 */

isc_result_t
dns_zone_flush(dns_zone_t *zone);
/*%<
 *	Write the zone to database if there are uncommitted changes.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

isc_result_t
dns_zone_dump(dns_zone_t *zone);
/*%<
 *	Write the zone to database.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

isc_result_t
dns_zone_dumptostream(dns_zone_t *zone, FILE *fd);

isc_result_t
dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
		       const dns_master_style_t *style);
isc_result_t
dns_zone_dumptostream3(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
		       const dns_master_style_t *style,
		       const uint32_t rawversion);
/*%<
 *    Write the zone to stream 'fd' in the specified 'format'.
 *    If the 'format' is dns_masterformat_text (RFC1035), 'style' also
 *    specifies the file style (e.g., &dns_master_style_default).
 *
 *    dns_zone_dumptostream() is a backward-compatible form of
 *    dns_zone_dumptostream2(), which always uses the dns_masterformat_text
 *    format and the dns_master_style_default style.
 *
 *    dns_zone_dumptostream2() is a backward-compatible form of
 *    dns_zone_dumptostream3(), which always uses the current
 *    default raw file format version.
 *
 *    Note that dns_zone_dumptostream3() is the most flexible form.  It
 *    can also provide the functionality of dns_zone_fulldumptostream().
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'fd' to be a stream open for writing.
 */

isc_result_t
dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd);
/*%<
 *	The same as dns_zone_dumptostream, but dumps the zone with
 *	different dump settings (dns_master_style_full).
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'fd' to be a stream open for writing.
 */

void
dns_zone_maintenance(dns_zone_t *zone);
/*%<
 *	Perform regular maintenance on the zone.  This is called as a
 *	result of a zone being managed.
 *
 * Require
 *\li	'zone' to be a valid zone.
 */

isc_result_t
dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
		    uint32_t count);
isc_result_t
dns_zone_setmasterswithkeys(dns_zone_t *zone,
			    const isc_sockaddr_t *masters,
			    dns_name_t **keynames,
			    uint32_t count);
/*%<
 *	Set the list of master servers for the zone.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'masters' array of isc_sockaddr_t with port set or NULL.
 *\li	'count' the number of masters.
 *\li      'keynames' array of dns_name_t's for tsig keys or NULL.
 *
 *  \li    dns_zone_setmasters() is just a wrapper to setmasterswithkeys(),
 *      passing NULL in the keynames field.
 *
 * \li	If 'masters' is NULL then 'count' must be zero.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *\li      Any result dns_name_dup() can return, if keynames!=NULL
 */

isc_result_t
dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
		       uint32_t count);
isc_result_t
dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
			       dns_name_t **keynames, uint32_t count);
isc_result_t
dns_zone_setalsonotifydscpkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
			       const isc_dscp_t *dscps, dns_name_t **keynames,
			       uint32_t count);
/*%<
 *	Set the list of additional servers to be notified when
 *	a zone changes.	 To clear the list use 'count = 0'.
 *
 *	dns_zone_alsonotifywithkeys() allows each notify address to
 *	be associated with a TSIG key.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'notify' to be non-NULL if count != 0.
 *\li	'count' to be the number of notifiees.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 */

void
dns_zone_unload(dns_zone_t *zone);
/*%<
 *	detach the database from the zone structure.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

void
dns_zone_setoption(dns_zone_t *zone, unsigned int option,
		   bool value);
void
dns_zone_setoption2(dns_zone_t *zone, unsigned int option,
		    bool value);
/*%<
 *	Set the given options on ('value' == true) or off
 *	('value' == #false).
 *
 *	dns_zone_setoption2() has been introduced because the number
 *	of options needed now exceeds the 32 bits in the zone->options
 *	field; it should be used set options with names beginning
 *	with DNS_ZONEOPT2_.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

unsigned int
dns_zone_getoptions(dns_zone_t *zone);
unsigned int
dns_zone_getoptions2(dns_zone_t *zone);
/*%<
 *	Returns the current zone options.
 *
 *	Callers should be aware there is now more than one set of zone
 *	options.  dns_zone_getoptions2() has been introduced because the
 *	number of options needed now exceeds the 32 bits in the
 *	zone->options field. It returns the options whose names begin
 *	with DNS_ZONEOPT2_.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

void
dns_zone_setkeyopt(dns_zone_t *zone, unsigned int option, bool value);
/*%<
 *	Set key options on ('value' == true) or off ('value' ==
 *	#false).
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

unsigned int
dns_zone_getkeyopts(dns_zone_t *zone);
/*%<
 *	Returns the current zone key options.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

void
dns_zone_setminrefreshtime(dns_zone_t *zone, uint32_t val);
/*%<
 *	Set the minimum refresh time.
 *
 * Requires:
 *\li	'zone' is valid.
 *\li	val > 0.
 */

void
dns_zone_setmaxrefreshtime(dns_zone_t *zone, uint32_t val);
/*%<
 *	Set the maximum refresh time.
 *
 * Requires:
 *\li	'zone' is valid.
 *\li	val > 0.
 */

void
dns_zone_setminretrytime(dns_zone_t *zone, uint32_t val);
/*%<
 *	Set the minimum retry time.
 *
 * Requires:
 *\li	'zone' is valid.
 *\li	val > 0.
 */

void
dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val);
/*%<
 *	Set the maximum retry time.
 *
 * Requires:
 *\li	'zone' is valid.
 *	val > 0.
 */

isc_result_t
dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource);
isc_result_t
dns_zone_setaltxfrsource4(dns_zone_t *zone,
			  const isc_sockaddr_t *xfrsource);
/*%<
 * 	Set the source address to be used in IPv4 zone transfers.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'xfrsource' to contain the address.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 */

isc_sockaddr_t *
dns_zone_getxfrsource4(dns_zone_t *zone);
isc_sockaddr_t *
dns_zone_getaltxfrsource4(dns_zone_t *zone);
/*%<
 *	Returns the source address set by a previous dns_zone_setxfrsource4
 *	call, or the default of inaddr_any, port 0.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

isc_result_t
dns_zone_setxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp);
isc_result_t
dns_zone_setaltxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp);
/*%<
 * Set the DSCP value associated with the transfer/alt-transfer source.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 */

isc_dscp_t
dns_zone_getxfrsource4dscp(dns_zone_t *zone);
isc_dscp_t
dns_zone_getaltxfrsource4dscp(dns_zone_t *zone);
/*%/
 * Get the DSCP value associated with the transfer/alt-transfer source.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */


isc_result_t
dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource);
isc_result_t
dns_zone_setaltxfrsource6(dns_zone_t *zone,
			  const isc_sockaddr_t *xfrsource);
/*%<
 * 	Set the source address to be used in IPv6 zone transfers.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'xfrsource' to contain the address.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 */

isc_sockaddr_t *
dns_zone_getxfrsource6(dns_zone_t *zone);
isc_sockaddr_t *
dns_zone_getaltxfrsource6(dns_zone_t *zone);
/*%<
 *	Returns the source address set by a previous dns_zone_setxfrsource6
 *	call, or the default of in6addr_any, port 0.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

isc_dscp_t
dns_zone_getxfrsource6dscp(dns_zone_t *zone);
isc_dscp_t
dns_zone_getaltxfrsource6dscp(dns_zone_t *zone);
/*%/
 * Get the DSCP value associated with the transfer/alt-transfer source.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

isc_result_t
dns_zone_setxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp);
isc_result_t
dns_zone_setaltxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp);
/*%<
 * Set the DSCP value associated with the transfer/alt-transfer source.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 */

isc_result_t
dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc);
/*%<
 * 	Set the source address to be used with IPv4 NOTIFY messages.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'notifysrc' to contain the address.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 */

isc_sockaddr_t *
dns_zone_getnotifysrc4(dns_zone_t *zone);
/*%<
 *	Returns the source address set by a previous dns_zone_setnotifysrc4
 *	call, or the default of inaddr_any, port 0.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

isc_dscp_t
dns_zone_getnotifysrc4dscp(dns_zone_t *zone);
/*%/
 * Get the DSCP value associated with the IPv4 notify source.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

isc_result_t
dns_zone_setnotifysrc4dscp(dns_zone_t *zone, isc_dscp_t dscp);
/*%<
 * Set the DSCP value associated with the IPv4 notify source.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 */

isc_result_t
dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc);
/*%<
 * 	Set the source address to be used with IPv6 NOTIFY messages.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'notifysrc' to contain the address.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 */

isc_sockaddr_t *
dns_zone_getnotifysrc6(dns_zone_t *zone);
/*%<
 *	Returns the source address set by a previous dns_zone_setnotifysrc6
 *	call, or the default of in6addr_any, port 0.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

isc_dscp_t
dns_zone_getnotifysrc6dscp(dns_zone_t *zone);
/*%/
 * Get the DSCP value associated with the IPv6 notify source.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

isc_result_t
dns_zone_setnotifysrc6dscp(dns_zone_t *zone, isc_dscp_t dscp);
/*%<
 * Set the DSCP value associated with the IPv6 notify source.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 */

void
dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl);
/*%<
 *	Sets the notify acl list for the zone.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'acl' to be a valid acl.
 */

void
dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl);
/*%<
 *	Sets the query acl list for the zone.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'acl' to be a valid acl.
 */

void
dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl);
/*%<
 *	Sets the query-on acl list for the zone.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'acl' to be a valid acl.
 */

void
dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl);
/*%<
 *	Sets the update acl list for the zone.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'acl' to be valid acl.
 */

void
dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl);
/*%<
 *	Sets the forward unsigned updates acl list for the zone.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'acl' to be valid acl.
 */

void
dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl);
/*%<
 *	Sets the transfer acl list for the zone.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'acl' to be valid acl.
 */

dns_acl_t *
dns_zone_getnotifyacl(dns_zone_t *zone);
/*%<
 * 	Returns the current notify acl or NULL.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *
 * Returns:
 *\li	acl a pointer to the acl.
 *\li	NULL
 */

dns_acl_t *
dns_zone_getqueryacl(dns_zone_t *zone);
/*%<
 * 	Returns the current query acl or NULL.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *
 * Returns:
 *\li	acl a pointer to the acl.
 *\li	NULL
 */

dns_acl_t *
dns_zone_getqueryonacl(dns_zone_t *zone);
/*%<
 * 	Returns the current query-on acl or NULL.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *
 * Returns:
 *\li	acl a pointer to the acl.
 *\li	NULL
 */

dns_acl_t *
dns_zone_getupdateacl(dns_zone_t *zone);
/*%<
 * 	Returns the current update acl or NULL.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *
 * Returns:
 *\li	acl a pointer to the acl.
 *\li	NULL
 */

dns_acl_t *
dns_zone_getforwardacl(dns_zone_t *zone);
/*%<
 * 	Returns the current forward unsigned updates acl or NULL.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *
 * Returns:
 *\li	acl a pointer to the acl.
 *\li	NULL
 */

dns_acl_t *
dns_zone_getxfracl(dns_zone_t *zone);
/*%<
 * 	Returns the current transfer acl or NULL.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *
 * Returns:
 *\li	acl a pointer to the acl.
 *\li	NULL
 */

void
dns_zone_clearupdateacl(dns_zone_t *zone);
/*%<
 *	Clear the current update acl.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

void
dns_zone_clearforwardacl(dns_zone_t *zone);
/*%<
 *	Clear the current forward unsigned updates acl.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

void
dns_zone_clearnotifyacl(dns_zone_t *zone);
/*%<
 *	Clear the current notify acl.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

void
dns_zone_clearqueryacl(dns_zone_t *zone);
/*%<
 *	Clear the current query acl.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

void
dns_zone_clearqueryonacl(dns_zone_t *zone);
/*%<
 *	Clear the current query-on acl.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

void
dns_zone_clearxfracl(dns_zone_t *zone);
/*%<
 *	Clear the current transfer acl.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

bool
dns_zone_getupdatedisabled(dns_zone_t *zone);
/*%<
 * Return update disabled.
 * Transient unless called when running in isc_task_exclusive() mode.
 */

void
dns_zone_setupdatedisabled(dns_zone_t *zone, bool state);
/*%<
 * Set update disabled.
 * Should only be called only when running in isc_task_exclusive() mode.
 * Failure to do so may result in updates being committed after the
 * call has been made.
 */

bool
dns_zone_getzeronosoattl(dns_zone_t *zone);
/*%<
 * Return zero-no-soa-ttl status.
 */

void
dns_zone_setzeronosoattl(dns_zone_t *zone, bool state);
/*%<
 * Set zero-no-soa-ttl status.
 */

void
dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity);
/*%<
 * 	Set the severity of name checking when loading a zone.
 *
 * Require:
 * \li     'zone' to be a valid zone.
 */

dns_severity_t
dns_zone_getchecknames(dns_zone_t *zone);
/*%<
 *	Return the current severity of name checking.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 */

void
dns_zone_setjournalsize(dns_zone_t *zone, int32_t size);
/*%<
 *	Sets the journal size for the zone.
 *
 * Requires:
 *\li	'zone' to be a valid zone.
 */

int32_t
dns_zone_getjournalsize(dns_zone_t *zone);
/*%<
 *	Return the journal size as set with a previous call to
 *	dns_zone_setjournalsize().
 *
 * Requires:
 *\li	'zone' to be a valid zone.
 */

isc_result_t
dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
		       dns_message_t *msg);
isc_result_t
dns_zone_notifyreceive2(dns_zone_t *zone, isc_sockaddr_t *from,
			isc_sockaddr_t *to, dns_message_t *msg);
/*%<
 *	Tell the zone that it has received a NOTIFY message from another
 *	server.  This may cause some zone maintenance activity to occur.
 *
 * Requires:
 *\li	'zone' to be a valid zone.
 *\li	'*from' to contain the address of the server from which 'msg'
 *		was received.
 *\li	'msg' a message with opcode NOTIFY and qr clear.
 *
 * Returns:
 *\li	DNS_R_REFUSED
 *\li	DNS_R_NOTIMP
 *\li	DNS_R_FORMERR
 *\li	DNS_R_SUCCESS
 */

void
dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin);
/*%<
 * Set the maximum time (in seconds) that a zone transfer in (AXFR/IXFR)
 * of this zone will use before being aborted.
 *
 * Requires:
 * \li	'zone' to be valid initialised zone.
 */

uint32_t
dns_zone_getmaxxfrin(dns_zone_t *zone);
/*%<
 * Returns the maximum transfer time for this zone.  This will be
 * either the value set by the last call to dns_zone_setmaxxfrin() or
 * the default value of 1 hour.
 *
 * Requires:
 *\li	'zone' to be valid initialised zone.
 */

void
dns_zone_setmaxxfrout(dns_zone_t *zone, uint32_t maxxfrout);
/*%<
 * Set the maximum time (in seconds) that a zone transfer out (AXFR/IXFR)
 * of this zone will use before being aborted.
 *
 * Requires:
 * \li	'zone' to be valid initialised zone.
 */

uint32_t
dns_zone_getmaxxfrout(dns_zone_t *zone);
/*%<
 * Returns the maximum transfer time for this zone.  This will be
 * either the value set by the last call to dns_zone_setmaxxfrout() or
 * the default value of 1 hour.
 *
 * Requires:
 *\li	'zone' to be valid initialised zone.
 */

isc_result_t
dns_zone_setjournal(dns_zone_t *zone, const char *myjournal);
/*%<
 * Sets the filename used for journaling updates / IXFR transfers.
 * The default journal name is set by dns_zone_setfile() to be
 * "file.jnl".  If 'myjournal' is NULL, the zone will have no
 * journal name.
 *
 * Requires:
 *\li	'zone' to be a valid zone.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 */

char *
dns_zone_getjournal(dns_zone_t *zone);
/*%<
 * Returns the journal name associated with this zone.
 * If no journal has been set this will be NULL.
 *
 * Requires:
 *\li	'zone' to be valid initialised zone.
 */

dns_zonetype_t
dns_zone_gettype(dns_zone_t *zone);
/*%<
 * Returns the type of the zone (master/slave/etc.)
 *
 * Requires:
 *\li	'zone' to be valid initialised zone.
 */

void
dns_zone_settask(dns_zone_t *zone, isc_task_t *task);
/*%<
 * Give a zone a task to work with.  Any current task will be detached.
 *
 * Requires:
 *\li	'zone' to be valid.
 *\li	'task' to be valid.
 */

void
dns_zone_gettask(dns_zone_t *zone, isc_task_t **target);
/*%<
 * Attach '*target' to the zone's task.
 *
 * Requires:
 *\li	'zone' to be valid initialised zone.
 *\li	'zone' to have a task.
 *\li	'target' to be != NULL && '*target' == NULL.
 */

void
dns_zone_notify(dns_zone_t *zone);
/*%<
 * Generate notify events for this zone.
 *
 * Requires:
 *\li	'zone' to be a valid zone.
 */

isc_result_t
dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump);
/*%<
 * Replace the database of "zone" with a new database "db".
 *
 * If "dump" is true, then the new zone contents are dumped
 * into to the zone's master file for persistence.  When replacing
 * a zone database by one just loaded from a master file, set
 * "dump" to false to avoid a redundant redump of the data just
 * loaded.  Otherwise, it should be set to true.
 *
 * If the "diff-on-reload" option is enabled in the configuration file,
 * the differences between the old and the new database are added to the
 * journal file, and the master file dump is postponed.
 *
 * Requires:
 * \li	'zone' to be a valid zone.
 *
 * Returns:
 * \li	DNS_R_SUCCESS
 * \li	DNS_R_BADZONE	zone failed basic consistency checks:
 *			* a single SOA must exist
 *			* some NS records must exist.
 *	Others
 */

uint32_t
dns_zone_getidlein(dns_zone_t *zone);
/*%<
 * Requires:
 * \li	'zone' to be a valid zone.
 *
 * Returns:
 * \li	number of seconds of idle time before we abort the transfer in.
 */

void
dns_zone_setidlein(dns_zone_t *zone, uint32_t idlein);
/*%<
 * \li	Set the idle timeout for transfer the.
 * \li	Zero set the default value, 1 hour.
 *
 * Requires:
 * \li	'zone' to be a valid zone.
 */

uint32_t
dns_zone_getidleout(dns_zone_t *zone);
/*%<
 *
 * Requires:
 * \li	'zone' to be a valid zone.
 *
 * Returns:
 * \li	number of seconds of idle time before we abort a transfer out.
 */

void
dns_zone_setidleout(dns_zone_t *zone, uint32_t idleout);
/*%<
 * \li	Set the idle timeout for transfers out.
 * \li	Zero set the default value, 1 hour.
 *
 * Requires:
 * \li	'zone' to be a valid zone.
 */

void
dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table);
/*%<
 * Get the simple-secure-update policy table.
 *
 * Requires:
 * \li	'zone' to be a valid zone.
 */

void
dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table);
/*%<
 * Set / clear the simple-secure-update policy table.
 *
 * Requires:
 * \li	'zone' to be a valid zone.
 */

isc_mem_t *
dns_zone_getmctx(dns_zone_t *zone);
/*%<
 * Get the memory context of a zone.
 *
 * Requires:
 * \li	'zone' to be a valid zone.
 */

dns_zonemgr_t *
dns_zone_getmgr(dns_zone_t *zone);
/*%<
 *	If 'zone' is managed return the zone manager otherwise NULL.
 *
 * Requires:
 * \li	'zone' to be a valid zone.
 */

void
dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval);
/*%<
 * Set the zone's RRSIG validity interval.  This is the length of time
 * for which DNSSEC signatures created as a result of dynamic updates
 * to secure zones will remain valid, in seconds.
 *
 * Requires:
 * \li	'zone' to be a valid zone.
 */

uint32_t
dns_zone_getsigvalidityinterval(dns_zone_t *zone);
/*%<
 * Get the zone's RRSIG validity interval.
 *
 * Requires:
 * \li	'zone' to be a valid zone.
 */

void
dns_zone_setsigresigninginterval(dns_zone_t *zone, uint32_t interval);
/*%<
 * Set the zone's RRSIG re-signing interval.  A dynamic zone's RRSIG's
 * will be re-signed 'interval' amount of time before they expire.
 *
 * Requires:
 * \li	'zone' to be a valid zone.
 */

uint32_t
dns_zone_getsigresigninginterval(dns_zone_t *zone);
/*%<
 * Get the zone's RRSIG re-signing interval.
 *
 * Requires:
 * \li	'zone' to be a valid zone.
 */

void
dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype);
/*%<
 * Sets zone notify method to "notifytype"
 */

isc_result_t
dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
		       dns_updatecallback_t callback, void *callback_arg);
/*%<
 * Forward 'msg' to each master in turn until we get an answer or we
 * have exhausted the list of masters. 'callback' will be called with
 * ISC_R_SUCCESS if we get an answer and the returned message will be
 * passed as 'answer_message', otherwise a non ISC_R_SUCCESS result code
 * will be passed and answer_message will be NULL.  The callback function
 * is responsible for destroying 'answer_message'.
 *		(callback)(callback_arg, result, answer_message);
 *
 * Require:
 *\li	'zone' to be valid
 *\li	'msg' to be valid.
 *\li	'callback' to be non NULL.
 * Returns:
 *\li	#ISC_R_SUCCESS if the message has been forwarded,
 *\li	#ISC_R_NOMEMORY
 *\li	Others
 */

isc_result_t
dns_zone_next(dns_zone_t *zone, dns_zone_t **next);
/*%<
 * Find the next zone in the list of managed zones.
 *
 * Requires:
 *\li	'zone' to be valid
 *\li	The zone manager for the indicated zone MUST be locked
 *	by the caller.  This is not checked.
 *\li	'next' be non-NULL, and '*next' be NULL.
 *
 * Ensures:
 *\li	'next' points to a valid zone (result ISC_R_SUCCESS) or to NULL
 *	(result ISC_R_NOMORE).
 */



isc_result_t
dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first);
/*%<
 * Find the first zone in the list of managed zones.
 *
 * Requires:
 *\li	'zonemgr' to be valid
 *\li	The zone manager for the indicated zone MUST be locked
 *	by the caller.  This is not checked.
 *\li	'first' be non-NULL, and '*first' be NULL
 *
 * Ensures:
 *\li	'first' points to a valid zone (result ISC_R_SUCCESS) or to NULL
 *	(result ISC_R_NOMORE).
 */

isc_result_t
dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory);
/*%<
 *	Sets the name of the directory where private keys used for
 *	online signing of dynamic zones are found.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *
 * Returns:
 *\li	#ISC_R_NOMEMORY
 *\li	#ISC_R_SUCCESS
 */

const char *
dns_zone_getkeydirectory(dns_zone_t *zone);
/*%<
 * 	Gets the name of the directory where private keys used for
 *	online signing of dynamic zones are found.
 *
 * Requires:
 *\li	'zone' to be valid initialised zone.
 *
 * Returns:
 *	Pointer to null-terminated file name, or NULL.
 */


isc_result_t
dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
		   isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
		   dns_zonemgr_t **zmgrp);
/*%<
 * Create a zone manager.  Note: the zone manager will not be able to
 * manage any zones until dns_zonemgr_setsize() has been run.
 *
 * Requires:
 *\li	'mctx' to be a valid memory context.
 *\li	'taskmgr' to be a valid task manager.
 *\li	'timermgr' to be a valid timer manager.
 *\li	'zmgrp'	to point to a NULL pointer.
 */

isc_result_t
dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones);
/*%<
 *	Set the size of the zone manager task pool.  This must be run
 *	before zmgr can be used for managing zones.  Currently, it can only
 *	be run once; the task pool cannot be resized.
 *
 * Requires:
 *\li	zmgr is a valid zone manager.
 *\li	zmgr->zonetasks has been initialized.
 */

isc_result_t
dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep);
/*%<
 *	Allocate a new zone using a memory context from the
 *	zone manager's memory context pool.
 *
 * Require:
 *\li	'zmgr' to be a valid zone manager.
 *\li	'zonep' != NULL and '*zonep' == NULL.
 */


isc_result_t
dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone);
/*%<
 *	Bring the zone under control of a zone manager.
 *
 * Require:
 *\li	'zmgr' to be a valid zone manager.
 *\li	'zone' to be a valid zone.
 */

isc_result_t
dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr);
/*%<
 * Force zone maintenance of all loaded zones managed by 'zmgr'
 * to take place at the system's earliest convenience.
 */

void
dns__zonemgr_run(isc_task_t *task, isc_event_t *event);
/*%<
 * Event handler to call dns_zonemgr_forcemaint(); used to start
 * zone operations from a unit test.  Not intended for use outside
 * libdns or related tests.
 */

void
dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr);
/*%<
 * Attempt to start any stalled zone transfers.
 */

void
dns_zonemgr_shutdown(dns_zonemgr_t *zmgr);
/*%<
 *	Shut down the zone manager.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager.
 */

void
dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target);
/*%<
 *	Attach '*target' to 'source' incrementing its external
 * 	reference count.
 *
 * Require:
 *\li	'zone' to be a valid zone.
 *\li	'target' to be non NULL and '*target' to be NULL.
 */

void
dns_zonemgr_detach(dns_zonemgr_t **zmgrp);
/*%<
 *	 Detach from a zone manager.
 *
 * Requires:
 *\li	'*zmgrp' is a valid, non-NULL zone manager pointer.
 *
 * Ensures:
 *\li	'*zmgrp' is NULL.
 */

void
dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone);
/*%<
 *	Release 'zone' from the managed by 'zmgr'.  'zmgr' is implicitly
 *	detached from 'zone'.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager.
 *\li	'zone' to be a valid zone.
 *\li	'zmgr' == 'zone->zmgr'
 *
 * Ensures:
 *\li	'zone->zmgr' == NULL;
 */

void
dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value);
/*%<
 *	Set the maximum number of simultaneous transfers in allowed by
 *	the zone manager.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager.
 */

uint32_t
dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr);
/*%<
 *	Return the maximum number of simultaneous transfers in allowed.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager.
 */

void
dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value);
/*%<
 *	Set the number of zone transfers allowed per nameserver.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager
 */

uint32_t
dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr);
/*%<
 *	Return the number of transfers allowed per nameserver.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager.
 */

void
dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, uint32_t iolimit);
/*%<
 *	Set the number of simultaneous file descriptors available for
 *	reading and writing masterfiles.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager.
 *\li	'iolimit' to be positive.
 */

uint32_t
dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr);
/*%<
 *	Get the number of simultaneous file descriptors available for
 *	reading and writing masterfiles.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager.
 */

void
dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value);
/*%<
 *	Set the number of NOTIFY requests sent per second.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager
 */

void
dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value);
/*%<
 *	Set the number of startup NOTIFY requests sent per second.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager
 */

void
dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value);
/*%<
 *	Set the number of SOA queries sent per second.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager
 */

unsigned int
dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr);
/*%<
 *	Return the number of NOTIFY requests sent per second.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager.
 */

unsigned int
dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr);
/*%<
 *	Return the number of startup NOTIFY requests sent per second.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager.
 */

unsigned int
dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr);
/*%<
 *	Return the number of SOA queries sent per second.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager.
 */

unsigned int
dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state);
/*%<
 *	Returns the number of zones in the specified state.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager.
 *\li	'state' to be a valid DNS_ZONESTATE_ constant.
 */

void
dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
			   isc_sockaddr_t *local, isc_time_t *now);
/*%<
 *	Add the pair of addresses to the unreachable cache.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager.
 *\li	'remote' to be a valid sockaddr.
 *\li	'local' to be a valid sockaddr.
 */

bool
dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
			isc_sockaddr_t *local, isc_time_t *now);
/*%<
 *	Returns true if the given local/remote address pair
 *	is found in the zone maanger's unreachable cache.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager.
 *\li	'remote' to be a valid sockaddr.
 *\li	'local' to be a valid sockaddr.
 *\li	'now' != NULL
 */

void
dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
			   isc_sockaddr_t *local);
/*%<
 *	Remove the pair of addresses from the unreachable cache.
 *
 * Requires:
 *\li	'zmgr' to be a valid zone manager.
 *\li	'remote' to be a valid sockaddr.
 *\li	'local' to be a valid sockaddr.
 */

void
dns_zone_forcereload(dns_zone_t *zone);
/*%<
 *      Force a reload of specified zone.
 *
 * Requires:
 *\li      'zone' to be a valid zone.
 */

bool
dns_zone_isforced(dns_zone_t *zone);
/*%<
 *      Check if the zone is waiting a forced reload.
 *
 * Requires:
 * \li     'zone' to be a valid zone.
 */

isc_result_t
dns_zone_setstatistics(dns_zone_t *zone, bool on);
/*%<
 * This function is obsoleted by dns_zone_setrequeststats().
 */

uint64_t *
dns_zone_getstatscounters(dns_zone_t *zone);
/*%<
 * This function is obsoleted by dns_zone_getrequeststats().
 */

void
dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats);
/*%<
 * Set a general zone-maintenance statistics set 'stats' for 'zone'.  This
 * function is expected to be called only on zone creation (when necessary).
 * Once installed, it cannot be removed or replaced.  Also, there is no
 * interface to get the installed stats from the zone; the caller must keep the
 * stats to reference (e.g. dump) it later.
 *
 * Requires:
 * \li	'zone' to be a valid zone and does not have a statistics set already
 *	installed.
 *
 *\li	stats is a valid statistics supporting zone statistics counters
 *	(see dns/stats.h).
 */

void
dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats);

void
dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats);
/*%<
 * Set additional statistics sets to zone.  These are attached to the zone
 * but are not counted in the zone module; only the caller updates the
 * counters.
 *
 * Requires:
 * \li	'zone' to be a valid zone.
 *
 *\li	stats is a valid statistics.
 */

isc_stats_t *
dns_zone_getrequeststats(dns_zone_t *zone);

dns_stats_t *
dns_zone_getrcvquerystats(dns_zone_t *zone);
/*%<
 * Get the additional statistics for zone, if one is installed.
 *
 * Requires:
 * \li	'zone' to be a valid zone.
 *
 * Returns:
 * \li	when available, a pointer to the statistics set installed in zone;
 *	otherwise NULL.
 */

void
dns_zone_dialup(dns_zone_t *zone);
/*%<
 * Perform dialup-time maintenance on 'zone'.
 */

void
dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup);
/*%<
 * Set the dialup type of 'zone' to 'dialup'.
 *
 * Requires:
 * \li	'zone' to be valid initialised zone.
 *\li	'dialup' to be a valid dialup type.
 */

void
dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
	      const char *prefix, const char *msg, va_list ap);
/*%<
 * Log the message 'msg...' at 'level' using log category 'category', including
 * text that identifies the message as applying to 'zone'.  If the (optional)
 * 'prefix' is not NULL, it will be placed at the start of the entire log line.
 */

void
dns_zone_log(dns_zone_t *zone, int level, const char *msg, ...)
	ISC_FORMAT_PRINTF(3, 4);
/*%<
 * Log the message 'msg...' at 'level', including text that identifies
 * the message as applying to 'zone'.
 */

void
dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category, int level,
	      const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
/*%<
 * Log the message 'msg...' at 'level', including text that identifies
 * the message as applying to 'zone'.
 */

void
dns_zone_name(dns_zone_t *zone, char *buf, size_t len);
/*%<
 * Return the name of the zone with class and view.
 *
 * Requires:
 *\li	'zone' to be valid.
 *\li	'buf' to be non NULL.
 */

void
dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t len);
/*%<
 * Return the name of the zone only.
 *
 * Requires:
 *\li	'zone' to be valid.
 *\li	'buf' to be non NULL.
 */

isc_result_t
dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata);
/*%<
 * Check if this record meets the check-names policy.
 *
 * Requires:
 *	'zone' to be valid.
 *	'name' to be valid.
 *	'rdata' to be valid.
 *
 * Returns:
 *	DNS_R_SUCCESS		passed checks.
 *	DNS_R_BADOWNERNAME	failed ownername checks.
 *	DNS_R_BADNAME		failed rdata checks.
 */

void
dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache);
/*%<
 *	Associate the zone with an additional cache.
 *
 * Require:
 *	'zone' to be a valid zone.
 *	'acache' to be a non NULL pointer.
 *
 * Ensures:
 *	'zone' will have a reference to 'acache'
 */

void
dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx);
/*%<
 *	Set the post load integrity callback function 'checkmx'.
 *	'checkmx' will be called if the MX TARGET is not within the zone.
 *
 * Require:
 *	'zone' to be a valid zone.
 */

void
dns_zone_setchecksrv(dns_zone_t *zone, dns_checkmxfunc_t checksrv);
/*%<
 *	Set the post load integrity callback function 'checksrv'.
 *	'checksrv' will be called if the SRV TARGET is not within the zone.
 *
 * Require:
 *	'zone' to be a valid zone.
 */

void
dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns);
/*%<
 *	Set the post load integrity callback function 'checkns'.
 *	'checkns' will be called if the NS TARGET is not within the zone.
 *
 * Require:
 *	'zone' to be a valid zone.
 */

void
dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay);
/*%<
 * Set the minimum delay between sets of notify messages.
 *
 * Requires:
 *	'zone' to be valid.
 */

uint32_t
dns_zone_getnotifydelay(dns_zone_t *zone);
/*%<
 * Get the minimum delay between sets of notify messages.
 *
 * Requires:
 *	'zone' to be valid.
 */

void
dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg);
/*%<
 * Set the isself callback function and argument.
 *
 * bool
 * isself(dns_view_t *myview, dns_tsigkey_t *mykey, isc_netaddr_t *srcaddr,
 *	  isc_netaddr_t *destaddr, dns_rdataclass_t rdclass, void *arg);
 *
 * 'isself' returns true if a non-recursive query from 'srcaddr' to
 * 'destaddr' with optional key 'mykey' for class 'rdclass' would be
 * delivered to 'myview'.
 */

void
dns_zone_setnodes(dns_zone_t *zone, uint32_t nodes);
/*%<
 * Set the number of nodes that will be checked per quantum.
 */

void
dns_zone_setsignatures(dns_zone_t *zone, uint32_t signatures);
/*%<
 * Set the number of signatures that will be generated per quantum.
 */

uint32_t
dns_zone_getsignatures(dns_zone_t *zone);
/*%<
 * Get the number of signatures that will be generated per quantum.
 */

isc_result_t
dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
		     uint16_t keyid, bool deleteit);
/*%<
 * Initiate/resume signing of the entire zone with the zone DNSKEY(s)
 * that match the given algorithm and keyid.
 */

isc_result_t
dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param);
/*%<
 * Incrementally add a NSEC3 chain that corresponds to 'nsec3param'.
 */

void
dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type);
dns_rdatatype_t
dns_zone_getprivatetype(dns_zone_t *zone);
/*
 * Get/Set the private record type.  It is expected that these interfaces
 * will not be permanent.
 */

void
dns_zone_rekey(dns_zone_t *zone, bool fullsign);
/*%<
 * Update the zone's DNSKEY set from the key repository.
 *
 * If 'fullsign' is true, trigger an immediate full signing of
 * the zone with the new key.  Otherwise, if there are no keys or
 * if the new keys are for algorithms that have already signed the
 * zone, then the zone can be re-signed incrementally.
 */

isc_result_t
dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
		 unsigned int *errors);
/*%
 * Check if the name servers for the zone are sane (have address, don't
 * refer to CNAMEs/DNAMEs.  The number of constiancy errors detected in
 * returned in '*errors'
 *
 * Requires:
 * \li	'zone' to be valid.
 * \li	'db' to be valid.
 * \li	'version' to be valid or NULL.
 * \li	'errors' to be non NULL.
 *
 * Returns:
 * 	ISC_R_SUCCESS if there were no errors examining the zone contents.
 */

isc_result_t
dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version);
/*%
 * Check if CSD, CDNSKEY and DNSKEY are consistent.
 *
 * Requires:
 * \li	'zone' to be valid.
 * \li	'db' to be valid.
 * \li	'version' to be valid or NULL.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#DNS_R_BADCDS
 *\li	#DNS_R_BADCDNSKEY
 *	Others
 */

void
dns_zone_setadded(dns_zone_t *zone, bool added);
/*%
 * Sets the value of zone->added, which should be true for
 * zones that were originally added by "rndc addzone".
 *
 * Requires:
 * \li	'zone' to be valid.
 */

bool
dns_zone_getadded(dns_zone_t *zone);
/*%
 * Returns true if the zone was originally added at runtime
 * using "rndc addzone".
 *
 * Requires:
 * \li	'zone' to be valid.
 */

void
dns_zone_setautomatic(dns_zone_t *zone, bool automatic);
/*%
 * Sets the value of zone->automatic, which should be true for
 * zones that were automatically added by named.
 *
 * Requires:
 * \li	'zone' to be valid.
 */

bool
dns_zone_getautomatic(dns_zone_t *zone);
/*%
 * Returns true if the zone was added automatically by named.
 *
 * Requires:
 * \li	'zone' to be valid.
 */

isc_result_t
dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db);
/*%
 * Load the origin names for a writeable DLZ database.
 */

bool
dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze);
/*%
 * Return true iff the zone is "dynamic", in the sense that the zone's
 * master file (if any) is written by the server, rather than being
 * updated manually and read by the server.
 *
 * This is true for slave zones, stub zones, key zones, and zones that
 * allow dynamic updates either by having an update policy ("ssutable")
 * or an "allow-update" ACL with a value other than exactly "{ none; }".
 *
 * If 'ignore_freeze' is true, then the zone which has had updates disabled
 * will still report itself to be dynamic.
 *
 * Requires:
 * \li	'zone' to be valid.
 */

isc_result_t
dns_zone_setrefreshkeyinterval(dns_zone_t *zone, uint32_t interval);
/*%
 * Sets the frequency, in minutes, with which the key repository will be
 * checked to see if the keys for this zone have been updated.  Any value
 * higher than 1440 minutes (24 hours) will be silently reduced.  A
 * value of zero will return an out-of-range error.
 *
 * Requires:
 * \li	'zone' to be valid.
 */

bool
dns_zone_getrequestexpire(dns_zone_t *zone);
/*%
 * Returns the true/false value of the request-expire option in the zone.
 *
 * Requires:
 * \li	'zone' to be valid.
 */

void
dns_zone_setrequestexpire(dns_zone_t *zone, bool flag);
/*%
 * Sets the request-expire option for the zone. Either true or false. The
 * default value is determined by the setting of this option in the view.
 *
 * Requires:
 * \li	'zone' to be valid.
 */


bool
dns_zone_getrequestixfr(dns_zone_t *zone);
/*%
 * Returns the true/false value of the request-ixfr option in the zone.
 *
 * Requires:
 * \li	'zone' to be valid.
 */

void
dns_zone_setrequestixfr(dns_zone_t *zone, bool flag);
/*%
 * Sets the request-ixfr option for the zone. Either true or false. The
 * default value is determined by the setting of this option in the view.
 *
 * Requires:
 * \li	'zone' to be valid.
 */

void
dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method);
/*%
 * Sets the update method to use when incrementing the zone serial number
 * due to a DDNS update.  Valid options are dns_updatemethod_increment
 * and dns_updatemethod_unixtime.
 *
 * Requires:
 * \li	'zone' to be valid.
 */

dns_updatemethod_t
dns_zone_getserialupdatemethod(dns_zone_t *zone);
/*%
 * Returns the update method to be used when incrementing the zone serial
 * number due to a DDNS update.
 *
 * Requires:
 * \li	'zone' to be valid.
 */

isc_result_t
dns_zone_link(dns_zone_t *zone, dns_zone_t *raw);

void
dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw);

isc_result_t
dns_zone_keydone(dns_zone_t *zone, const char *data);

isc_result_t
dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags,
		       uint16_t iter, uint8_t saltlen,
		       unsigned char *salt, bool replace);
/*%
 * Set the NSEC3 parameters for the zone.
 *
 * If 'replace' is true, then the existing NSEC3 chain, if any, will
 * be replaced with the new one.  If 'hash' is zero, then the replacement
 * chain will be NSEC rather than NSEC3.
 *
 * Requires:
 * \li	'zone' to be valid.
 */

void
dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header);
/*%
 * Set the data to be included in the header when the zone is dumped in
 * binary format.
 */

isc_result_t
dns_zone_synckeyzone(dns_zone_t *zone);
/*%
 * Force the managed key zone to synchronize, and start the key
 * maintenance timer.
 */

isc_result_t
dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime);
/*%
 * Return the time when the zone was last loaded.
 */

isc_result_t
dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime);
/*%
 * Return the time when the (slave) zone will need to be refreshed.
 */

isc_result_t
dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime);
/*%
 * Return the time when the (slave) zone will expire.
 */

isc_result_t
dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime);
/*%
 * Return the time of the next scheduled DNSSEC key event.
 */

unsigned int
dns_zone_getincludes(dns_zone_t *zone, char ***includesp);
/*%
 * Return the number include files that were encountered
 * during load.  If the number is greater than zero, 'includesp'
 * will point to an array containing the filenames.
 *
 * The array and its contents need to be freed using isc_mem_free.
 */

isc_result_t
dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
		    dns_rpz_num_t rpz_num);
/*%
 * Set the response policy associated with a zone.
 */

void
dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db);
/*%
 * If a zone is a response policy zone, mark its new database.
 */

dns_rpz_num_t
dns_zone_get_rpz_num(dns_zone_t *zone);

void
dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs);
/*%<
 * Enable zone as catalog zone.
 *
 * Requires:
 *
 * \li	'zone' is a valid zone object
 * \li	'catzs' is not NULL
 * \li	prior to calling, zone->catzs is NULL or is equal to 'catzs'
 */

void
dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db);
/*%<
 * If 'zone' is a catalog zone, then set up a notify-on-update trigger
 * in its database. (If not a catalog zone, this function has no effect.)
 *
 * Requires:
 *
 * \li	'zone' is a valid zone object
 * \li	'db' is not NULL
 */
void
dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz);
/*%<
 * Set parent catalog zone for this zone
 *
 * Requires:
 *
 * \li	'zone' is a valid zone object
 * \li	'catz' is not NULL
 */

dns_catz_zone_t *
dns_zone_get_parentcatz(const dns_zone_t *zone);
/*%<
 * Get parent catalog zone for this zone
 *
 * Requires:
 *
 * \li	'zone' is a valid zone object
 */


void
dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level);

dns_zonestat_level_t
dns_zone_getstatlevel(dns_zone_t *zone);
/*%
 * Set and get the statistics reporting level for the zone;
 * full, terse, or none.
 */

isc_result_t
dns_zone_setserial(dns_zone_t *zone, uint32_t serial);
/*%
 * Set the zone's serial to 'serial'.
 */
ISC_LANG_ENDDECLS


#endif /* DNS_ZONE_H */
ecdb.h000064400000001451150415243050005612 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_ECDB_H
#define DNS_ECDB_H 1

/*****
 ***** Module Info
 *****/

/* TBD */

/***
 *** Imports
 ***/

#include <dns/types.h>

/***
 *** Types
 ***/

/***
 *** Functions
 ***/

ISC_LANG_BEGINDECLS

/* TBD: describe those */

isc_result_t
dns_ecdb_register(isc_mem_t *mctx, dns_dbimplementation_t **dbimp);

void
dns_ecdb_unregister(dns_dbimplementation_t **dbimp);

ISC_LANG_ENDDECLS

#endif /* DNS_ECDB_H */
log.h000064400000007574150415243050005512 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/*! \file dns/log.h
 */

#ifndef DNS_LOG_H
#define DNS_LOG_H 1

#include <isc/lang.h>
#include <isc/log.h>

LIBDNS_EXTERNAL_DATA extern isc_log_t *dns_lctx;
LIBDNS_EXTERNAL_DATA extern isc_logcategory_t dns_categories[];
LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[];

#define DNS_LOGCATEGORY_NOTIFY		(&dns_categories[0])
#define DNS_LOGCATEGORY_DATABASE	(&dns_categories[1])
#define DNS_LOGCATEGORY_SECURITY	(&dns_categories[2])
/* DNS_LOGCATEGORY_CONFIG superseded by CFG_LOGCATEGORY_CONFIG */
#define DNS_LOGCATEGORY_DNSSEC		(&dns_categories[4])
#define DNS_LOGCATEGORY_RESOLVER	(&dns_categories[5])
#define DNS_LOGCATEGORY_XFER_IN		(&dns_categories[6])
#define DNS_LOGCATEGORY_XFER_OUT	(&dns_categories[7])
#define DNS_LOGCATEGORY_DISPATCH	(&dns_categories[8])
#define DNS_LOGCATEGORY_LAME_SERVERS	(&dns_categories[9])
#define DNS_LOGCATEGORY_DELEGATION_ONLY	(&dns_categories[10])
#define DNS_LOGCATEGORY_EDNS_DISABLED	(&dns_categories[11])
#define DNS_LOGCATEGORY_RPZ		(&dns_categories[12])
#define DNS_LOGCATEGORY_RRL		(&dns_categories[13])
#define DNS_LOGCATEGORY_CNAME		(&dns_categories[14])
#define DNS_LOGCATEGORY_SPILL		(&dns_categories[15])
#define DNS_LOGCATEGORY_DNSTAP		(&dns_categories[16])

/* Backwards compatibility. */
#define DNS_LOGCATEGORY_GENERAL		ISC_LOGCATEGORY_GENERAL

#define DNS_LOGMODULE_DB		(&dns_modules[0])
#define DNS_LOGMODULE_RBTDB		(&dns_modules[1])
#define DNS_LOGMODULE_RBTDB64		(&dns_modules[2])
#define DNS_LOGMODULE_RBT		(&dns_modules[3])
#define DNS_LOGMODULE_RDATA		(&dns_modules[4])
#define DNS_LOGMODULE_MASTER		(&dns_modules[5])
#define DNS_LOGMODULE_MESSAGE		(&dns_modules[6])
#define DNS_LOGMODULE_CACHE		(&dns_modules[7])
#define DNS_LOGMODULE_CONFIG		(&dns_modules[8])
#define DNS_LOGMODULE_RESOLVER		(&dns_modules[9])
#define DNS_LOGMODULE_ZONE		(&dns_modules[10])
#define DNS_LOGMODULE_JOURNAL		(&dns_modules[11])
#define DNS_LOGMODULE_ADB		(&dns_modules[12])
#define DNS_LOGMODULE_XFER_IN		(&dns_modules[13])
#define DNS_LOGMODULE_XFER_OUT		(&dns_modules[14])
#define DNS_LOGMODULE_ACL		(&dns_modules[15])
#define DNS_LOGMODULE_VALIDATOR		(&dns_modules[16])
#define DNS_LOGMODULE_DISPATCH		(&dns_modules[17])
#define DNS_LOGMODULE_REQUEST		(&dns_modules[18])
#define DNS_LOGMODULE_MASTERDUMP	(&dns_modules[19])
#define DNS_LOGMODULE_TSIG		(&dns_modules[20])
#define DNS_LOGMODULE_TKEY		(&dns_modules[21])
#define DNS_LOGMODULE_SDB		(&dns_modules[22])
#define DNS_LOGMODULE_DIFF		(&dns_modules[23])
#define DNS_LOGMODULE_HINTS		(&dns_modules[24])
#define DNS_LOGMODULE_ACACHE		(&dns_modules[25])
#define DNS_LOGMODULE_DLZ		(&dns_modules[26])
#define DNS_LOGMODULE_DNSSEC		(&dns_modules[27])
#define DNS_LOGMODULE_CRYPTO		(&dns_modules[28])
#define DNS_LOGMODULE_PACKETS		(&dns_modules[29])
#define DNS_LOGMODULE_NTA		(&dns_modules[30])
#define DNS_LOGMODULE_DYNDB		(&dns_modules[31])
#define DNS_LOGMODULE_DNSTAP		(&dns_modules[32])
#define DNS_LOGMODULE_SSU		(&dns_modules[33])

ISC_LANG_BEGINDECLS

void
dns_log_init(isc_log_t *lctx);
/*%
 * Make the libdns categories and modules available for use with the
 * ISC logging library.
 *
 * Requires:
 *\li	lctx is a valid logging context.
 *
 *\li	dns_log_init() is called only once.
 *
 * Ensures:
 * \li	The categories and modules defined above are available for
 * 	use by isc_log_usechannnel() and isc_log_write().
 */

void
dns_log_setcontext(isc_log_t *lctx);
/*%
 * Make the libdns library use the provided context for logging internal
 * messages.
 *
 * Requires:
 *\li	lctx is a valid logging context.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_LOG_H */
keyflags.h000064400000002376150415243050006531 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_KEYFLAGS_H
#define DNS_KEYFLAGS_H 1

/*! \file dns/keyflags.h */

#include <isc/lang.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

isc_result_t
dns_keyflags_fromtext(dns_keyflags_t *flagsp, isc_textregion_t *source);
/*%<
 * Convert the text 'source' refers to into a DNSSEC KEY flags value.
 * The text may contain either a set of flag mnemonics separated by
 * vertical bars or a decimal flags value.  For compatibility with
 * older versions of BIND and the DNSSEC signer, octal values
 * prefixed with a zero and hexadecimal values prefixed with "0x"
 * are also accepted.
 *
 * Requires:
 *\li	'flagsp' is a valid pointer.
 *
 *\li	'source' is a valid text region.
 *
 * Returns:
 *\li	ISC_R_SUCCESS			on success
 *\li	ISC_R_RANGE			numeric flag value is out of range
 *\li	DNS_R_UNKNOWN			mnemonic flag is unknown
 */

ISC_LANG_ENDDECLS

#endif /* DNS_KEYFLAGS_H */
keydata.h000064400000002043150415243050006335 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_KEYDATA_H
#define DNS_KEYDATA_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/keydata.h
 * \brief
 * KEYDATA utilities.
 */

/***
 *** Imports
 ***/

#include <inttypes.h>

#include <isc/lang.h>
#include <isc/types.h>

#include <dns/types.h>
#include <dns/rdatastruct.h>

ISC_LANG_BEGINDECLS

isc_result_t
dns_keydata_todnskey(dns_rdata_keydata_t *keydata,
		     dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx);

isc_result_t
dns_keydata_fromdnskey(dns_rdata_keydata_t *keydata,
		       dns_rdata_dnskey_t *dnskey,
		       uint32_t refresh, uint32_t addhd,
		       uint32_t removehd, isc_mem_t *mctx);

ISC_LANG_ENDDECLS

#endif /* DNS_KEYDATA_H */
rootns.h000064400000001574150415243050006247 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_ROOTNS_H
#define DNS_ROOTNS_H 1

/*! \file dns/rootns.h */

#include <isc/lang.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

isc_result_t
dns_rootns_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
		  const char *filename, dns_db_t **target);

void
dns_root_checkhints(dns_view_t *view, dns_db_t *hints, dns_db_t *db);
/*
 * Reports differences between hints and the real roots.
 *
 * Requires view, hints and (cache) db to be valid.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_ROOTNS_H */
ssu.h000064400000020164150415243050005531 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_SSU_H
#define DNS_SSU_H 1

/*! \file dns/ssu.h */

#include <stdbool.h>

#include <isc/lang.h>

#include <dns/acl.h>
#include <dns/types.h>
#include <dst/dst.h>

ISC_LANG_BEGINDECLS

typedef enum {
	dns_ssumatchtype_name = 0,
	dns_ssumatchtype_subdomain = 1,
	dns_ssumatchtype_wildcard = 2,
	dns_ssumatchtype_self    = 3,
	dns_ssumatchtype_selfsub = 4,
	dns_ssumatchtype_selfwild = 5,
	dns_ssumatchtype_selfkrb5 = 6,
	dns_ssumatchtype_selfms  = 7,
	dns_ssumatchtype_subdomainms = 8,
	dns_ssumatchtype_subdomainkrb5 = 9,
	dns_ssumatchtype_tcpself = 10,
	dns_ssumatchtype_6to4self = 11,
	dns_ssumatchtype_external = 12,
	dns_ssumatchtype_local = 13,
	dns_ssumatchtype_selfsubms = 14,
	dns_ssumatchtype_selfsubkrb5 = 15,
	dns_ssumatchtype_max = 15,	/* max value */

	dns_ssumatchtype_dlz = 16	/* intentionally higher than _max */
} dns_ssumatchtype_t;

#define DNS_SSUMATCHTYPE_NAME		dns_ssumatchtype_name
#define DNS_SSUMATCHTYPE_SUBDOMAIN	dns_ssumatchtype_subdomain
#define DNS_SSUMATCHTYPE_WILDCARD	dns_ssumatchtype_wildcard
#define DNS_SSUMATCHTYPE_SELF		dns_ssumatchtype_self
#define DNS_SSUMATCHTYPE_SELFSUB	dns_ssumatchtype_selfsub
#define DNS_SSUMATCHTYPE_SELFWILD	dns_ssumatchtype_selfwild
#define DNS_SSUMATCHTYPE_SELFKRB5	dns_ssumatchtype_selfkrb5
#define DNS_SSUMATCHTYPE_SELFMS		dns_ssumatchtype_selfms
#define DNS_SSUMATCHTYPE_SUBDOMAINMS	dns_ssumatchtype_subdomainms
#define DNS_SSUMATCHTYPE_SUBDOMAINKRB5	dns_ssumatchtype_subdomainkrb5
#define DNS_SSUMATCHTYPE_TCPSELF	dns_ssumatchtype_tcpself
#define DNS_SSUMATCHTYPE_6TO4SELF	dns_ssumatchtype_6to4self
#define DNS_SSUMATCHTYPE_EXTERNAL	dns_ssumatchtype_external
#define DNS_SSUMATCHTYPE_LOCAL		dns_ssumatchtype_local
#define DNS_SSUMATCHTYPE_MAX 		dns_ssumatchtype_max  /* max value */

#define DNS_SSUMATCHTYPE_DLZ		dns_ssumatchtype_dlz  /* intentionally higher than _MAX */

isc_result_t
dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **table);
/*%<
 *	Creates a table that will be used to store simple-secure-update rules.
 *	Note: all locking must be provided by the client.
 *
 *	Requires:
 *\li		'mctx' is a valid memory context
 *\li		'table' is not NULL, and '*table' is NULL
 *
 *	Returns:
 *\li		ISC_R_SUCCESS
 *\li		ISC_R_NOMEMORY
 */

isc_result_t
dns_ssutable_createdlz(isc_mem_t *mctx, dns_ssutable_t **tablep,
		       dns_dlzdb_t *dlzdatabase);
/*%<
 * Create an SSU table that contains a dlzdatabase pointer, and a
 * single rule with matchtype DNS_SSUMATCHTYPE_DLZ. This type of SSU
 * table is used by writeable DLZ drivers to offload authorization for
 * updates to the driver.
 */

void
dns_ssutable_attach(dns_ssutable_t *source, dns_ssutable_t **targetp);
/*%<
 *	Attach '*targetp' to 'source'.
 *
 *	Requires:
 *\li		'source' is a valid SSU table
 *\li		'targetp' points to a NULL dns_ssutable_t *.
 *
 *	Ensures:
 *\li		*targetp is attached to source.
 */

void
dns_ssutable_detach(dns_ssutable_t **tablep);
/*%<
 *	Detach '*tablep' from its simple-secure-update rule table.
 *
 *	Requires:
 *\li		'tablep' points to a valid dns_ssutable_t
 *
 *	Ensures:
 *\li		*tablep is NULL
 *\li		If '*tablep' is the last reference to the SSU table, all
 *			resources used by the table will be freed.
 */

isc_result_t
dns_ssutable_addrule(dns_ssutable_t *table, bool grant,
		     dns_name_t *identity, unsigned int matchtype,
		     dns_name_t *name, unsigned int ntypes,
		     dns_rdatatype_t *types);
/*%<
 *	Adds a new rule to a simple-secure-update rule table.  The rule
 *	either grants or denies update privileges of an identity (or set of
 *	identities) to modify a name (or set of names) or certain types present
 *	at that name.
 *
 *	Notes:
 *\li		If 'matchtype' is of SELF type, this rule only matches if the
 *              name to be updated matches the signing identity.
 *
 *\li		If 'ntypes' is 0, this rule applies to all types except
 *		NS, SOA, RRSIG, and NSEC.
 *
 *\li		If 'types' includes ANY, this rule applies to all types
 *		except NSEC.
 *
 *	Requires:
 *\li		'table' is a valid SSU table
 *\li		'identity' is a valid absolute name
 *\li		'matchtype' must be one of the defined constants.
 *\li		'name' is a valid absolute name
 *\li		If 'ntypes' > 0, 'types' must not be NULL
 *
 *	Returns:
 *\li		ISC_R_SUCCESS
 *\li		ISC_R_NOMEMORY
 */

bool
dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
			dns_name_t *name, isc_netaddr_t *addr,
			dns_rdatatype_t type, const dst_key_t *key);
bool
dns_ssutable_checkrules2(dns_ssutable_t *table, dns_name_t *signer,
			dns_name_t *name, isc_netaddr_t *addr,
			bool tcp, const dns_aclenv_t *env,
			dns_rdatatype_t type, const dst_key_t *key);
/*%<
 *	Checks that the attempted update of (name, type) is allowed according
 *	to the rules specified in the simple-secure-update rule table.  If
 *	no rules are matched, access is denied.
 *
 *	Notes:
 *		In dns_ssutable_checkrules(), 'addr' should only be
 *		set if the request received via TCP.  This provides a
 *		weak assurance that the request was not spoofed.
 *		'addr' is to to validate DNS_SSUMATCHTYPE_TCPSELF
 *		and DNS_SSUMATCHTYPE_6TO4SELF rules.
 *
 *		In dns_ssutable_checkrules2(), 'addr' can also be passed for
 *		UDP requests and TCP is specified via the 'tcp' parameter.
 *		In addition to DNS_SSUMATCHTYPE_TCPSELF and
 *		tcp_ssumatchtype_6to4self  rules, the address
 *		also be used to check DNS_SSUMATCHTYPE_LOCAL rules.
 *		If 'addr' is set then 'env' must also be set so that
 *		requests from non-localhost addresses can be rejected.
 *
 *		For DNS_SSUMATCHTYPE_TCPSELF the addresses are mapped to
 *		the standard reverse names under IN-ADDR.ARPA and IP6.ARPA.
 *		RFC 1035, Section 3.5, "IN-ADDR.ARPA domain" and RFC 3596,
 *		Section 2.5, "IP6.ARPA Domain".
 *
 *		For DNS_SSUMATCHTYPE_6TO4SELF, IPv4 address are converted
 *		to a 6to4 prefix (48 bits) per the rules in RFC 3056.  Only
 *		the top	48 bits of the IPv6 address are mapped to the reverse
 *		name. This is independent of whether the most significant 16
 *		bits match 2002::/16, assigned for 6to4 prefixes, or not.
 *
 *	Requires:
 *\li		'table' is a valid SSU table
 *\li		'signer' is NULL or a valid absolute name
 *\li		'addr' is NULL or a valid network address.
 *\li		'aclenv' is NULL or a valid ACL environment.
 *\li		'name' is a valid absolute name
 *\li		if 'addr' is not NULL, 'env' is not NULL.
 */


/*% Accessor functions to extract rule components */
bool	dns_ssurule_isgrant(const dns_ssurule_t *rule);
/*% Accessor functions to extract rule components */
dns_name_t *	dns_ssurule_identity(const dns_ssurule_t *rule);
/*% Accessor functions to extract rule components */
unsigned int	dns_ssurule_matchtype(const dns_ssurule_t *rule);
/*% Accessor functions to extract rule components */
dns_name_t *	dns_ssurule_name(const dns_ssurule_t *rule);
/*% Accessor functions to extract rule components */
unsigned int	dns_ssurule_types(const dns_ssurule_t *rule,
				  dns_rdatatype_t **types);

isc_result_t	dns_ssutable_firstrule(const dns_ssutable_t *table,
				       dns_ssurule_t **rule);
/*%<
 * Initiates a rule iterator.  There is no need to maintain any state.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMORE
 */

isc_result_t	dns_ssutable_nextrule(dns_ssurule_t *rule,
				      dns_ssurule_t **nextrule);
/*%<
 * Returns the next rule in the table.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMORE
 */

bool
dns_ssu_external_match(dns_name_t *identity, dns_name_t *signer,
		       dns_name_t *name, isc_netaddr_t *tcpaddr,
		       dns_rdatatype_t type, const dst_key_t *key,
		       isc_mem_t *mctx);
/*%<
 * Check a policy rule via an external application
 */

isc_result_t
dns_ssu_mtypefromstring(const char *str, dns_ssumatchtype_t *mtype);
/*%<
 * Set 'mtype' from 'str'
 *
 * Requires:
 *\li		'str' is not NULL.
 *\li		'mtype' is not NULL,
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOTFOUND
 */

ISC_LANG_ENDDECLS

#endif /* DNS_SSU_H */
dlz_dlopen.h000064400000011105150415243050007044 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


/*! \file dns/dlz_dlopen.h */

#ifndef DLZ_DLOPEN_H
#define DLZ_DLOPEN_H

#include <inttypes.h>
#include <stdbool.h>

#include <dns/sdlz.h>

ISC_LANG_BEGINDECLS

/*
 * This header provides a minimal set of defines and typedefs needed
 * for the entry points of an external DLZ module for bind9.
 */

#define DLZ_DLOPEN_VERSION 3
#define DLZ_DLOPEN_AGE 0

/*
 * dlz_dlopen_version() is required for all DLZ external drivers. It
 * should return DLZ_DLOPEN_VERSION
 */
typedef int dlz_dlopen_version_t(unsigned int *flags);

/*
 * dlz_dlopen_create() is required for all DLZ external drivers.
 */
typedef isc_result_t dlz_dlopen_create_t(const char *dlzname,
					 unsigned int argc,
					 char *argv[],
					 void **dbdata,
					 ...);

/*
 * dlz_dlopen_destroy() is optional, and will be called when the
 * driver is unloaded if supplied
 */
typedef void dlz_dlopen_destroy_t(void *dbdata);

/*
 * dlz_dlopen_findzonedb() is required for all DLZ external drivers
 */
typedef isc_result_t dlz_dlopen_findzonedb_t(void *dbdata,
					     const char *name,
					     dns_clientinfomethods_t *methods,
					     dns_clientinfo_t *clientinfo);

/*
 * dlz_dlopen_lookup() is required for all DLZ external drivers
 */
typedef isc_result_t dlz_dlopen_lookup_t(const char *zone,
					 const char *name,
					 void *dbdata,
					 dns_sdlzlookup_t *lookup,
					 dns_clientinfomethods_t *methods,
					 dns_clientinfo_t *clientinfo);

/*
 * dlz_dlopen_authority is optional() if dlz_dlopen_lookup()
 * supplies authority information for the dns record
 */
typedef isc_result_t dlz_dlopen_authority_t(const char *zone,
					    void *dbdata,
					    dns_sdlzlookup_t *lookup);

/*
 * dlz_dlopen_allowzonexfr() is optional, and should be supplied if
 * you want to support zone transfers
 */
typedef isc_result_t dlz_dlopen_allowzonexfr_t(void *dbdata,
					       const char *name,
					       const char *client);

/*
 * dlz_dlopen_allnodes() is optional, but must be supplied if supply a
 * dlz_dlopen_allowzonexfr() function
 */
typedef isc_result_t dlz_dlopen_allnodes_t(const char *zone,
					   void *dbdata,
					   dns_sdlzallnodes_t *allnodes);

/*
 * dlz_dlopen_newversion() is optional. It should be supplied if you
 * want to support dynamic updates.
 */
typedef isc_result_t dlz_dlopen_newversion_t(const char *zone,
					     void *dbdata,
					     void **versionp);

/*
 * dlz_closeversion() is optional, but must be supplied if you supply
 * a dlz_newversion() function
 */
typedef void dlz_dlopen_closeversion_t(const char *zone,
				       bool commit,
				       void *dbdata,
				       void **versionp);

/*
 * dlz_dlopen_configure() is optional, but must be supplied if you
 * want to support dynamic updates
 */
typedef isc_result_t dlz_dlopen_configure_t(dns_view_t *view,
					    dns_dlzdb_t *dlzdb,
					    void *dbdata);

/*
 * dlz_dlopen_setclientcallback() is optional, but must be supplied if you
 * want to retrieve information about the client (e.g., source address)
 * before sending a replay.
 */
typedef isc_result_t dlz_dlopen_setclientcallback_t(dns_view_t *view,
						    void *dbdata);


/*
 * dlz_dlopen_ssumatch() is optional, but must be supplied if you want
 * to support dynamic updates
 */
typedef bool dlz_dlopen_ssumatch_t(const char *signer,
					    const char *name,
					    const char *tcpaddr,
					    const char *type,
					    const char *key,
					    uint32_t keydatalen,
					    unsigned char *keydata,
					    void *dbdata);

/*
 * dlz_dlopen_addrdataset() is optional, but must be supplied if you
 * want to support dynamic updates
 */
typedef isc_result_t dlz_dlopen_addrdataset_t(const char *name,
					      const char *rdatastr,
					      void *dbdata,
					      void *version);

/*
 * dlz_dlopen_subrdataset() is optional, but must be supplied if you
 * want to support dynamic updates
 */
typedef isc_result_t dlz_dlopen_subrdataset_t(const char *name,
					      const char *rdatastr,
					      void *dbdata,
					      void *version);

/*
 * dlz_dlopen_delrdataset() is optional, but must be supplied if you
 * want to support dynamic updates
 */
typedef isc_result_t dlz_dlopen_delrdataset_t(const char *name,
					      const char *type,
					      void *dbdata,
					      void *version);

ISC_LANG_ENDDECLS

#endif
rdata.h000064400000052155150415243050006017 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_RDATA_H
#define DNS_RDATA_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/rdata.h
 * \brief
 * Provides facilities for manipulating DNS rdata, including conversions to
 * and from wire format and text format.
 *
 * Given the large amount of rdata possible in a nameserver, it was important
 * to come up with a very efficient way of storing rdata, but at the same
 * time allow it to be manipulated.
 *
 * The decision was to store rdata in uncompressed wire format,
 * and not to make it a fully abstracted object; i.e. certain parts of the
 * server know rdata is stored that way.  This saves a lot of memory, and
 * makes adding rdata to messages easy.  Having much of the server know
 * the representation would be perilous, and we certainly don't want each
 * user of rdata to be manipulating such a low-level structure.  This is
 * where the rdata module comes in.  The module allows rdata handles to be
 * created and attached to uncompressed wire format regions.  All rdata
 * operations and conversions are done through these handles.
 *
 * Implementation Notes:
 *
 *\li	The routines in this module are expected to be synthesized by the
 *	build process from a set of source files, one per rdata type.  For
 *	portability, it's probably best that the building be done by a C
 *	program.  Adding a new rdata type will be a simple matter of adding
 *	a file to a directory and rebuilding the server.  *All* knowledge of
 *	the format of a particular rdata type is in this file.
 *
 * MP:
 *\li	Clients of this module must impose any required synchronization.
 *
 * Reliability:
 *\li	This module deals with low-level byte streams.  Errors in any of
 *	the functions are likely to crash the server or corrupt memory.
 *
 *\li	Rdata is typed, and the caller must know what type of rdata it has.
 *	A caller that gets this wrong could crash the server.
 *
 *\li	The fromstruct() and tostruct() routines use a void * pointer to
 *	represent the structure.  The caller must ensure that it passes a
 *	pointer to the appropriate type, or the server could crash or memory
 *	could be corrupted.
 *
 * Resources:
 *\li	None.
 *
 * Security:
 *
 *\li	*** WARNING ***
 *	dns_rdata_fromwire() deals with raw network data.  An error in
 *	this routine could result in the failure or hijacking of the server.
 *
 * Standards:
 *\li	RFC1035
 *\li	Draft EDNS0 (0)
 *\li	Draft EDNS1 (0)
 *\li	Draft Binary Labels (2)
 *\li	Draft Local Compression (1)
 *\li	Various RFCs for particular types; these will be documented in the
 *	 sources files of the types.
 *
 */

/***
 *** Imports
 ***/

#include <stdbool.h>

#include <isc/lang.h>

#include <dns/types.h>
#include <dns/name.h>
#include <dns/message.h>

ISC_LANG_BEGINDECLS


/***
 *** Types
 ***/

/*%
 ***** An 'rdata' is a handle to a binary region.  The handle has an RR
 ***** class and type, and the data in the binary region is in the format
 ***** of the given class and type.
 *****/
/*%
 * Clients are strongly discouraged from using this type directly, with
 * the exception of the 'link' field which may be used directly for whatever
 * purpose the client desires.
 */
struct dns_rdata {
	unsigned char *			data;
	unsigned int			length;
	dns_rdataclass_t		rdclass;
	dns_rdatatype_t			type;
	unsigned int			flags;
	ISC_LINK(dns_rdata_t)		link;
};

#define DNS_RDATA_INIT { NULL, 0, 0, 0, 0, {(void*)(-1), (void *)(-1)}}

#define DNS_RDATA_CHECKINITIALIZED
#ifdef DNS_RDATA_CHECKINITIALIZED
#define DNS_RDATA_INITIALIZED(rdata) \
	((rdata)->data == NULL && (rdata)->length == 0 && \
	 (rdata)->rdclass == 0 && (rdata)->type == 0 && (rdata)->flags == 0 && \
	 !ISC_LINK_LINKED((rdata), link))
#else
#ifdef ISC_LIST_CHECKINIT
#define DNS_RDATA_INITIALIZED(rdata) \
	(!ISC_LINK_LINKED((rdata), link))
#else
#define DNS_RDATA_INITIALIZED(rdata) true
#endif
#endif

#define DNS_RDATA_UPDATE	0x0001		/*%< update pseudo record. */
#define DNS_RDATA_OFFLINE	0x0002		/*%< RRSIG has a offline key. */

#define DNS_RDATA_VALIDFLAGS(rdata) \
	(((rdata)->flags & ~(DNS_RDATA_UPDATE|DNS_RDATA_OFFLINE)) == 0)

/*
 * The maximum length of a RDATA that can be sent on the wire.
 * Max packet size (65535) less header (12), less name (1), type (2),
 * class (2), ttl(4), length (2).
 *
 * None of the defined types that support name compression can exceed
 * this and all new types are to be sent uncompressed.
 */

#define DNS_RDATA_MAXLENGTH	65512U

/*
 * Flags affecting rdata formatting style.  Flags 0xFFFF0000
 * are used by masterfile-level formatting and defined elsewhere.
 * See additional comments at dns_rdata_tofmttext().
 */

/*% Split the rdata into multiple lines to try to keep it
 within the "width". */
#define DNS_STYLEFLAG_MULTILINE		0x00000001ULL

/*% Output explanatory comments. */
#define DNS_STYLEFLAG_COMMENT		0x00000002ULL
#define DNS_STYLEFLAG_RRCOMMENT		0x00000004ULL

/*% Output KEYDATA in human readable format. */
#define DNS_STYLEFLAG_KEYDATA		0x00000008ULL

/*% Output textual RR type and RDATA in RFC 3597 unknown format */
#define DNS_STYLEFLAG_UNKNOWNFORMAT	0x00000010ULL

#define DNS_RDATA_DOWNCASE		DNS_NAME_DOWNCASE
#define DNS_RDATA_CHECKNAMES		DNS_NAME_CHECKNAMES
#define DNS_RDATA_CHECKNAMESFAIL	DNS_NAME_CHECKNAMESFAIL
#define DNS_RDATA_CHECKREVERSE		DNS_NAME_CHECKREVERSE
#define DNS_RDATA_CHECKMX		DNS_NAME_CHECKMX
#define DNS_RDATA_CHECKMXFAIL		DNS_NAME_CHECKMXFAIL
#define DNS_RDATA_UNKNOWNESCAPE		0x80000000

/***
 *** Initialization
 ***/

void
dns_rdata_init(dns_rdata_t *rdata);
/*%<
 * Make 'rdata' empty.
 *
 * Requires:
 *	'rdata' is a valid rdata (i.e. not NULL, points to a struct dns_rdata)
 */

void
dns_rdata_reset(dns_rdata_t *rdata);
/*%<
 * Make 'rdata' empty.
 *
 * Requires:
 *\li	'rdata' is a previously initialized rdata and is not linked.
 */

void
dns_rdata_clone(const dns_rdata_t *src, dns_rdata_t *target);
/*%<
 * Clone 'target' from 'src'.
 *
 * Requires:
 *\li	'src' to be initialized.
 *\li	'target' to be initialized.
 */

/***
 *** Comparisons
 ***/

int
dns_rdata_compare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2);
/*%<
 * Determine the relative ordering under the DNSSEC order relation of
 * 'rdata1' and 'rdata2'.
 *
 * Requires:
 *
 *\li	'rdata1' is a valid, non-empty rdata
 *
 *\li	'rdata2' is a valid, non-empty rdata
 *
 * Returns:
 *\li	< 0		'rdata1' is less than 'rdata2'
 *\li	0		'rdata1' is equal to 'rdata2'
 *\li	> 0		'rdata1' is greater than 'rdata2'
 */

int
dns_rdata_casecompare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2);
/*%<
 * dns_rdata_casecompare() is similar to dns_rdata_compare() but also
 * compares domain names case insensitively in known rdata types that
 * are treated as opaque data by dns_rdata_compare().
 *
 * Requires:
 *
 *\li	'rdata1' is a valid, non-empty rdata
 *
 *\li	'rdata2' is a valid, non-empty rdata
 *
 * Returns:
 *\li	< 0		'rdata1' is less than 'rdata2'
 *\li	0		'rdata1' is equal to 'rdata2'
 *\li	> 0		'rdata1' is greater than 'rdata2'
 */

/***
 *** Conversions
 ***/

void
dns_rdata_fromregion(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
		     dns_rdatatype_t type, isc_region_t *r);
/*%<
 * Make 'rdata' refer to region 'r'.
 *
 * Requires:
 *
 *\li	The data in 'r' is properly formatted for whatever type it is.
 */

void
dns_rdata_toregion(const dns_rdata_t *rdata, isc_region_t *r);
/*%<
 * Make 'r' refer to 'rdata'.
 */

isc_result_t
dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
		   dns_rdatatype_t type, isc_buffer_t *source,
		   dns_decompress_t *dctx, unsigned int options,
		   isc_buffer_t *target);
/*%<
 * Copy the possibly-compressed rdata at source into the target region.
 *
 * Notes:
 *\li	Name decompression policy is controlled by 'dctx'.
 *
 *	'options'
 *\li	DNS_RDATA_DOWNCASE	downcase domain names when they are copied
 *				into target.
 *
 * Requires:
 *
 *\li	'rdclass' and 'type' are valid.
 *
 *\li	'source' is a valid buffer, and the active region of 'source'
 *	references the rdata to be processed.
 *
 *\li	'target' is a valid buffer.
 *
 *\li	'dctx' is a valid decompression context.
 *
 * Ensures,
 *	if result is success:
 *	\li 	If 'rdata' is not NULL, it is attached to the target.
 *	\li	The conditions dns_name_fromwire() ensures for names hold
 *		for all names in the rdata.
 *	\li	The current location in source is advanced, and the used space
 *		in target is updated.
 *
 * Result:
 *\li	Success
 *\li	Any non-success status from dns_name_fromwire()
 *\li	Various 'Bad Form' class failures depending on class and type
 *\li	Bad Form: Input too short
 *\li	Resource Limit: Not enough space
 */

isc_result_t
dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx,
		 isc_buffer_t *target);
/*%<
 * Convert 'rdata' into wire format, compressing it as specified by the
 * compression context 'cctx', and storing the result in 'target'.
 *
 * Notes:
 *\li	If the compression context allows global compression, then the
 *	global compression table may be updated.
 *
 * Requires:
 *\li	'rdata' is a valid, non-empty rdata
 *
 *\li	target is a valid buffer
 *
 *\li	Any offsets specified in a global compression table are valid
 *	for target.
 *
 * Ensures,
 *	if the result is success:
 *	\li	The used space in target is updated.
 *
 * Returns:
 *\li	Success
 *\li	Any non-success status from dns_name_towire()
 *\li	Resource Limit: Not enough space
 */

isc_result_t
dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
		   dns_rdatatype_t type, isc_lex_t *lexer, dns_name_t *origin,
		   unsigned int options, isc_mem_t *mctx,
		   isc_buffer_t *target, dns_rdatacallbacks_t *callbacks);
/*%<
 * Convert the textual representation of a DNS rdata into uncompressed wire
 * form stored in the target region.  Tokens constituting the text of the rdata
 * are taken from 'lexer'.
 *
 * Notes:
 *\li	Relative domain names in the rdata will have 'origin' appended to them.
 *	A NULL origin implies "origin == dns_rootname".
 *
 *
 *	'options'
 *\li	DNS_RDATA_DOWNCASE	downcase domain names when they are copied
 *				into target.
 *\li	DNS_RDATA_CHECKNAMES 	perform checknames checks.
 *\li	DNS_RDATA_CHECKNAMESFAIL fail if the checknames check fail.  If
 *				not set a warning will be issued.
 *\li	DNS_RDATA_CHECKREVERSE  this should set if the owner name ends
 *				in IP6.ARPA, IP6.INT or IN-ADDR.ARPA.
 *
 * Requires:
 *
 *\li	'rdclass' and 'type' are valid.
 *
 *\li	'lexer' is a valid isc_lex_t.
 *
 *\li	'mctx' is a valid isc_mem_t.
 *
 *\li	'target' is a valid region.
 *
 *\li	'origin' if non NULL it must be absolute.
 *
 *\li	'callbacks' to be NULL or callbacks->warn and callbacks->error be
 *	initialized.
 *
 * Ensures,
 *	if result is success:
 *\li	 	If 'rdata' is not NULL, it is attached to the target.

 *\li		The conditions dns_name_fromtext() ensures for names hold
 *		for all names in the rdata.

 *\li		The used space in target is updated.
 *
 * Result:
 *\li	Success
 *\li	Translated result codes from isc_lex_gettoken
 *\li	Various 'Bad Form' class failures depending on class and type
 *\li	Bad Form: Input too short
 *\li	Resource Limit: Not enough space
 *\li	Resource Limit: Not enough memory
 */

isc_result_t
dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target);
/*%<
 * Convert 'rdata' into text format, storing the result in 'target'.
 * The text will consist of a single line, with fields separated by
 * single spaces.
 *
 * Notes:
 *\li	If 'origin' is not NULL, then any names in the rdata that are
 *	subdomains of 'origin' will be made relative it.
 *
 *\li	XXX Do we *really* want to support 'origin'?  I'm inclined towards "no"
 *	at the moment.
 *
 * Requires:
 *
 *\li	'rdata' is a valid, non-empty rdata
 *
 *\li	'origin' is NULL, or is a valid name
 *
 *\li	'target' is a valid text buffer
 *
 * Ensures,
 *	if the result is success:
 *
 *	\li	The used space in target is updated.
 *
 * Returns:
 *\li	Success
 *\li	Any non-success status from dns_name_totext()
 *\li	Resource Limit: Not enough space
 */

isc_result_t
dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin, unsigned int flags,
		    unsigned int width, unsigned int split_width,
		    const char *linebreak, isc_buffer_t *target);
/*%<
 * Like dns_rdata_totext, but do formatted output suitable for
 * database dumps.  This is intended for use by dns_db_dump();
 * library users are discouraged from calling it directly.
 *
 * If (flags & #DNS_STYLEFLAG_MULTILINE) != 0, attempt to stay
 * within 'width' by breaking the text into multiple lines.
 * The string 'linebreak' is inserted between lines, and parentheses
 * are added when necessary.  Because RRs contain unbreakable elements
 * such as domain names whose length is variable, unpredictable, and
 * potentially large, there is no guarantee that the lines will
 * not exceed 'width' anyway.
 *
 * If (flags & #DNS_STYLEFLAG_MULTILINE) == 0, the rdata is always
 * printed as a single line, and no parentheses are used.
 * The 'width' and 'linebreak' arguments are ignored.
 *
 * If (flags & #DNS_STYLEFLAG_COMMENT) != 0, output explanatory
 * comments next to things like the SOA timer fields.  Some
 * comments (e.g., the SOA ones) are only printed when multiline
 * output is selected.
 *
 * base64 rdata text (e.g., DNSKEY records) will be split into chunks
 * of 'split_width' characters.  If split_width == 0, the text will
 * not be split at all.  If split_width == UINT_MAX (0xffffffff), then
 * it is undefined and falls back to the default value of 'width'
 */

isc_result_t
dns_rdata_fromstruct(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
		     dns_rdatatype_t type, void *source, isc_buffer_t *target);
/*%<
 * Convert the C structure representation of an rdata into uncompressed wire
 * format in 'target'.
 *
 * XXX  Should we have a 'size' parameter as a sanity check on target?
 *
 * Requires:
 *
 *\li	'rdclass' and 'type' are valid.
 *
 *\li	'source' points to a valid C struct for the class and type.
 *
 *\li	'target' is a valid buffer.
 *
 *\li	All structure pointers to memory blocks should be NULL if their
 *	corresponding length values are zero.
 *
 * Ensures,
 *	if result is success:
 *	\li 	If 'rdata' is not NULL, it is attached to the target.
 *
 *	\li	The used space in 'target' is updated.
 *
 * Result:
 *\li	Success
 *\li	Various 'Bad Form' class failures depending on class and type
 *\li	Resource Limit: Not enough space
 */

isc_result_t
dns_rdata_tostruct(const dns_rdata_t *rdata, void *target, isc_mem_t *mctx);
/*%<
 * Convert an rdata into its C structure representation.
 *
 * If 'mctx' is NULL then 'rdata' must persist while 'target' is being used.
 *
 * If 'mctx' is non NULL then memory will be allocated if required.
 *
 * Requires:
 *
 *\li	'rdata' is a valid, non-empty, non-pseudo rdata.
 *
 *\li	'target' to point to a valid pointer for the type and class.
 *
 * Result:
 *\li	Success
 *\li	Resource Limit: Not enough memory
 */

void
dns_rdata_freestruct(void *source);
/*%<
 * Free dynamic memory attached to 'source' (if any).
 *
 * Requires:
 *
 *\li	'source' to point to the structure previously filled in by
 *	dns_rdata_tostruct().
 */

bool
dns_rdatatype_ismeta(dns_rdatatype_t type);
/*%<
 * Return true iff the rdata type 'type' is a meta-type
 * like ANY or AXFR.
 */

bool
dns_rdatatype_issingleton(dns_rdatatype_t type);
/*%<
 * Return true iff the rdata type 'type' is a singleton type,
 * like CNAME or SOA.
 *
 * Requires:
 * \li	'type' is a valid rdata type.
 *
 */

bool
dns_rdataclass_ismeta(dns_rdataclass_t rdclass);
/*%<
 * Return true iff the rdata class 'rdclass' is a meta-class
 * like ANY or NONE.
 */

bool
dns_rdatatype_isdnssec(dns_rdatatype_t type);
/*%<
 * Return true iff 'type' is one of the DNSSEC
 * rdata types that may exist alongside a CNAME record.
 *
 * Requires:
 * \li	'type' is a valid rdata type.
 */

bool
dns_rdatatype_iszonecutauth(dns_rdatatype_t type);
/*%<
 * Return true iff rdata of type 'type' is considered authoritative
 * data (not glue) in the NSEC chain when it occurs in the parent zone
 * at a zone cut.
 *
 * Requires:
 * \li	'type' is a valid rdata type.
 *
 */

bool
dns_rdatatype_isknown(dns_rdatatype_t type);
/*%<
 * Return true iff the rdata type 'type' is known.
 *
 * Requires:
 * \li	'type' is a valid rdata type.
 *
 */

isc_result_t
dns_rdata_additionaldata(dns_rdata_t *rdata, dns_additionaldatafunc_t add,
			 void *arg);
/*%<
 * Call 'add' for each name and type from 'rdata' which is subject to
 * additional section processing.
 *
 * Requires:
 *
 *\li	'rdata' is a valid, non-empty rdata.
 *
 *\li	'add' is a valid dns_additionalfunc_t.
 *
 * Ensures:
 *
 *\li	If successful, then add() will have been called for each name
 *	and type subject to additional section processing.
 *
 *\li	If add() returns something other than #ISC_R_SUCCESS, that result
 *	will be returned as the result of dns_rdata_additionaldata().
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *
 *\li	Many other results are possible if not successful.
 */

isc_result_t
dns_rdata_digest(dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg);
/*%<
 * Send 'rdata' in DNSSEC canonical form to 'digest'.
 *
 * Note:
 *\li	'digest' may be called more than once by dns_rdata_digest().  The
 *	concatenation of all the regions, in the order they were given
 *	to 'digest', will be the DNSSEC canonical form of 'rdata'.
 *
 * Requires:
 *
 *\li	'rdata' is a valid, non-empty rdata.
 *
 *\li	'digest' is a valid dns_digestfunc_t.
 *
 * Ensures:
 *
 *\li	If successful, then all of the rdata's data has been sent, in
 *	DNSSEC canonical form, to 'digest'.
 *
 *\li	If digest() returns something other than ISC_R_SUCCESS, that result
 *	will be returned as the result of dns_rdata_digest().
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *
 *\li	Many other results are possible if not successful.
 */

bool
dns_rdatatype_questiononly(dns_rdatatype_t type);
/*%<
 * Return true iff rdata of type 'type' can only appear in the question
 * section of a properly formatted message.
 *
 * Requires:
 * \li	'type' is a valid rdata type.
 *
 */

bool
dns_rdatatype_notquestion(dns_rdatatype_t type);
/*%<
 * Return true iff rdata of type 'type' can not appear in the question
 * section of a properly formatted message.
 *
 * Requires:
 * \li	'type' is a valid rdata type.
 *
 */

bool
dns_rdatatype_atparent(dns_rdatatype_t type);
/*%<
 * Return true iff rdata of type 'type' should appear at the parent of
 * a zone cut.
 *
 * Requires:
 * \li	'type' is a valid rdata type.
 *
 */

bool
dns_rdatatype_atcname(dns_rdatatype_t type);
/*%<
 * Return true iff rdata of type 'type' can appear beside a cname.
 *
 * Requires:
 * \li	'type' is a valid rdata type.
 *
 */

unsigned int
dns_rdatatype_attributes(dns_rdatatype_t rdtype);
/*%<
 * Return attributes for the given type.
 *
 * Requires:
 *\li	'rdtype' are known.
 *
 * Returns:
 *\li	a bitmask consisting of the following flags.
 */

/*% only one may exist for a name */
#define DNS_RDATATYPEATTR_SINGLETON		0x00000001U
/*% requires no other data be present */
#define DNS_RDATATYPEATTR_EXCLUSIVE		0x00000002U
/*% Is a meta type */
#define DNS_RDATATYPEATTR_META			0x00000004U
/*% Is a DNSSEC type, like RRSIG or NSEC */
#define DNS_RDATATYPEATTR_DNSSEC		0x00000008U
/*% Is a zone cut authority type */
#define DNS_RDATATYPEATTR_ZONECUTAUTH		0x00000010U
/*% Is reserved (unusable) */
#define DNS_RDATATYPEATTR_RESERVED		0x00000020U
/*% Is an unknown type */
#define DNS_RDATATYPEATTR_UNKNOWN		0x00000040U
/*% Is META, and can only be in a question section */
#define DNS_RDATATYPEATTR_QUESTIONONLY		0x00000080U
/*% Is META, and can NOT be in a question section */
#define DNS_RDATATYPEATTR_NOTQUESTION		0x00000100U
/*% Is present at zone cuts in the parent, not the child */
#define DNS_RDATATYPEATTR_ATPARENT		0x00000200U
/*% Can exist along side a CNAME */
#define DNS_RDATATYPEATTR_ATCNAME		0x00000400U

dns_rdatatype_t
dns_rdata_covers(dns_rdata_t *rdata);
/*%<
 * Return the rdatatype that this type covers.
 *
 * Requires:
 *\li	'rdata' is a valid, non-empty rdata.
 *
 *\li	'rdata' is a type that covers other rdata types.
 *
 * Returns:
 *\li	The type covered.
 */

bool
dns_rdata_checkowner(dns_name_t* name, dns_rdataclass_t rdclass,
		     dns_rdatatype_t type, bool wildcard);
/*
 * Returns whether this is a valid ownername for this <type,class>.
 * If wildcard is true allow the first label to be a wildcard if
 * appropriate.
 *
 * Requires:
 *	'name' is a valid name.
 */

bool
dns_rdata_checknames(dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad);
/*
 * Returns whether 'rdata' contains valid domain names.  The checks are
 * sensitive to the owner name.
 *
 * If 'bad' is non-NULL and a domain name fails the check the
 * the offending name will be return in 'bad' by cloning from
 * the 'rdata' contents.
 *
 * Requires:
 *	'rdata' to be valid.
 *	'owner' to be valid.
 *	'bad'	to be NULL or valid.
 */

void
dns_rdata_exists(dns_rdata_t *rdata, dns_rdatatype_t type);

void
dns_rdata_notexist(dns_rdata_t *rdata, dns_rdatatype_t type);

void
dns_rdata_deleterrset(dns_rdata_t *rdata, dns_rdatatype_t type);

void
dns_rdata_makedelete(dns_rdata_t *rdata);

const char *
dns_rdata_updateop(dns_rdata_t *rdata, dns_section_t section);

ISC_LANG_ENDDECLS

#endif /* DNS_RDATA_H */
byaddr.h000064400000007642150415243050006172 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_BYADDR_H
#define DNS_BYADDR_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/byaddr.h
 * \brief
 * The byaddr module provides reverse lookup services for IPv4 and IPv6
 * addresses.
 *
 * MP:
 *\li	The module ensures appropriate synchronization of data structures it
 *	creates and manipulates.
 *
 * Reliability:
 *\li	No anticipated impact.
 *
 * Resources:
 *\li	TBS
 *
 * Security:
 *\li	No anticipated impact.
 *
 * Standards:
 *\li	RFCs:	1034, 1035, 2181, TBS
 *\li	Drafts:	TBS
 */

#include <stdbool.h>

#include <isc/lang.h>
#include <isc/event.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

/*%
 * A 'dns_byaddrevent_t' is returned when a byaddr completes.
 * The sender field will be set to the byaddr that completed.  If 'result'
 * is ISC_R_SUCCESS, then 'names' will contain a list of names associated
 * with the address.  The recipient of the event must not change the list
 * and must not refer to any of the name data after the event is freed.
 */
typedef struct dns_byaddrevent {
	ISC_EVENT_COMMON(struct dns_byaddrevent);
	isc_result_t			result;
	dns_namelist_t			names;
} dns_byaddrevent_t;

/*
 * This option is deprecated since we now only consider nibbles.
#define DNS_BYADDROPT_IPV6NIBBLE	0x0001
 */
/*% Note DNS_BYADDROPT_IPV6NIBBLE is now deprecated. */
#define DNS_BYADDROPT_IPV6INT		0x0002

isc_result_t
dns_byaddr_create(isc_mem_t *mctx, isc_netaddr_t *address, dns_view_t *view,
		  unsigned int options, isc_task_t *task,
		  isc_taskaction_t action, void *arg, dns_byaddr_t **byaddrp);
/*%<
 * Find the domain name of 'address'.
 *
 * Notes:
 *
 *\li	There is a reverse lookup format for IPv6 addresses, 'nibble'
 *
 *\li	The 'nibble' format for that address is
 *
 * \code
 *   1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa.
 * \endcode
 *
 *\li	#DNS_BYADDROPT_IPV6INT can be used to get nibble lookups under ip6.int.
 *
 * Requires:
 *
 *\li	'mctx' is a valid mctx.
 *
 *\li	'address' is a valid IPv4 or IPv6 address.
 *
 *\li	'view' is a valid view which has a resolver.
 *
 *\li	'task' is a valid task.
 *
 *\li	byaddrp != NULL && *byaddrp == NULL
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *
 *\li	Any resolver-related error (e.g. #ISC_R_SHUTTINGDOWN) may also be
 *	returned.
 */

void
dns_byaddr_cancel(dns_byaddr_t *byaddr);
/*%<
 * Cancel 'byaddr'.
 *
 * Notes:
 *
 *\li	If 'byaddr' has not completed, post its #DNS_EVENT_BYADDRDONE
 *	event with a result code of #ISC_R_CANCELED.
 *
 * Requires:
 *
 *\li	'byaddr' is a valid byaddr.
 */

void
dns_byaddr_destroy(dns_byaddr_t **byaddrp);
/*%<
 * Destroy 'byaddr'.
 *
 * Requires:
 *
 *\li	'*byaddrp' is a valid byaddr.
 *
 *\li	The caller has received the #DNS_EVENT_BYADDRDONE event (either because
 *	the byaddr completed or because dns_byaddr_cancel() was called).
 *
 * Ensures:
 *
 *\li	*byaddrp == NULL.
 */

isc_result_t
dns_byaddr_createptrname(isc_netaddr_t *address, bool nibble,
			 dns_name_t *name);

isc_result_t
dns_byaddr_createptrname2(isc_netaddr_t *address, unsigned int options,
			  dns_name_t *name);
/*%<
 * Creates a name that would be used in a PTR query for this address.  The
 * nibble flag indicates that the 'nibble' format is to be used if an IPv6
 * address is provided, instead of the 'bitstring' format.  Since we dropped
 * the support of the bitstring labels, it is expected that the flag is always
 * set.  'options' are the same as for dns_byaddr_create().
 *
 * Requires:
 *
 * \li	'address' is a valid address.
 * \li	'name' is a valid name with a dedicated buffer.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_BYADDR_H */
nsec.h000064400000005560150415243050005652 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_NSEC_H
#define DNS_NSEC_H 1

/*! \file dns/nsec.h */

#include <stdbool.h>

#include <isc/lang.h>

#include <dns/types.h>
#include <dns/name.h>

#define DNS_NSEC_BUFFERSIZE (DNS_NAME_MAXWIRE + 8192 + 512)

ISC_LANG_BEGINDECLS

isc_result_t
dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version,
		    dns_dbnode_t *node, dns_name_t *target,
		    unsigned char *buffer, dns_rdata_t *rdata);
/*%<
 * Build the rdata of a NSEC record.
 *
 * Requires:
 *\li	buffer	Points to a temporary buffer of at least
 * 		DNS_NSEC_BUFFERSIZE bytes.
 *\li	rdata	Points to an initialized dns_rdata_t.
 *
 * Ensures:
 *  \li    *rdata	Contains a valid NSEC rdata.  The 'data' member refers
 *		to 'buffer'.
 */

isc_result_t
dns_nsec_build(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node,
	       dns_name_t *target, dns_ttl_t ttl);
/*%<
 * Build a NSEC record and add it to a database.
 */

bool
dns_nsec_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type);
/*%<
 * Determine if a type is marked as present in an NSEC record.
 *
 * Requires:
 *\li	'nsec' points to a valid rdataset of type NSEC
 */

isc_result_t
dns_nsec_nseconly(dns_db_t *db, dns_dbversion_t *version,
		  bool *answer);
/*
 * Report whether the DNSKEY RRset has a NSEC only algorithm.  Unknown
 * algorithms are assumed to support NSEC3.  If DNSKEY is not found,
 * *answer is set to false, and ISC_R_NOTFOUND is returned.
 *
 * Requires:
 * 	'answer' to be non NULL.
 */

unsigned int
dns_nsec_compressbitmap(unsigned char *map, const unsigned char *raw,
			unsigned int max_type);
/*%<
 * Convert a raw bitmap into a compressed windowed bit map.  'map' and 'raw'
 * may overlap.
 *
 * Returns the length of the compressed windowed bit map.
 */

void
dns_nsec_setbit(unsigned char *array, unsigned int type, unsigned int bit);
/*%<
 * Set type bit in raw 'array' to 'bit'.
 */

bool
dns_nsec_isset(const unsigned char *array, unsigned int type);
/*%<
 * Test if the corresponding 'type' bit is set in 'array'.
 */

isc_result_t
dns_nsec_noexistnodata(dns_rdatatype_t type, dns_name_t *name,
		       dns_name_t *nsecname, dns_rdataset_t *nsecset,
		       bool *exists, bool *data,
		       dns_name_t *wild, dns_nseclog_t log, void *arg);
/*%
 * Return ISC_R_SUCCESS if we can determine that the name doesn't exist
 * or we can determine whether there is data or not at the name.
 * If the name does not exist return the wildcard name.
 *
 * Return ISC_R_IGNORE when the NSEC is not the appropriate one.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_NSEC_H */
result.h000064400000022104150415243050006231 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_RESULT_H
#define DNS_RESULT_H 1

/*! \file dns/result.h */

#include <isc/lang.h>
#include <isc/resultclass.h>

#include <dns/types.h>

/*
 * Nothing in this file truly depends on <isc/result.h>, but the
 * DNS result codes are considered to be publicly derived from
 * the ISC result codes, so including this file buys you the ISC_R_
 * namespace too.
 */
#include <isc/result.h>		/* Contractual promise. */

/*
 * DNS library result codes
 */
#define DNS_R_LABELTOOLONG		(ISC_RESULTCLASS_DNS + 0)
#define DNS_R_BADESCAPE			(ISC_RESULTCLASS_DNS + 1)
/*
 * Since we dropped the support of bitstring labels, deprecate the related
 * result codes too.

#define DNS_R_BADBITSTRING		(ISC_RESULTCLASS_DNS + 2)
#define DNS_R_BITSTRINGTOOLONG		(ISC_RESULTCLASS_DNS + 3)
*/
#define DNS_R_EMPTYLABEL		(ISC_RESULTCLASS_DNS + 4)
#define DNS_R_BADDOTTEDQUAD		(ISC_RESULTCLASS_DNS + 5)
#define DNS_R_INVALIDNS			(ISC_RESULTCLASS_DNS + 6)
#define DNS_R_UNKNOWN			(ISC_RESULTCLASS_DNS + 7)
#define DNS_R_BADLABELTYPE		(ISC_RESULTCLASS_DNS + 8)
#define DNS_R_BADPOINTER		(ISC_RESULTCLASS_DNS + 9)
#define DNS_R_TOOMANYHOPS		(ISC_RESULTCLASS_DNS + 10)
#define DNS_R_DISALLOWED		(ISC_RESULTCLASS_DNS + 11)
#define DNS_R_EXTRATOKEN		(ISC_RESULTCLASS_DNS + 12)
#define DNS_R_EXTRADATA			(ISC_RESULTCLASS_DNS + 13)
#define DNS_R_TEXTTOOLONG		(ISC_RESULTCLASS_DNS + 14)
#define DNS_R_NOTZONETOP		(ISC_RESULTCLASS_DNS + 15)
#define DNS_R_SYNTAX			(ISC_RESULTCLASS_DNS + 16)
#define DNS_R_BADCKSUM			(ISC_RESULTCLASS_DNS + 17)
#define DNS_R_BADAAAA			(ISC_RESULTCLASS_DNS + 18)
#define DNS_R_NOOWNER			(ISC_RESULTCLASS_DNS + 19)
#define DNS_R_NOTTL			(ISC_RESULTCLASS_DNS + 20)
#define DNS_R_BADCLASS			(ISC_RESULTCLASS_DNS + 21)
#define DNS_R_NAMETOOLONG		(ISC_RESULTCLASS_DNS + 22)
#define DNS_R_PARTIALMATCH		(ISC_RESULTCLASS_DNS + 23)
#define DNS_R_NEWORIGIN			(ISC_RESULTCLASS_DNS + 24)
#define DNS_R_UNCHANGED			(ISC_RESULTCLASS_DNS + 25)
#define DNS_R_BADTTL			(ISC_RESULTCLASS_DNS + 26)
#define DNS_R_NOREDATA			(ISC_RESULTCLASS_DNS + 27)
#define DNS_R_CONTINUE			(ISC_RESULTCLASS_DNS + 28)
#define DNS_R_DELEGATION		(ISC_RESULTCLASS_DNS + 29)
#define DNS_R_GLUE			(ISC_RESULTCLASS_DNS + 30)
#define DNS_R_DNAME			(ISC_RESULTCLASS_DNS + 31)
#define DNS_R_CNAME			(ISC_RESULTCLASS_DNS + 32)
#define DNS_R_BADDB			(ISC_RESULTCLASS_DNS + 33)
#define DNS_R_ZONECUT			(ISC_RESULTCLASS_DNS + 34)
#define DNS_R_BADZONE			(ISC_RESULTCLASS_DNS + 35)
#define DNS_R_MOREDATA			(ISC_RESULTCLASS_DNS + 36)
#define DNS_R_UPTODATE			(ISC_RESULTCLASS_DNS + 37)
#define DNS_R_TSIGVERIFYFAILURE		(ISC_RESULTCLASS_DNS + 38)
#define DNS_R_TSIGERRORSET		(ISC_RESULTCLASS_DNS + 39)
#define DNS_R_SIGINVALID		(ISC_RESULTCLASS_DNS + 40)
#define DNS_R_SIGEXPIRED		(ISC_RESULTCLASS_DNS + 41)
#define DNS_R_SIGFUTURE			(ISC_RESULTCLASS_DNS + 42)
#define DNS_R_KEYUNAUTHORIZED		(ISC_RESULTCLASS_DNS + 43)
#define DNS_R_INVALIDTIME		(ISC_RESULTCLASS_DNS + 44)
#define DNS_R_EXPECTEDTSIG		(ISC_RESULTCLASS_DNS + 45)
#define DNS_R_UNEXPECTEDTSIG		(ISC_RESULTCLASS_DNS + 46)
#define DNS_R_INVALIDTKEY		(ISC_RESULTCLASS_DNS + 47)
#define DNS_R_HINT			(ISC_RESULTCLASS_DNS + 48)
#define DNS_R_DROP			(ISC_RESULTCLASS_DNS + 49)
#define DNS_R_NOTLOADED			(ISC_RESULTCLASS_DNS + 50)
#define DNS_R_NCACHENXDOMAIN		(ISC_RESULTCLASS_DNS + 51)
#define DNS_R_NCACHENXRRSET		(ISC_RESULTCLASS_DNS + 52)
#define DNS_R_WAIT			(ISC_RESULTCLASS_DNS + 53)
#define DNS_R_NOTVERIFIEDYET		(ISC_RESULTCLASS_DNS + 54)
#define DNS_R_NOIDENTITY		(ISC_RESULTCLASS_DNS + 55)
#define DNS_R_NOJOURNAL			(ISC_RESULTCLASS_DNS + 56)
#define DNS_R_ALIAS			(ISC_RESULTCLASS_DNS + 57)
#define DNS_R_USETCP			(ISC_RESULTCLASS_DNS + 58)
#define DNS_R_NOVALIDSIG		(ISC_RESULTCLASS_DNS + 59)
#define DNS_R_NOVALIDNSEC		(ISC_RESULTCLASS_DNS + 60)
#define DNS_R_NOTINSECURE		(ISC_RESULTCLASS_DNS + 61)
#define DNS_R_UNKNOWNSERVICE		(ISC_RESULTCLASS_DNS + 62)
#define DNS_R_RECOVERABLE		(ISC_RESULTCLASS_DNS + 63)
#define DNS_R_UNKNOWNOPT		(ISC_RESULTCLASS_DNS + 64)
#define DNS_R_UNEXPECTEDID		(ISC_RESULTCLASS_DNS + 65)
#define DNS_R_SEENINCLUDE		(ISC_RESULTCLASS_DNS + 66)
#define DNS_R_NOTEXACT			(ISC_RESULTCLASS_DNS + 67)
#define DNS_R_BLACKHOLED		(ISC_RESULTCLASS_DNS + 68)
#define DNS_R_BADALG			(ISC_RESULTCLASS_DNS + 69)
#define DNS_R_METATYPE			(ISC_RESULTCLASS_DNS + 70)
#define DNS_R_CNAMEANDOTHER		(ISC_RESULTCLASS_DNS + 71)
#define DNS_R_SINGLETON			(ISC_RESULTCLASS_DNS + 72)
#define DNS_R_HINTNXRRSET		(ISC_RESULTCLASS_DNS + 73)
#define DNS_R_NOMASTERFILE		(ISC_RESULTCLASS_DNS + 74)
#define DNS_R_UNKNOWNPROTO		(ISC_RESULTCLASS_DNS + 75)
#define DNS_R_CLOCKSKEW			(ISC_RESULTCLASS_DNS + 76)
#define DNS_R_BADIXFR			(ISC_RESULTCLASS_DNS + 77)
#define DNS_R_NOTAUTHORITATIVE		(ISC_RESULTCLASS_DNS + 78)
#define DNS_R_NOVALIDKEY		(ISC_RESULTCLASS_DNS + 79)
#define DNS_R_OBSOLETE			(ISC_RESULTCLASS_DNS + 80)
#define DNS_R_FROZEN			(ISC_RESULTCLASS_DNS + 81)
#define DNS_R_UNKNOWNFLAG		(ISC_RESULTCLASS_DNS + 82)
#define DNS_R_EXPECTEDRESPONSE		(ISC_RESULTCLASS_DNS + 83)
#define DNS_R_NOVALIDDS			(ISC_RESULTCLASS_DNS + 84)
#define DNS_R_NSISADDRESS		(ISC_RESULTCLASS_DNS + 85)
#define DNS_R_REMOTEFORMERR		(ISC_RESULTCLASS_DNS + 86)
#define DNS_R_TRUNCATEDTCP		(ISC_RESULTCLASS_DNS + 87)
#define DNS_R_LAME			(ISC_RESULTCLASS_DNS + 88)
#define DNS_R_UNEXPECTEDRCODE		(ISC_RESULTCLASS_DNS + 89)
#define DNS_R_UNEXPECTEDOPCODE		(ISC_RESULTCLASS_DNS + 90)
#define DNS_R_CHASEDSSERVERS		(ISC_RESULTCLASS_DNS + 91)
#define DNS_R_EMPTYNAME			(ISC_RESULTCLASS_DNS + 92)
#define DNS_R_EMPTYWILD			(ISC_RESULTCLASS_DNS + 93)
#define DNS_R_BADBITMAP			(ISC_RESULTCLASS_DNS + 94)
#define DNS_R_FROMWILDCARD		(ISC_RESULTCLASS_DNS + 95)
#define DNS_R_BADOWNERNAME		(ISC_RESULTCLASS_DNS + 96)
#define DNS_R_BADNAME			(ISC_RESULTCLASS_DNS + 97)
#define DNS_R_DYNAMIC			(ISC_RESULTCLASS_DNS + 98)
#define DNS_R_UNKNOWNCOMMAND		(ISC_RESULTCLASS_DNS + 99)
#define DNS_R_MUSTBESECURE		(ISC_RESULTCLASS_DNS + 100)
#define DNS_R_COVERINGNSEC		(ISC_RESULTCLASS_DNS + 101)
#define DNS_R_MXISADDRESS		(ISC_RESULTCLASS_DNS + 102)
#define DNS_R_DUPLICATE			(ISC_RESULTCLASS_DNS + 103)
#define DNS_R_INVALIDNSEC3		(ISC_RESULTCLASS_DNS + 104)
#define DNS_R_NOTMASTER 		(ISC_RESULTCLASS_DNS + 105)
#define DNS_R_BROKENCHAIN		(ISC_RESULTCLASS_DNS + 106)
#define DNS_R_EXPIRED			(ISC_RESULTCLASS_DNS + 107)
#define DNS_R_NOTDYNAMIC 		(ISC_RESULTCLASS_DNS + 108)
#define DNS_R_BADEUI	 		(ISC_RESULTCLASS_DNS + 109)
#define DNS_R_NTACOVERED		(ISC_RESULTCLASS_DNS + 110)
#define DNS_R_BADCDS			(ISC_RESULTCLASS_DNS + 111)
#define DNS_R_BADCDNSKEY		(ISC_RESULTCLASS_DNS + 112)
#define DNS_R_OPTERR			(ISC_RESULTCLASS_DNS + 113)
#define DNS_R_BADDNSTAP			(ISC_RESULTCLASS_DNS + 114)
#define DNS_R_BADTSIG			(ISC_RESULTCLASS_DNS + 115)
#define DNS_R_BADSIG0			(ISC_RESULTCLASS_DNS + 116)
#define DNS_R_TOOMANYRECORDS		(ISC_RESULTCLASS_DNS + 117)
#define DNS_R_VERIFYFAILURE		(ISC_RESULTCLASS_DNS + 118)
#define DNS_R_ATZONETOP			(ISC_RESULTCLASS_DNS + 119)
#define DNS_R_NOKEYMATCH		(ISC_RESULTCLASS_DNS + 120)
#define DNS_R_TOOMANYKEYS		(ISC_RESULTCLASS_DNS + 121)
#define DNS_R_KEYNOTACTIVE		(ISC_RESULTCLASS_DNS + 122)
#define DNS_R_NSEC3ITERRANGE		(ISC_RESULTCLASS_DNS + 123)
#define DNS_R_NSEC3SALTRANGE		(ISC_RESULTCLASS_DNS + 124)
#define DNS_R_NSEC3BADALG		(ISC_RESULTCLASS_DNS + 125)
#define DNS_R_NSEC3RESALT		(ISC_RESULTCLASS_DNS + 126)

#define DNS_R_NRESULTS			127	/*%< Number of results */


/*
 * DNS wire format rcodes.
 *
 * By making these their own class we can easily convert them into the
 * wire-format rcode value simply by masking off the resultclass.
 */
#define DNS_R_NOERROR			(ISC_RESULTCLASS_DNSRCODE + 0)
#define DNS_R_FORMERR			(ISC_RESULTCLASS_DNSRCODE + 1)
#define DNS_R_SERVFAIL			(ISC_RESULTCLASS_DNSRCODE + 2)
#define DNS_R_NXDOMAIN			(ISC_RESULTCLASS_DNSRCODE + 3)
#define DNS_R_NOTIMP			(ISC_RESULTCLASS_DNSRCODE + 4)
#define DNS_R_REFUSED			(ISC_RESULTCLASS_DNSRCODE + 5)
#define DNS_R_YXDOMAIN			(ISC_RESULTCLASS_DNSRCODE + 6)
#define DNS_R_YXRRSET			(ISC_RESULTCLASS_DNSRCODE + 7)
#define DNS_R_NXRRSET			(ISC_RESULTCLASS_DNSRCODE + 8)
#define DNS_R_NOTAUTH			(ISC_RESULTCLASS_DNSRCODE + 9)
#define DNS_R_NOTZONE			(ISC_RESULTCLASS_DNSRCODE + 10)
#define DNS_R_RCODE11			(ISC_RESULTCLASS_DNSRCODE + 11)
#define DNS_R_RCODE12			(ISC_RESULTCLASS_DNSRCODE + 12)
#define DNS_R_RCODE13			(ISC_RESULTCLASS_DNSRCODE + 13)
#define DNS_R_RCODE14			(ISC_RESULTCLASS_DNSRCODE + 14)
#define DNS_R_RCODE15			(ISC_RESULTCLASS_DNSRCODE + 15)
#define DNS_R_BADVERS			(ISC_RESULTCLASS_DNSRCODE + 16)

#define DNS_R_NRCODERESULTS		17	/*%< Number of rcode results */

#define DNS_RESULT_ISRCODE(result) \
	(ISC_RESULTCLASS_INCLASS(ISC_RESULTCLASS_DNSRCODE, (result)))

ISC_LANG_BEGINDECLS

const char *
dns_result_totext(isc_result_t);

void
dns_result_register(void);

dns_rcode_t
dns_result_torcode(isc_result_t result);

ISC_LANG_ENDDECLS

#endif /* DNS_RESULT_H */
rcode.h000064400000004661150415243050006017 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_RCODE_H
#define DNS_RCODE_H 1

/*! \file dns/rcode.h */

#include <isc/lang.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

isc_result_t dns_rcode_fromtext(dns_rcode_t *rcodep, isc_textregion_t *source);
/*%<
 * Convert the text 'source' refers to into a DNS error value.
 *
 * Requires:
 *\li	'rcodep' is a valid pointer.
 *
 *\li	'source' is a valid text region.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS			on success
 *\li	#DNS_R_UNKNOWN			type is unknown
 */

isc_result_t dns_rcode_totext(dns_rcode_t rcode, isc_buffer_t *target);
/*%<
 * Put a textual representation of error 'rcode' into 'target'.
 *
 * Requires:
 *\li	'rcode' is a valid rcode.
 *
 *\li	'target' is a valid text buffer.
 *
 * Ensures:
 *\li	If the result is success:
 *		The used space in 'target' is updated.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS			on success
 *\li	#ISC_R_NOSPACE			target buffer is too small
 */

isc_result_t dns_tsigrcode_fromtext(dns_rcode_t *rcodep,
				    isc_textregion_t *source);
/*%<
 * Convert the text 'source' refers to into a TSIG/TKEY error value.
 *
 * Requires:
 *\li	'rcodep' is a valid pointer.
 *
 *\li	'source' is a valid text region.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS			on success
 *\li	#DNS_R_UNKNOWN			type is unknown
 */

isc_result_t dns_tsigrcode_totext(dns_rcode_t rcode, isc_buffer_t *target);
/*%<
 * Put a textual representation of TSIG/TKEY error 'rcode' into 'target'.
 *
 * Requires:
 *\li	'rcode' is a valid TSIG/TKEY error code.
 *
 *\li	'target' is a valid text buffer.
 *
 * Ensures:
 *\li	If the result is success:
 *		The used space in 'target' is updated.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS			on success
 *\li	#ISC_R_NOSPACE			target buffer is too small
 */

isc_result_t
dns_hashalg_fromtext(unsigned char *hashalg, isc_textregion_t *source);
/*%<
 * Convert the text 'source' refers to into a has algorithm value.
 *
 * Requires:
 *\li	'hashalg' is a valid pointer.
 *
 *\li	'source' is a valid text region.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS			on success
 *\li	#DNS_R_UNKNOWN			type is unknown
 */

ISC_LANG_ENDDECLS

#endif /* DNS_RCODE_H */
journal.h000064400000020043150415243050006365 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_JOURNAL_H
#define DNS_JOURNAL_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/journal.h
 * \brief
 * Database journaling.
 */

/***
 *** Imports
 ***/

#include <inttypes.h>
#include <stdbool.h>

#include <isc/lang.h>
#include <isc/magic.h>

#include <dns/name.h>
#include <dns/diff.h>
#include <dns/rdata.h>
#include <dns/types.h>

/***
 *** Defines.
 ***/
#define DNS_JOURNALOPT_RESIGN	0x00000001

#define DNS_JOURNAL_READ	0x00000000	/* false */
#define DNS_JOURNAL_CREATE	0x00000001	/* true */
#define DNS_JOURNAL_WRITE	0x00000002

/***
 *** Types
 ***/

/*%
 * A dns_journal_t represents an open journal file.  This is an opaque type.
 *
 * A particular dns_journal_t object may be opened for writing, in which case
 * it can be used for writing transactions to a journal file, or it can be
 * opened for reading, in which case it can be used for reading transactions
 * from (iterating over) a journal file.  A single dns_journal_t object may
 * not be used for both purposes.
 */
typedef struct dns_journal dns_journal_t;


/***
 *** Functions
 ***/

ISC_LANG_BEGINDECLS

/**************************************************************************/

isc_result_t
dns_db_createsoatuple(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx,
		      dns_diffop_t op, dns_difftuple_t **tp);
/*!< brief
 * Create a diff tuple for the current database SOA.
 * XXX this probably belongs somewhere else.
 */


/*@{*/
#define DNS_SERIAL_GT(a, b) ((int)(((a) - (b)) & 0xFFFFFFFF) > 0)
#define DNS_SERIAL_GE(a, b) ((int)(((a) - (b)) & 0xFFFFFFFF) >= 0)
/*!< brief
 * Compare SOA serial numbers.  DNS_SERIAL_GT(a, b) returns true iff
 * a is "greater than" b where "greater than" is as defined in RFC1982.
 * DNS_SERIAL_GE(a, b) returns true iff a is "greater than or equal to" b.
 */
/*@}*/

/**************************************************************************/
/*
 * Journal object creation and destruction.
 */

isc_result_t
dns_journal_open(isc_mem_t *mctx, const char *filename, unsigned int mode,
		 dns_journal_t **journalp);
/*%<
 * Open the journal file 'filename' and create a dns_journal_t object for it.
 *
 * DNS_JOURNAL_CREATE open the journal for reading and writing and create
 * the journal if it does not exist.
 * DNS_JOURNAL_WRITE open the journal for reading and writing.
 * DNS_JOURNAL_READ open the journal for reading only.
 */

void
dns_journal_destroy(dns_journal_t **journalp);
/*%<
 * Destroy a dns_journal_t, closing any open files and freeing its memory.
 */

/**************************************************************************/
/*
 * Writing transactions to journals.
 */

isc_result_t
dns_journal_begin_transaction(dns_journal_t *j);
/*%<
 * Prepare to write a new transaction to the open journal file 'j'.
 *
 * Requires:
 *     \li 'j' is open for writing.
 */

isc_result_t
dns_journal_writediff(dns_journal_t *j, dns_diff_t *diff);
/*%<
 * Write 'diff' to the current transaction of journal file 'j'.
 *
 * Requires:
 * \li     'j' is open for writing and dns_journal_begin_transaction()
 * 	has been called.
 *
 *\li 	'diff' is a full or partial, correctly ordered IXFR
 *      difference sequence.
 */

isc_result_t
dns_journal_commit(dns_journal_t *j);
/*%<
 * Commit the current transaction of journal file 'j'.
 *
 * Requires:
 * \li     'j' is open for writing and dns_journal_begin_transaction()
 * 	has been called.
 *
 *   \li   dns_journal_writediff() has been called one or more times
 * 	to form a complete, correctly ordered IXFR difference
 *      sequence.
 */

isc_result_t
dns_journal_write_transaction(dns_journal_t *j, dns_diff_t *diff);
/*%
 * Write a complete transaction at once to a journal file,
 * sorting it if necessary, and commit it.  Equivalent to calling
 * dns_diff_sort(), dns_journal_begin_transaction(),
 * dns_journal_writediff(), and dns_journal_commit().
 *
 * Requires:
 *\li      'j' is open for writing.
 *
 * \li	'diff' contains exactly one SOA deletion, one SOA addition
 *       with a greater serial number, and possibly other changes,
 *       in arbitrary order.
 */

/**************************************************************************/
/*
 * Reading transactions from journals.
 */

uint32_t
dns_journal_first_serial(dns_journal_t *j);
uint32_t
dns_journal_last_serial(dns_journal_t *j);
/*%<
 * Get the first and last addressable serial number in the journal.
 */

isc_result_t
dns_journal_iter_init(dns_journal_t *j,
		      uint32_t begin_serial, uint32_t end_serial);
/*%<
 * Prepare to iterate over the transactions that will bring the database
 * from SOA serial number 'begin_serial' to 'end_serial'.
 *
 * Returns:
 *\li	ISC_R_SUCCESS
 *\li	ISC_R_RANGE	begin_serial is outside the addressable range.
 *\li	ISC_R_NOTFOUND	begin_serial is within the range of addressable
 *			serial numbers covered by the journal, but
 *			this particular serial number does not exist.
 */

/*@{*/
isc_result_t
dns_journal_first_rr(dns_journal_t *j);
isc_result_t
dns_journal_next_rr(dns_journal_t *j);
/*%<
 * Position the iterator at the first/next RR in a journal
 * transaction sequence established using dns_journal_iter_init().
 *
 * Requires:
 *    \li  dns_journal_iter_init() has been called.
 *
 */
/*@}*/

void
dns_journal_current_rr(dns_journal_t *j, dns_name_t **name, uint32_t *ttl,
		       dns_rdata_t **rdata);
/*%<
 * Get the name, ttl, and rdata of the current journal RR.
 *
 * Requires:
 * \li     The last call to dns_journal_first_rr() or dns_journal_next_rr()
 *      returned ISC_R_SUCCESS.
 */

/**************************************************************************/
/*
 * Database roll-forward.
 */

isc_result_t
dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db, unsigned int options,
			const char *filename);
/*%<
 * Roll forward (play back) the journal file "filename" into the
 * database "db".  This should be called when the server starts
 * after a shutdown or crash.
 *
 * Requires:
 *\li   'mctx' is a valid memory context.
 *\li	'db' is a valid database which does not have a version
 *           open for writing.
 *\li   'filename' is the name of the journal file belonging to 'db'.
 *
 * Returns:
 *\li	DNS_R_NOJOURNAL when journal does not exist.
 *\li	ISC_R_NOTFOUND when current serial in not in journal.
 *\li	ISC_R_RANGE when current serial in not in journals range.
 *\li	ISC_R_SUCCESS journal has been applied successfully to database.
 *	others
 */

isc_result_t
dns_journal_print(isc_mem_t *mctx, const char *filename, FILE *file);
/* For debugging not general use */

isc_result_t
dns_db_diff(isc_mem_t *mctx,
	    dns_db_t *dba, dns_dbversion_t *dbvera,
	    dns_db_t *dbb, dns_dbversion_t *dbverb,
	    const char *journal_filename);

isc_result_t
dns_db_diffx(dns_diff_t *diff, dns_db_t *dba, dns_dbversion_t *dbvera,
	     dns_db_t *dbb, dns_dbversion_t *dbverb,
	     const char *journal_filename);
/*%<
 * Compare the databases 'dba' and 'dbb' and generate a diff/journal
 * entry containing the changes to make 'dba' from 'dbb' (note
 * the order).  This journal entry will consist of a single,
 * possibly very large transaction.  Append the journal
 * entry to the journal file specified by 'journal_filename' if
 * non-NULL.
 */

isc_result_t
dns_journal_compact(isc_mem_t *mctx, char *filename, uint32_t serial,
		    uint32_t target_size);
/*%<
 * Attempt to compact the journal if it is greater that 'target_size'.
 * Changes from 'serial' onwards will be preserved.  If the journal
 * exists and is non-empty 'serial' must exist in the journal.
 */

bool
dns_journal_get_sourceserial(dns_journal_t *j, uint32_t *sourceserial);
void
dns_journal_set_sourceserial(dns_journal_t *j, uint32_t sourceserial);
/*%<
 * Get and set source serial.
 *
 * Returns:
 *	 true if sourceserial has previously been set.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_JOURNAL_H */
tsec.h000064400000005605150415243050005660 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_TSEC_H
#define DNS_TSEC_H 1

/*****
 ***** Module Info
 *****/

/*! \file
 *
 * \brief
 * The TSEC (Transaction Security) module is an abstraction layer for managing
 * DNS transaction mechanisms such as TSIG or SIG(0).  A TSEC structure is a
 * mechanism-independent object containing key information specific to the
 * mechanism, and is expected to be used as an argument to other modules
 * that use transaction security in a mechanism-independent manner.
 *
 * MP:
 *\li	A TSEC structure is expected to be thread-specific.  No inter-thread
 *	synchronization is ensured in multiple access to a single TSEC
 *	structure.
 *
 * Resources:
 *\li	TBS
 *
 * Security:
 *\li	This module does not handle any low-level data directly, and so no
 *	security issue specific to this module is anticipated.
 */

#include <dns/types.h>

#include <dst/dst.h>

ISC_LANG_BEGINDECLS

/***
 *** Types
 ***/

/*%
 * Transaction security types.
 */
typedef enum {
	dns_tsectype_none,
	dns_tsectype_tsig,
	dns_tsectype_sig0
} dns_tsectype_t;

isc_result_t
dns_tsec_create(isc_mem_t *mctx, dns_tsectype_t type, dst_key_t *key,
		dns_tsec_t **tsecp);
/*%<
 * Create a TSEC structure and stores a type-dependent key structure in it.
 * For a TSIG key (type is dns_tsectype_tsig), dns_tsec_create() creates a
 * TSIG key structure from '*key' and keeps it in the structure.  For other
 * types, this function simply retains '*key' in the structure.  In either
 * case, the ownership of '*key' is transferred to the TSEC module; the caller
 * must not modify or destroy it after the call to dns_tsec_create().
 *
 * Requires:
 *
 *\li	'mctx' is a valid memory context.
 *
 *\li	'type' is a valid value of dns_tsectype_t (see above).
 *
 *\li	'key' is a valid key.
 *
 *\li	tsecp != NULL && *tsecp == NULL.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS				On success.
 *
 *\li	Anything else				Failure.
 */

void
dns_tsec_destroy(dns_tsec_t **tsecp);
/*%<
 * Destroy the TSEC structure.  The stored key is also detached or destroyed.
 *
 * Requires
 *
 *\li	'*tsecp' is a valid TSEC structure.
 *
 * Ensures
 *
 *\li	*tsecp == NULL.
 *
 */

dns_tsectype_t
dns_tsec_gettype(dns_tsec_t *tsec);
/*%<
 * Return the TSEC type of '*tsec'.
 *
 * Requires
 *
 *\li	'tsec' is a valid TSEC structure.
 *
 */

void
dns_tsec_getkey(dns_tsec_t *tsec, void *keyp);
/*%<
 * Return the TSEC key of '*tsec' in '*keyp'.
 *
 * Requires
 *
 *\li	keyp != NULL
 *
 * Ensures
 *
 *\li	*tsecp points to a valid key structure depending on the TSEC type.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_TSEC_H */
portlist.h000064400000004065150415243050006601 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/*! \file dns/portlist.h */

#include <stdbool.h>

#include <isc/lang.h>
#include <isc/net.h>
#include <isc/types.h>

#include <dns/types.h>

#ifndef DNS_PORTLIST_H
#define DNS_PORTLIST_H 1

ISC_LANG_BEGINDECLS

isc_result_t
dns_portlist_create(isc_mem_t *mctx, dns_portlist_t **portlistp);
/*%<
 * Create a port list.
 *
 * Requires:
 *\li	'mctx' to be valid.
 *\li	'portlistp' to be non NULL and '*portlistp' to be NULL;
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *\li	#ISC_R_UNEXPECTED
 */

isc_result_t
dns_portlist_add(dns_portlist_t *portlist, int af, in_port_t port);
/*%<
 * Add the given <port,af> tuple to the portlist.
 *
 * Requires:
 *\li	'portlist' to be valid.
 *\li	'af' to be AF_INET or AF_INET6
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 */

void
dns_portlist_remove(dns_portlist_t *portlist, int af, in_port_t port);
/*%<
 * Remove the given <port,af> tuple to the portlist.
 *
 * Requires:
 *\li	'portlist' to be valid.
 *\li	'af' to be AF_INET or AF_INET6
 */

bool
dns_portlist_match(dns_portlist_t *portlist, int af, in_port_t port);
/*%<
 * Find the given <port,af> tuple to the portlist.
 *
 * Requires:
 *\li	'portlist' to be valid.
 *\li	'af' to be AF_INET or AF_INET6
 *
 * Returns
 * \li	#true if the tuple is found, false otherwise.
 */

void
dns_portlist_attach(dns_portlist_t *portlist, dns_portlist_t **portlistp);
/*%<
 * Attach to a port list.
 *
 * Requires:
 *\li	'portlist' to be valid.
 *\li	'portlistp' to be non NULL and '*portlistp' to be NULL;
 */

void
dns_portlist_detach(dns_portlist_t **portlistp);
/*%<
 * Detach from a port list.
 *
 * Requires:
 *\li	'*portlistp' to be valid.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_PORTLIST_H */
ttl.h000064400000003631150415243050005522 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_TTL_H
#define DNS_TTL_H 1

/*! \file dns/ttl.h */

/***
 ***	Imports
 ***/

#include <stdbool.h>

#include <isc/lang.h>
#include <isc/types.h>

ISC_LANG_BEGINDECLS

/***
 ***	Functions
 ***/

isc_result_t
dns_ttl_totext(uint32_t src, bool verbose,
	       isc_buffer_t *target);
isc_result_t
dns_ttl_totext2(uint32_t src, bool verbose,
		bool upcase, isc_buffer_t *target);
/*%<
 * Output a TTL or other time interval in a human-readable form.
 * The time interval is given as a count of seconds in 'src'.
 * The text representation is appended to 'target'.
 *
 * If 'verbose' is false, use the terse BIND 8 style, like "1w2d3h4m5s".
 *
 * If 'verbose' is true, use a verbose style like the SOA comments
 * in "dig", like "1 week 2 days 3 hours 4 minutes 5 seconds".
 *
 * If 'upcase' is true, we conform to the BIND 8 style in which
 * the unit letter is capitalized if there is only a single unit
 * letter to print (for example, "1m30s", but "2M")
 *
 * If 'upcase' is false, unit letters are always in lower case.
 *
 * Returns:
 * \li	ISC_R_SUCCESS
 * \li	ISC_R_NOSPACE
 */

isc_result_t
dns_counter_fromtext(isc_textregion_t *source, uint32_t *ttl);
/*%<
 * Converts a counter from either a plain number or a BIND 8 style value.
 *
 * Returns:
 *\li	ISC_R_SUCCESS
 *\li	DNS_R_SYNTAX
 */

isc_result_t
dns_ttl_fromtext(isc_textregion_t *source, uint32_t *ttl);
/*%<
 * Converts a ttl from either a plain number or a BIND 8 style value.
 *
 * Returns:
 *\li	ISC_R_SUCCESS
 *\li	DNS_R_BADTTL
 */

ISC_LANG_ENDDECLS

#endif /* DNS_TTL_H */
version.h000064400000001544150415243050006405 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

/*! \file dns/version.h */

#ifndef DNS_VERSION_H
#define DNS_VERSION_H 1

#include <isc/platform.h>

LIBDNS_EXTERNAL_DATA extern const char dns_version[];
LIBDNS_EXTERNAL_DATA extern const char dns_major[];
LIBDNS_EXTERNAL_DATA extern const char dns_mapapi[];

LIBDNS_EXTERNAL_DATA extern const unsigned int dns_libinterface;
LIBDNS_EXTERNAL_DATA extern const unsigned int dns_librevision;
LIBDNS_EXTERNAL_DATA extern const unsigned int dns_libage;

#endif /* DNS_VERSION_H */
rdatatype.h000064400000004372150415243050006717 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_RDATATYPE_H
#define DNS_RDATATYPE_H 1

/*! \file dns/rdatatype.h */

#include <isc/lang.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

isc_result_t
dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source);
/*%<
 * Convert the text 'source' refers to into a DNS rdata type.
 *
 * Requires:
 *\li	'typep' is a valid pointer.
 *
 *\li	'source' is a valid text region.
 *
 * Returns:
 *\li	ISC_R_SUCCESS			on success
 *\li	DNS_R_UNKNOWN			type is unknown
 */

isc_result_t
dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target);
/*%<
 * Put a textual representation of type 'type' into 'target'.
 *
 * Requires:
 *\li	'type' is a valid type.
 *
 *\li	'target' is a valid text buffer.
 *
 * Ensures,
 *	if the result is success:
 *\li		The used space in 'target' is updated.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS			on success
 *\li	#ISC_R_NOSPACE			target buffer is too small
 */

isc_result_t
dns_rdatatype_tounknowntext(dns_rdatatype_t type, isc_buffer_t *target);
/*%<
 * Put textual RFC3597 TYPEXXXX representation of type 'type' into
 * 'target'.
 *
 * Requires:
 *\li	'type' is a valid type.
 *
 *\li	'target' is a valid text buffer.
 *
 * Ensures,
 *	if the result is success:
 *\li		The used space in 'target' is updated.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS			on success
 *\li	#ISC_R_NOSPACE			target buffer is too small
 */

void
dns_rdatatype_format(dns_rdatatype_t rdtype,
		     char *array, unsigned int size);
/*%<
 * Format a human-readable representation of the type 'rdtype'
 * into the character array 'array', which is of size 'size'.
 * The resulting string is guaranteed to be null-terminated.
 */

#define DNS_RDATATYPE_FORMATSIZE sizeof("NSEC3PARAM")

/*%<
 * Minimum size of array to pass to dns_rdatatype_format().
 * May need to be adjusted if a new RR type with a very long
 * name is defined.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_RDATATYPE_H */
zt.h000064400000012672150415243050005361 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_ZT_H
#define DNS_ZT_H 1

/*! \file dns/zt.h */

#include <stdbool.h>

#include <isc/lang.h>
#include <isc/rwlock.h>

#include <dns/types.h>

#define DNS_ZTFIND_NOEXACT		0x01

ISC_LANG_BEGINDECLS

typedef isc_result_t
(*dns_zt_allloaded_t)(void *arg);
/*%<
 * Method prototype: when all pending zone loads are complete,
 * the zone table can inform the caller via a callback function with
 * this signature.
 */

typedef isc_result_t
(*dns_zt_zoneloaded_t)(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task);
/*%<
 * Method prototype: when a zone finishes loading, the zt object
 * can be informed via a callback function with this signature.
 */

isc_result_t
dns_zt_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_zt_t **zt);
/*%<
 * Creates a new zone table.
 *
 * Requires:
 * \li	'mctx' to be initialized.
 *
 * Returns:
 * \li	#ISC_R_SUCCESS on success.
 * \li	#ISC_R_NOMEMORY
 */

isc_result_t
dns_zt_mount(dns_zt_t *zt, dns_zone_t *zone);
/*%<
 * Mounts the zone on the zone table.
 *
 * Requires:
 * \li	'zt' to be valid
 * \li	'zone' to be valid
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_EXISTS
 * \li	#ISC_R_NOSPACE
 * \li	#ISC_R_NOMEMORY
 */

isc_result_t
dns_zt_unmount(dns_zt_t *zt, dns_zone_t *zone);
/*%<
 * Unmount the given zone from the table.
 *
 * Requires:
 * 	'zt' to be valid
 * \li	'zone' to be valid
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOTFOUND
 * \li	#ISC_R_NOMEMORY
 */

isc_result_t
dns_zt_find(dns_zt_t *zt, const dns_name_t *name, unsigned int options,
	    dns_name_t *foundname, dns_zone_t **zone);
/*%<
 * Find the best match for 'name' in 'zt'.  If foundname is non NULL
 * then the name of the zone found is returned.
 *
 * Notes:
 * \li	If the DNS_ZTFIND_NOEXACT is set, the best partial match (if any)
 *	to 'name' will be returned.
 *
 * Requires:
 * \li	'zt' to be valid
 * \li	'name' to be valid
 * \li	'foundname' to be initialized and associated with a fixedname or NULL
 * \li	'zone' to be non NULL and '*zone' to be NULL
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#DNS_R_PARTIALMATCH
 * \li	#ISC_R_NOTFOUND
 * \li	#ISC_R_NOSPACE
 */

void
dns_zt_detach(dns_zt_t **ztp);
/*%<
 * Detach the given zonetable, if the reference count goes to zero the
 * zonetable will be freed.  In either case 'ztp' is set to NULL.
 *
 * Requires:
 * \li	'*ztp' to be valid
 */

void
dns_zt_flushanddetach(dns_zt_t **ztp);
/*%<
 * Detach the given zonetable, if the reference count goes to zero the
 * zonetable will be flushed and then freed.  In either case 'ztp' is
 * set to NULL.
 *
 * Requires:
 * \li	'*ztp' to be valid
 */

void
dns_zt_attach(dns_zt_t *zt, dns_zt_t **ztp);
/*%<
 * Attach 'zt' to '*ztp'.
 *
 * Requires:
 * \li	'zt' to be valid
 * \li	'*ztp' to be NULL
 */

isc_result_t
dns_zt_load(dns_zt_t *zt, bool stop);

isc_result_t
dns_zt_loadnew(dns_zt_t *zt, bool stop);

isc_result_t
dns_zt_asyncload(dns_zt_t *zt, dns_zt_allloaded_t alldone, void *arg);

isc_result_t
dns_zt_asyncload2(dns_zt_t *zt, dns_zt_allloaded_t alldone, void *arg,
		  bool newonly);
/*%<
 * Load all zones in the table.  If 'stop' is true,
 * stop on the first error and return it.  If 'stop'
 * is false, ignore errors.
 *
 * dns_zt_loadnew() only loads zones that are not yet loaded.
 * dns_zt_load() also loads zones that are already loaded and
 * and whose master file has changed since the last load.
 * dns_zt_asyncload() loads zones asynchronously; when all
 * zones in the zone table have finished loaded (or failed due
 * to errors), the caller is informed by calling 'alldone'
 * with an argument of 'arg'.
 *
 * Requires:
 * \li	'zt' to be valid
 */

isc_result_t
dns_zt_freezezones(dns_zt_t *zt, bool freeze);
/*%<
 * Freeze/thaw updates to master zones.
 * Any pending updates will be flushed.
 * Zones will be reloaded on thaw.
 */

isc_result_t
dns_zt_apply(dns_zt_t *zt, isc_rwlocktype_t lock, bool stop,
	     isc_result_t (*action)(dns_zone_t *, void *), void *uap);

isc_result_t
dns_zt_apply2(dns_zt_t *zt, isc_rwlocktype_t lock, bool stop, isc_result_t *sub,
	      isc_result_t (*action)(dns_zone_t *, void *), void *uap);
/*%<
 * Apply a given 'action' to all zone zones in the table.
 * If 'stop' is 'true' then walking the zone tree will stop if
 * 'action' does not return ISC_R_SUCCESS.
 *
 * Requires:
 * \li	'zt' to be valid.
 * \li	'action' to be non NULL.
 *
 * Returns:
 * \li	ISC_R_SUCCESS if action was applied to all nodes.  If 'stop' is
 *	false and 'sub' is non NULL then the first error (if any)
 *	reported by 'action' is returned in '*sub';
 *	any error code from 'action'.
 */

bool
dns_zt_loadspending(dns_zt_t *zt);
/*%<
 * Returns true if and only if there are zones still waiting to
 * be loaded in zone table 'zt'.
 *
 * Requires:
 * \li	'zt' to be valid.
 */

void
dns_zt_setviewcommit(dns_zt_t *zt);
/*%<
 * Commit dns_zone_setview() calls previously made for all zones in this
 * zone table.
 *
 * Requires:
 *\li	'view' to be valid.
 */

void
dns_zt_setviewrevert(dns_zt_t *zt);
/*%<
 * Revert dns_zone_setview() calls previously made for all zones in this
 * zone table.
 *
 * Requires:
 *\li	'view' to be valid.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_ZT_H */
dnssec.h000064400000027523150415243060006205 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_DNSSEC_H
#define DNS_DNSSEC_H 1

/*! \file dns/dnssec.h */

#include <stdbool.h>

#include <isc/lang.h>
#include <isc/stdtime.h>
#include <isc/stats.h>

#include <dns/diff.h>
#include <dns/types.h>

#include <dst/dst.h>

ISC_LANG_BEGINDECLS

LIBDNS_EXTERNAL_DATA extern isc_stats_t *dns_dnssec_stats;

/*%< Maximum number of keys supported in a zone. */
#define DNS_MAXZONEKEYS 32

/*
 * Indicates how the signer found this key: in the key repository, at the
 * zone apex, or specified by the user.
 */
typedef enum {
	dns_keysource_unknown,
	dns_keysource_repository,
	dns_keysource_zoneapex,
	dns_keysource_user
} dns_keysource_t;

/*
 * A DNSSEC key and hints about its intended use gleaned from metadata
 */
struct dns_dnsseckey {
	dst_key_t *key;
	bool hint_publish;  /*% metadata says to publish */
	bool force_publish; /*% publish regardless of metadata */
	bool hint_sign;     /*% metadata says to sign with this key */
	bool force_sign;    /*% sign with key regardless of metadata */
	bool hint_remove;   /*% metadata says *don't* publish */
	bool is_active;     /*% key is already active */
	bool first_sign;    /*% key is newly becoming active */
	unsigned int prepublish;     /*% how long until active? */
	dns_keysource_t source;      /*% how the key was found */
	bool ksk;           /*% this is a key-signing key */
	bool legacy;        /*% this is old-style key with no
					 metadata (possibly generated by
					 an older version of BIND9) and
					 should be ignored when searching
					 for keys to import into the zone */
	unsigned int index;          /*% position in list */
	ISC_LINK(dns_dnsseckey_t) link;
};

isc_result_t
dns_dnssec_keyfromrdata(dns_name_t *name, dns_rdata_t *rdata, isc_mem_t *mctx,
			dst_key_t **key);
/*%<
 *	Creates a DST key from a DNS record.  Basically a wrapper around
 *	dst_key_fromdns().
 *
 *	Requires:
 *\li		'name' is not NULL
 *\li		'rdata' is not NULL
 *\li		'mctx' is not NULL
 *\li		'key' is not NULL
 *\li		'*key' is NULL
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS
 *\li		#ISC_R_NOMEMORY
 *\li		DST_R_INVALIDPUBLICKEY
 *\li		various errors from dns_name_totext
 */

isc_result_t
dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
		isc_stdtime_t *inception, isc_stdtime_t *expire,
		isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata);
/*%<
 *	Generates a RRSIG record covering this rdataset.  This has no effect
 *	on existing RRSIG records.
 *
 *	Requires:
 *\li		'name' (the owner name of the record) is a valid name
 *\li		'set' is a valid rdataset
 *\li		'key' is a valid key
 *\li		'inception' is not NULL
 *\li		'expire' is not NULL
 *\li		'mctx' is not NULL
 *\li		'buffer' is not NULL
 *\li		'sigrdata' is not NULL
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS
 *\li		#ISC_R_NOMEMORY
 *\li		#ISC_R_NOSPACE
 *\li		#DNS_R_INVALIDTIME - the expiration is before the inception
 *\li		#DNS_R_KEYUNAUTHORIZED - the key cannot sign this data (either
 *			it is not a zone key or its flags prevent
 *			authentication)
 *\li		DST_R_*
 */

isc_result_t
dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
		  bool ignoretime, isc_mem_t *mctx,
		  dns_rdata_t *sigrdata);

isc_result_t
dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
		   bool ignoretime, isc_mem_t *mctx,
		   dns_rdata_t *sigrdata, dns_name_t *wild);

isc_result_t
dns_dnssec_verify3(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
		   bool ignoretime, unsigned int maxbits,
		   isc_mem_t *mctx, dns_rdata_t *sigrdata, dns_name_t *wild);
/*%<
 *	Verifies the RRSIG record covering this rdataset signed by a specific
 *	key.  This does not determine if the key's owner is authorized to sign
 *	this record, as this requires a resolver or database.
 *	If 'ignoretime' is true, temporal validity will not be checked.
 *
 *	'maxbits' specifies the maximum number of rsa exponent bits accepted.
 *
 *	Requires:
 *\li		'name' (the owner name of the record) is a valid name
 *\li		'set' is a valid rdataset
 *\li		'key' is a valid key
 *\li		'mctx' is not NULL
 *\li		'sigrdata' is a valid rdata containing a SIG record
 *\li		'wild' if non-NULL then is a valid and has a buffer.
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS
 *\li		#ISC_R_NOMEMORY
 *\li		#DNS_R_FROMWILDCARD - the signature is valid and is from
 *			a wildcard expansion.  dns_dnssec_verify2() only.
 *			'wild' contains the name of the wildcard if non-NULL.
 *\li		#DNS_R_SIGINVALID - the signature fails to verify
 *\li		#DNS_R_SIGEXPIRED - the signature has expired
 *\li		#DNS_R_SIGFUTURE - the signature's validity period has not begun
 *\li		#DNS_R_KEYUNAUTHORIZED - the key cannot sign this data (either
 *			it is not a zone key or its flags prevent
 *			authentication)
 *\li		DST_R_*
 */

/*@{*/
isc_result_t
dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
			dns_name_t *name, isc_mem_t *mctx,
			unsigned int maxkeys, dst_key_t **keys,
			unsigned int *nkeys);

isc_result_t
dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver,
			 dns_dbnode_t *node, dns_name_t *name,
			 const char *directory, isc_mem_t *mctx,
			 unsigned int maxkeys, dst_key_t **keys,
			 unsigned int *nkeys);

isc_result_t
dns_dnssec_findzonekeys3(dns_db_t *db, dns_dbversion_t *ver,
			 dns_dbnode_t *node, dns_name_t *name,
			 const char *directory, isc_stdtime_t now,
			 isc_mem_t *mctx, unsigned int maxkeys,
			 dst_key_t **keys, unsigned int *nkeys);

/*%<
 * 	Finds a set of zone keys.
 * 	XXX temporary - this should be handled in dns_zone_t.
 */
/*@}*/

bool
dns_dnssec_keyactive(dst_key_t *key, isc_stdtime_t now);
/*%<
 *
 * 	Returns true if 'key' is active as of the time specified
 * 	in 'now' (i.e., if the activation date has passed, inactivation or
 * 	deletion date has not yet been reached, and the key is not revoked
 * 	-- or if it is a legacy key without metadata). Otherwise returns
 * 	false.
 *
 *	Requires:
 *\li		'key' is a valid key
 */

isc_result_t
dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key);
/*%<
 *	Signs a message with a SIG(0) record.  This is implicitly called by
 *	dns_message_renderend() if msg->sig0key is not NULL.
 *
 *	Requires:
 *\li		'msg' is a valid message
 *\li		'key' is a valid key that can be used for signing
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS
 *\li		#ISC_R_NOMEMORY
 *\li		DST_R_*
 */

isc_result_t
dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg,
			 dst_key_t *key);
/*%<
 *	Verifies a message signed by a SIG(0) record.  This is not
 *	called implicitly by dns_message_parse().  If dns_message_signer()
 *	is called before dns_dnssec_verifymessage(), it will return
 *	#DNS_R_NOTVERIFIEDYET.  dns_dnssec_verifymessage() will set
 *	the verified_sig0 flag in msg if the verify succeeds, and
 *	the sig0status field otherwise.
 *
 *	Requires:
 *\li		'source' is a valid buffer containing the unparsed message
 *\li		'msg' is a valid message
 *\li		'key' is a valid key
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS
 *\li		#ISC_R_NOMEMORY
 *\li		#ISC_R_NOTFOUND - no SIG(0) was found
 *\li		#DNS_R_SIGINVALID - the SIG record is not well-formed or
 *				   was not generated by the key.
 *\li		DST_R_*
 */

bool
dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name,
		     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
		     bool ignoretime, isc_mem_t *mctx);


bool
dns_dnssec_signs(dns_rdata_t *rdata, dns_name_t *name,
		 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
		 bool ignoretime, isc_mem_t *mctx);
/*%<
 * Verify that 'rdataset' is validly signed in 'sigrdataset' by
 * the key in 'rdata'.
 *
 * dns_dnssec_selfsigns() requires that rdataset be a DNSKEY or KEY
 * rrset.  dns_dnssec_signs() works on any rrset.
 */


isc_result_t
dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey,
		     dns_dnsseckey_t **dkp);
/*%<
 * Create and initialize a dns_dnsseckey_t structure.
 *
 *	Requires:
 *\li		'dkp' is not NULL and '*dkp' is NULL.
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS
 *\li		#ISC_R_NOMEMORY
 */

void
dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp);
/*%<
 * Reclaim a dns_dnsseckey_t structure.
 *
 *	Requires:
 *\li		'dkp' is not NULL and '*dkp' is not NULL.
 *
 *	Ensures:
 *\li		'*dkp' is NULL.
 */

isc_result_t
dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory,
			    isc_mem_t *mctx, dns_dnsseckeylist_t *keylist);

isc_result_t
dns_dnssec_findmatchingkeys2(dns_name_t *origin, const char *directory,
			     isc_stdtime_t now, isc_mem_t *mctx,
			     dns_dnsseckeylist_t *keylist);
/*%<
 * Search 'directory' for K* key files matching the name in 'origin'.
 * Append all such keys, along with use hints gleaned from their
 * metadata, onto 'keylist'.  Skip any unsupported algorithms.
 *
 *	Requires:
 *\li		'keylist' is not NULL
 *
 *	Returns:
 *\li		#ISC_R_SUCCESS
 *\li		#ISC_R_NOTFOUND
 *\li		#ISC_R_NOMEMORY
 *\li		any error returned by dns_name_totext(), isc_dir_open(), or
 *              dst_key_fromnamedfile()
 *
 *	Ensures:
 *\li		On error, keylist is unchanged
 */

isc_result_t
dns_dnssec_keylistfromrdataset(dns_name_t *origin,
			       const char *directory, isc_mem_t *mctx,
			       dns_rdataset_t *keyset, dns_rdataset_t *keysigs,
			       dns_rdataset_t *soasigs, bool savekeys,
			       bool publickey,
			       dns_dnsseckeylist_t *keylist);
/*%<
 * Append the contents of a DNSKEY rdataset 'keyset' to 'keylist'.
 * Omit duplicates.  If 'publickey' is false, search 'directory' for
 * matching key files, and load the private keys that go with
 * the public ones.  If 'savekeys' is true, mark the keys so
 * they will not be deleted or inactivated regardless of metadata.
 *
 * 'keysigs' and 'soasigs', if not NULL and associated, contain the
 * RRSIGS for the DNSKEY and SOA records respectively and are used to mark
 * whether a key is already active in the zone.
 */

isc_result_t
dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys,
		      dns_dnsseckeylist_t *removed, dns_name_t *origin,
		      dns_ttl_t hint_ttl, dns_diff_t *diff, bool allzsk,
		      isc_mem_t *mctx, void (*report)(const char *, ...));
/*%<
 * Update the list of keys in 'keys' with new key information in 'newkeys'.
 *
 * For each key in 'newkeys', see if it has a match in 'keys'.
 * - If not, and if the metadata says the key should be published:
 *   add it to 'keys', and place a dns_difftuple into 'diff' so
 *   the key can be added to the DNSKEY set.  If the metadata says it
 *   should be active, set the first_sign flag.
 * - If so, and if the metadata says it should be removed:
 *   remove it from 'keys', and place a dns_difftuple into 'diff' so
 *   the key can be removed from the DNSKEY set.  if 'removed' is non-NULL,
 *   copy the key into that list; otherwise destroy it.
 * - Otherwise, make sure keys has current metadata.
 *
 * If 'allzsk' is true, we are allowing KSK-flagged keys to be used as
 * ZSKs.
 *
 * 'hint_ttl' is the TTL to use for the DNSKEY RRset if there is no
 * existing RRset, and if none of the keys to be added has a default TTL
 * (in which case we would use the shortest one).  If the TTL is longer
 * than the time until a new key will be activated, then we have to delay
 * the key's activation.
 *
 * 'report' points to a function for reporting status.
 *
 * On completion, any remaining keys in 'newkeys' are freed.
 */

isc_result_t
dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
		      dns_rdataset_t *cds, dns_rdataset_t *cdnskey,
		      isc_stdtime_t now, dns_ttl_t hint_ttl, dns_diff_t *diff,
		      isc_mem_t *mctx);
/*%<
 * Update the CDS and CDNSKEY RRsets, adding and removing keys as needed.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_DNSSEC_H */
secalg.h000064400000003252150415243060006155 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_SECALG_H
#define DNS_SECALG_H 1

/*! \file dns/secalg.h */

#include <isc/lang.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

isc_result_t
dns_secalg_fromtext(dns_secalg_t *secalgp, isc_textregion_t *source);
/*%<
 * Convert the text 'source' refers to into a DNSSEC security algorithm value.
 * The text may contain either a mnemonic algorithm name or a decimal algorithm
 * number.
 *
 * Requires:
 *\li	'secalgp' is a valid pointer.
 *
 *\li	'source' is a valid text region.
 *
 * Returns:
 *\li	ISC_R_SUCCESS			on success
 *\li	ISC_R_RANGE			numeric type is out of range
 *\li	DNS_R_UNKNOWN			mnemonic type is unknown
 */

isc_result_t
dns_secalg_totext(dns_secalg_t secalg, isc_buffer_t *target);
/*%<
 * Put a textual representation of the DNSSEC security algorithm 'secalg'
 * into 'target'.
 *
 * Requires:
 *\li	'secalg' is a valid secalg.
 *
 *\li	'target' is a valid text buffer.
 *
 * Ensures,
 *	if the result is success:
 *\li		The used space in 'target' is updated.
 *
 * Returns:
 *\li	ISC_R_SUCCESS			on success
 *\li	ISC_R_NOSPACE			target buffer is too small
 */

#define DNS_SECALG_FORMATSIZE 20
void
dns_secalg_format(dns_secalg_t alg, char *cp, unsigned int size);
/*%<
 * Wrapper for dns_secalg_totext(), writing text into 'cp'
 */

ISC_LANG_ENDDECLS

#endif /* DNS_SECALG_H */
stats.h000064400000032213150415243060006054 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_STATS_H
#define DNS_STATS_H 1

/*! \file dns/stats.h */

#include <inttypes.h>

#include <dns/types.h>

/*%
 * Statistics counters.  Used as isc_statscounter_t values.
 */
enum {
	/*%
	 * Resolver statistics counters.
	 */
	dns_resstatscounter_queryv4 = 0,
	dns_resstatscounter_queryv6 = 1,
	dns_resstatscounter_responsev4 = 2,
	dns_resstatscounter_responsev6 = 3,
	dns_resstatscounter_nxdomain = 4,
	dns_resstatscounter_servfail = 5,
	dns_resstatscounter_formerr = 6,
	dns_resstatscounter_othererror = 7,
	dns_resstatscounter_edns0fail = 8,
	dns_resstatscounter_mismatch = 9,
	dns_resstatscounter_truncated = 10,
	dns_resstatscounter_lame = 11,
	dns_resstatscounter_retry = 12,
	dns_resstatscounter_gluefetchv4 = 13,
	dns_resstatscounter_gluefetchv6 = 14,
	dns_resstatscounter_gluefetchv4fail = 15,
	dns_resstatscounter_gluefetchv6fail = 16,
	dns_resstatscounter_val = 17,
	dns_resstatscounter_valsuccess = 18,
	dns_resstatscounter_valnegsuccess = 19,
	dns_resstatscounter_valfail = 20,
	dns_resstatscounter_dispabort = 21,
	dns_resstatscounter_dispsockfail = 22,
	dns_resstatscounter_querytimeout = 23,
	dns_resstatscounter_queryrtt0 = 24,
	dns_resstatscounter_queryrtt1 = 25,
	dns_resstatscounter_queryrtt2 = 26,
	dns_resstatscounter_queryrtt3 = 27,
	dns_resstatscounter_queryrtt4 = 28,
	dns_resstatscounter_queryrtt5 = 29,
	dns_resstatscounter_nfetch = 30,
	dns_resstatscounter_disprequdp = 31,
	dns_resstatscounter_dispreqtcp = 32,
	dns_resstatscounter_buckets = 33,
	dns_resstatscounter_refused = 34,
	dns_resstatscounter_cookienew = 35,
	dns_resstatscounter_cookieout = 36,
	dns_resstatscounter_cookiein = 37,
	dns_resstatscounter_cookieok = 38,
	dns_resstatscounter_badvers = 39,
	dns_resstatscounter_badcookie = 40,
	dns_resstatscounter_zonequota = 41,
	dns_resstatscounter_serverquota = 42,
	dns_resstatscounter_nextitem = 43,
	dns_resstatscounter_max = 44,

	/*
	 * DNSSEC stats.
	 */
	dns_dnssecstats_asis = 0,
	dns_dnssecstats_downcase = 1,
	dns_dnssecstats_wildcard = 2,
	dns_dnssecstats_fail = 3,

	dns_dnssecstats_max = 4,

	/*%
	 * Zone statistics counters.
	 */
	dns_zonestatscounter_notifyoutv4 = 0,
	dns_zonestatscounter_notifyoutv6 = 1,
	dns_zonestatscounter_notifyinv4 = 2,
	dns_zonestatscounter_notifyinv6 = 3,
	dns_zonestatscounter_notifyrej = 4,
	dns_zonestatscounter_soaoutv4 = 5,
	dns_zonestatscounter_soaoutv6 = 6,
	dns_zonestatscounter_axfrreqv4 = 7,
	dns_zonestatscounter_axfrreqv6 = 8,
	dns_zonestatscounter_ixfrreqv4 = 9,
	dns_zonestatscounter_ixfrreqv6 = 10,
	dns_zonestatscounter_xfrsuccess = 11,
	dns_zonestatscounter_xfrfail = 12,

	dns_zonestatscounter_max = 13,

	/*
	 * Adb statistics values.
	 */
	dns_adbstats_nentries = 0,
	dns_adbstats_entriescnt = 1,
	dns_adbstats_nnames = 2,
	dns_adbstats_namescnt = 3,

	dns_adbstats_max = 4,

	/*
	 * Cache statistics values.
	 */
	dns_cachestatscounter_hits = 1,
	dns_cachestatscounter_misses = 2,
	dns_cachestatscounter_queryhits = 3,
	dns_cachestatscounter_querymisses = 4,
	dns_cachestatscounter_deletelru = 5,
	dns_cachestatscounter_deletettl = 6,

	dns_cachestatscounter_max = 7,

	/*%
	 * Query statistics counters (obsolete).
	 */
	dns_statscounter_success = 0,    /*%< Successful lookup */
	dns_statscounter_referral = 1,   /*%< Referral result */
	dns_statscounter_nxrrset = 2,    /*%< NXRRSET result */
	dns_statscounter_nxdomain = 3,   /*%< NXDOMAIN result */
	dns_statscounter_recursion = 4,  /*%< Recursion was used */
	dns_statscounter_failure = 5,    /*%< Some other failure */
	dns_statscounter_duplicate = 6,  /*%< Duplicate query */
	dns_statscounter_dropped = 7,	 /*%< Duplicate query (dropped) */

	/*%
	 * DNSTAP statistics counters.
	 */
	dns_dnstapcounter_success = 0,
	dns_dnstapcounter_drop =  1,
	dns_dnstapcounter_max = 2
};

#define DNS_STATS_NCOUNTERS 8

#if 0
/*%<
 * Flag(s) for dns_xxxstats_dump().  DNS_STATSDUMP_VERBOSE is obsolete.
 * ISC_STATSDUMP_VERBOSE should be used instead.  These two values are
 * intentionally defined to be the same value to ensure binary compatibility.
 */
#define DNS_STATSDUMP_VERBOSE	0x00000001 /*%< dump 0-value counters */
#endif

/*%<
 * (Obsoleted)
 */
LIBDNS_EXTERNAL_DATA extern const char *dns_statscounter_names[];

/*%
 * Attributes for statistics counters of RRset and Rdatatype types.
 *
 * _OTHERTYPE
 *	The rdata type is not explicitly supported and the corresponding counter
 *	is counted for other such types, too.  When this attribute is set,
 *	the base type is of no use.
 *
 * _NXRRSET
 * 	RRset type counters only.  Indicates the RRset is non existent.
 *
 * _NXDOMAIN
 *	RRset type counters only.  Indicates a non existent name.  When this
 *	attribute is set, the base type is of no use.
 *
 * _STALE
 *	RRset type counters only.  This indicates a record that marked for
 *	removal.
 *
 *	Note: incrementing _STALE will decrement the corresponding non-stale
 *	counter.
 */
#define DNS_RDATASTATSTYPE_ATTR_OTHERTYPE	0x0001
#define DNS_RDATASTATSTYPE_ATTR_NXRRSET		0x0002
#define DNS_RDATASTATSTYPE_ATTR_NXDOMAIN	0x0004
#define DNS_RDATASTATSTYPE_ATTR_STALE		0x0008

/*%<
 * Conversion macros among dns_rdatatype_t, attributes and isc_statscounter_t.
 */
#define DNS_RDATASTATSTYPE_BASE(type)	((dns_rdatatype_t)((type) & 0xFFFF))
#define DNS_RDATASTATSTYPE_ATTR(type)	((type) >> 16)
#define DNS_RDATASTATSTYPE_VALUE(b, a)	(((a) << 16) | (b))

/*%<
 * Types of dump callbacks.
 */
typedef void (*dns_generalstats_dumper_t)(isc_statscounter_t, uint64_t,
					  void *);
typedef void (*dns_rdatatypestats_dumper_t)(dns_rdatastatstype_t, uint64_t,
					    void *);
typedef void (*dns_opcodestats_dumper_t)(dns_opcode_t, uint64_t, void *);

typedef void (*dns_rcodestats_dumper_t)(dns_rcode_t, uint64_t, void *);

ISC_LANG_BEGINDECLS

isc_result_t
dns_generalstats_create(isc_mem_t *mctx, dns_stats_t **statsp, int ncounters);
/*%<
 * Create a statistics counter structure of general type.  It counts a general
 * set of counters indexed by an ID between 0 and ncounters -1.
 * This function is obsolete.  A more general function, isc_stats_create(),
 * should be used.
 *
 * Requires:
 *\li	'mctx' must be a valid memory context.
 *
 *\li	'statsp' != NULL && '*statsp' == NULL.
 *
 * Returns:
 *\li	ISC_R_SUCCESS	-- all ok
 *
 *\li	anything else	-- failure
 */

isc_result_t
dns_rdatatypestats_create(isc_mem_t *mctx, dns_stats_t **statsp);
/*%<
 * Create a statistics counter structure per rdatatype.
 *
 * Requires:
 *\li	'mctx' must be a valid memory context.
 *
 *\li	'statsp' != NULL && '*statsp' == NULL.
 *
 * Returns:
 *\li	ISC_R_SUCCESS	-- all ok
 *
 *\li	anything else	-- failure
 */

isc_result_t
dns_rdatasetstats_create(isc_mem_t *mctx, dns_stats_t **statsp);
/*%<
 * Create a statistics counter structure per RRset.
 *
 * Requires:
 *\li	'mctx' must be a valid memory context.
 *
 *\li	'statsp' != NULL && '*statsp' == NULL.
 *
 * Returns:
 *\li	ISC_R_SUCCESS	-- all ok
 *
 *\li	anything else	-- failure
 */

isc_result_t
dns_opcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp);
/*%<
 * Create a statistics counter structure per opcode.
 *
 * Requires:
 *\li	'mctx' must be a valid memory context.
 *
 *\li	'statsp' != NULL && '*statsp' == NULL.
 *
 * Returns:
 *\li	ISC_R_SUCCESS	-- all ok
 *
 *\li	anything else	-- failure
 */

isc_result_t
dns_rcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp);
/*%<
 * Create a statistics counter structure per assigned rcode.
 *
 * Requires:
 *\li	'mctx' must be a valid memory context.
 *
 *\li	'statsp' != NULL && '*statsp' == NULL.
 *
 * Returns:
 *\li	ISC_R_SUCCESS	-- all ok
 *
 *\li	anything else	-- failure
 */

void
dns_stats_attach(dns_stats_t *stats, dns_stats_t **statsp);
/*%<
 * Attach to a statistics set.
 *
 * Requires:
 *\li	'stats' is a valid dns_stats_t.
 *
 *\li	'statsp' != NULL && '*statsp' == NULL
 */

void
dns_stats_detach(dns_stats_t **statsp);
/*%<
 * Detaches from the statistics set.
 *
 * Requires:
 *\li	'statsp' != NULL and '*statsp' is a valid dns_stats_t.
 */

void
dns_generalstats_increment(dns_stats_t *stats, isc_statscounter_t counter);
/*%<
 * Increment the counter-th counter of stats.  This function is obsolete.
 * A more general function, isc_stats_increment(), should be used.
 *
 * Requires:
 *\li	'stats' is a valid dns_stats_t created by dns_generalstats_create().
 *
 *\li	counter is less than the maximum available ID for the stats specified
 *	on creation.
 */

void
dns_rdatatypestats_increment(dns_stats_t *stats, dns_rdatatype_t type);
/*%<
 * Increment the statistics counter for 'type'.
 *
 * Requires:
 *\li	'stats' is a valid dns_stats_t created by dns_rdatatypestats_create().
 */

void
dns_rdatasetstats_increment(dns_stats_t *stats, dns_rdatastatstype_t rrsettype);
/*%<
 * Increment the statistics counter for 'rrsettype'.
 *
 * Note: if 'rrsettype' has the _STALE attribute set the corresponding
 * non-stale counter will be decremented.
 *
 * Requires:
 *\li	'stats' is a valid dns_stats_t created by dns_rdatasetstats_create().
 */

void
dns_rdatasetstats_decrement(dns_stats_t *stats, dns_rdatastatstype_t rrsettype);
/*%<
 * Decrement the statistics counter for 'rrsettype'.
 *
 * Requires:
 *\li	'stats' is a valid dns_stats_t created by dns_rdatasetstats_create().
 */

void
dns_opcodestats_increment(dns_stats_t *stats, dns_opcode_t code);
/*%<
 * Increment the statistics counter for 'code'.
 *
 * Requires:
 *\li	'stats' is a valid dns_stats_t created by dns_opcodestats_create().
 */

void
dns_rcodestats_increment(dns_stats_t *stats, dns_opcode_t code);
/*%<
 * Increment the statistics counter for 'code'.
 *
 * Requires:
 *\li	'stats' is a valid dns_stats_t created by dns_rcodestats_create().
 */

void
dns_generalstats_dump(dns_stats_t *stats, dns_generalstats_dumper_t dump_fn,
		      void *arg, unsigned int options);
/*%<
 * Dump the current statistics counters in a specified way.  For each counter
 * in stats, dump_fn is called with its current value and the given argument
 * arg.  By default counters that have a value of 0 is skipped; if options has
 * the ISC_STATSDUMP_VERBOSE flag, even such counters are dumped.
 *
 * This function is obsolete.  A more general function, isc_stats_dump(),
 * should be used.
 *
 * Requires:
 *\li	'stats' is a valid dns_stats_t created by dns_generalstats_create().
 */

void
dns_rdatatypestats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
			void *arg, unsigned int options);
/*%<
 * Dump the current statistics counters in a specified way.  For each counter
 * in stats, dump_fn is called with the corresponding type in the form of
 * dns_rdatastatstype_t, the current counter value and the given argument
 * arg.  By default counters that have a value of 0 is skipped; if options has
 * the ISC_STATSDUMP_VERBOSE flag, even such counters are dumped.
 *
 * Requires:
 *\li	'stats' is a valid dns_stats_t created by dns_generalstats_create().
 */

void
dns_rdatasetstats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
		       void *arg, unsigned int options);
/*%<
 * Dump the current statistics counters in a specified way.  For each counter
 * in stats, dump_fn is called with the corresponding type in the form of
 * dns_rdatastatstype_t, the current counter value and the given argument
 * arg.  By default counters that have a value of 0 is skipped; if options has
 * the ISC_STATSDUMP_VERBOSE flag, even such counters are dumped.
 *
 * Requires:
 *\li	'stats' is a valid dns_stats_t created by dns_generalstats_create().
 */

void
dns_opcodestats_dump(dns_stats_t *stats, dns_opcodestats_dumper_t dump_fn,
		     void *arg, unsigned int options);
/*%<
 * Dump the current statistics counters in a specified way.  For each counter
 * in stats, dump_fn is called with the corresponding opcode, the current
 * counter value and the given argument arg.  By default counters that have a
 * value of 0 is skipped; if options has the ISC_STATSDUMP_VERBOSE flag, even
 * such counters are dumped.
 *
 * Requires:
 *\li	'stats' is a valid dns_stats_t created by dns_generalstats_create().
 */

void
dns_rcodestats_dump(dns_stats_t *stats, dns_rcodestats_dumper_t dump_fn,
		    void *arg, unsigned int options);
/*%<
 * Dump the current statistics counters in a specified way.  For each counter
 * in stats, dump_fn is called with the corresponding rcode, the current
 * counter value and the given argument arg.  By default counters that have a
 * value of 0 is skipped; if options has the ISC_STATSDUMP_VERBOSE flag, even
 * such counters are dumped.
 *
 * Requires:
 *\li	'stats' is a valid dns_stats_t created by dns_generalstats_create().
 */

isc_result_t
dns_stats_alloccounters(isc_mem_t *mctx, uint64_t **ctrp);
/*%<
 * Allocate an array of query statistics counters from the memory
 * context 'mctx'.
 *
 * This function is obsoleted.  Use dns_xxxstats_create() instead.
 */

void
dns_stats_freecounters(isc_mem_t *mctx, uint64_t **ctrp);
/*%<
 * Free an array of query statistics counters allocated from the memory
 * context 'mctx'.
 *
 * This function is obsoleted.  Use dns_stats_destroy() instead.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_STATS_H */
timer.h000064400000002033150415243060006033 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_TIMER_H
#define DNS_TIMER_H 1

/*! \file dns/timer.h */

/***
 ***	Imports
 ***/

#include <stdbool.h>

#include <isc/buffer.h>
#include <isc/lang.h>

ISC_LANG_BEGINDECLS

/***
 ***	Functions
 ***/

isc_result_t
dns_timer_setidle(isc_timer_t *timer, unsigned int maxtime,
		  unsigned int idletime, bool purge);
/*%<
 * Convenience function for setting up simple, one-second-granularity
 * idle timers as used by zone transfers.
 * \brief
 * Set the timer 'timer' to go off after 'idletime' seconds of inactivity,
 * or after 'maxtime' at the very latest.  Events are purged iff
 * 'purge' is true.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_TIMER_H */
resolver.h000064400000047403150415243060006566 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_RESOLVER_H
#define DNS_RESOLVER_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/resolver.h
 *
 * \brief
 * This is the BIND 9 resolver, the module responsible for resolving DNS
 * requests by iteratively querying authoritative servers and following
 * referrals.  This is a "full resolver", not to be confused with
 * the stub resolvers most people associate with the word "resolver".
 * The full resolver is part of the caching name server or resolver
 * daemon the stub resolver talks to.
 *
 * MP:
 *\li	The module ensures appropriate synchronization of data structures it
 *	creates and manipulates.
 *
 * Reliability:
 *\li	No anticipated impact.
 *
 * Resources:
 *\li	TBS
 *
 * Security:
 *\li	No anticipated impact.
 *
 * Standards:
 *\li	RFCs:	1034, 1035, 2181, TBS
 *\li	Drafts:	TBS
 */

#include <inttypes.h>
#include <stdbool.h>

#include <isc/lang.h>
#include <isc/socket.h>
#include <isc/stats.h>

#include <dns/types.h>
#include <dns/fixedname.h>

ISC_LANG_BEGINDECLS

/*%
 * A dns_fetchevent_t is sent when a 'fetch' completes.  Any of 'db',
 * 'node', 'rdataset', and 'sigrdataset' may be bound.  It is the
 * receiver's responsibility to detach before freeing the event.
 * \brief
 * 'rdataset', 'sigrdataset', 'client' and 'id' are the values that were
 * supplied when dns_resolver_createfetch() was called.  They are returned
 *  to the caller so that they may be freed.
 */
typedef struct dns_fetchevent {
	ISC_EVENT_COMMON(struct dns_fetchevent);
	dns_fetch_t *			fetch;
	isc_result_t			result;
	dns_rdatatype_t			qtype;
	dns_db_t *			db;
	dns_dbnode_t *			node;
	dns_rdataset_t *		rdataset;
	dns_rdataset_t *		sigrdataset;
	dns_fixedname_t			foundname;
	isc_sockaddr_t *		client;
	dns_messageid_t			id;
	isc_result_t			vresult;
} dns_fetchevent_t;

/*%
 * The two quota types (fetches-per-zone and fetches-per-server)
 */
typedef enum {
	dns_quotatype_zone = 0,
	dns_quotatype_server
} dns_quotatype_t;

/*
 * Options that modify how a 'fetch' is done.
 */
#define DNS_FETCHOPT_TCP		0x00001	     /*%< Use TCP. */
#define DNS_FETCHOPT_UNSHARED		0x00002	     /*%< See below. */
#define DNS_FETCHOPT_RECURSIVE		0x00004	     /*%< Set RD? */
#define DNS_FETCHOPT_NOEDNS0		0x00008	     /*%< Do not use EDNS. */
#define DNS_FETCHOPT_FORWARDONLY	0x00010	     /*%< Only use forwarders. */
#define DNS_FETCHOPT_NOVALIDATE		0x00020	     /*%< Disable validation. */
#define DNS_FETCHOPT_EDNS512		0x00040	     /*%< Advertise a 512 byte
					0		  UDP buffer. */
#define DNS_FETCHOPT_WANTNSID		0x00080	     /*%< Request NSID */
#define DNS_FETCHOPT_PREFETCH		0x00100	     /*%< Do prefetch */
#define DNS_FETCHOPT_NOCDFLAG		0x00200	     /*%< Don't set CD flag. */
#define DNS_FETCHOPT_NONTA		0x00400	     /*%< Ignore NTA table. */
/* RESERVED ECS				0x00000 */
/* RESERVED ECS				0x01000 */
/* RESERVED ECS				0x02000 */
/* RESERVED TCPCLIENT			0x04000 */
#define DNS_FETCHOPT_NOCACHED		0x08000	     /*%< Force cache update. */
#define DNS_FETCHOPT_NOFORWARD		0x80000 /*%< Do not use forwarders
							if possible. */

/* Reserved in use by adb.c		0x00400000 */
#define	DNS_FETCHOPT_EDNSVERSIONSET	0x00800000
#define	DNS_FETCHOPT_EDNSVERSIONMASK	0xff000000
#define	DNS_FETCHOPT_EDNSVERSIONSHIFT	24

/*
 * Upper bounds of class of query RTT (ms).  Corresponds to
 * dns_resstatscounter_queryrttX statistics counters.
 */
#define DNS_RESOLVER_QRYRTTCLASS0	10
#define DNS_RESOLVER_QRYRTTCLASS0STR	"10"
#define DNS_RESOLVER_QRYRTTCLASS1	100
#define DNS_RESOLVER_QRYRTTCLASS1STR	"100"
#define DNS_RESOLVER_QRYRTTCLASS2	500
#define DNS_RESOLVER_QRYRTTCLASS2STR	"500"
#define DNS_RESOLVER_QRYRTTCLASS3	800
#define DNS_RESOLVER_QRYRTTCLASS3STR	"800"
#define DNS_RESOLVER_QRYRTTCLASS4	1600
#define DNS_RESOLVER_QRYRTTCLASS4STR	"1600"

/*
 * XXXRTH  Should this API be made semi-private?  (I.e.
 * _dns_resolver_create()).
 */

#define DNS_RESOLVER_CHECKNAMES		0x01
#define DNS_RESOLVER_CHECKNAMESFAIL	0x02

isc_result_t
dns_resolver_create(dns_view_t *view,
		    isc_taskmgr_t *taskmgr,
		    unsigned int ntasks, unsigned int ndisp,
		    isc_socketmgr_t *socketmgr,
		    isc_timermgr_t *timermgr,
		    unsigned int options,
		    dns_dispatchmgr_t *dispatchmgr,
		    dns_dispatch_t *dispatchv4,
		    dns_dispatch_t *dispatchv6,
		    dns_resolver_t **resp);

/*%<
 * Create a resolver.
 *
 * Notes:
 *
 *\li	Generally, applications should not create a resolver directly, but
 *	should instead call dns_view_createresolver().
 *
 * Requires:
 *
 *\li	'view' is a valid view.
 *
 *\li	'taskmgr' is a valid task manager.
 *
 *\li	'ntasks' > 0.
 *
 *\li	'socketmgr' is a valid socket manager.
 *
 *\li	'timermgr' is a valid timer manager.
 *
 *\li	'dispatchv4' is a dispatch with an IPv4 UDP socket, or is NULL.
 *	If not NULL, 'ndisp' clones of it will be created by the resolver.
 *
 *\li	'dispatchv6' is a dispatch with an IPv6 UDP socket, or is NULL.
 *	If not NULL, 'ndisp' clones of it will be created by the resolver.
 *
 *\li	resp != NULL && *resp == NULL.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS				On success.
 *
 *\li	Anything else				Failure.
 */

void
dns_resolver_freeze(dns_resolver_t *res);
/*%<
 * Freeze resolver.
 *
 * Notes:
 *
 *\li	Certain configuration changes cannot be made after the resolver
 *	is frozen.  Fetches cannot be created until the resolver is frozen.
 *
 * Requires:
 *
 *\li	'res' is a valid resolver.
 *
 * Ensures:
 *
 *\li	'res' is frozen.
 */

void
dns_resolver_prime(dns_resolver_t *res);
/*%<
 * Prime resolver.
 *
 * Notes:
 *
 *\li	Resolvers which have a forwarding policy other than dns_fwdpolicy_only
 *	need to be primed with the root nameservers, otherwise the root
 *	nameserver hints data may be used indefinitely.  This function requests
 *	that the resolver start a priming fetch, if it isn't already priming.
 *
 * Requires:
 *
 *\li	'res' is a valid, frozen resolver.
 */


void
dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
			  isc_event_t **eventp);
/*%<
 * Send '*eventp' to 'task' when 'res' has completed shutdown.
 *
 * Notes:
 *
 *\li	It is not safe to detach the last reference to 'res' until
 *	shutdown is complete.
 *
 * Requires:
 *
 *\li	'res' is a valid resolver.
 *
 *\li	'task' is a valid task.
 *
 *\li	*eventp is a valid event.
 *
 * Ensures:
 *
 *\li	*eventp == NULL.
 */

void
dns_resolver_shutdown(dns_resolver_t *res);
/*%<
 * Start the shutdown process for 'res'.
 *
 * Notes:
 *
 *\li	This call has no effect if the resolver is already shutting down.
 *
 * Requires:
 *
 *\li	'res' is a valid resolver.
 */

void
dns_resolver_attach(dns_resolver_t *source, dns_resolver_t **targetp);

void
dns_resolver_detach(dns_resolver_t **resp);

isc_result_t
dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
			 dns_rdatatype_t type,
			 dns_name_t *domain, dns_rdataset_t *nameservers,
			 dns_forwarders_t *forwarders,
			 unsigned int options, isc_task_t *task,
			 isc_taskaction_t action, void *arg,
			 dns_rdataset_t *rdataset,
			 dns_rdataset_t *sigrdataset,
			 dns_fetch_t **fetchp);

isc_result_t
dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
			  dns_rdatatype_t type,
			  dns_name_t *domain, dns_rdataset_t *nameservers,
			  dns_forwarders_t *forwarders,
			  isc_sockaddr_t *client, uint16_t id,
			  unsigned int options, isc_task_t *task,
			  isc_taskaction_t action, void *arg,
			  dns_rdataset_t *rdataset,
			  dns_rdataset_t *sigrdataset,
			  dns_fetch_t **fetchp);
isc_result_t
dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name,
			  dns_rdatatype_t type,
			  dns_name_t *domain, dns_rdataset_t *nameservers,
			  dns_forwarders_t *forwarders,
			  isc_sockaddr_t *client, uint16_t id,
			  unsigned int options, unsigned int depth,
			  isc_counter_t *qc, isc_task_t *task,
			  isc_taskaction_t action, void *arg,
			  dns_rdataset_t *rdataset,
			  dns_rdataset_t *sigrdataset,
			  dns_fetch_t **fetchp);
/*%<
 * Recurse to answer a question.
 *
 * Notes:
 *
 *\li	This call starts a query for 'name', type 'type'.
 *
 *\li	The 'domain' is a parent domain of 'name' for which
 *	a set of name servers 'nameservers' is known.  If no
 *	such name server information is available, set
 * 	'domain' and 'nameservers' to NULL.
 *
 *\li	'forwarders' is unimplemented, and subject to change when
 *	we figure out how selective forwarding will work.
 *
 *\li	When the fetch completes (successfully or otherwise), a
 *	#DNS_EVENT_FETCHDONE event with action 'action' and arg 'arg' will be
 *	posted to 'task'.
 *
 *\li	The values of 'rdataset' and 'sigrdataset' will be returned in
 *	the FETCHDONE event.
 *
 *\li	'client' and 'id' are used for duplicate query detection.  '*client'
 *	must remain stable until after 'action' has been called or
 *	dns_resolver_cancelfetch() is called.
 *
 * Requires:
 *
 *\li	'res' is a valid resolver that has been frozen.
 *
 *\li	'name' is a valid name.
 *
 *\li	'type' is not a meta type other than ANY.
 *
 *\li	'domain' is a valid name or NULL.
 *
 *\li	'nameservers' is a valid NS rdataset (whose owner name is 'domain')
 *	iff. 'domain' is not NULL.
 *
 *\li	'forwarders' is NULL.
 *
 *\li	'client' is a valid sockaddr or NULL.
 *
 *\li	'options' contains valid options.
 *
 *\li	'rdataset' is a valid, disassociated rdataset.
 *
 *\li	'sigrdataset' is NULL, or is a valid, disassociated rdataset.
 *
 *\li	fetchp != NULL && *fetchp == NULL.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS					Success
 *\li	#DNS_R_DUPLICATE
 *\li	#DNS_R_DROP
 *
 *\li	Many other values are possible, all of which indicate failure.
 */

void
dns_resolver_cancelfetch(dns_fetch_t *fetch);
/*%<
 * Cancel 'fetch'.
 *
 * Notes:
 *
 *\li	If 'fetch' has not completed, post its FETCHDONE event with a
 *	result code of #ISC_R_CANCELED.
 *
 * Requires:
 *
 *\li	'fetch' is a valid fetch.
 */

void
dns_resolver_destroyfetch(dns_fetch_t **fetchp);
/*%<
 * Destroy 'fetch'.
 *
 * Requires:
 *
 *\li	'*fetchp' is a valid fetch.
 *
 *\li	The caller has received the FETCHDONE event (either because the
 *	fetch completed or because dns_resolver_cancelfetch() was called).
 *
 * Ensures:
 *
 *\li	*fetchp == NULL.
 */

void
dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx,
		      isc_logcategory_t *category, isc_logmodule_t *module,
		      int level, bool duplicateok);
/*%<
 * Dump a log message on internal state at the completion of given 'fetch'.
 * 'lctx', 'category', 'module', and 'level' are used to write the log message.
 * By default, only one log message is written even if the corresponding fetch
 * context serves multiple clients; if 'duplicateok' is true the suppression
 * is disabled and the message can be written every time this function is
 * called.
 *
 * Requires:
 *
 *\li	'fetch' is a valid fetch, and has completed.
 */

dns_dispatchmgr_t *
dns_resolver_dispatchmgr(dns_resolver_t *resolver);

dns_dispatch_t *
dns_resolver_dispatchv4(dns_resolver_t *resolver);

dns_dispatch_t *
dns_resolver_dispatchv6(dns_resolver_t *resolver);

isc_socketmgr_t *
dns_resolver_socketmgr(dns_resolver_t *resolver);

isc_taskmgr_t *
dns_resolver_taskmgr(dns_resolver_t *resolver);

uint32_t
dns_resolver_getlamettl(dns_resolver_t *resolver);
/*%<
 * Get the resolver's lame-ttl.  zero => no lame processing.
 *
 * Requires:
 *\li	'resolver' to be valid.
 */

void
dns_resolver_setlamettl(dns_resolver_t *resolver, uint32_t lame_ttl);
/*%<
 * Set the resolver's lame-ttl.  zero => no lame processing.
 *
 * Requires:
 *\li	'resolver' to be valid.
 */

unsigned int
dns_resolver_nrunning(dns_resolver_t *resolver);
/*%<
 * Return the number of currently running resolutions in this
 * resolver.  This is may be less than the number of outstanding
 * fetches due to multiple identical fetches, or more than the
 * number of of outstanding fetches due to the fact that resolution
 * can continue even though a fetch has been canceled.
 */

isc_result_t
dns_resolver_addalternate(dns_resolver_t *resolver, isc_sockaddr_t *alt,
			  dns_name_t *name, in_port_t port);
/*%<
 * Add alternate addresses to be tried in the event that the nameservers
 * for a zone are not available in the address families supported by the
 * operating system.
 *
 * Require:
 * \li	only one of 'name' or 'alt' to be valid.
 */

void
dns_resolver_setudpsize(dns_resolver_t *resolver, uint16_t udpsize);
/*%<
 * Set the EDNS UDP buffer size advertised by the server.
 */

uint16_t
dns_resolver_getudpsize(dns_resolver_t *resolver);
/*%<
 * Get the current EDNS UDP buffer size.
 */

void
dns_resolver_reset_algorithms(dns_resolver_t *resolver);
/*%<
 * Clear the disabled DNSSEC algorithms.
 */

void
dns_resolver_reset_ds_digests(dns_resolver_t *resolver);
/*%<
 * Clear the disabled DS/DLV digest types.
 */

isc_result_t
dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
			       unsigned int alg);
/*%<
 * Mark the given DNSSEC algorithm as disabled and below 'name'.
 * Valid algorithms are less than 256.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_RANGE
 *\li	#ISC_R_NOMEMORY
 */

isc_result_t
dns_resolver_disable_ds_digest(dns_resolver_t *resolver, dns_name_t *name,
			       unsigned int digest_type);
/*%<
 * Mark the given DS/DLV digest type as disabled and below 'name'.
 * Valid types are less than 256.
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_RANGE
 *\li	#ISC_R_NOMEMORY
 */

bool
dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
				 unsigned int alg);
/*%<
 * Check if the given algorithm is supported by this resolver.
 * This checks whether the algorithm has been disabled via
 * dns_resolver_disable_algorithm(), then checks the underlying
 * crypto libraries if it was not specifically disabled.
 */

bool
dns_resolver_ds_digest_supported(dns_resolver_t *resolver, dns_name_t *name,
				 unsigned int digest_type);
/*%<
 * Check if the given digest type is supported by this resolver.
 * This checks whether the digest type has been disabled via
 * dns_resolver_disable_ds_digest(), then checks the underlying
 * crypto libraries if it was not specifically disabled.
 */

void
dns_resolver_resetmustbesecure(dns_resolver_t *resolver);

isc_result_t
dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
			     bool value);

bool
dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name);


void
dns_resolver_settimeout(dns_resolver_t *resolver, unsigned int timeout);
/*%<
 * Set the length of time the resolver will work on a query, in milliseconds.
 *
 * 'timeout' was originally defined in seconds, and later redefined to be in
 * milliseconds.  Values less than or equal to 300 are treated as seconds.
 *
 * If timeout is 0, the default timeout will be applied.
 *
 * Requires:
 * \li  resolver to be valid.
 */

unsigned int
dns_resolver_gettimeout(dns_resolver_t *resolver);
/*%<
 * Get the current length of time the resolver will work on a query,
 * in milliseconds.
 *
 * Requires:
 * \li  resolver to be valid.
 */

void
dns_resolver_setclientsperquery(dns_resolver_t *resolver,
				uint32_t min, uint32_t max);
void
dns_resolver_setfetchesperzone(dns_resolver_t *resolver, uint32_t clients);

void
dns_resolver_getclientsperquery(dns_resolver_t *resolver, uint32_t *cur,
				uint32_t *min, uint32_t *max);

bool
dns_resolver_getzeronosoattl(dns_resolver_t *resolver);

void
dns_resolver_setzeronosoattl(dns_resolver_t *resolver, bool state);

unsigned int
dns_resolver_getretryinterval(dns_resolver_t *resolver);

void
dns_resolver_setretryinterval(dns_resolver_t *resolver, unsigned int interval);
/*%<
 * Sets the amount of time, in millseconds, that is waited for a reply
 * to a server before another server is tried.  Interacts with the
 * value of dns_resolver_getnonbackofftries() by trying that number of times
 * at this interval, before doing exponential backoff and doubling the interval
 * on each subsequent try, to a maximum of 10 seconds.  Defaults to 800 ms;
 * silently capped at 2000 ms.
 *
 * Requires:
 * \li	resolver to be valid.
 * \li  interval > 0.
 */

unsigned int
dns_resolver_getnonbackofftries(dns_resolver_t *resolver);

void
dns_resolver_setnonbackofftries(dns_resolver_t *resolver, unsigned int tries);
/*%<
 * Sets the number of failures of getting a reply from remote servers for
 * a query before backing off by doubling the retry interval for each
 * subsequent request sent.  Defaults to 3.
 *
 * Requires:
 * \li	resolver to be valid.
 * \li  tries > 0.
 */

unsigned int
dns_resolver_getoptions(dns_resolver_t *resolver);

void
dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name,
			 dns_rdatatype_t type, isc_time_t *expire);
/*%<
 * Add a entry to the bad cache for <name,type> that will expire at 'expire'.
 *
 * Requires:
 * \li	resolver to be valid.
 * \li	name to be valid.
 */

bool
dns_resolver_getbadcache(dns_resolver_t *resolver, dns_name_t *name,
			 dns_rdatatype_t type, isc_time_t *now);
/*%<
 * Check to see if there is a unexpired entry in the bad cache for
 * <name,type>.
 *
 * Requires:
 * \li	resolver to be valid.
 * \li	name to be valid.
 */

void
dns_resolver_flushbadcache(dns_resolver_t *resolver, dns_name_t *name);
/*%<
 * Flush the bad cache of all entries at 'name' if 'name' is non NULL.
 * Flush the entire bad cache if 'name' is NULL.
 *
 * Requires:
 * \li	resolver to be valid.
 */

void
dns_resolver_flushbadnames(dns_resolver_t *resolver, dns_name_t *name);
/*%<
 * Flush the bad cache of all entries at or below 'name'.
 *
 * Requires:
 * \li	resolver to be valid.
 * \li  name != NULL
 */

void
dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp);
/*%
 * Print out the contents of the bad cache to 'fp'.
 *
 * Requires:
 * \li	resolver to be valid.
 */

void
dns_resolver_setquerydscp4(dns_resolver_t *resolver, isc_dscp_t dscp);
isc_dscp_t
dns_resolver_getquerydscp4(dns_resolver_t *resolver);

void
dns_resolver_setquerydscp6(dns_resolver_t *resolver, isc_dscp_t dscp);
isc_dscp_t
dns_resolver_getquerydscp6(dns_resolver_t *resolver);
/*%
 * Get and set the DSCP values for the resolver's IPv4 and IPV6 query
 * sources.
 *
 * Requires:
 * \li	resolver to be valid.
 */

void
dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth);
unsigned int
dns_resolver_getmaxdepth(dns_resolver_t *resolver);
/*%
 * Get and set how many NS indirections will be followed when looking for
 * nameserver addresses.
 *
 * Requires:
 * \li	resolver to be valid.
 */

void
dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries);
unsigned int
dns_resolver_getmaxqueries(dns_resolver_t *resolver);
/*%
 * Get and set how many iterative queries will be allowed before
 * terminating a recursive query.
 *
 * Requires:
 * \li	resolver to be valid.
 */

void
dns_resolver_setquotaresponse(dns_resolver_t *resolver,
			     dns_quotatype_t which, isc_result_t resp);
isc_result_t
dns_resolver_getquotaresponse(dns_resolver_t *resolver, dns_quotatype_t which);
/*%
 * Get and set the result code that will be used when quotas
 * are exceeded. If 'which' is set to quotatype "zone", then the
 * result specified in 'resp' will be used when the fetches-per-zone
 * quota is exceeded by a fetch.  If 'which' is set to quotatype "server",
 * then the result specified in 'resp' will be used when the
 * fetches-per-server quota has been exceeded for all the
 * authoritative servers for a zone.  Valid choices are
 * DNS_R_DROP or DNS_R_SERVFAIL.
 *
 * Requires:
 * \li	'resolver' to be valid.
 * \li	'which' to be dns_quotatype_zone or dns_quotatype_server
 * \li	'resp' to be DNS_R_DROP or DNS_R_SERVFAIL.
 */

void
dns_resolver_dumpfetches(dns_resolver_t *resolver,
			 isc_statsformat_t format, FILE *fp);


#ifdef ENABLE_AFL
/*%
 * Enable fuzzing of resolver, changes behaviour and eliminates retries
 */
void dns_resolver_setfuzzing(void);
#endif

ISC_LANG_ENDDECLS

#endif /* DNS_RESOLVER_H */
db.h000064400000132747150415243060005320 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_DB_H
#define DNS_DB_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/db.h
 * \brief
 * The DNS DB interface allows named rdatasets to be stored and retrieved.
 *
 * The dns_db_t type is like a "virtual class".  To actually use
 * DBs, an implementation of the class is required.
 *
 * XXX more XXX
 *
 * MP:
 * \li	The module ensures appropriate synchronization of data structures it
 *	creates and manipulates.
 *
 * Reliability:
 * \li	No anticipated impact.
 *
 * Resources:
 * \li	TBS
 *
 * Security:
 * \li	No anticipated impact.
 *
 * Standards:
 * \li	None.
 */

/*****
 ***** Imports
 *****/

#include <inttypes.h>
#include <stdbool.h>

#include <isc/deprecated.h>
#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/ondestroy.h>
#include <isc/stats.h>
#include <isc/stdtime.h>

#include <dns/clientinfo.h>
#include <dns/fixedname.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdataset.h>
#include <dns/rpz.h>
#include <dns/types.h>

ISC_LANG_BEGINDECLS

/*****
 ***** Types
 *****/

typedef struct dns_dbmethods {
	void		(*attach)(dns_db_t *source, dns_db_t **targetp);
	void		(*detach)(dns_db_t **dbp);
	isc_result_t	(*beginload)(dns_db_t *db,
				     dns_rdatacallbacks_t *callbacks);
	isc_result_t	(*endload)(dns_db_t *db,
				     dns_rdatacallbacks_t *callbacks);
	isc_result_t	(*serialize)(dns_db_t *db,
				     dns_dbversion_t *version, FILE *file);
	isc_result_t	(*dump)(dns_db_t *db, dns_dbversion_t *version,
				const char *filename,
				dns_masterformat_t masterformat);
	void		(*currentversion)(dns_db_t *db,
					  dns_dbversion_t **versionp);
	isc_result_t	(*newversion)(dns_db_t *db,
				      dns_dbversion_t **versionp);
	void		(*attachversion)(dns_db_t *db, dns_dbversion_t *source,
					 dns_dbversion_t **targetp);
	void		(*closeversion)(dns_db_t *db,
					dns_dbversion_t **versionp,
					bool commit);
	isc_result_t	(*findnode)(dns_db_t *db, dns_name_t *name,
				    bool create,
				    dns_dbnode_t **nodep);
	isc_result_t	(*find)(dns_db_t *db, dns_name_t *name,
				dns_dbversion_t *version,
				dns_rdatatype_t type, unsigned int options,
				isc_stdtime_t now,
				dns_dbnode_t **nodep, dns_name_t *foundname,
				dns_rdataset_t *rdataset,
				dns_rdataset_t *sigrdataset);
	isc_result_t	(*findzonecut)(dns_db_t *db, dns_name_t *name,
				       unsigned int options, isc_stdtime_t now,
				       dns_dbnode_t **nodep,
				       dns_name_t *foundname,
				       dns_rdataset_t *rdataset,
				       dns_rdataset_t *sigrdataset);
	void		(*attachnode)(dns_db_t *db,
				      dns_dbnode_t *source,
				      dns_dbnode_t **targetp);
	void		(*detachnode)(dns_db_t *db,
				      dns_dbnode_t **targetp);
	isc_result_t	(*expirenode)(dns_db_t *db, dns_dbnode_t *node,
				      isc_stdtime_t now);
	void		(*printnode)(dns_db_t *db, dns_dbnode_t *node,
				     FILE *out);
	isc_result_t 	(*createiterator)(dns_db_t *db, unsigned int options,
					  dns_dbiterator_t **iteratorp);
	isc_result_t	(*findrdataset)(dns_db_t *db, dns_dbnode_t *node,
					dns_dbversion_t *version,
					dns_rdatatype_t type,
					dns_rdatatype_t covers,
					isc_stdtime_t now,
					dns_rdataset_t *rdataset,
					dns_rdataset_t *sigrdataset);
	isc_result_t	(*allrdatasets)(dns_db_t *db, dns_dbnode_t *node,
					dns_dbversion_t *version,
					isc_stdtime_t now,
					dns_rdatasetiter_t **iteratorp);
	isc_result_t	(*addrdataset)(dns_db_t *db, dns_dbnode_t *node,
				       dns_dbversion_t *version,
				       isc_stdtime_t now,
				       dns_rdataset_t *rdataset,
				       unsigned int options,
				       dns_rdataset_t *addedrdataset);
	isc_result_t	(*subtractrdataset)(dns_db_t *db, dns_dbnode_t *node,
					    dns_dbversion_t *version,
					    dns_rdataset_t *rdataset,
					    unsigned int options,
					    dns_rdataset_t *newrdataset);
	isc_result_t	(*deleterdataset)(dns_db_t *db, dns_dbnode_t *node,
					  dns_dbversion_t *version,
					  dns_rdatatype_t type,
					  dns_rdatatype_t covers);
	bool	(*issecure)(dns_db_t *db);
	unsigned int	(*nodecount)(dns_db_t *db);
	bool	(*ispersistent)(dns_db_t *db);
	void		(*overmem)(dns_db_t *db, bool overmem);
	void		(*settask)(dns_db_t *db, isc_task_t *);
	isc_result_t	(*getoriginnode)(dns_db_t *db, dns_dbnode_t **nodep);
	void		(*transfernode)(dns_db_t *db, dns_dbnode_t **sourcep,
					dns_dbnode_t **targetp);
	isc_result_t    (*getnsec3parameters)(dns_db_t *db,
					      dns_dbversion_t *version,
					      dns_hash_t *hash,
					      uint8_t *flags,
					      uint16_t *iterations,
					      unsigned char *salt,
					      size_t *salt_len);
	isc_result_t    (*findnsec3node)(dns_db_t *db, dns_name_t *name,
					 bool create,
					 dns_dbnode_t **nodep);
	isc_result_t	(*setsigningtime)(dns_db_t *db,
					  dns_rdataset_t *rdataset,
					  isc_stdtime_t resign);
	isc_result_t	(*getsigningtime)(dns_db_t *db,
					  dns_rdataset_t *rdataset,
					  dns_name_t *name);
	void		(*resigned)(dns_db_t *db, dns_rdataset_t *rdataset,
					   dns_dbversion_t *version);
	bool	(*isdnssec)(dns_db_t *db);
	dns_stats_t	*(*getrrsetstats)(dns_db_t *db);
	void		(*rpz_attach)(dns_db_t *db, dns_rpz_zones_t *rpzs,
				      dns_rpz_num_t rpz_num);
	isc_result_t	(*rpz_ready)(dns_db_t *db);
	isc_result_t	(*findnodeext)(dns_db_t *db, dns_name_t *name,
				     bool create,
				     dns_clientinfomethods_t *methods,
				     dns_clientinfo_t *clientinfo,
				     dns_dbnode_t **nodep);
	isc_result_t	(*findext)(dns_db_t *db, dns_name_t *name,
				   dns_dbversion_t *version,
				   dns_rdatatype_t type, unsigned int options,
				   isc_stdtime_t now,
				   dns_dbnode_t **nodep, dns_name_t *foundname,
				   dns_clientinfomethods_t *methods,
				   dns_clientinfo_t *clientinfo,
				   dns_rdataset_t *rdataset,
				   dns_rdataset_t *sigrdataset);
	isc_result_t	(*setcachestats)(dns_db_t *db, isc_stats_t *stats);
	size_t		(*hashsize)(dns_db_t *db);
	isc_result_t	(*nodefullname)(dns_db_t *db, dns_dbnode_t *node,
					dns_name_t *name);
	isc_result_t	(*getsize)(dns_db_t *db, dns_dbversion_t *version,
				   uint64_t *records, uint64_t *bytes);
	isc_result_t	(*setservestalettl)(dns_db_t *db, dns_ttl_t ttl);
	isc_result_t	(*getservestalettl)(dns_db_t *db, dns_ttl_t *ttl);
} dns_dbmethods_t;

typedef isc_result_t
(*dns_dbcreatefunc_t)(isc_mem_t *mctx, dns_name_t *name,
		      dns_dbtype_t type, dns_rdataclass_t rdclass,
		      unsigned int argc, char *argv[], void *driverarg,
		      dns_db_t **dbp);

typedef isc_result_t
(*dns_dbupdate_callback_t)(dns_db_t *db, void *fn_arg);

#define DNS_DB_MAGIC		ISC_MAGIC('D','N','S','D')
#define DNS_DB_VALID(db)	ISC_MAGIC_VALID(db, DNS_DB_MAGIC)

/*%
 * This structure is actually just the common prefix of a DNS db
 * implementation's version of a dns_db_t.
 * \brief
 * Direct use of this structure by clients is forbidden.  DB implementations
 * may change the structure.  'magic' must be DNS_DB_MAGIC for any of the
 * dns_db_ routines to work.  DB implementations must maintain all DB
 * invariants.
 */
struct dns_db {
	unsigned int				magic;
	unsigned int				impmagic;
	dns_dbmethods_t *			methods;
	uint16_t				attributes;
	dns_rdataclass_t			rdclass;
	dns_name_t				origin;
	isc_ondestroy_t				ondest;
	isc_mem_t *				mctx;
	ISC_LIST(dns_dbonupdatelistener_t)	update_listeners;
};

#define DNS_DBATTR_CACHE		0x01
#define DNS_DBATTR_STUB			0x02

struct dns_dbonupdatelistener {
	dns_dbupdate_callback_t			onupdate;
	void *					onupdate_arg;
	ISC_LINK(dns_dbonupdatelistener_t)	link;
};

/*@{*/
/*%
 * Options that can be specified for dns_db_find().
 */
#define DNS_DBFIND_GLUEOK		0x0001
#define DNS_DBFIND_VALIDATEGLUE		0x0002
#define DNS_DBFIND_NOWILD		0x0004
#define DNS_DBFIND_PENDINGOK		0x0008
#define DNS_DBFIND_NOEXACT		0x0010
#define DNS_DBFIND_FORCENSEC		0x0020
#define DNS_DBFIND_COVERINGNSEC		0x0040
#define DNS_DBFIND_FORCENSEC3		0x0080
#define DNS_DBFIND_ADDITIONALOK		0x0100
#define DNS_DBFIND_NOZONECUT		0x0200
#define DNS_DBFIND_STALEOK		0x0400
/*@}*/

/*@{*/
/*%
 * Options that can be specified for dns_db_addrdataset().
 */
#define DNS_DBADD_MERGE			0x01
#define DNS_DBADD_FORCE			0x02
#define DNS_DBADD_EXACT			0x04
#define DNS_DBADD_EXACTTTL		0x08
#define DNS_DBADD_PREFETCH		0x10
/*@}*/

/*%
 * Options that can be specified for dns_db_subtractrdataset().
 */
#define DNS_DBSUB_EXACT			0x01
#define DNS_DBSUB_WANTOLD		0x02

/*@{*/
/*%
 * Iterator options
 */
#define DNS_DB_RELATIVENAMES	0x1
#define DNS_DB_NSEC3ONLY	0x2
#define DNS_DB_NONSEC3		0x4
/*@}*/

/*****
 ***** Methods
 *****/

/***
 *** Basic DB Methods
 ***/

isc_result_t
dns_db_create(isc_mem_t *mctx, const char *db_type, dns_name_t *origin,
	      dns_dbtype_t type, dns_rdataclass_t rdclass,
	      unsigned int argc, char *argv[], dns_db_t **dbp);
/*%<
 * Create a new database using implementation 'db_type'.
 *
 * Notes:
 * \li	All names in the database must be subdomains of 'origin' and in class
 *	'rdclass'.  The database makes its own copy of the origin, so the
 *	caller may do whatever they like with 'origin' and its storage once the
 *	call returns.
 *
 * \li	DB implementation-specific parameters are passed using argc and argv.
 *
 * Requires:
 *
 * \li	dbp != NULL and *dbp == NULL
 *
 * \li	'origin' is a valid absolute domain name.
 *
 * \li	mctx is a valid memory context
 *
 * Ensures:
 *
 * \li	A copy of 'origin' has been made for the databases use, and the
 *	caller is free to do whatever they want with the name and storage
 *	associated with 'origin'.
 *
 * Returns:
 *
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOMEMORY
 * \li	#ISC_R_NOTFOUND				db_type not found
 *
 * \li	Many other errors are possible, depending on what db_type was
 *	specified.
 */

void
dns_db_attach(dns_db_t *source, dns_db_t **targetp);
/*%<
 * Attach *targetp to source.
 *
 * Requires:
 *
 * \li	'source' is a valid database.
 *
 * \li	'targetp' points to a NULL dns_db_t *.
 *
 * Ensures:
 *
 * \li	*targetp is attached to source.
 */

void
dns_db_detach(dns_db_t **dbp);
/*%<
 * Detach *dbp from its database.
 *
 * Requires:
 *
 * \li	'dbp' points to a valid database.
 *
 * Ensures:
 *
 * \li	*dbp is NULL.
 *
 * \li	If '*dbp' is the last reference to the database,
 *		all resources used by the database will be freed
 */

isc_result_t
dns_db_ondestroy(dns_db_t *db, isc_task_t *task, isc_event_t **eventp);
/*%<
 * Causes 'eventp' to be sent to be sent to 'task' when the database is
 * destroyed.
 *
 * Note; ownership of the eventp is taken from the caller (and *eventp is
 * set to NULL). The sender field of the event is set to 'db' before it is
 * sent to the task.
 */

bool
dns_db_iscache(dns_db_t *db);
/*%<
 * Does 'db' have cache semantics?
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * Returns:
 * \li	#true	'db' has cache semantics
 * \li	#false	otherwise
 */

bool
dns_db_iszone(dns_db_t *db);
/*%<
 * Does 'db' have zone semantics?
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * Returns:
 * \li	#true	'db' has zone semantics
 * \li	#false	otherwise
 */

bool
dns_db_isstub(dns_db_t *db);
/*%<
 * Does 'db' have stub semantics?
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * Returns:
 * \li	#true	'db' has zone semantics
 * \li	#false	otherwise
 */

bool
dns_db_issecure(dns_db_t *db);
/*%<
 * Is 'db' secure?
 *
 * Requires:
 *
 * \li	'db' is a valid database with zone semantics.
 *
 * Returns:
 * \li	#true	'db' is secure.
 * \li	#false	'db' is not secure.
 */

bool
dns_db_isdnssec(dns_db_t *db);
/*%<
 * Is 'db' secure or partially secure?
 *
 * Requires:
 *
 * \li	'db' is a valid database with zone semantics.
 *
 * Returns:
 * \li	#true	'db' is secure or is partially.
 * \li	#false	'db' is not secure.
 */

dns_name_t *
dns_db_origin(dns_db_t *db);
/*%<
 * The origin of the database.
 *
 * Note: caller must not try to change this name.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * Returns:
 *
 * \li	The origin of the database.
 */

dns_rdataclass_t
dns_db_class(dns_db_t *db);
/*%<
 * The class of the database.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * Returns:
 *
 * \li	The class of the database.
 */

isc_result_t
dns_db_beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks);
/*%<
 * Begin loading 'db'.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	This is the first attempt to load 'db'.
 *
 * \li  'callbacks' is a pointer to an initialized dns_rdatacallbacks_t
 *       structure.
 *
 * Ensures:
 *
 * \li	On success, callbacks->add will be a valid dns_addrdatasetfunc_t
 *      suitable for loading records into 'db' from a raw or text zone
 *      file. callbacks->add_private will be a valid DB load context
 *      which should be used as 'arg' when callbacks->add is called.
 *      callbacks->deserialize will be a valid dns_deserialize_func_t
 *      suitable for loading 'db' from a map format zone file.
 *
 * Returns:
 *
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOMEMORY
 *
 * \li	Other results are possible, depending upon the database
 *	implementation used, syntax errors in the master file, etc.
 */

isc_result_t
dns_db_endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks);
/*%<
 * Finish loading 'db'.
 *
 * Requires:
 *
 * \li	'db' is a valid database that is being loaded.
 *
 * \li	'callbacks' is a valid dns_rdatacallbacks_t structure.
 *
 * \li	callbacks->add_private is not NULL and is a valid database load context.
 *
 * Ensures:
 *
 * \li	'callbacks' is returned to its state prior to calling dns_db_beginload()
 *
 * Returns:
 *
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOMEMORY
 *
 * \li	Other results are possible, depending upon the database
 *	implementation used, syntax errors in the master file, etc.
 */

isc_result_t
dns_db_load(dns_db_t *db, const char *filename);

isc_result_t
dns_db_load2(dns_db_t *db, const char *filename, dns_masterformat_t format);

isc_result_t
dns_db_load3(dns_db_t *db, const char *filename, dns_masterformat_t format,
	     unsigned int options);
/*%<
 * Load master file 'filename' into 'db'.
 *
 * Notes:
 * \li	This routine is equivalent to calling
 *
 *\code
 *		dns_db_beginload();
 *		dns_master_loadfile();
 *		dns_db_endload();
 *\endcode
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	This is the first attempt to load 'db'.
 *
 * Returns:
 *
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOMEMORY
 *
 * \li	Other results are possible, depending upon the database
 *	implementation used, syntax errors in the master file, etc.
 */

isc_result_t
dns_db_serialize(dns_db_t *db, dns_dbversion_t *version, FILE *rbtfile);
/*%<
 * Dump version 'version' of 'db' to map-format file 'filename'.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	'version' is a valid version.
 *
 * Returns:
 *
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOMEMORY
 *
 * \li	Other results are possible, depending upon the database
 *	implementation used, OS file errors, etc.
 */

isc_result_t
dns_db_dump(dns_db_t *db, dns_dbversion_t *version, const char *filename);

isc_result_t
dns_db_dump2(dns_db_t *db, dns_dbversion_t *version, const char *filename,
	     dns_masterformat_t masterformat);
/*%<
 * Dump version 'version' of 'db' to master file 'filename'.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	'version' is a valid version.
 *
 * Returns:
 *
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOMEMORY
 *
 * \li	Other results are possible, depending upon the database
 *	implementation used, OS file errors, etc.
 */

/***
 *** Version Methods
 ***/

void
dns_db_currentversion(dns_db_t *db, dns_dbversion_t **versionp);
/*%<
 * Open the current version for reading.
 *
 * Requires:
 *
 * \li	'db' is a valid database with zone semantics.
 *
 * \li	versionp != NULL && *verisonp == NULL
 *
 * Ensures:
 *
 * \li	On success, '*versionp' is attached to the current version.
 *
 */

isc_result_t
dns_db_newversion(dns_db_t *db, dns_dbversion_t **versionp);
/*%<
 * Open a new version for reading and writing.
 *
 * Requires:
 *
 * \li	'db' is a valid database with zone semantics.
 *
 * \li	versionp != NULL && *verisonp == NULL
 *
 * Ensures:
 *
 * \li	On success, '*versionp' is attached to the current version.
 *
 * Returns:
 *
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOMEMORY
 *
 * \li	Other results are possible, depending upon the database
 *	implementation used.
 */

void
dns_db_attachversion(dns_db_t *db, dns_dbversion_t *source,
		     dns_dbversion_t **targetp);
/*%<
 * Attach '*targetp' to 'source'.
 *
 * Requires:
 *
 * \li	'db' is a valid database with zone semantics.
 *
 * \li	source is a valid open version
 *
 * \li	targetp != NULL && *targetp == NULL
 *
 * Ensures:
 *
 * \li	'*targetp' is attached to source.
 */

void
dns_db_closeversion(dns_db_t *db, dns_dbversion_t **versionp,
		    bool commit);
/*%<
 * Close version '*versionp'.
 *
 * Note: if '*versionp' is a read-write version and 'commit' is true,
 * then all changes made in the version will take effect, otherwise they
 * will be rolled back.  The value of 'commit' is ignored for read-only
 * versions.
 *
 * Requires:
 *
 * \li	'db' is a valid database with zone semantics.
 *
 * \li	'*versionp' refers to a valid version.
 *
 * \li	If committing a writable version, then there must be no other
 *	outstanding references to the version (e.g. an active rdataset
 *	iterator).
 *
 * Ensures:
 *
 * \li	*versionp == NULL
 *
 * \li	If *versionp is a read-write version, and commit is true, then
 *	the version will become the current version.  If !commit, then all
 *	changes made in the version will be undone, and the version will
 *	not become the current version.
 */

/***
 *** Node Methods
 ***/

isc_result_t
dns_db_findnode(dns_db_t *db, dns_name_t *name, bool create,
		dns_dbnode_t **nodep);

isc_result_t
dns_db_findnodeext(dns_db_t *db, dns_name_t *name, bool create,
		   dns_clientinfomethods_t *methods,
		   dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep);
/*%<
 * Find the node with name 'name'.
 *
 * dns_db_findnodeext() (findnode extended) also accepts parameters
 * 'methods' and 'clientinfo', which, when provided, enable the database to
 * retrieve information about the client from the caller, and modify its
 * response on the basis of that information.
 *
 * Notes:
 * \li	If 'create' is true and no node with name 'name' exists, then
 *	such a node will be created.
 *
 * \li	This routine is for finding or creating a node with the specified
 *	name.  There are no partial matches.  It is not suitable for use
 *	in building responses to ordinary DNS queries; clients which wish
 *	to do that should use dns_db_find() instead.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	'name' is a valid, non-empty, absolute name.
 *
 * \li	nodep != NULL && *nodep == NULL
 *
 * Ensures:
 *
 * \li	On success, *nodep is attached to the node with name 'name'.
 *
 * Returns:
 *
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOTFOUND			If !create and name not found.
 * \li	#ISC_R_NOMEMORY			Can only happen if create is true.
 *
 * \li	Other results are possible, depending upon the database
 *	implementation used.
 */

isc_result_t
dns_db_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
	    dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
	    dns_dbnode_t **nodep, dns_name_t *foundname,
	    dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);

isc_result_t
dns_db_findext(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
	       dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
	       dns_dbnode_t **nodep, dns_name_t *foundname,
	       dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
	       dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
/*%<
 * Find the best match for 'name' and 'type' in version 'version' of 'db'.
 *
 * dns_db_findext() (find extended) also accepts parameters 'methods'
 * and 'clientinfo', which when provided enable the database to retrieve
 * information about the client from the caller, and modify its response
 * on the basis of this information.
 *
 * Notes:
 *
 * \li	If type == dns_rdataset_any, then rdataset will not be bound.
 *
 * \li	If 'options' does not have #DNS_DBFIND_GLUEOK set, then no glue will
 *	be returned.  For zone databases, glue is as defined in RFC2181.
 *	For cache databases, glue is any rdataset with a trust of
 *	dns_trust_glue.
 *
 * \li	If 'options' does not have #DNS_DBFIND_ADDITIONALOK set, then no
 *	additional records will be returned.  Only caches can have
 *	rdataset with trust dns_trust_additional.
 *
 * \li	If 'options' does not have #DNS_DBFIND_PENDINGOK set, then no
 *	pending data will be returned.  This option is only meaningful for
 *	cache databases.
 *
 * \li	If the #DNS_DBFIND_NOWILD option is set, then wildcard matching will
 *	be disabled.  This option is only meaningful for zone databases.
 *
 * \li  If the #DNS_DBFIND_NOZONECUT option is set, the database is
 *	assumed to contain no zone cuts above 'name'.  An implementation
 *	may therefore choose to search for a match beginning at 'name'
 *	rather than walking down the tree to check check for delegations.
 *	If #DNS_DBFIND_NOWILD is not set, wildcard matching will be
 *	attempted at each node starting at the direct ancestor of 'name'
 *	and working up to the zone origin.  This option is only meaningful
 *	when querying redirect zones.
 *
 * \li	If the #DNS_DBFIND_FORCENSEC option is set, the database is assumed to
 *	have NSEC records, and these will be returned when appropriate.  This
 *	is only necessary when querying a database that was not secure
 *	when created.
 *
 * \li	If the DNS_DBFIND_COVERINGNSEC option is set, then look for a
 *	NSEC record that potentially covers 'name' if a answer cannot
 *	be found.  Note the returned NSEC needs to be checked to ensure
 *	that it is correct.  This only affects answers returned from the
 *	cache.
 *
 * \li	If the #DNS_DBFIND_FORCENSEC3 option is set, then we are looking
 *	in the NSEC3 tree and not the main tree.  Without this option being
 *	set NSEC3 records will not be found.
 *
 * \li	To respond to a query for SIG records, the caller should create a
 *	rdataset iterator and extract the signatures from each rdataset.
 *
 * \li	Making queries of type ANY with #DNS_DBFIND_GLUEOK is not recommended,
 *	because the burden of determining whether a given rdataset is valid
 *	glue or not falls upon the caller.
 *
 * \li	The 'now' field is ignored if 'db' is a zone database.  If 'db' is a
 *	cache database, an rdataset will not be found unless it expires after
 *	'now'.  Any ANY query will not match unless at least one rdataset at
 *	the node expires after 'now'.  If 'now' is zero, then the current time
 *	will be used.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	'type' is not SIG, or a meta-RR type other than 'ANY' (e.g. 'OPT').
 *
 * \li	'nodep' is NULL, or nodep is a valid pointer and *nodep == NULL.
 *
 * \li	'foundname' is a valid name with a dedicated buffer.
 *
 * \li	'rdataset' is NULL, or is a valid unassociated rdataset.
 *
 * Ensures,
 *	on a non-error completion:
 *
 *	\li	If nodep != NULL, then it is bound to the found node.
 *
 *	\li	If foundname != NULL, then it contains the full name of the
 *		found node.
 *
 *	\li	If rdataset != NULL and type != dns_rdatatype_any, then
 *		rdataset is bound to the found rdataset.
 *
 *	Non-error results are:
 *
 *	\li	#ISC_R_SUCCESS			The desired node and type were
 *						found.
 *
 *	\li	#DNS_R_GLUE			The desired node and type were
 *						found, but are glue.  This
 *						result can only occur if
 *						the DNS_DBFIND_GLUEOK option
 *						is set.  This result can only
 *						occur if 'db' is a zone
 *						database.  If type ==
 *						dns_rdatatype_any, then the
 *						node returned may contain, or
 *						consist entirely of invalid
 *						glue (i.e. data occluded by a
 *						zone cut).  The caller must
 *						take care not to return invalid
 *						glue to a client.
 *
 *	\li	#DNS_R_DELEGATION		The data requested is beneath
 *						a zone cut.  node, foundname,
 *						and rdataset reference the
 *						NS RRset of the zone cut.
 *						If 'db' is a cache database,
 *						then this is the deepest known
 *						delegation.
 *
 *	\li	#DNS_R_ZONECUT			type == dns_rdatatype_any, and
 *						the desired node is a zonecut.
 *						The caller must take care not
 *						to return inappropriate glue
 *						to a client.  This result can
 *						only occur if 'db' is a zone
 *						database and DNS_DBFIND_GLUEOK
 *						is set.
 *
 *	\li	#DNS_R_DNAME			The data requested is beneath
 *						a DNAME.  node, foundname,
 *						and rdataset reference the
 *						DNAME RRset.
 *
 *	\li	#DNS_R_CNAME			The rdataset requested was not
 *						found, but there is a CNAME
 *						at the desired name.  node,
 *						foundname, and rdataset
 *						reference the CNAME RRset.
 *
 *	\li	#DNS_R_NXDOMAIN			The desired name does not
 *						exist.
 *
 *	\li	#DNS_R_NXRRSET			The desired name exists, but
 *						the desired type does not.
 *
 *	\li	#ISC_R_NOTFOUND			The desired name does not
 *						exist, and no delegation could
 *						be found.  This result can only
 *						occur if 'db' is a cache
 *						database.  The caller should
 *						use its nameserver(s) of last
 *						resort (e.g. root hints).
 *
 *	\li	#DNS_R_NCACHENXDOMAIN		The desired name does not
 *						exist.  'node' is bound to the
 *						cache node with the desired
 *						name, and 'rdataset' contains
 *						the negative caching proof.
 *
 *	\li	#DNS_R_NCACHENXRRSET		The desired type does not
 *						exist.  'node' is bound to the
 *						cache node with the desired
 *						name, and 'rdataset' contains
 *						the negative caching proof.
 *
 *	\li	#DNS_R_EMPTYNAME		The name exists but there is
 *						no data at the name.
 *
 *	\li	#DNS_R_COVERINGNSEC		The returned data is a NSEC
 *						that potentially covers 'name'.
 *
 *	\li	#DNS_R_EMPTYWILD		The name is a wildcard without
 *						resource records.
 *
 *	Error results:
 *
 *	\li	#ISC_R_NOMEMORY
 *
 *	\li	#DNS_R_BADDB			Data that is required to be
 *						present in the DB, e.g. an NSEC
 *						record in a secure zone, is not
 *						present.
 *
 *	\li	Other results are possible, and should all be treated as
 *		errors.
 */

isc_result_t
dns_db_findzonecut(dns_db_t *db, dns_name_t *name,
		   unsigned int options, isc_stdtime_t now,
		   dns_dbnode_t **nodep, dns_name_t *foundname,
		   dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
/*%<
 * Find the deepest known zonecut which encloses 'name' in 'db'.
 *
 * Notes:
 *
 * \li	If the #DNS_DBFIND_NOEXACT option is set, then the zonecut returned
 *	(if any) will be the deepest known ancestor of 'name'.
 *
 * \li	If 'now' is zero, then the current time will be used.
 *
 * Requires:
 *
 * \li	'db' is a valid database with cache semantics.
 *
 * \li	'nodep' is NULL, or nodep is a valid pointer and *nodep == NULL.
 *
 * \li	'foundname' is a valid name with a dedicated buffer.
 *
 * \li	'rdataset' is NULL, or is a valid unassociated rdataset.
 *
 * Ensures, on a non-error completion:
 *
 * \li	If nodep != NULL, then it is bound to the found node.
 *
 * \li	If foundname != NULL, then it contains the full name of the
 *	found node.
 *
 * \li	If rdataset != NULL and type != dns_rdatatype_any, then
 *	rdataset is bound to the found rdataset.
 *
 * Non-error results are:
 *
 * \li	#ISC_R_SUCCESS
 *
 * \li	#ISC_R_NOTFOUND
 *
 * \li	Other results are possible, and should all be treated as
 *	errors.
 */

void
dns_db_attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp);
/*%<
 * Attach *targetp to source.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	'source' is a valid node.
 *
 * \li	'targetp' points to a NULL dns_dbnode_t *.
 *
 * Ensures:
 *
 * \li	*targetp is attached to source.
 */

void
dns_db_detachnode(dns_db_t *db, dns_dbnode_t **nodep);
/*%<
 * Detach *nodep from its node.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	'nodep' points to a valid node.
 *
 * Ensures:
 *
 * \li	*nodep is NULL.
 */

void
dns_db_transfernode(dns_db_t *db, dns_dbnode_t **sourcep,
		    dns_dbnode_t **targetp);
/*%<
 * Transfer a node between pointer.
 *
 * This is equivalent to calling dns_db_attachnode() then dns_db_detachnode().
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	'*sourcep' is a valid node.
 *
 * \li	'targetp' points to a NULL dns_dbnode_t *.
 *
 * Ensures:
 *
 * \li	'*sourcep' is NULL.
 */

isc_result_t
dns_db_expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now);
/*%<
 * Mark as stale all records at 'node' which expire at or before 'now'.
 *
 * Note: if 'now' is zero, then the current time will be used.
 *
 * Requires:
 *
 * \li	'db' is a valid cache database.
 *
 * \li	'node' is a valid node.
 */

void
dns_db_printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out);
/*%<
 * Print a textual representation of the contents of the node to
 * 'out'.
 *
 * Note: this function is intended for debugging, not general use.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	'node' is a valid node.
 */

/***
 *** DB Iterator Creation
 ***/

isc_result_t
dns_db_createiterator(dns_db_t *db, unsigned int options,
		      dns_dbiterator_t **iteratorp);
/*%<
 * Create an iterator for version 'version' of 'db'.
 *
 * Notes:
 *
 * \li	One or more of the following options can be set.
 *	#DNS_DB_RELATIVENAMES
 *	#DNS_DB_NSEC3ONLY
 *	#DNS_DB_NONSEC3
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	iteratorp != NULL && *iteratorp == NULL
 *
 * Ensures:
 *
 * \li	On success, *iteratorp will be a valid database iterator.
 *
 * Returns:
 *
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOMEMORY
 */

/***
 *** Rdataset Methods
 ***/

/*
 * XXXRTH  Should we check for glue and pending data in dns_db_findrdataset()?
 */

isc_result_t
dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
		    dns_rdatatype_t type, dns_rdatatype_t covers,
		    isc_stdtime_t now, dns_rdataset_t *rdataset,
		    dns_rdataset_t *sigrdataset);

/*%<
 * Search for an rdataset of type 'type' at 'node' that are in version
 * 'version' of 'db'.  If found, make 'rdataset' refer to it.
 *
 * Notes:
 *
 * \li	If 'version' is NULL, then the current version will be used.
 *
 * \li	Care must be used when using this routine to build a DNS response:
 *	'node' should have been found with dns_db_find(), not
 *	dns_db_findnode().  No glue checking is done.  No checking for
 *	pending data is done.
 *
 * \li	The 'now' field is ignored if 'db' is a zone database.  If 'db' is a
 *	cache database, an rdataset will not be found unless it expires after
 *	'now'.  If 'now' is zero, then the current time will be used.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	'node' is a valid node.
 *
 * \li	'rdataset' is a valid, disassociated rdataset.
 *
 * \li	'sigrdataset' is a valid, disassociated rdataset, or it is NULL.
 *
 * \li	If 'covers' != 0, 'type' must be SIG.
 *
 * \li	'type' is not a meta-RR type such as 'ANY' or 'OPT'.
 *
 * Ensures:
 *
 * \li	On success, 'rdataset' is associated with the found rdataset.
 *
 * Returns:
 *
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOTFOUND
 *
 * \li	Other results are possible, depending upon the database
 *	implementation used.
 */

isc_result_t
dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
		    isc_stdtime_t now, dns_rdatasetiter_t **iteratorp);
/*%<
 * Make '*iteratorp' an rdataset iterator for all rdatasets at 'node' in
 * version 'version' of 'db'.
 *
 * Notes:
 *
 * \li	If 'version' is NULL, then the current version will be used.
 *
 * \li	The 'now' field is ignored if 'db' is a zone database.  If 'db' is a
 *	cache database, an rdataset will not be found unless it expires after
 *	'now'.  Any ANY query will not match unless at least one rdataset at
 *	the node expires after 'now'.  If 'now' is zero, then the current time
 *	will be used.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	'node' is a valid node.
 *
 * \li	iteratorp != NULL && *iteratorp == NULL
 *
 * Ensures:
 *
 * \li	On success, '*iteratorp' is a valid rdataset iterator.
 *
 * Returns:
 *
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOTFOUND
 *
 * \li	Other results are possible, depending upon the database
 *	implementation used.
 */

isc_result_t
dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
		   isc_stdtime_t now, dns_rdataset_t *rdataset,
		   unsigned int options, dns_rdataset_t *addedrdataset);
/*%<
 * Add 'rdataset' to 'node' in version 'version' of 'db'.
 *
 * Notes:
 *
 * \li	If the database has zone semantics, the #DNS_DBADD_MERGE option is set,
 *	and an rdataset of the same type as 'rdataset' already exists at
 *	'node' then the contents of 'rdataset' will be merged with the existing
 *	rdataset.  If the option is not set, then rdataset will replace any
 *	existing rdataset of the same type.  If not merging and the
 *	#DNS_DBADD_FORCE option is set, then the data will update the database
 *	without regard to trust levels.  If not forcing the data, then the
 *	rdataset will only be added if its trust level is >= the trust level of
 *	any existing rdataset.  Forcing is only meaningful for cache databases.
 *	If #DNS_DBADD_EXACT is set then there must be no rdata in common between
 *	the old and new rdata sets.  If #DNS_DBADD_EXACTTTL is set then both
 *	the old and new rdata sets must have the same ttl.
 *
 * \li	The 'now' field is ignored if 'db' is a zone database.  If 'db' is
 *	a cache database, then the added rdataset will expire no later than
 *	now + rdataset->ttl.
 *
 * \li	If 'addedrdataset' is not NULL, then it will be attached to the
 *	resulting new rdataset in the database, or to the existing data if
 *	the existing data was better.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	'node' is a valid node.
 *
 * \li	'rdataset' is a valid, associated rdataset with the same class
 *	as 'db'.
 *
 * \li	'addedrdataset' is NULL, or a valid, unassociated rdataset.
 *
 * \li	The database has zone semantics and 'version' is a valid
 *	read-write version, or the database has cache semantics
 *	and version is NULL.
 *
 * \li	If the database has cache semantics, the #DNS_DBADD_MERGE option must
 *	not be set.
 *
 * Returns:
 *
 * \li	#ISC_R_SUCCESS
 * \li	#DNS_R_UNCHANGED			The operation did not change anything.
 * \li	#ISC_R_NOMEMORY
 * \li	#DNS_R_NOTEXACT
 *
 * \li	Other results are possible, depending upon the database
 *	implementation used.
 */

isc_result_t
dns_db_subtractrdataset(dns_db_t *db, dns_dbnode_t *node,
			dns_dbversion_t *version, dns_rdataset_t *rdataset,
			unsigned int options, dns_rdataset_t *newrdataset);
/*%<
 * Remove any rdata in 'rdataset' from 'node' in version 'version' of
 * 'db'.
 *
 * Notes:
 *
 * \li	If 'newrdataset' is not NULL, then it will be attached to the
 *	resulting new rdataset in the database, unless the rdataset has
 *	become nonexistent.  If DNS_DBSUB_EXACT is set then all elements
 *	of 'rdataset' must exist at 'node'.
 *
 *\li	If DNS_DBSUB_WANTOLD is set and the entire rdataset was deleted
 *	then return the original rdatatset in newrdataset if that existed.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	'node' is a valid node.
 *
 * \li	'rdataset' is a valid, associated rdataset with the same class
 *	as 'db'.
 *
 * \li	'newrdataset' is NULL, or a valid, unassociated rdataset.
 *
 * \li	The database has zone semantics and 'version' is a valid
 *	read-write version.
 *
 * Returns:
 *
 * \li	#ISC_R_SUCCESS
 * \li	#DNS_R_UNCHANGED			The operation did not change anything.
 * \li	#DNS_R_NXRRSET			All rdata of the same type as those
 *					in 'rdataset' have been deleted.
 * \li	#DNS_R_NOTEXACT			Some part of 'rdataset' did not
 *					exist and DNS_DBSUB_EXACT was set.
 *
 * \li	Other results are possible, depending upon the database
 *	implementation used.
 */

isc_result_t
dns_db_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
		      dns_dbversion_t *version, dns_rdatatype_t type,
		      dns_rdatatype_t covers);
/*%<
 * Make it so that no rdataset of type 'type' exists at 'node' in version
 * version 'version' of 'db'.
 *
 * Notes:
 *
 * \li	If 'type' is dns_rdatatype_any, then no rdatasets will exist in
 *	'version' (provided that the dns_db_deleterdataset() isn't followed
 *	by one or more dns_db_addrdataset() calls).
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	'node' is a valid node.
 *
 * \li	The database has zone semantics and 'version' is a valid
 *	read-write version, or the database has cache semantics
 *	and version is NULL.
 *
 * \li	'type' is not a meta-RR type, except for dns_rdatatype_any, which is
 *	allowed.
 *
 * \li	If 'covers' != 0, 'type' must be SIG.
 *
 * Returns:
 *
 * \li	#ISC_R_SUCCESS
 * \li	#DNS_R_UNCHANGED			No rdatasets of 'type' existed before
 *					the operation was attempted.
 *
 * \li	Other results are possible, depending upon the database
 *	implementation used.
 */

isc_result_t
dns_db_getsoaserial(dns_db_t *db, dns_dbversion_t *ver, uint32_t *serialp);
/*%<
 * Get the current SOA serial number from a zone database.
 *
 * Requires:
 * \li	'db' is a valid database with zone semantics.
 * \li	'ver' is a valid version.
 */

void
dns_db_overmem(dns_db_t *db, bool overmem);
/*%<
 * Enable / disable aggressive cache cleaning.
 */

unsigned int
dns_db_nodecount(dns_db_t *db);
/*%<
 * Count the number of nodes in 'db'.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * Returns:
 * \li	The number of nodes in the database
 */

size_t
dns_db_hashsize(dns_db_t *db);
/*%<
 * For database implementations using a hash table, report the
 * current number of buckets.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * Returns:
 * \li	The number of buckets in the database's hash table, or
 *      0 if not implemented.
 */

void
dns_db_settask(dns_db_t *db, isc_task_t *task);
/*%<
 * If task is set then the final detach maybe performed asynchronously.
 *
 * Requires:
 * \li	'db' is a valid database.
 * \li	'task' to be valid or NULL.
 */

bool
dns_db_ispersistent(dns_db_t *db);
/*%<
 * Is 'db' persistent?  A persistent database does not need to be loaded
 * from disk or written to disk.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * Returns:
 * \li	#true	'db' is persistent.
 * \li	#false	'db' is not persistent.
 */

isc_result_t
dns_db_register(const char *name, dns_dbcreatefunc_t create, void *driverarg,
		isc_mem_t *mctx, dns_dbimplementation_t **dbimp);

/*%<
 * Register a new database implementation and add it to the list of
 * supported implementations.
 *
 * Requires:
 *
 * \li 	'name' is not NULL
 * \li	'order' is a valid function pointer
 * \li	'mctx' is a valid memory context
 * \li	dbimp != NULL && *dbimp == NULL
 *
 * Returns:
 * \li	#ISC_R_SUCCESS	The registration succeeded
 * \li	#ISC_R_NOMEMORY	Out of memory
 * \li	#ISC_R_EXISTS	A database implementation with the same name exists
 *
 * Ensures:
 *
 * \li	*dbimp points to an opaque structure which must be passed to
 *	dns_db_unregister().
 */

void
dns_db_unregister(dns_dbimplementation_t **dbimp);
/*%<
 * Remove a database implementation from the list of supported
 * implementations.  No databases of this type can be active when this
 * is called.
 *
 * Requires:
 * \li 	dbimp != NULL && *dbimp == NULL
 *
 * Ensures:
 *
 * \li	Any memory allocated in *dbimp will be freed.
 */

isc_result_t
dns_db_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep);
/*%<
 * Get the origin DB node corresponding to the DB's zone.  This function
 * should typically succeed unless the underlying DB implementation doesn't
 * support the feature.
 *
 * Requires:
 *
 * \li	'db' is a valid zone database.
 * \li	'nodep' != NULL && '*nodep' == NULL
 *
 * Ensures:
 * \li	On success, '*nodep' will point to the DB node of the zone's origin.
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOTFOUND - the DB implementation does not support this feature.
 */

isc_result_t
dns_db_getnsec3parameters(dns_db_t *db, dns_dbversion_t *version,
			  dns_hash_t *hash, uint8_t *flags,
			  uint16_t *iterations,
			  unsigned char *salt, size_t *salt_length);
/*%<
 * Get the NSEC3 parameters that are associated with this zone.
 *
 * Requires:
 * \li	'db' is a valid zone database.
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOTFOUND - the DB implementation does not support this feature
 *			  or this zone does not have NSEC3 records.
 */

isc_result_t
dns_db_getsize(dns_db_t *db, dns_dbversion_t *version, uint64_t *records,
	       uint64_t *bytes);
/*%<
 * Get the number of records in the given version of the database as well
 * as the number bytes used to store those records.
 *
 * Requires:
 * \li	'db' is a valid zone database.
 * \li	'version' is NULL or a valid version.
 * \li	'records' is NULL or a pointer to return the record count in.
 * \li	'bytes' is NULL or a pointer to return the byte count in.
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOTIMPLEMENTED
 */

isc_result_t
dns_db_findnsec3node(dns_db_t *db, dns_name_t *name,
		     bool create, dns_dbnode_t **nodep);
/*%<
 * Find the NSEC3 node with name 'name'.
 *
 * Notes:
 * \li	If 'create' is true and no node with name 'name' exists, then
 *	such a node will be created.
 *
 * Requires:
 *
 * \li	'db' is a valid database.
 *
 * \li	'name' is a valid, non-empty, absolute name.
 *
 * \li	nodep != NULL && *nodep == NULL
 *
 * Ensures:
 *
 * \li	On success, *nodep is attached to the node with name 'name'.
 *
 * Returns:
 *
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOTFOUND			If !create and name not found.
 * \li	#ISC_R_NOMEMORY			Can only happen if create is true.
 *
 * \li	Other results are possible, depending upon the database
 *	implementation used.
 */

isc_result_t
dns_db_setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
		      isc_stdtime_t resign);
/*%<
 * Sets the re-signing time associated with 'rdataset' to 'resign'.
 *
 * Requires:
 * \li	'db' is a valid zone database.
 * \li	'rdataset' is or is to be associated with 'db'.
 * \li  'rdataset' is not pending removed from the heap via an
 *       uncommitted call to dns_db_resigned().
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOMEMORY
 * \li	#ISC_R_NOTIMPLEMENTED - Not supported by this DB implementation.
 */

isc_result_t
dns_db_getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, dns_name_t *name);
/*%<
 * Return the rdataset with the earliest signing time in the zone.
 * Note: the rdataset is version agnostic.
 *
 * Requires:
 * \li	'db' is a valid zone database.
 * \li	'rdataset' to be initialized but not associated.
 * \li	'name' to be NULL or have a buffer associated with it.
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOTFOUND - No dataset exists.
 */

void
dns_db_resigned(dns_db_t *db, dns_rdataset_t *rdataset,
		dns_dbversion_t *version);
/*%<
 * Mark 'rdataset' as not being available to be returned by
 * dns_db_getsigningtime().  If the changes associated with 'version'
 * are committed this will be permanent.  If the version is not committed
 * this change will be rolled back when the version is closed.  Until
 * 'version' is either committed or rolled back, 'rdataset' can no longer
 * be acted upon by dns_db_setsigningtime().
 *
 * Requires:
 * \li	'db' is a valid zone database.
 * \li	'rdataset' to be associated with 'db'.
 * \li	'version' to be open for writing.
 */

dns_stats_t *
dns_db_getrrsetstats(dns_db_t *db);
/*%<
 * Get statistics information counting RRsets stored in the DB, when available.
 * The statistics may not be available depending on the DB implementation.
 *
 * Requires:
 *
 * \li	'db' is a valid database (cache only).
 *
 * Returns:
 * \li	when available, a pointer to a statistics object created by
 *	dns_rdatasetstats_create(); otherwise NULL.
 */

isc_result_t
dns_db_setcachestats(dns_db_t *db, isc_stats_t *stats);
/*%<
 * Set the location in which to collect cache statistics.
 * This option may not exist depending on the DB implementation.
 *
 * Requires:
 *
 * \li	'db' is a valid database (cache only).
 *
 * Returns:
 * \li	when available, a pointer to a statistics object created by
 *	dns_rdatasetstats_create(); otherwise NULL.
 */

void
dns_db_rpz_attach(dns_db_t *db, dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num);
/*%<
 * Attach the response policy information for a view to a database for a
 * zone for the view.
 */

isc_result_t
dns_db_rpz_ready(dns_db_t *db);
/*%<
 * Finish loading a response policy zone.
 */

isc_result_t
dns_db_updatenotify_register(dns_db_t *db,
			     dns_dbupdate_callback_t fn,
			     void *fn_arg);
/*%<
 * Register a notify-on-update callback function to a database.
 *
 * Requires:
 *
 * \li	'db' is a valid database
 * \li	'db' does not have an update callback registered
 * \li	'fn' is not NULL
 *
 */

isc_result_t
dns_db_updatenotify_unregister(dns_db_t *db,
			       dns_dbupdate_callback_t fn,
			       void *fn_arg);
/*%<
 * Unregister a notify-on-update callback.
 *
 * Requires:
 *
 * \li	'db' is a valid database
 * \li	'db' has update callback registered
 *
 */

isc_result_t
dns_db_nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name);
/*%<
 * Get the name associated with a database node.
 *
 * Requires:
 *
 * \li	'db' is a valid database
 * \li	'node' and 'name' are not NULL
 */

isc_result_t
dns_db_setservestalettl(dns_db_t *db, dns_ttl_t ttl);
/*%<
 * Sets the maximum length of time that cached answers may be retained
 * past their normal TTL. Default value for the library is 0, disabling
 * the use of stale data.
 *
 * Requires:
 * \li	'db' is a valid cache database.
 * \li	'ttl' is the number of seconds to retain data past its normal expiry.
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOTIMPLEMENTED - Not supported by this DB implementation.
 */

isc_result_t
dns_db_getservestalettl(dns_db_t *db, dns_ttl_t *ttl);
/*%<
 * Gets maximum length of time that cached answers may be kept past
 * normal TTL expiration.
 *
 * Requires:
 * \li	'db' is a valid cache database.
 * \li	'ttl' is the number of seconds to retain data past its normal expiry.
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOTIMPLEMENTED - Not supported by this DB implementation.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_DB_H */
geoip.h000064400000005350150415243060006023 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_GEOIP_H
#define DNS_GEOIP_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/geoip.h
 * \brief
 * GeoIP/GeoIP2 data types and function prototypes.
 */

#if defined(HAVE_GEOIP) || defined(HAVE_GEOIP2)

/***
 *** Imports
 ***/

#include <stdbool.h>

#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/netaddr.h>

#include <dns/name.h>
#include <dns/types.h>
#include <dns/iptable.h>

/***
 *** Types
 ***/

typedef enum {
	dns_geoip_countrycode,
	dns_geoip_countrycode3,
	dns_geoip_countryname,
	dns_geoip_continentcode,
	dns_geoip_continent,
	dns_geoip_region,
	dns_geoip_regionname,
	dns_geoip_country_code,
	dns_geoip_country_code3,
	dns_geoip_country_name,
	dns_geoip_country_continentcode,
	dns_geoip_country_continent,
	dns_geoip_region_countrycode,
	dns_geoip_region_code,
	dns_geoip_region_name,
	dns_geoip_city_countrycode,
	dns_geoip_city_countrycode3,
	dns_geoip_city_countryname,
	dns_geoip_city_region,
	dns_geoip_city_regionname,
	dns_geoip_city_name,
	dns_geoip_city_postalcode,
	dns_geoip_city_metrocode,
	dns_geoip_city_areacode,
	dns_geoip_city_continentcode,
	dns_geoip_city_continent,
	dns_geoip_city_timezonecode,
	dns_geoip_isp_name,
	dns_geoip_org_name,
	dns_geoip_as_asnum,
	dns_geoip_domain_name,
	dns_geoip_netspeed_id
} dns_geoip_subtype_t;

typedef struct dns_geoip_elem {
	dns_geoip_subtype_t subtype;
	void *db;
	union {
		char as_string[256];
		int as_int;
	};
} dns_geoip_elem_t;

struct dns_geoip_databases {
#ifdef HAVE_GEOIP2
	void *country;		/* GeoIP2-Country or GeoLite2-Country */
	void *city;		/* GeoIP2-CIty or GeoLite2-City */
	void *domain;		/* GeoIP2-Domain */
	void *isp;		/* GeoIP2-ISP */
	void *as;		/* GeoIP2-ASN or GeoLite2-ASN */
#else /* HAVE_GEOIP */
	void *country_v4;	/* GeoIP DB 1 */
	void *city_v4;		/* GeoIP DB 2 or 6 */
	void *region;		/* GeoIP DB 3 or 7 */
	void *isp;		/* GeoIP DB 4 */
	void *org;		/* GeoIP DB 5 */
	void *as;		/* GeoIP DB 9 */
	void *netspeed;		/* GeoIP DB 10 */
	void *domain;		/* GeoIP DB 11 */
	void *country_v6;	/* GeoIP DB 12 */
	void *city_v6;		/* GeoIP DB 30 or 31 */
#endif /* HAVE_GEOIP */
};

/***
 *** Functions
 ***/

ISC_LANG_BEGINDECLS

bool
dns_geoip_match(const isc_netaddr_t *reqaddr, uint8_t *scope,
		const dns_geoip_databases_t *geoip,
		const dns_geoip_elem_t *elt);

void
dns_geoip_shutdown(void);

ISC_LANG_ENDDECLS

#endif /* HAVE_GEOIP | HAVE_GEOIP2 */

#endif /* DNS_GEOIP_H */
dbtable.h000064400000006135150415243060006317 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_DBTABLE_H
#define DNS_DBTABLE_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/dbtable.h
 * \brief
 * DNS DB Tables
 *
 * XXX TBS XXX
 *
 * MP:
 *\li	The module ensures appropriate synchronization of data structures it
 *	creates and manipulates.
 *
 * Reliability:
 *\li	No anticipated impact.
 *
 * Resources:
 *\li	None.
 *
 * Security:
 *\li	No anticipated impact.
 *
 * Standards:
 *\li	None.
 */

#include <isc/lang.h>

#include <dns/types.h>

#define DNS_DBTABLEFIND_NOEXACT		0x01

ISC_LANG_BEGINDECLS

isc_result_t
dns_dbtable_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
		   dns_dbtable_t **dbtablep);
/*%<
 * Make a new dbtable of class 'rdclass'
 *
 * Requires:
 *\li	mctx != NULL
 * \li	dbtablep != NULL && *dptablep == NULL
 *\li	'rdclass' is a valid class
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *\li	#ISC_R_UNEXPECTED
 */

void
dns_dbtable_attach(dns_dbtable_t *source, dns_dbtable_t **targetp);
/*%<
 * Attach '*targetp' to 'source'.
 *
 * Requires:
 *
 *\li	'source' is a valid dbtable.
 *
 *\li	'targetp' points to a NULL dns_dbtable_t *.
 *
 * Ensures:
 *
 *\li	*targetp is attached to source.
 */

void
dns_dbtable_detach(dns_dbtable_t **dbtablep);
/*%<
 * Detach *dbtablep from its dbtable.
 *
 * Requires:
 *
 *\li	'*dbtablep' points to a valid dbtable.
 *
 * Ensures:
 *
 *\li	*dbtablep is NULL.
 *
 *\li	If '*dbtablep' is the last reference to the dbtable,
 *		all resources used by the dbtable will be freed
 */

isc_result_t
dns_dbtable_add(dns_dbtable_t *dbtable, dns_db_t *db);
/*%<
 * Add 'db' to 'dbtable'.
 *
 * Requires:
 *\li	'dbtable' is a valid dbtable.
 *
 *\li	'db' is a valid database with the same class as 'dbtable'
 */

void
dns_dbtable_remove(dns_dbtable_t *dbtable, dns_db_t *db);
/*%<
 * Remove 'db' from 'dbtable'.
 *
 * Requires:
 *\li	'db' was previously added to 'dbtable'.
 */

void
dns_dbtable_adddefault(dns_dbtable_t *dbtable, dns_db_t *db);
/*%<
 * Use 'db' as the result of a dns_dbtable_find() if no better match is
 * available.
 */

void
dns_dbtable_getdefault(dns_dbtable_t *dbtable, dns_db_t **db);
/*%<
 * Get the 'db' used as the result of a dns_dbtable_find()
 * if no better match is available.
 */

void
dns_dbtable_removedefault(dns_dbtable_t *dbtable);
/*%<
 * Remove the default db from 'dbtable'.
 */

isc_result_t
dns_dbtable_find(dns_dbtable_t *dbtable, dns_name_t *name,
		 unsigned int options, dns_db_t **dbp);
/*%<
 * Find the deepest match to 'name' in the dbtable, and return it
 *
 * Notes:
 *\li	If the DNS_DBTABLEFIND_NOEXACT option is set, the best partial
 *	match (if any) to 'name' will be returned.
 *
 * Returns:
 * \li #ISC_R_SUCCESS		on success
 *\li	     something else:		no default and match
 */

ISC_LANG_ENDDECLS

#endif /* DNS_DBTABLE_H */
adb.h000064400000054103150415243060005446 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_ADB_H
#define DNS_ADB_H 1

/*****
 ***** Module Info
 *****/

/*! \file dns/adb.h
 *\brief
 * DNS Address Database
 *
 * This module implements an address database (ADB) for mapping a name
 * to an isc_sockaddr_t. It also provides statistical information on
 * how good that address might be.
 *
 * A client will pass in a dns_name_t, and the ADB will walk through
 * the rdataset looking up addresses associated with the name.  If it
 * is found on the internal lists, a structure is filled in with the
 * address information and stats for found addresses.
 *
 * If the name cannot be found on the internal lists, a new entry will
 * be created for a name if all the information needed can be found
 * in the zone table or cache.  This new address will then be returned.
 *
 * If a request must be made to remote servers to satisfy a name lookup,
 * this module will start fetches to try to complete these addresses.  When
 * at least one more completes, an event is sent to the caller.  If none of
 * them resolve before the fetch times out, an event indicating this is
 * sent instead.
 *
 * Records are stored internally until a timer expires. The timer is the
 * smaller of the TTL or signature validity period.
 *
 * Lameness is stored per <qname,qtype> tuple, and this data hangs off each
 * address field.  When an address is marked lame for a given tuple the address
 * will not be returned to a caller.
 *
 *
 * MP:
 *
 *\li	The ADB takes care of all necessary locking.
 *
 *\li	Only the task which initiated the name lookup can cancel the lookup.
 *
 *
 * Security:
 *
 *\li	None, since all data stored is required to be pre-filtered.
 *	(Cache needs to be sane, fetches return bounds-checked and sanity-
 *       checked data, caller passes a good dns_name_t for the zone, etc)
 */

/***
 *** Imports
 ***/

#include <inttypes.h>
#include <stdbool.h>

#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/sockaddr.h>

#include <dns/types.h>
#include <dns/view.h>

ISC_LANG_BEGINDECLS

/***
 *** Magic number checks
 ***/

#define DNS_ADBFIND_MAGIC	  ISC_MAGIC('a','d','b','H')
#define DNS_ADBFIND_VALID(x)	  ISC_MAGIC_VALID(x, DNS_ADBFIND_MAGIC)
#define DNS_ADBADDRINFO_MAGIC	  ISC_MAGIC('a','d','A','I')
#define DNS_ADBADDRINFO_VALID(x)  ISC_MAGIC_VALID(x, DNS_ADBADDRINFO_MAGIC)


/***
 *** TYPES
 ***/

typedef struct dns_adbname		dns_adbname_t;

/*!
 *\brief
 * Represents a lookup for a single name.
 *
 * On return, the client can safely use "list", and can reorder the list.
 * Items may not be _deleted_ from this list, however, or added to it
 * other than by using the dns_adb_*() API.
 */
struct dns_adbfind {
	/* Public */
	unsigned int			magic;		/*%< RO: magic */
	dns_adbaddrinfolist_t		list;		/*%< RO: list of addrs */
	unsigned int			query_pending;	/*%< RO: partial list */
	unsigned int			partial_result;	/*%< RO: addrs missing */
	unsigned int			options;	/*%< RO: options */
	isc_result_t			result_v4;	/*%< RO: v4 result */
	isc_result_t			result_v6;	/*%< RO: v6 result */
	ISC_LINK(dns_adbfind_t)		publink;	/*%< RW: client use */

	/* Private */
	isc_mutex_t			lock;		/* locks all below */
	in_port_t			port;
	int				name_bucket;
	unsigned int			flags;
	dns_adbname_t		       *adbname;
	dns_adb_t		       *adb;
	isc_event_t			event;
	ISC_LINK(dns_adbfind_t)		plink;
};

/*
 * _INET:
 * _INET6:
 *	return addresses of that type.
 *
 * _EMPTYEVENT:
 *	Only schedule an event if no addresses are known.
 *	Must set _WANTEVENT for this to be meaningful.
 *
 * _WANTEVENT:
 *	An event is desired.  Check this bit in the returned find to see
 *	if one will actually be generated.
 *
 * _AVOIDFETCHES:
 *	If set, fetches will not be generated unless no addresses are
 *	available in any of the address families requested.
 *
 * _STARTATZONE:
 *	Fetches will start using the closest zone data or use the root servers.
 *	This is useful for reestablishing glue that has expired.
 *
 * _GLUEOK:
 * _HINTOK:
 *	Glue or hints are ok.  These are used when matching names already
 *	in the adb, and when dns databases are searched.
 *
 * _RETURNLAME:
 *	Return lame servers in a find, so that all addresses are returned.
 *
 * _LAMEPRUNED:
 *	At least one address was omitted from the list because it was lame.
 *	This bit will NEVER be set if _RETURNLAME is set in the createfind().
 */
/*% Return addresses of type INET. */
#define DNS_ADBFIND_INET		0x00000001
/*% Return addresses of type INET6. */
#define DNS_ADBFIND_INET6		0x00000002
#define DNS_ADBFIND_ADDRESSMASK		0x00000003
/*%
 *      Only schedule an event if no addresses are known.
 *      Must set _WANTEVENT for this to be meaningful.
 */
#define DNS_ADBFIND_EMPTYEVENT		0x00000004
/*%
 *	An event is desired.  Check this bit in the returned find to see
 *	if one will actually be generated.
 */
#define DNS_ADBFIND_WANTEVENT		0x00000008
/*%
 *	If set, fetches will not be generated unless no addresses are
 *	available in any of the address families requested.
 */
#define DNS_ADBFIND_AVOIDFETCHES	0x00000010
/*%
 *	Fetches will start using the closest zone data or use the root servers.
 *	This is useful for reestablishing glue that has expired.
 */
#define DNS_ADBFIND_STARTATZONE		0x00000020
/*%
 *	Glue or hints are ok.  These are used when matching names already
 *	in the adb, and when dns databases are searched.
 */
#define DNS_ADBFIND_GLUEOK		0x00000040
/*%
 *	Glue or hints are ok.  These are used when matching names already
 *	in the adb, and when dns databases are searched.
 */
#define DNS_ADBFIND_HINTOK		0x00000080
/*%
 *	Return lame servers in a find, so that all addresses are returned.
 */
#define DNS_ADBFIND_RETURNLAME		0x00000100
/*%
 *      Only schedule an event if no addresses are known.
 *      Must set _WANTEVENT for this to be meaningful.
 */
#define DNS_ADBFIND_LAMEPRUNED		0x00000200
/*%
 *      The server's fetch quota is exceeded; it will be treated as
 *      lame for this query.
 */
#define DNS_ADBFIND_OVERQUOTA		0x00000400
/*%
 *	Don't perform a fetch even if there are no address records available.
 */
#define DNS_ADBFIND_NOFETCH		0x00000800

/*%
 * The answers to queries come back as a list of these.
 */
struct dns_adbaddrinfo {
	unsigned int			magic;		/*%< private */

	isc_sockaddr_t			sockaddr;	/*%< [rw] */
	unsigned int			srtt;		/*%< [rw] microsecs */
	isc_dscp_t			dscp;

	unsigned int			flags;		/*%< [rw] */
	dns_adbentry_t		       *entry;		/*%< private */
	ISC_LINK(dns_adbaddrinfo_t)	publink;
};

/*!<
 * The event sent to the caller task is just a plain old isc_event_t.  It
 * contains no data other than a simple status, passed in the "type" field
 * to indicate that another address resolved, or all partially resolved
 * addresses have failed to resolve.
 *
 * "sender" is the dns_adbfind_t used to issue this query.
 *
 * This is simply a standard event, with the "type" set to:
 *
 *\li	#DNS_EVENT_ADBMOREADDRESSES   -- another address resolved.
 *\li	#DNS_EVENT_ADBNOMOREADDRESSES -- all pending addresses failed,
 *					were canceled, or otherwise will
 *					not be usable.
 *\li	#DNS_EVENT_ADBCANCELED	     -- The request was canceled by a
 *					3rd party.
 *\li	#DNS_EVENT_ADBNAMEDELETED     -- The name was deleted, so this request
 *					was canceled.
 *
 * In each of these cases, the addresses returned by the initial call
 * to dns_adb_createfind() can still be used until they are no longer needed.
 */

/****
 **** FUNCTIONS
 ****/


isc_result_t
dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *tmgr,
	       isc_taskmgr_t *taskmgr, dns_adb_t **newadb);
/*%<
 * Create a new ADB.
 *
 * Notes:
 *
 *\li	Generally, applications should not create an ADB directly, but
 *	should instead call dns_view_createresolver().
 *
 * Requires:
 *
 *\li	'mem' must be a valid memory context.
 *
 *\li	'view' be a pointer to a valid view.
 *
 *\li	'tmgr' be a pointer to a valid timer manager.
 *
 *\li	'taskmgr' be a pointer to a valid task manager.
 *
 *\li	'newadb' != NULL && '*newadb' == NULL.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS	after happiness.
 *\li	#ISC_R_NOMEMORY	after resource allocation failure.
 */

void
dns_adb_attach(dns_adb_t *adb, dns_adb_t **adbp);
/*%
 * Attach to an 'adb' to 'adbp'.
 *
 * Requires:
 *\li	'adb' to be a valid dns_adb_t, created via dns_adb_create().
 *\li	'adbp' to be a valid pointer to a *dns_adb_t which is initialized
 *	to NULL.
 */

void
dns_adb_detach(dns_adb_t **adb);
/*%
 * Delete the ADB. Sets *ADB to NULL. Cancels any outstanding requests.
 *
 * Requires:
 *
 *\li	'adb' be non-NULL and '*adb' be a valid dns_adb_t, created via
 *	dns_adb_create().
 */

void
dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp);
/*%
 * Send '*eventp' to 'task' when 'adb' has shutdown.
 *
 * Requires:
 *
 *\li	'*adb' is a valid dns_adb_t.
 *
 *\li	eventp != NULL && *eventp is a valid event.
 *
 * Ensures:
 *
 *\li	*eventp == NULL
 *
 *\li	The event's sender field is set to the value of adb when the event
 *	is sent.
 */

void
dns_adb_shutdown(dns_adb_t *adb);
/*%<
 * Shutdown 'adb'.
 *
 * Requires:
 *
 * \li	'*adb' is a valid dns_adb_t.
 */

isc_result_t
dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
		   void *arg, dns_name_t *name, dns_name_t *qname,
		   dns_rdatatype_t qtype, unsigned int options,
		   isc_stdtime_t now, dns_name_t *target,
		   in_port_t port, dns_adbfind_t **find);
isc_result_t
dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
		    void *arg, dns_name_t *name, dns_name_t *qname,
		    dns_rdatatype_t qtype, unsigned int options,
		    isc_stdtime_t now, dns_name_t *target, in_port_t port,
		    unsigned int depth, isc_counter_t *qc,
		    dns_adbfind_t **find);
/*%<
 * Main interface for clients. The adb will look up the name given in
 * "name" and will build up a list of found addresses, and perhaps start
 * internal fetches to resolve names that are unknown currently.
 *
 * If other addresses resolve after this call completes, an event will
 * be sent to the <task, taskaction, arg> with the sender of that event
 * set to a pointer to the dns_adbfind_t returned by this function.
 *
 * If no events will be generated, the *find->result_v4 and/or result_v6
 * members may be examined for address lookup status.  The usual #ISC_R_SUCCESS,
 * #ISC_R_FAILURE, #DNS_R_NXDOMAIN, and #DNS_R_NXRRSET are returned, along with
 * #ISC_R_NOTFOUND meaning the ADB has not _yet_ found the values.  In this
 * latter case, retrying may produce more addresses.
 *
 * If events will be returned, the result_v[46] members are only valid
 * when that event is actually returned.
 *
 * The list of addresses returned is unordered.  The caller must impose
 * any ordering required.  The list will not contain "known bad" addresses,
 * however.  For instance, it will not return hosts that are known to be
 * lame for the zone in question.
 *
 * The caller cannot (directly) modify the contents of the address list's
 * fields other than the "link" field.  All values can be read at any
 * time, however.
 *
 * The "now" parameter is used only for determining which entries that
 * have a specific time to live or expire time should be removed from
 * the running database.  If specified as zero, the current time will
 * be retrieved and used.
 *
 * If 'target' is not NULL and 'name' is an alias (i.e. the name is
 * CNAME'd or DNAME'd to another name), then 'target' will be updated with
 * the domain name that 'name' is aliased to.
 *
 * All addresses returned will have the sockaddr's port set to 'port.'
 * The caller may change them directly in the dns_adbaddrinfo_t since
 * they are copies of the internal address only.
 *
 * XXXMLG  Document options, especially the flags which control how
 *         events are sent.
 *
 * Requires:
 *
 *\li	*adb be a valid isc_adb_t object.
 *
 *\li	If events are to be sent, *task be a valid task,
 *	and isc_taskaction_t != NULL.
 *
 *\li	*name is a valid dns_name_t.
 *
 *\li	qname != NULL and *qname be a valid dns_name_t.
 *
 *\li	target == NULL or target is a valid name with a buffer.
 *
 *\li	find != NULL && *find == NULL.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS	Addresses might have been returned, and events will be
 *			delivered for unresolved addresses.
 *\li	#ISC_R_NOMORE	Addresses might have been returned, but no events
 *			will ever be posted for this context.  This is only
 *			returned if task != NULL.
 *\li	#ISC_R_NOMEMORY	insufficient resources
 *\li	#DNS_R_ALIAS	'name' is an alias for another name.
 *
 * Calls, and returns error codes from:
 *
 *\li	isc_stdtime_get()
 *
 * Notes:
 *
 *\li	No internal reference to "name" exists after this function
 *	returns.
 */

void
dns_adb_cancelfind(dns_adbfind_t *find);
/*%<
 * Cancels the find, and sends the event off to the caller.
 *
 * It is an error to call dns_adb_cancelfind() on a find where
 * no event is wanted, or will ever be sent.
 *
 * Note:
 *
 *\li	It is possible that the real completion event was posted just
 *	before the dns_adb_cancelfind() call was made.  In this case,
 *	dns_adb_cancelfind() will do nothing.  The event callback needs
 *	to be prepared to find this situation (i.e. result is valid but
 *	the caller expects it to be canceled).
 *
 * Requires:
 *
 *\li	'find' be a valid dns_adbfind_t pointer.
 *
 *\li	events would have been posted to the task.  This can be checked
 *	with (find->options & DNS_ADBFIND_WANTEVENT).
 *
 * Ensures:
 *
 *\li	The event was posted to the task.
 */

void
dns_adb_destroyfind(dns_adbfind_t **find);
/*%<
 * Destroys the find reference.
 *
 * Note:
 *
 *\li	This can only be called after the event was delivered for a
 *	find.  Additionally, the event MUST have been freed via
 *	isc_event_free() BEFORE this function is called.
 *
 * Requires:
 *
 *\li	'find' != NULL and *find be valid dns_adbfind_t pointer.
 *
 * Ensures:
 *
 *\li	No "address found" events will be posted to the originating task
 *	after this function returns.
 */

void
dns_adb_dump(dns_adb_t *adb, FILE *f);
/*%<
 * This function is only used for debugging.  It will dump as much of the
 * state of the running system as possible.
 *
 * Requires:
 *
 *\li	adb be valid.
 *
 *\li	f != NULL, and is a file open for writing.
 */

void
dns_adb_dumpfind(dns_adbfind_t *find, FILE *f);
/*%<
 * This function is only used for debugging.  Dump the data associated
 * with a find.
 *
 * Requires:
 *
 *\li	find is valid.
 *
 * \li	f != NULL, and is a file open for writing.
 */

isc_result_t
dns_adb_marklame(dns_adb_t *adb, dns_adbaddrinfo_t *addr, dns_name_t *qname,
		 dns_rdatatype_t type, isc_stdtime_t expire_time);
/*%<
 * Mark the given address as lame for the <qname,qtype>.  expire_time should
 * be set to the time when the entry should expire.  That is, if it is to
 * expire 10 minutes in the future, it should set it to (now + 10 * 60).
 *
 * Requires:
 *
 *\li	adb be valid.
 *
 *\li	addr be valid.
 *
 *\li	qname be the qname used in the dns_adb_createfind() call.
 *
 * Returns:
 *
 *\li	#ISC_R_SUCCESS		-- all is well.
 *\li	#ISC_R_NOMEMORY		-- could not mark address as lame.
 */

/*
 * Reasonable defaults for RTT adjustments
 *
 * (Note: these values function both as scaling factors and as
 * indicators of the type of RTT adjustment operation taking place.
 * Adjusting the scaling factors is fine, as long as they all remain
 * unique values.)
 */
#define DNS_ADB_RTTADJDEFAULT		7	/*%< default scale */
#define DNS_ADB_RTTADJREPLACE		0	/*%< replace with our rtt */
#define DNS_ADB_RTTADJAGE		10	/*%< age this rtt */

void
dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
		   unsigned int rtt, unsigned int factor);
/*%<
 * Mix the round trip time into the existing smoothed rtt.
 *
 * Requires:
 *
 *\li	adb be valid.
 *
 *\li	addr be valid.
 *
 *\li	0 <= factor <= 10
 *
 * Note:
 *
 *\li	The srtt in addr will be updated to reflect the new global
 *	srtt value.  This may include changes made by others.
 */

void
dns_adb_agesrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, isc_stdtime_t now);
/*
 * dns_adb_agesrtt is equivalent to dns_adb_adjustsrtt with factor
 * equal to DNS_ADB_RTTADJAGE and the current time passed in.
 *
 * Requires:
 *
 *\li	adb be valid.
 *
 *\li	addr be valid.
 *
 * Note:
 *
 *\li	The srtt in addr will be updated to reflect the new global
 *	srtt value.  This may include changes made by others.
 */

void
dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
		    unsigned int bits, unsigned int mask);
/*%
 * Change Flags.
 *
 * Set the flags as given by:
 *
 *\li	newflags = (oldflags & ~mask) | (bits & mask);
 *
 * Requires:
 *
 *\li	adb be valid.
 *
 *\li	addr be valid.
 */

void
dns_adb_setudpsize(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int size);
/*%
 * Update seen UDP response size.  The largest seen will be returned by
 * dns_adb_getudpsize().
 *
 * Requires:
 *
 *\li	adb be valid.
 *
 *\li	addr be valid.
 */

unsigned int
dns_adb_getudpsize(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
/*%
 * Return the largest seen UDP response size.
 *
 * Requires:
 *
 *\li	adb be valid.
 *
 *\li	addr be valid.
 */

unsigned int
dns_adb_probesize(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
unsigned int
dns_adb_probesize2(dns_adb_t *adb, dns_adbaddrinfo_t *addr, int lookups);
/*%
 * Return suggested EDNS UDP size based on observed responses / failures.
 * 'lookups' is the number of times the current lookup has been attempted.
 *
 * Requires:
 *
 *\li	adb be valid.
 *
 *\li	addr be valid.
 */

void
dns_adb_plainresponse(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
/*%
 * Record a successful plain DNS response.
 *
 * Requires:
 *
 *\li	adb be valid.
 *
 *\li	addr be valid.
 */

void
dns_adb_timeout(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
/*%
 * Record a plain DNS UDP query failed.
 *
 * Requires:
 *
 *\li	adb be valid.
 *
 *\li	addr be valid.
 */

void
dns_adb_ednsto(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int size);
/*%
 * Record a failed EDNS UDP response and the advertised EDNS UDP buffer size
 * used.
 *
 * Requires:
 *
 *\li	adb be valid.
 *
 *\li	addr be valid.
 */

bool
dns_adb_noedns(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
/*%
 * Return whether EDNS should be disabled for this server.
 *
 * Requires:
 *
 *\li	adb be valid.
 *
 *\li	addr be valid.
 */


isc_result_t
dns_adb_findaddrinfo(dns_adb_t *adb, isc_sockaddr_t *sa,
		     dns_adbaddrinfo_t **addrp, isc_stdtime_t now);
/*%<
 * Return a dns_adbaddrinfo_t that is associated with address 'sa'.
 *
 * Requires:
 *
 *\li	adb is valid.
 *
 *\li	sa is valid.
 *
 *\li	addrp != NULL && *addrp == NULL
 *
 * Returns:
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *\li	#ISC_R_SHUTTINGDOWN
 */

void
dns_adb_freeaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **addrp);
/*%<
 * Free a dns_adbaddrinfo_t allocated by dns_adb_findaddrinfo().
 *
 * Requires:
 *
 *\li	adb is valid.
 *
 *\li	*addrp is a valid dns_adbaddrinfo_t *.
 */

void
dns_adb_flush(dns_adb_t *adb);
/*%<
 * Flushes all cached data from the adb.
 *
 * Requires:
 *\li 	adb is valid.
 */

void
dns_adb_setadbsize(dns_adb_t *adb, size_t size);
/*%<
 * Set a target memory size.  If memory usage exceeds the target
 * size entries will be removed before they would have expired on
 * a random basis.
 *
 * If 'size' is 0 then memory usage is unlimited.
 *
 * Requires:
 *\li	'adb' is valid.
 */

void
dns_adb_flushname(dns_adb_t *adb, dns_name_t *name);
/*%<
 * Flush 'name' from the adb cache.
 *
 * Requires:
 *\li	'adb' is valid.
 *\li	'name' is valid.
 */

void
dns_adb_flushnames(dns_adb_t *adb, dns_name_t *name);
/*%<
 * Flush 'name' and all subdomains from the adb cache.
 *
 * Requires:
 *\li	'adb' is valid.
 *\li	'name' is valid.
 */

void
dns_adb_setcookie(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
		  const unsigned char *cookie, size_t len);
/*%<
 * Record the COOKIE associated with this address.  If
 * cookie is NULL or len is zero the recorded COOKIE is cleared.
 *
 * Requires:
 *\li	'adb' is valid.
 *\li	'addr' is valid.
 */

size_t
dns_adb_getcookie(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
		  unsigned char *cookie, size_t len);
/*
 * Retrieve the saved COOKIE value and store it in 'cookie' which has
 * size 'len'.
 *
 * Requires:
 *\li	'adb' is valid.
 *\li	'addr' is valid.
 *
 * Returns:
 *	The size of the cookie or zero if it doesn't fit in the buffer
 *	or it doesn't exist.
 */

void
dns_adb_setquota(dns_adb_t *adb, uint32_t quota, uint32_t freq,
		 double low, double high, double discount);
/*%<
 * Set the baseline ADB quota, and configure parameters for the
 * quota adjustment algorithm.
 *
 * If the number of fetches currently waiting for responses from this
 * address exceeds the current quota, then additional fetches are spilled.
 *
 * 'quota' is the highest permissible quota; it will adjust itself
 * downward in response to detected congestion.
 *
 * After every 'freq' fetches have either completed or timed out, an
 * exponentially weighted moving average of the ratio of timeouts
 * to responses is calculated.  If the EWMA goes above a 'high'
 * threshold, then the quota is adjusted down one step; if it drops
 * below a 'low' threshold, then the quota is adjusted back up one
 * step.
 *
 * The quota adjustment is based on the function (1 / 1 + (n/10)^(3/2)),
 * for values of n from 0 to 99.  It starts at 100% of the baseline
 * quota, and descends after 100 steps to 2%.
 *
 * 'discount' represents the discount rate of the moving average. Higher
 * values cause older values to be discounted sooner, providing a faster
 * response to changes in the timeout ratio.
 *
 * Requires:
 *\li	'adb' is valid.
 */

bool
dns_adbentry_overquota(dns_adb_t *adb, dns_adbentry_t *entry);
/*%<
 * Returns true if the specified ADB has too many active fetches.
 *
 * Requires:
 *\li	'entry' is valid.
 */

void
dns_adb_beginudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
void
dns_adb_endudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
/*%
 * Begin/end a UDP fetch on a particular address.
 *
 * These functions increment or decrement the fetch counter for
 * the ADB entry so that the fetch quota can be enforced.
 *
 * Requires:
 *
 *\li	adb be valid.
 *
 *\li	addr be valid.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_ADB_H */
ds.h000064400000002311150415243060005320 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_DS_H
#define DNS_DS_H 1

#include <isc/lang.h>

#include <dns/types.h>

#define DNS_DSDIGEST_SHA1 (1)
#define DNS_DSDIGEST_SHA256 (2)
#define DNS_DSDIGEST_GOST (3)
#define DNS_DSDIGEST_SHA384 (4)

/*
 * Assuming SHA-384 digest type.
 */
#define DNS_DS_BUFFERSIZE (52)

ISC_LANG_BEGINDECLS

isc_result_t
dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
		  dns_dsdigest_t digest_type, unsigned char *buffer,
		  dns_rdata_t *rdata);
/*%<
 * Build the rdata of a DS record.
 *
 * Requires:
 *\li	key	Points to a valid DNS KEY record.
 *\li	buffer	Points to a temporary buffer of at least
 * 		#DNS_DS_BUFFERSIZE bytes.
 *\li	rdata	Points to an initialized dns_rdata_t.
 *
 * Ensures:
 *  \li    *rdata	Contains a valid DS rdata.  The 'data' member refers
 *		to 'buffer'.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_DS_H */
secproto.h000064400000003025150415243060006553 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_SECPROTO_H
#define DNS_SECPROTO_H 1

/*! \file dns/secproto.h */

#include <isc/lang.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

isc_result_t
dns_secproto_fromtext(dns_secproto_t *secprotop, isc_textregion_t *source);
/*%<
 * Convert the text 'source' refers to into a DNSSEC security protocol value.
 * The text may contain either a mnemonic protocol name or a decimal protocol
 * number.
 *
 * Requires:
 *\li	'secprotop' is a valid pointer.
 *
 *\li	'source' is a valid text region.
 *
 * Returns:
 *\li	ISC_R_SUCCESS			on success
 *\li	ISC_R_RANGE			numeric type is out of range
 *\li	DNS_R_UNKNOWN			mnemonic type is unknown
 */

isc_result_t
dns_secproto_totext(dns_secproto_t secproto, isc_buffer_t *target);
/*%<
 * Put a textual representation of the DNSSEC security protocol 'secproto'
 * into 'target'.
 *
 * Requires:
 *\li	'secproto' is a valid secproto.
 *
 *\li	'target' is a valid text buffer.
 *
 * Ensures,
 *	if the result is success:
 *	\li	The used space in 'target' is updated.
 *
 * Returns:
 *\li	ISC_R_SUCCESS			on success
 *\li	ISC_R_NOSPACE			target buffer is too small
 */

ISC_LANG_ENDDECLS

#endif /* DNS_SECPROTO_H */
forward.h000064400000006574150415243060006375 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_FORWARD_H
#define DNS_FORWARD_H 1

/*! \file dns/forward.h */

#include <isc/lang.h>
#include <isc/result.h>
#include <isc/sockaddr.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

struct dns_forwarder {
	isc_sockaddr_t			addr;
	isc_dscp_t			dscp;
	ISC_LINK(dns_forwarder_t)	link;
};

typedef ISC_LIST(struct dns_forwarder)	dns_forwarderlist_t;

struct dns_forwarders {
	dns_forwarderlist_t	fwdrs;
	dns_fwdpolicy_t		fwdpolicy;
};

isc_result_t
dns_fwdtable_create(isc_mem_t *mctx, dns_fwdtable_t **fwdtablep);
/*%<
 * Creates a new forwarding table.
 *
 * Requires:
 * \li 	mctx is a valid memory context.
 * \li	fwdtablep != NULL && *fwdtablep == NULL
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOMEMORY
 */

isc_result_t
dns_fwdtable_addfwd(dns_fwdtable_t *fwdtable, dns_name_t *name,
		    dns_forwarderlist_t *fwdrs, dns_fwdpolicy_t policy);
isc_result_t
dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name,
		 isc_sockaddrlist_t *addrs, dns_fwdpolicy_t policy);
/*%<
 * Adds an entry to the forwarding table.  The entry associates
 * a domain with a list of forwarders and a forwarding policy.  The
 * addrs/fwdrs list is copied if not empty, so the caller should free
 * its copy.
 *
 * Requires:
 * \li	fwdtable is a valid forwarding table.
 * \li	name is a valid name
 * \li	addrs/fwdrs is a valid list of isc_sockaddr/dns_forwarder
 *      structures, which may be empty.
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOMEMORY
 */

isc_result_t
dns_fwdtable_delete(dns_fwdtable_t *fwdtable, dns_name_t *name);
/*%<
 * Removes an entry for 'name' from the forwarding table.  If an entry
 * that exactly matches 'name' does not exist, ISC_R_NOTFOUND will be returned.
 *
 * Requires:
 * \li	fwdtable is a valid forwarding table.
 * \li	name is a valid name
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOTFOUND
 */

isc_result_t
dns_fwdtable_find(dns_fwdtable_t *fwdtable, dns_name_t *name,
		  dns_forwarders_t **forwardersp);
/*%<
 * Finds a domain in the forwarding table.  The closest matching parent
 * domain is returned.
 *
 * Requires:
 * \li	fwdtable is a valid forwarding table.
 * \li	name is a valid name
 * \li	forwardersp != NULL && *forwardersp == NULL
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOTFOUND
 */

isc_result_t
dns_fwdtable_find2(dns_fwdtable_t *fwdtable, dns_name_t *name,
		   dns_name_t *foundname, dns_forwarders_t **forwardersp);
/*%<
 * Finds a domain in the forwarding table.  The closest matching parent
 * domain is returned.
 *
 * Requires:
 * \li	fwdtable is a valid forwarding table.
 * \li	name is a valid name
 * \li	forwardersp != NULL && *forwardersp == NULL
 * \li	foundname to be NULL or a valid name with buffer.
 *
 * Returns:
 * \li	#ISC_R_SUCCESS
 * \li	#ISC_R_NOTFOUND
 */

void
dns_fwdtable_destroy(dns_fwdtable_t **fwdtablep);
/*%<
 * Destroys a forwarding table.
 *
 * Requires:
 * \li	fwtablep != NULL && *fwtablep != NULL
 *
 * Ensures:
 * \li	all memory associated with the forwarding table is freed.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_FORWARD_H */
acache.h000064400000033630150415243060006126 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_ACACHE_H
#define DNS_ACACHE_H 1

/*****
 ***** Module Info
 *****/

/*
 * Acache
 *
 * The Additional Cache Object
 *
 *	This module manages internal caching entries that correspond to
 *	the additional section data of a DNS DB node (an RRset header, more
 *	accurately).  An additional cache entry is expected to be (somehow)
 *	attached to a particular RR in a particular DB node, and contains a set
 *	of information of an additional data for the DB node.
 *
 *	An additional cache object is intended to be created as a per-view
 *	object, and manages all cache entries within the view.
 *
 *	The intended usage of the additional caching is to provide a short cut
 *	to additional glue RRs of an NS RR.  For each NS RR, it is often
 *	necessary to look for glue RRs to make a proper response.  Once the
 *	glue RRs are known, the additional caching allows the client to
 *	associate the information to the original NS RR so that further
 *	expensive lookups can be avoided for the NS RR.
 *
 *	Each additional cache entry contains information to identify a
 *	particular DB node and (optionally) an associated RRset.  The
 *	information consists of its zone, database, the version of the
 *	database, database node, and RRset.
 *
 *	A "negative" information can also be cached.  For example, if a glue
 *	RR does not exist as an authoritative data in the same zone as that
 *	of the NS RR, this fact can be cached by specifying a NULL pointer
 *	for the database, version, and node.  (See the description for
 *	dns_acache_getentry() below for more details.)
 *
 *	Since each member stored in an additional cache entry holds a reference
 *	to a corresponding object, a stale cache entry may cause unnecessary
 *	memory consumption.  For instance, when a zone is reloaded, additional
 *	cache entries that have a reference to the zone (and its DB and/or
 *	DB nodes) can delay the cleanup of the referred objects.  In order to
 *	minimize such a bad effect, this module provides several cleanup
 *	mechanisms.
 *
 *	The first one is a shutdown procedure called when the associated view
 *	is shut down.  In this case, dns_acache_shutdown() will be called and
 *	all cache entries will be purged.  This mechanism will help the
 *	situation when the configuration is reloaded or the main server is
 *	stopped.
 *
 *	Per-DB cleanup mechanism is also provided.  Each additional cache entry
 *	is associated with related DB, which is expected to have been
 *	registered when the DB was created by dns_acache_setdb().  If a
 *	particular DB is going to be destroyed, the primary holder of the DB,
 *	a typical example of which is a zone, will call dns_acache_putdb().
 *	Then this module will clean-up all cache entries associated with the
 *	DB.  This mechanism is effective when a secondary zone DB is going to
 *	be stale after a zone transfer.
 *
 *	Finally, this module supports for periodic clean-up of stale entries.
 *	Each cache entry has a timestamp field, which is updated every time
 *	the entry is referred.  A periodically invoked cleaner checks the
 *	timestamp of each entry, and purge entries that have not been referred
 *	for a certain period.  The cleaner interval can be specified by
 *	dns_acache_setcleaninginterval().  If the periodic clean-up is not
 *	enough, it is also possible to specify the upper limit of entries
 *	in terms of the memory consumption.  If the maximum value is
 *	specified, the cleaner is invoked when the memory consumption reaches
 *	the high watermark inferred from the maximum value.  In this case,
 *	the cleaner will use more aggressive algorithm to decide the "victim"
 *	entries.  The maximum value can be specified by
 *	dns_acache_setcachesize().
 *
 *	When a cache entry is going to be purged within this module, the
 *	callback function specified at the creation time will be called.
 *	The callback function is expected to release all internal resources
 *	related to the entry, which will typically be specific to DB
 *	implementation, and to call dns_acache_detachentry().  The callback
 *	mechanism is very important, since the holder of an additional cache
 *	entry may not be able to initiate the clean-up of the entry, due to
 *	the reference ordering.  For example, as long as an additional cache
 *	entry has a reference to a DB object, the DB cannot be freed, in which
 *	a DB node may have a reference to the cache entry.
 *
 *	Credits:
 *	The basic idea of this kind of short-cut for frequently used
 *	information is similar to the "pre-compiled answer" approach adopted
 *	in nsd by NLnet LABS with RIPE NCC.  Our work here is an independent
 *	effort, but the success of nsd encouraged us to pursue this path.
 *
 *	The design and implementation of the periodic memory management and
 *	the upper limitation of memory consumption was derived from the cache
 *	DB implementation of BIND9.
 *
 * MP:
 *	There are two main locks in this module.  One is for each entry, and
 *	the other is for the additional cache object.
 *
 * Reliability:
 *	The callback function for a cache entry is called with holding the
 *	entry lock.  Thus, it implicitly assumes the callback function does not
 *	call a function that can require the lock.  Typically, the only
 *	function that can be called from the callback function safely is
 *	dns_acache_detachentry().  The breakage of this implicit assumption
 *	may cause a deadlock.
 *
 * Resources:
 *	In a 32-bit architecture (such as i386), the following additional
 *	memory is required comparing to the case that disables this module.
 *	- 76 bytes for each additional cache entry
 *	- if the entry has a DNS name and associated RRset,
 *	  * 44 bytes + size of the name (1-255 bytes)
 *	  * 52 bytes x number_of_RRs
 *	- 28 bytes for each DB related to this module
 *
 *	Using the additional cache also requires extra memory consumption in
 *	the DB implementation.  In the current implementation for rbtdb, we
 *	need:
 *	- two additional pointers for each DB node (8 bytes for a 32-bit
 *	  architecture
 *	- for each RR associated to an RR in a DB node, we also need
 *	  a pointer and management objects to support the additional cache
 *	  function.  These are allocated on-demand.  The total size is
 *	  32 bytes for a 32-bit architecture.
 *
 * Security:
 *	Since this module does not handle any low-level data directly,
 *	no security issue specific to this module is anticipated.
 *
 * Standards:
 *	None.
 */

/***
 *** Imports
 ***/

#include <isc/mutex.h>
#include <isc/lang.h>
#include <isc/stdtime.h>

#include <dns/types.h>

/***
 *** Functions
 ***/
ISC_LANG_BEGINDECLS

isc_result_t
dns_acache_create(dns_acache_t **acachep, isc_mem_t *mctx,
		  isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr);
/*
 * Create a new DNS additional cache object.
 *
 * Requires:
 *
 *	'mctx' is a valid memory context
 *
 *	'taskmgr' is a valid task manager
 *
 *	'timermgr' is a valid timer or NULL.  If NULL, no periodic cleaning of
 *	the cache will take place.
 *
 *	'acachep' is a valid pointer, and *acachep == NULL
 *
 * Ensures:
 *
 *	'*acachep' is attached to the newly created cache
 *
 * Returns:
 *
 *	ISC_R_SUCCESS
 *	ISC_R_NOMEMORY
 *	ISC_R_UNEXPECTED
 */

void
dns_acache_attach(dns_acache_t *source, dns_acache_t **targetp);
/*
 * Attach *targetp to cache.
 *
 * Requires:
 *
 *	'acache' is a valid additional cache.
 *
 *	'targetp' points to a NULL dns_acache_t *.
 *
 * Ensures:
 *
 *	*targetp is attached to the 'source' additional cache.
 */

void
dns_acache_detach(dns_acache_t **acachep);
/*
 * Detach *acachep from its cache.
 *
 * Requires:
 *
 *	'*acachep' points to a valid additional cache.
 *
 * Ensures:
 *
 *	*acachep is NULL.
 *
 *	If '*acachep' is the last reference to the cache and the additional
 *	cache does not have an outstanding task, all resources used by the
 *	cache will be freed.
 */

void
dns_acache_setcleaninginterval(dns_acache_t *acache, unsigned int t);
/*
 * Set the periodic cleaning interval of an additional cache to 'interval'
 * seconds.
 */

void
dns_acache_setcachesize(dns_acache_t *acache, size_t size);
/*
 * Set the maximum additional cache size.  0 means unlimited.
 */

isc_result_t
dns_acache_setdb(dns_acache_t *acache, dns_db_t *db);
/*
 * Set 'db' in 'acache' when the db can be referred from acache, in order
 * to provide a hint for resolving the back reference.
 *
 * Requires:
 *	'acache' is a valid acache pointer.
 *	'db' is a valid DNS DB pointer.
 *
 * Ensures:
 *	'acache' will have a reference to 'db'.
 *
 * Returns:
 *	ISC_R_SUCCESS
 *	ISC_R_EXISTS	(which means the specified 'db' is already set)
 *	ISC_R_NOMEMORY
 */

isc_result_t
dns_acache_putdb(dns_acache_t *acache, dns_db_t *db);
/*
 * Release 'db' from 'acache' if it has been set by dns_acache_setdb().
 *
 * Requires:
 *	'acache' is a valid acache pointer.
 *	'db' is a valid DNS DB pointer.
 *
 * Ensures:
 *	'acache' will release the reference to 'db'.  Additionally, the content
 *	of each cache entry that is related to the 'db' will be released via
 *	the callback function.
 *
 * Returns:
 *	ISC_R_SUCCESS
 *	ISC_R_NOTFOUND	(which means the specified 'db' is not set in 'acache')
 *	ISC_R_NOMEMORY
 */

void
dns_acache_shutdown(dns_acache_t *acache);
/*
 * Shutdown 'acache'.
 *
 * Requires:
 *
 * 	'*acache' is a valid additional cache.
 */

isc_result_t
dns_acache_createentry(dns_acache_t *acache, dns_db_t *origdb,
		       void (*callback)(dns_acacheentry_t *, void **),
		       void *cbarg, dns_acacheentry_t **entryp);
/*
 * Create an additional cache entry.  A new entry is created and attached to
 * the given additional cache object.  A callback function is also associated
 * with the created entry, which will be called when the cache entry is purged
 * for some reason.
 *
 * Requires:
 *
 * 	'acache' is a valid additional cache.
 *	'entryp' is a valid pointer, and *entryp == NULL
 *	'origdb' is a valid DNS DB pointer.
 *	'callback' and 'cbarg' can be NULL.  In this case, however, the entry
 *	is meaningless (and will be cleaned-up in the next periodical
 *	cleaning).
 *
 * Ensures:
 *	'*entryp' will point to a new additional cache entry.
 *
 * Returns:
 *	ISC_R_SUCCESS
 *	ISC_R_NOMEMORY
 */

isc_result_t
dns_acache_getentry(dns_acacheentry_t *entry, dns_zone_t **zonep,
		    dns_db_t **dbp, dns_dbversion_t **versionp,
		    dns_dbnode_t **nodep, dns_name_t *fname,
		    dns_message_t *msg, isc_stdtime_t now);
/*
 * Get content from a particular additional cache entry.
 *
 * Requires:
 *
 * 	'entry' is a valid additional cache entry.
 *	'zonep' is a NULL pointer or '*zonep' == NULL (this is the only
 *	optional parameter.)
 *	'dbp' is a valid pointer, and '*dbp' == NULL
 *	'versionp' is a valid pointer, and '*versionp' == NULL
 *	'nodep' is a valid pointer, and '*nodep' == NULL
 *	'fname' is a valid DNS name.
 *	'msg' is a valid DNS message.
 *
 * Ensures:
 *	Several possible cases can happen according to the content.
 *	1. For a positive cache entry,
 *	'*zonep' will point to the corresponding zone (if zonep is a valid
 *	pointer),
 *	'*dbp' will point to a DB for the zone,
 *	'*versionp' will point to its version, and
 *	'*nodep' will point to the corresponding DB node.
 *	'fname' will have the DNS name of the DB node and contain a list of
 *	rdataset for the node (which can be an empty list).
 *
 * 	2. For a negative cache entry that means no corresponding zone exists,
 *	'*zonep' == NULL (if zonep is a valid pointer)
 *	'*dbp', '*versionp', and '*nodep' will be NULL.
 *
 *	3. For a negative cache entry that means no corresponding DB node
 *	exists, '*zonep' will point to the corresponding zone (if zonep is a
 *	valid pointer),
 *	'*dbp' will point to a corresponding DB for zone,
 *	'*versionp' will point to its version.
 *	'*nodep' will be kept as NULL.
 *	'fname' will not change.
 *
 *	On failure, no new references will be created.
 *
 * Returns:
 *	ISC_R_SUCCESS
 *	ISC_R_NOMEMORY
 */

isc_result_t
dns_acache_setentry(dns_acache_t *acache, dns_acacheentry_t *entry,
		    dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
		    dns_dbnode_t *node, dns_name_t *fname);
/*
 * Set content to a particular additional cache entry.
 *
 * Requires:
 *	'acache' is a valid additional cache.
 *	'entry' is a valid additional cache entry.
 *	All the others pointers are NULL or a valid pointer of the
 *	corresponding type.
 *
 * Returns:
 *	ISC_R_SUCCESS
 *	ISC_R_NOMEMORY
 *	ISC_R_NOTFOUND
 */

bool
dns_acache_cancelentry(dns_acacheentry_t *entry);
/*
 * Cancel the use of the cache entry 'entry'.  This function is supposed to
 * be called when the node that holds the entry finds the content is not
 * correct any more.  This function will try to release as much dependency as
 * possible, and will be ready to be cleaned-up.  The registered callback
 * function will be canceled and will never called.
 *
 * Requires:
 *	'entry' is a valid additional cache entry.
 *
 * Returns:
 * 	true if the entry was active when canceled
 */

void
dns_acache_attachentry(dns_acacheentry_t *source, dns_acacheentry_t **targetp);
/*
 * Attach *targetp to the cache entry 'source'.
 *
 * Requires:
 *
 *	'source' is a valid additional cache entry.
 *
 *	'targetp' points to a NULL dns_acacheentry_t *.
 *
 * Ensures:
 *
 *	*targetp is attached to 'source'.
 */

void
dns_acache_detachentry(dns_acacheentry_t **entryp);
/*
 * Detach *entryp from its cache.
 *
 * Requires:
 *
 *	'*entryp' points to a valid additional cache entry.
 *
 * Ensures:
 *
 *	*entryp is NULL.
 *
 *	If '*entryp' is the last reference to the entry,
 *	cache does not have an outstanding task, all resources used by the
 *	entry (including the entry object itself) will be freed.
 */

void
dns_acache_countquerymiss(dns_acache_t *acache);
/*
 * Count up a missed acache query.  XXXMLG need more docs.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_ACACHE_H */
bit.h000064400000001447150415243060005501 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_BIT_H
#define DNS_BIT_H 1

/*! \file dns/bit.h */

#include <inttypes.h>

typedef uint64_t dns_bitset_t;

#define DNS_BIT_SET(bit, bitset) \
	(*(bitset) |= ((dns_bitset_t)1 << (bit)))
#define DNS_BIT_CLEAR(bit, bitset) \
	(*(bitset) &= ~((dns_bitset_t)1 << (bit)))
#define DNS_BIT_CHECK(bit, bitset) \
	((*(bitset) & ((dns_bitset_t)1 << (bit)))	\
	 == ((dns_bitset_t)1 << (bit)))

#endif /* DNS_BIT_H */
dns64.h000064400000013003150415243060005650 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */


#ifndef DNS_DNS64_H
#define DNS_DNS64_H 1

#include <stdbool.h>

#include <isc/lang.h>

#include <dns/types.h>

ISC_LANG_BEGINDECLS

/*
 * dns_dns64_create() flags.
 */
#define DNS_DNS64_RECURSIVE_ONLY	0x01	/* If set then this record
						 * only applies to recursive
						 * queries.
						 */
#define DNS_DNS64_BREAK_DNSSEC		0x02	/* If set then still perform
						 * DNSSEC synthesis even
						 * though the result would
						 * fail validation.
						 */

/*
 * dns_dns64_aaaaok() and dns_dns64_aaaafroma() flags.
 */
#define DNS_DNS64_RECURSIVE		0x01	/* Recursive query. */
#define DNS_DNS64_DNSSEC		0x02	/* DNSSEC sensitive query. */

isc_result_t
dns_dns64_create(isc_mem_t *mctx, isc_netaddr_t *prefix,
		 unsigned int prefixlen, isc_netaddr_t *suffix,
		 dns_acl_t *client, dns_acl_t *mapped, dns_acl_t *excluded,
		 unsigned int flags, dns_dns64_t **dns64);
/*
 * Create a dns64 record which is used to identify the set of clients
 * it applies to and how to perform the DNS64 synthesis.
 *
 * 'prefix' and 'prefixlen' defined the leading bits of the AAAA records
 * to be synthesised.  'suffix' defines the bits after the A records bits.
 * If suffix is NULL zeros will be used for these bits.  'client' defines
 * for which clients this record applies.  If 'client' is NULL then all
 * clients apply.  'mapped' defines which A records are candidated for
 * mapping.  If 'mapped' is NULL then all A records will be mapped.
 * 'excluded' defines which AAAA are to be treated as non-existent for the
 * purposed of determining whether to perform synthesis.  If 'excluded' is
 * NULL then no AAAA records prevent synthesis.
 *
 * If DNS_DNS64_RECURSIVE_ONLY is set then the record will only match if
 * DNS_DNS64_RECURSIVE is set when calling  dns_dns64_aaaaok() and
 * dns_dns64_aaaafroma().
 *
 * If DNS_DNS64_BREAK_DNSSEC is set then the record will still apply if
 * DNS_DNS64_DNSSEC is set when calling  dns_dns64_aaaaok() and
 * dns_dns64_aaaafroma() otherwise the record will be ignored.
 *
 * Requires:
 *      'mctx'          to be valid.
 *      'prefix'        to be valid and the address family to AF_INET6.
 *      'prefixlen'     to be one of 32, 40, 48, 56, 72 and 96.
 *                      the bits not covered by prefixlen in prefix to
 *                      be zero.
 *      'suffix'        to be NULL or the address family be set to AF_INET6
 *                      and the leading 'prefixlen' + 32 bits of the 'suffix'
 *                      to be zero.  If 'prefixlen' is 40, 48 or 56 then the
 *                      the leading 'prefixlen' + 40 bits of 'suffix' must be
 *                      zero.
 *	'client'	to be NULL or a valid acl.
 *	'mapped'	to be NULL or a valid acl.
 *	'excluded'	to be NULL or a valid acl.
 *
 * Returns:
 *	ISC_R_SUCCESS
 *	ISC_R_NOMEMORY
 */

void
dns_dns64_destroy(dns_dns64_t **dns64p);
/*
 * Destroys a dns64 record.
 *
 * Requires the record to not be linked.
 */

isc_result_t
dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
		    const dns_name_t *reqsigner, const dns_aclenv_t *env,
		    unsigned int flags, unsigned char *a, unsigned char *aaaa);
/*
 * dns_dns64_aaaafroma() determines whether to perform a DNS64 address
 * synthesis from 'a' based on 'dns64', 'reqaddr', 'reqsigner', 'env',
 * 'flags' and 'aaaa'.  If synthesis is performed then the result is
 * written to '*aaaa'.
 *
 * The synthesised address will be of the form:
 *
 *	 <prefix bits><a bits><suffix bits>
 *
 * If <a bits> straddle bits 64-71 of the AAAA record, then 8 zero bits will
 * be inserted at bits 64-71.
 *
 * Requires:
 *	'dns64'		to be valid.
 *	'reqaddr'	to be valid.
 *	'reqsigner'	to be NULL or valid.
 *	'env'		to be valid.
 *	'a'		to point to a IPv4 address in network order.
 *	'aaaa'		to point to a IPv6 address buffer in network order.
 *
 * Returns:
 *	ISC_R_SUCCESS		if synthesis was performed.
 *	DNS_R_DISALLOWED	if there is no match.
 */

dns_dns64_t *
dns_dns64_next(dns_dns64_t *dns64);
/*
 * Return the next dns64 record in the list.
 */

void
dns_dns64_append(dns_dns64list_t *list, dns_dns64_t *dns64);
/*
 * Append the dns64 record to the list.
 */

void
dns_dns64_unlink(dns_dns64list_t *list, dns_dns64_t *dns64);
/*
 * Unlink the dns64 record from the list.
 */

bool
dns_dns64_aaaaok(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
		 const dns_name_t *reqsigner, const dns_aclenv_t *env,
		 unsigned int flags, dns_rdataset_t *rdataset,
		 bool *aaaaok, size_t aaaaoklen);
/*
 * Determine if there are any non-excluded AAAA records in from the
 * matching dns64 records in the list starting at 'dns64'.  If there
 * is a non-excluded address return true.  If all addresses are
 * excluded in the matched records return false.   If no records
 * match then return true.
 *
 * If aaaaok is defined then dns_dns64_aaaaok() return a array of which
 * addresses in 'rdataset' were deemed to not be exclude by any matching
 * record.  If there are no matching records then all entries are set
 * to true.
 *
 * Requires
 * 	'rdataset'	to be valid and to be for type AAAA and class IN.
 *	'aaaaoklen'	must match the number of records in 'rdataset'
 *			if 'aaaaok' in non NULL.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_DNS64_H */
enumclass.h000064400000002304150415243060006706 0ustar00/*
 * Copyright (C) 1998-2025  Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

/***************
 ***************
 ***************   THIS FILE IS AUTOMATICALLY GENERATED BY gen.c.
 ***************   DO NOT EDIT!
 ***************
 ***************/

/*! \file */

#ifndef DNS_ENUMCLASS_H
#define DNS_ENUMCLASS_H 1

enum {
	dns_rdataclass_reserved0 = 0,
#define dns_rdataclass_reserved0 \
				((dns_rdataclass_t)dns_rdataclass_reserved0)
	dns_rdataclass_in = 1,
#define dns_rdataclass_in	((dns_rdataclass_t)dns_rdataclass_in)
	dns_rdataclass_chaos = 3,
#define dns_rdataclass_chaos	((dns_rdataclass_t)dns_rdataclass_chaos)
	dns_rdataclass_ch = 3,
#define dns_rdataclass_ch	((dns_rdataclass_t)dns_rdataclass_ch)
	dns_rdataclass_hs = 4,
#define dns_rdataclass_hs	((dns_rdataclass_t)dns_rdataclass_hs)
	dns_rdataclass_none = 254,
#define dns_rdataclass_none	((dns_rdataclass_t)dns_rdataclass_none)
	dns_rdataclass_any = 255
#define dns_rdataclass_any	((dns_rdataclass_t)dns_rdataclass_any)
};

#endif /* DNS_ENUMCLASS_H */
nta.h000064400000010704150415243060005501 0ustar00/*
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef DNS_NTA_H
#define DNS_NTA_H 1

/*****
 ***** Module Info
 *****/

/*! \file
 * \brief
 * The NTA module provides services for storing and retrieving negative
 * trust anchors, and determine whether a given domain is subject to
 * DNSSEC validation.
 */

#include <inttypes.h>
#include <stdbool.h>

#include <isc/buffer.h>
#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/rwlock.h>
#include <isc/stdtime.h>
#include <isc/task.h>
#include <isc/timer.h>

#include <dns/types.h>
#include <dns/rdataset.h>
#include <dns/resolver.h>
#include <dns/view.h>

ISC_LANG_BEGINDECLS

struct dns_ntatable {
	/* Unlocked. */
	unsigned int		magic;
	dns_view_t		*view;
	isc_rwlock_t		rwlock;
	isc_taskmgr_t		*taskmgr;
	isc_timermgr_t		*timermgr;
	isc_task_t		*task;
	/* Locked by rwlock. */
	uint32_t		references;
	dns_rbt_t		*table;
	bool	   		shuttingdown;
};

#define NTATABLE_MAGIC		ISC_MAGIC('N', 'T', 'A', 't')
#define VALID_NTATABLE(nt) 	ISC_MAGIC_VALID(nt, NTATABLE_MAGIC)

isc_result_t
dns_ntatable_create(dns_view_t *view,
		    isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr,
		    dns_ntatable_t **ntatablep);
/*%<
 * Create an NTA table in view 'view'.
 *
 * Requires:
 *
 *\li	'view' is a valid view.
 *
 *\li	'tmgr' is a valid timer manager.
 *
 *\li	ntatablep != NULL && *ntatablep == NULL
 *
 * Ensures:
 *
 *\li	On success, *ntatablep is a valid, empty NTA table.
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *\li	Any other result indicates failure.
 */

void
dns_ntatable_attach(dns_ntatable_t *source, dns_ntatable_t **targetp);
/*%<
 * Attach *targetp to source.
 *
 * Requires:
 *
 *\li	'source' is a valid ntatable.
 *
 *\li	'targetp' points to a NULL dns_ntatable_t *.
 *
 * Ensures:
 *
 *\li	*targetp is attached to source.
 */

void
dns_ntatable_detach(dns_ntatable_t **ntatablep);
/*%<
 * Detach *ntatablep from its ntatable.
 *
 * Requires:
 *
 *\li	'ntatablep' points to a valid ntatable.
 *
 * Ensures:
 *
 *\li	*ntatablep is NULL.
 *
 *\li	If '*ntatablep' is the last reference to the ntatable,
 *		all resources used by the ntatable will be freed
 */

isc_result_t
dns_ntatable_add(dns_ntatable_t *ntatable, dns_name_t *name,
		 bool force, isc_stdtime_t now,
		 uint32_t lifetime);
/*%<
 * Add a negative trust anchor to 'ntatable' for name 'name',
 * which will expire at time 'now' + 'lifetime'.  If 'force' is false,
 * then the name will be checked periodically to see if it's bogus;
 * if not, then the NTA will be allowed to expire early.
 *
 * Notes:
 *
 *\li   If an NTA already exists in the table, its expiry time
 *      is updated.
 *
 * Requires:
 *
 *\li	'ntatable' points to a valid ntatable.
 *
 *\li	'name' points to a valid name.
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *
 *\li	Any other result indicates failure.
 */

isc_result_t
dns_ntatable_delete(dns_ntatable_t *ntatable, dns_name_t *keyname);
/*%<
 * Delete node(s) from 'ntatable' matching name 'keyname'
 *
 * Requires:
 *
 *\li	'ntatable' points to a valid ntatable.
 *
 *\li	'name' is not NULL
 *
 * Returns:
 *
 *\li	ISC_R_SUCCESS
 *
 *\li	Any other result indicates failure.
 */

bool
dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
		     dns_name_t *name, dns_name_t *anchor);
/*%<
 * Return true if 'name' is below a non-expired negative trust
 * anchor which in turn is at or below 'anchor'.
 *
 * If 'ntatable' has not been initialized, return false.
 *
 * Requires:
 *
 *\li	'ntatable' is NULL or is a valid ntatable.
 *
 *\li	'name' is a valid absolute name.
 */

isc_result_t
dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t **buf);
/*%<
 * Dump the NTA table to buffer at 'buf'
 *
 * Requires:
 * \li   "ntatable" is a valid table.
 *
 * \li   "*buf" is a valid buffer.
 */

isc_result_t
dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp);
/*%<
 * Dump the NTA table to the file opened as 'fp'.
 */

isc_result_t
dns_ntatable_save(dns_ntatable_t *ntatable, FILE *fp);
/*%<
 * Save the NTA table to the file opened as 'fp', for later loading.
 */

void
dns_ntatable_shutdown(dns_ntatable_t *ntatable);
/*%<
 * Cancel future checks to see if NTAs can be removed.
 */

ISC_LANG_ENDDECLS

#endif /* DNS_NTA_H */