1 # Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc.
3 # Permission to use, copy, modify, and distribute this software and its
4 # documentation for any purpose with or without fee is hereby granted,
5 # provided that the above copyright notice and this permission notice
6 # appear in all copies.
8 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
9 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
11 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
14 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 class NSEC(dns.rdata.Rdata):
26 @ivar next: the next name
27 @type next: dns.name.Name object
28 @ivar windows: the windowed bitmap list
29 @type windows: list of (window number, string) tuples"""
31 __slots__ = ['next', 'windows']
33 def __init__(self, rdclass, rdtype, next, windows):
34 super(NSEC, self).__init__(rdclass, rdtype)
36 self.windows = windows
38 def to_text(self, origin=None, relativize=True, **kw):
39 next = self.next.choose_relativity(origin, relativize)
41 for (window, bitmap) in self.windows:
43 for i in xrange(0, len(bitmap)):
45 for j in xrange(0, 8):
46 if byte & (0x80 >> j):
47 bits.append(dns.rdatatype.to_text(window * 256 + \
49 text += (' ' + ' '.join(bits))
50 return '%s%s' % (next, text)
52 def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
54 next = next.choose_relativity(origin, relativize)
57 token = tok.get().unescape()
58 if token.is_eol_or_eof():
60 nrdtype = dns.rdatatype.from_text(token.value)
62 raise dns.exception.SyntaxError("NSEC with bit 0")
64 raise dns.exception.SyntaxError("NSEC with bit > 65535")
65 rdtypes.append(nrdtype)
72 for nrdtype in rdtypes:
73 if nrdtype == prior_rdtype:
75 prior_rdtype = nrdtype
76 new_window = nrdtype // 256
77 if new_window != window:
78 windows.append((window, ''.join(bitmap[0:octets])))
81 offset = nrdtype % 256
85 bitmap[byte] = chr(ord(bitmap[byte]) | (0x80 >> bit))
86 windows.append((window, ''.join(bitmap[0:octets])))
87 return cls(rdclass, rdtype, next, windows)
89 from_text = classmethod(from_text)
91 def to_wire(self, file, compress = None, origin = None):
92 self.next.to_wire(file, None, origin)
93 for (window, bitmap) in self.windows:
94 file.write(chr(window))
95 file.write(chr(len(bitmap)))
98 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
99 (next, cused) = dns.name.from_wire(wire[: current + rdlen], current)
105 raise dns.exception.FormError("NSEC too short")
106 window = ord(wire[current])
107 octets = ord(wire[current + 1])
108 if octets == 0 or octets > 32:
109 raise dns.exception.FormError("bad NSEC octets")
113 raise dns.exception.FormError("bad NSEC bitmap length")
114 bitmap = wire[current : current + octets]
117 windows.append((window, bitmap))
118 if not origin is None:
119 next = next.relativize(origin)
120 return cls(rdclass, rdtype, next, windows)
122 from_wire = classmethod(from_wire)
124 def choose_relativity(self, origin = None, relativize = True):
125 self.next = self.next.choose_relativity(origin, relativize)
127 def _cmp(self, other):
128 v = cmp(self.next, other.next)
130 b1 = cStringIO.StringIO()
131 for (window, bitmap) in self.windows:
132 b1.write(chr(window))
133 b1.write(chr(len(bitmap)))
135 b2 = cStringIO.StringIO()
136 for (window, bitmap) in other.windows:
137 b2.write(chr(window))
138 b2.write(chr(len(bitmap)))
140 v = cmp(b1.getvalue(), b2.getvalue())