133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck#
333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# Permission to use, copy, modify, and distribute this software and its
433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# documentation for any purpose with or without fee is hereby granted,
533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# provided that the above copyright notice and this permission notice
633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# appear in all copies.
733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck#
833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
1133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
1633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck"""DNS rdata.
1733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
1833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck@var _rdata_modules: A dictionary mapping a (rdclass, rdtype) tuple to
1933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckthe module which implements that type.
2033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck@type _rdata_modules: dict
2133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck@var _module_prefix: The prefix to use when forming modules names.  The
2233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdefault is 'dns.rdtypes'.  Changing this value will break the library.
2333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck@type _module_prefix: string
2433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck@var _hex_chunk: At most this many octets that will be represented in each
2533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckchunk of hexstring that _hexify() produces before whitespace occurs.
2633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck@type _hex_chunk: int"""
2733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
2833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport cStringIO
2933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
3033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport dns.exception
3133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport dns.rdataclass
3233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport dns.rdatatype
3333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport dns.tokenizer
3433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
3533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck_hex_chunksize = 32
3633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
3733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef _hexify(data, chunksize=None):
3833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    """Convert a binary string into its hex encoding, broken up into chunks
3933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    of I{chunksize} characters separated by a space.
4033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
4133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param data: the binary string
4233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @type data: string
4333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param chunksize: the chunk size.  Default is L{dns.rdata._hex_chunksize}
4433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @rtype: string
4533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    """
4633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
4733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    if chunksize is None:
4833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        chunksize = _hex_chunksize
4933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    hex = data.encode('hex_codec')
5033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    l = len(hex)
5133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    if l > chunksize:
5233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        chunks = []
5333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        i = 0
5433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        while i < l:
5533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            chunks.append(hex[i : i + chunksize])
5633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            i += chunksize
5733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        hex = ' '.join(chunks)
5833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return hex
5933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
6033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck_base64_chunksize = 32
6133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
6233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef _base64ify(data, chunksize=None):
6333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    """Convert a binary string into its base64 encoding, broken up into chunks
6433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    of I{chunksize} characters separated by a space.
6533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
6633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param data: the binary string
6733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @type data: string
6833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param chunksize: the chunk size.  Default is
6933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    L{dns.rdata._base64_chunksize}
7033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @rtype: string
7133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    """
7233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
7333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    if chunksize is None:
7433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        chunksize = _base64_chunksize
7533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    b64 = data.encode('base64_codec')
7633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    b64 = b64.replace('\n', '')
7733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    l = len(b64)
7833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    if l > chunksize:
7933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        chunks = []
8033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        i = 0
8133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        while i < l:
8233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            chunks.append(b64[i : i + chunksize])
8333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            i += chunksize
8433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        b64 = ' '.join(chunks)
8533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return b64
8633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
8733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck__escaped = {
8833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    '"' : True,
8933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    '\\' : True,
9033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    }
9133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
9233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef _escapify(qstring):
9333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    """Escape the characters in a quoted string which need it.
9433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
9533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param qstring: the string
9633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @type qstring: string
9733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @returns: the escaped string
9833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @rtype: string
9933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    """
10033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
10133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    text = ''
10233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for c in qstring:
10333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        if c in __escaped:
10433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            text += '\\' + c
10533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        elif ord(c) >= 0x20 and ord(c) < 0x7F:
10633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            text += c
10733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        else:
10833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            text += '\\%03d' % ord(c)
10933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return text
11033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
11133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef _truncate_bitmap(what):
11233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    """Determine the index of greatest byte that isn't all zeros, and
11333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return the bitmap that contains all the bytes less than that index.
11433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
11533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param what: a string of octets representing a bitmap.
11633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @type what: string
11733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @rtype: string
11833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    """
11933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
12033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    for i in xrange(len(what) - 1, -1, -1):
12133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        if what[i] != '\x00':
12233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            break
12333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return ''.join(what[0 : i + 1])
12433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
12533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass Rdata(object):
12633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    """Base class for all DNS rdata types.
12733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    """
12833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
12933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    __slots__ = ['rdclass', 'rdtype']
13033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
13133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def __init__(self, rdclass, rdtype):
13233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """Initialize an rdata.
13333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @param rdclass: The rdata class
13433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @type rdclass: int
13533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @param rdtype: The rdata type
13633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @type rdtype: int
13733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """
13833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
13933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        self.rdclass = rdclass
14033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        self.rdtype = rdtype
14133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
14233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def covers(self):
14333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """DNS SIG/RRSIG rdatas apply to a specific type; this type is
14433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        returned by the covers() function.  If the rdata type is not
14533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        SIG or RRSIG, dns.rdatatype.NONE is returned.  This is useful when
14633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        creating rdatasets, allowing the rdataset to contain only RRSIGs
14733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        of a particular type, e.g. RRSIG(NS).
14833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @rtype: int
14933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """
15033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
15133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        return dns.rdatatype.NONE
15233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
15333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def extended_rdatatype(self):
15433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """Return a 32-bit type value, the least significant 16 bits of
15533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        which are the ordinary DNS type, and the upper 16 bits of which are
15633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        the "covered" type, if any.
15733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @rtype: int
15833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """
15933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
16033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        return self.covers() << 16 | self.rdtype
16133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
16233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def to_text(self, origin=None, relativize=True, **kw):
16333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """Convert an rdata to text format.
16433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @rtype: string
16533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """
16633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        raise NotImplementedError
16733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
16833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def to_wire(self, file, compress = None, origin = None):
16933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """Convert an rdata to wire format.
17033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @rtype: string
17133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """
17233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
17333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        raise NotImplementedError
17433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
17533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def to_digestable(self, origin = None):
17633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """Convert rdata to a format suitable for digesting in hashes.  This
17733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        is also the DNSSEC canonical form."""
17833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        f = cStringIO.StringIO()
17933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        self.to_wire(f, None, origin)
18033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        return f.getvalue()
18133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
18233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def validate(self):
18333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """Check that the current contents of the rdata's fields are
18433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        valid.  If you change an rdata by assigning to its fields,
18533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        it is a good idea to call validate() when you are done making
18633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        changes.
18733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """
18833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        dns.rdata.from_text(self.rdclass, self.rdtype, self.to_text())
18933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
19033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def __repr__(self):
19133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        covers = self.covers()
19233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        if covers == dns.rdatatype.NONE:
19333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            ctext = ''
19433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        else:
19533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            ctext = '(' + dns.rdatatype.to_text(covers) + ')'
19633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        return '<DNS ' + dns.rdataclass.to_text(self.rdclass) + ' ' + \
19733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck               dns.rdatatype.to_text(self.rdtype) + ctext + ' rdata: ' + \
19833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck               str(self) + '>'
19933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
20033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def __str__(self):
20133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        return self.to_text()
20233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
20333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def _cmp(self, other):
20433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """Compare an rdata with another rdata of the same rdtype and
20533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        rdclass.  Return < 0 if self < other in the DNSSEC ordering,
20633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        0 if self == other, and > 0 if self > other.
20733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """
20833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
20933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        raise NotImplementedError
21033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
21133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def __eq__(self, other):
21233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        if not isinstance(other, Rdata):
21333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            return False
21433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        if self.rdclass != other.rdclass or \
21533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck           self.rdtype != other.rdtype:
21633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            return False
21733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        return self._cmp(other) == 0
21833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
21933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def __ne__(self, other):
22033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        if not isinstance(other, Rdata):
22133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            return True
22233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        if self.rdclass != other.rdclass or \
22333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck           self.rdtype != other.rdtype:
22433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            return True
22533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        return self._cmp(other) != 0
22633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
22733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def __lt__(self, other):
22833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        if not isinstance(other, Rdata) or \
22933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck               self.rdclass != other.rdclass or \
23033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck               self.rdtype != other.rdtype:
23133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            return NotImplemented
23233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        return self._cmp(other) < 0
23333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
23433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def __le__(self, other):
23533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        if not isinstance(other, Rdata) or \
23633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck               self.rdclass != other.rdclass or \
23733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck               self.rdtype != other.rdtype:
23833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            return NotImplemented
23933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        return self._cmp(other) <= 0
24033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
24133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def __ge__(self, other):
24233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        if not isinstance(other, Rdata) or \
24333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck               self.rdclass != other.rdclass or \
24433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck               self.rdtype != other.rdtype:
24533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            return NotImplemented
24633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        return self._cmp(other) >= 0
24733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
24833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def __gt__(self, other):
24933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        if not isinstance(other, Rdata) or \
25033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck               self.rdclass != other.rdclass or \
25133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck               self.rdtype != other.rdtype:
25233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            return NotImplemented
25333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        return self._cmp(other) > 0
25433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
25533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
25633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """Build an rdata object from text format.
25733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
25833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @param rdclass: The rdata class
25933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @type rdclass: int
26033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @param rdtype: The rdata type
26133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @type rdtype: int
26233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @param tok: The tokenizer
26333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @type tok: dns.tokenizer.Tokenizer
26433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @param origin: The origin to use for relative names
26533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @type origin: dns.name.Name
26633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @param relativize: should names be relativized?
26733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @type relativize: bool
26833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @rtype: dns.rdata.Rdata instance
26933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """
27033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
27133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        raise NotImplementedError
27233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
27333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    from_text = classmethod(from_text)
27433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
27533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
27633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """Build an rdata object from wire format
27733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
27833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @param rdclass: The rdata class
27933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @type rdclass: int
28033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @param rdtype: The rdata type
28133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @type rdtype: int
28233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @param wire: The wire-format message
28333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @type wire: string
28433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @param current: The offet in wire of the beginning of the rdata.
28533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @type current: int
28633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @param rdlen: The length of the wire-format rdata
28733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @type rdlen: int
28833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @param origin: The origin to use for relative names
28933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @type origin: dns.name.Name
29033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        @rtype: dns.rdata.Rdata instance
29133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """
29233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
29333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        raise NotImplementedError
29433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
29533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    from_wire = classmethod(from_wire)
29633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
29733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def choose_relativity(self, origin = None, relativize = True):
29833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """Convert any domain names in the rdata to the specified
29933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        relativization.
30033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        """
30133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
30233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        pass
30333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
30433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
30533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass GenericRdata(Rdata):
30633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    """Generate Rdata Class
30733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
30833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    This class is used for rdata types for which we have no better
30933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    implementation.  It implements the DNS "unknown RRs" scheme.
31033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    """
31133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
31233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    __slots__ = ['data']
31333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
31433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def __init__(self, rdclass, rdtype, data):
31533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        super(GenericRdata, self).__init__(rdclass, rdtype)
31633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        self.data = data
31733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
31833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def to_text(self, origin=None, relativize=True, **kw):
31933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        return r'\# %d ' % len(self.data) + _hexify(self.data)
32033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
32133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
32233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        token = tok.get()
32333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        if not token.is_identifier() or token.value != '\#':
32433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            raise dns.exception.SyntaxError(r'generic rdata does not start with \#')
32533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        length = tok.get_int()
32633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        chunks = []
32733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        while 1:
32833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            token = tok.get()
32933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            if token.is_eol_or_eof():
33033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                break
33133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            chunks.append(token.value)
33233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        hex = ''.join(chunks)
33333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        data = hex.decode('hex_codec')
33433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        if len(data) != length:
33533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            raise dns.exception.SyntaxError('generic rdata hex data has wrong length')
33633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        return cls(rdclass, rdtype, data)
33733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
33833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    from_text = classmethod(from_text)
33933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
34033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def to_wire(self, file, compress = None, origin = None):
34133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        file.write(self.data)
34233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
34333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
34433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        return cls(rdclass, rdtype, wire[current : current + rdlen])
34533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
34633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    from_wire = classmethod(from_wire)
34733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
34833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def _cmp(self, other):
34933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        return cmp(self.data, other.data)
35033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
35133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck_rdata_modules = {}
35233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck_module_prefix = 'dns.rdtypes'
35333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
35433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef get_rdata_class(rdclass, rdtype):
35533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
35633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    def import_module(name):
35733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        mod = __import__(name)
35833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        components = name.split('.')
35933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        for comp in components[1:]:
36033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            mod = getattr(mod, comp)
36133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        return mod
36233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
36333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    mod = _rdata_modules.get((rdclass, rdtype))
36433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    rdclass_text = dns.rdataclass.to_text(rdclass)
36533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    rdtype_text = dns.rdatatype.to_text(rdtype)
36633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    rdtype_text = rdtype_text.replace('-', '_')
36733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    if not mod:
36833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        mod = _rdata_modules.get((dns.rdatatype.ANY, rdtype))
36933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        if not mod:
37033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            try:
37133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                mod = import_module('.'.join([_module_prefix,
37233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                                              rdclass_text, rdtype_text]))
37333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                _rdata_modules[(rdclass, rdtype)] = mod
37433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            except ImportError:
37533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                try:
37633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                    mod = import_module('.'.join([_module_prefix,
37733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                                                  'ANY', rdtype_text]))
37833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                    _rdata_modules[(dns.rdataclass.ANY, rdtype)] = mod
37933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                except ImportError:
38033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                    mod = None
38133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    if mod:
38233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        cls = getattr(mod, rdtype_text)
38333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    else:
38433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        cls = GenericRdata
38533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return cls
38633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
38733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef from_text(rdclass, rdtype, tok, origin = None, relativize = True):
38833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    """Build an rdata object from text format.
38933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
39033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    This function attempts to dynamically load a class which
39133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    implements the specified rdata class and type.  If there is no
39233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    class-and-type-specific implementation, the GenericRdata class
39333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    is used.
39433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
39533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    Once a class is chosen, its from_text() class method is called
39633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    with the parameters to this function.
39733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
39833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param rdclass: The rdata class
39933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @type rdclass: int
40033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param rdtype: The rdata type
40133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @type rdtype: int
40233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param tok: The tokenizer
40333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @type tok: dns.tokenizer.Tokenizer
40433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param origin: The origin to use for relative names
40533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @type origin: dns.name.Name
40633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param relativize: Should names be relativized?
40733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @type relativize: bool
40833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @rtype: dns.rdata.Rdata instance"""
40933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
41033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    if isinstance(tok, str):
41133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        tok = dns.tokenizer.Tokenizer(tok)
41233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    cls = get_rdata_class(rdclass, rdtype)
41333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    if cls != GenericRdata:
41433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        # peek at first token
41533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        token = tok.get()
41633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        tok.unget(token)
41733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck        if token.is_identifier() and \
41833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck           token.value == r'\#':
41933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            #
42033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            # Known type using the generic syntax.  Extract the
42133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            # wire form from the generic syntax, and then run
42233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            # from_wire on it.
42333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            #
42433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            rdata = GenericRdata.from_text(rdclass, rdtype, tok, origin,
42533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                                           relativize)
42633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck            return from_wire(rdclass, rdtype, rdata.data, 0, len(rdata.data),
42733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck                             origin)
42833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return cls.from_text(rdclass, rdtype, tok, origin, relativize)
42933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
43033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef from_wire(rdclass, rdtype, wire, current, rdlen, origin = None):
43133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    """Build an rdata object from wire format
43233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
43333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    This function attempts to dynamically load a class which
43433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    implements the specified rdata class and type.  If there is no
43533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    class-and-type-specific implementation, the GenericRdata class
43633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    is used.
43733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
43833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    Once a class is chosen, its from_wire() class method is called
43933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    with the parameters to this function.
44033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
44133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param rdclass: The rdata class
44233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @type rdclass: int
44333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param rdtype: The rdata type
44433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @type rdtype: int
44533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param wire: The wire-format message
44633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @type wire: string
44733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param current: The offet in wire of the beginning of the rdata.
44833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @type current: int
44933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param rdlen: The length of the wire-format rdata
45033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @type rdlen: int
45133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @param origin: The origin to use for relative names
45233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @type origin: dns.name.Name
45333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    @rtype: dns.rdata.Rdata instance"""
45433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck
45533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    cls = get_rdata_class(rdclass, rdtype)
45633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck    return cls.from_wire(rdclass, rdtype, wire, current, rdlen, origin)
457