133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# Copyright (C) 2003-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"""MX-like base classes.""" 1733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 1833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport cStringIO 1933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport struct 2033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 2133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport dns.exception 2233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport dns.rdata 2333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport dns.name 2433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 2533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass MXBase(dns.rdata.Rdata): 2633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Base class for rdata that is like an MX record. 2733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 2833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @ivar preference: the preference value 2933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type preference: int 3033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @ivar exchange: the exchange name 3133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type exchange: dns.name.Name object""" 3233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 3333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck __slots__ = ['preference', 'exchange'] 3433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 3533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __init__(self, rdclass, rdtype, preference, exchange): 3633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck super(MXBase, self).__init__(rdclass, rdtype) 3733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.preference = preference 3833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.exchange = exchange 3933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 4033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def to_text(self, origin=None, relativize=True, **kw): 4133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck exchange = self.exchange.choose_relativity(origin, relativize) 4233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return '%d %s' % (self.preference, exchange) 4333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 4433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): 4533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck preference = tok.get_uint16() 4633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck exchange = tok.get_name() 4733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck exchange = exchange.choose_relativity(origin, relativize) 4833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck tok.get_eol() 4933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return cls(rdclass, rdtype, preference, exchange) 5033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 5133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck from_text = classmethod(from_text) 5233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 5333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def to_wire(self, file, compress = None, origin = None): 5433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pref = struct.pack("!H", self.preference) 5533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck file.write(pref) 5633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.exchange.to_wire(file, compress, origin) 5733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 5833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def to_digestable(self, origin = None): 5933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return struct.pack("!H", self.preference) + \ 6033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.exchange.to_digestable(origin) 6133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 6233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): 6333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck (preference, ) = struct.unpack('!H', wire[current : current + 2]) 6433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck current += 2 6533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck rdlen -= 2 6633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck (exchange, cused) = dns.name.from_wire(wire[: current + rdlen], 6733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck current) 6833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if cused != rdlen: 6933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise dns.exception.FormError 7033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not origin is None: 7133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck exchange = exchange.relativize(origin) 7233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return cls(rdclass, rdtype, preference, exchange) 7333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 7433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck from_wire = classmethod(from_wire) 7533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 7633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def choose_relativity(self, origin = None, relativize = True): 7733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.exchange = self.exchange.choose_relativity(origin, relativize) 7833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 7933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def _cmp(self, other): 8033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sp = struct.pack("!H", self.preference) 8133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck op = struct.pack("!H", other.preference) 8233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck v = cmp(sp, op) 8333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if v == 0: 8433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck v = cmp(self.exchange, other.exchange) 8533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return v 8633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 8733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass UncompressedMX(MXBase): 8833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Base class for rdata that is like an MX record, but whose name 8933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck is not compressed when converted to DNS wire format, and whose 9033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck digestable form is not downcased.""" 9133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 9233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def to_wire(self, file, compress = None, origin = None): 9333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck super(UncompressedMX, self).to_wire(file, None, origin) 9433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 9533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def to_digestable(self, origin = None): 9633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck f = cStringIO.StringIO() 9733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.to_wire(f, None, origin) 9833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return f.getvalue() 9933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 10033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass UncompressedDowncasingMX(MXBase): 10133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Base class for rdata that is like an MX record, but whose name 10233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck is not compressed when convert to DNS wire format.""" 10333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 10433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def to_wire(self, file, compress = None, origin = None): 10533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck super(UncompressedDowncasingMX, self).to_wire(file, None, origin) 106