| Class | Dnsruby::RR::NSEC |
| In: |
lib/Dnsruby/resource/NSEC.rb
|
| Parent: | RR |
RFC4034, section 4 The NSEC resource record lists two separate things: the next owner name (in the canonical ordering of the zone) that contains authoritative data or a delegation point NS RRset, and the set of RR types present at the NSEC RR‘s owner name [RFC3845]. The complete set of NSEC RRs in a zone indicates which authoritative RRsets exist in a zone and also form a chain of authoritative owner names in the zone. This information is used to provide authenticated denial of existence for DNS data, as described in [RFC4035].
| TypeValue | = | Types::NSEC #:nodoc: all |
| next_domain | [R] | The next name which exists after this NSEC The Next Domain field contains the next owner name (in the canonical ordering of the zone) that has authoritative data or contains a delegation point NS RRset |
| types | [R] | The Type Bit Maps field identifies the RRset types that exist at the NSEC RR‘s owner name |
# File lib/Dnsruby/resource/NSEC.rb, line 105
105: def self.decode_types(bytes)
106: types = []
107: #RFC4034 section 4.1.2
108: #The RR type space is split into 256 window blocks, each representing
109: #the low-order 8 bits of the 16-bit RR type space. Each block that
110: #has at least one active RR type is encoded using a single octet
111: #window number (from 0 to 255), a single octet bitmap length (from 1
112: #to 32) indicating the number of octets used for the window block's
113: #bitmap, and up to 32 octets (256 bits) of bitmap.
114:
115: #Blocks are present in the NSEC RR RDATA in increasing numerical
116: #order.
117:
118: # Type Bit Maps Field = ( Window Block # | Bitmap Length | Bitmap )+
119:
120: # where "|" denotes concatenation.
121:
122: pos = 0
123: while (pos < bytes.length)
124: #So, read the first two octets
125: if (bytes.length-pos < 2)
126: raise DecodeError.new("NSEC : Expected window number and bitmap length octets")
127: end
128: window_number = bytes[pos]
129: bitmap_length = bytes[pos+1]
130: if (window_number.class == String) # Ruby 1.9
131: window_number = window_number.getbyte(0)
132: bitmap_length = bitmap_length.getbyte(0)
133: end
134: pos += 2
135: bitmap = bytes[pos,bitmap_length]
136: pos += bitmap_length
137: #Each bitmap encodes the low-order 8 bits of RR types within the
138: #window block, in network bit order. The first bit is bit 0. For
139: #window block 0, bit 1 corresponds to RR type 1 (A), bit 2 corresponds
140: #to RR type 2 (NS), and so forth. For window block 1, bit 1
141: #corresponds to RR type 257, and bit 2 to RR type 258. If a bit is
142: #set, it indicates that an RRset of that type is present for the NSEC
143: #RR's owner name. If a bit is clear, it indicates that no RRset of
144: #that type is present for the NSEC RR's owner name.
145: index = 0
146: bitmap.each_byte do |char|
147: if char.to_i != 0
148: # decode these RR types
149: 0..8.times do |i|
150: if (((1 << (7-i)) & char) == (1 << (7-i)))
151: type = Types.new((256 * window_number) + (8 * index) + i)
152: #Bits representing pseudo-types MUST be clear, as they do not appear
153: #in zone data. If encountered, they MUST be ignored upon being read.
154: if (!([Types::OPT, Types::TSIG].include?(type)))
155: types.push(type)
156: end
157: end
158: end
159: end
160: index += 1
161: end
162: end
163: return types
164: end
# File lib/Dnsruby/resource/NSEC.rb, line 170
170: def self.encode_types(nsec)
171: output=""
172: #types represents all 65536 possible RR types.
173: #Split up types into sets of 256 different types.
174: type_codes = []
175: nsec.types.each do |type|
176: type_codes.push(type.code)
177: end
178: type_codes.sort!
179: window = -1
180: 0.step(65536,256) { |step|
181: # Gather up the RR types for this set of 256
182: types_to_go = []
183: while (!type_codes.empty? && type_codes[0] < step)
184: types_to_go.push(type_codes[0])
185: # And delete them from type_codes
186: type_codes=type_codes.last(type_codes.length-1)
187: break if (type_codes.empty?)
188: end
189:
190: if (!types_to_go.empty?)
191: # Then create the bitmap for them
192: bitmap=""
193: # keep on adding them until there's none left
194: pos = 0
195: bitmap_pos = 0
196: while (!types_to_go.empty?)
197:
198: # Check the next eight
199: byte = 0
200: pos += 8
201: while (types_to_go[0] < pos + step-256)
202: byte = byte | (1 << (pos-1-(types_to_go[0] - (step-256) )))
203: # Add it to the list
204: # And remove it from the to_go queue
205: types_to_go =types_to_go.last(types_to_go.length-1)
206: break if (types_to_go.empty?)
207: end
208: bitmap += " "
209: if (bitmap[bitmap_pos].class == String)
210: bitmap.setbyte(bitmap_pos, byte) # Ruby 1.9
211: else
212: bitmap[bitmap_pos]=byte
213: end
214: bitmap_pos+=1
215: end
216:
217: # Now add data to output bytes
218: start = output.length
219: (2+bitmap.length).times do
220: output += " "
221: end
222:
223: if (output[start].class == String)
224: output.setbyte(start, window)
225: output.setbyte(start+1, bitmap.length)
226: bitmap.length.times do |i|
227: output.setbyte(start+2+i, bitmap[i].getbyte(0))
228: end
229: else
230: output[start] = window
231: output[start+1] = bitmap.length
232: bitmap.length.times do |i|
233: output[start+2+i] = bitmap[i]
234: end
235: end
236: end
237: window += 1
238:
239: # Are there any more types after this?
240: if (type_codes.empty?)
241: # If not, then break (so we don't add more zeros)
242: break
243: end
244: }
245: if (output[0].class == String)
246: output = output.force_encoding("ascii-8bit")
247: end
248: return output
249: end
# File lib/Dnsruby/resource/NSEC.rb, line 76
76: def self.get_types(t)
77: types = nil
78: if (t.instance_of?Array)
79: # from the wire, already decoded
80: types =t
81: elsif (t.instance_of?String)
82: if (index = t.index";")
83: t = t[0, index]
84: end
85: if (index = t.index")")
86: t = t[0, index]
87: end
88: # List of mnemonics
89: types=[]
90: mnemonics = t.split(" ")
91: mnemonics.each do |m|
92: type = Types.new(m)
93: types.push(type)
94: end
95: else
96: raise DecodeError.new("Unknown format of types for Dnsruby::RR::NSEC")
97: end
98: return types
99: end
# File lib/Dnsruby/resource/NSEC.rb, line 101
101: def add_type(t)
102: self.types=(@types + [t])
103: end
# File lib/Dnsruby/resource/NSEC.rb, line 45
45: def check_name_in_range(n)
46: # Check if the name is covered by this record
47: if (@name.wild?)
48: return check_name_in_wildcard_range(n)
49: end
50: if (name.canonically_before(n) && (n.canonically_before(next_domain)))
51: return true
52: end
53: return false
54: end
# File lib/Dnsruby/resource/NSEC.rb, line 56
56: def check_name_in_wildcard_range(n)
57: # Check if the name is covered by this record
58: return false if !@name.wild?
59: return false if @next_domain.canonically_before(n)
60: # Now just check that the wildcard is *before* the name
61: # Strip the first label ("*") and then compare
62: n2 = Name.create(@name)
63: n2.labels.delete_at(0)
64: return false if n.canonically_before(n2)
65: return true
66: end
# File lib/Dnsruby/resource/NSEC.rb, line 166
166: def encode_types
167: NSEC.encode_types(self)
168: end
# File lib/Dnsruby/resource/NSEC.rb, line 257
257: def from_string(input)
258: if (input.length > 0)
259: data = input.split(" ")
260: self.next_domain=(data[0])
261: len = data[0].length+ 1
262: if (data[1] == "(")
263: len = len + data[1].length
264: end
265: self.types=(input[len, input.length-len])
266: @types = NSEC.get_types(input[len, input.length-len])
267: end
268: end