1 | var types = require('./types')
|
---|
2 | var rcodes = require('./rcodes')
|
---|
3 | var opcodes = require('./opcodes')
|
---|
4 | var ip = require('ip')
|
---|
5 | var Buffer = require('safe-buffer').Buffer
|
---|
6 |
|
---|
7 | var QUERY_FLAG = 0
|
---|
8 | var RESPONSE_FLAG = 1 << 15
|
---|
9 | var FLUSH_MASK = 1 << 15
|
---|
10 | var NOT_FLUSH_MASK = ~FLUSH_MASK
|
---|
11 | var QU_MASK = 1 << 15
|
---|
12 | var NOT_QU_MASK = ~QU_MASK
|
---|
13 |
|
---|
14 | var name = exports.txt = exports.name = {}
|
---|
15 |
|
---|
16 | name.encode = function (str, buf, offset) {
|
---|
17 | if (!buf) buf = Buffer.alloc(name.encodingLength(str))
|
---|
18 | if (!offset) offset = 0
|
---|
19 | var oldOffset = offset
|
---|
20 |
|
---|
21 | // strip leading and trailing .
|
---|
22 | var n = str.replace(/^\.|\.$/gm, '')
|
---|
23 | if (n.length) {
|
---|
24 | var list = n.split('.')
|
---|
25 |
|
---|
26 | for (var i = 0; i < list.length; i++) {
|
---|
27 | var len = buf.write(list[i], offset + 1)
|
---|
28 | buf[offset] = len
|
---|
29 | offset += len + 1
|
---|
30 | }
|
---|
31 | }
|
---|
32 |
|
---|
33 | buf[offset++] = 0
|
---|
34 |
|
---|
35 | name.encode.bytes = offset - oldOffset
|
---|
36 | return buf
|
---|
37 | }
|
---|
38 |
|
---|
39 | name.encode.bytes = 0
|
---|
40 |
|
---|
41 | name.decode = function (buf, offset) {
|
---|
42 | if (!offset) offset = 0
|
---|
43 |
|
---|
44 | var list = []
|
---|
45 | var oldOffset = offset
|
---|
46 | var len = buf[offset++]
|
---|
47 |
|
---|
48 | if (len === 0) {
|
---|
49 | name.decode.bytes = 1
|
---|
50 | return '.'
|
---|
51 | }
|
---|
52 | if (len >= 0xc0) {
|
---|
53 | var res = name.decode(buf, buf.readUInt16BE(offset - 1) - 0xc000)
|
---|
54 | name.decode.bytes = 2
|
---|
55 | return res
|
---|
56 | }
|
---|
57 |
|
---|
58 | while (len) {
|
---|
59 | if (len >= 0xc0) {
|
---|
60 | list.push(name.decode(buf, buf.readUInt16BE(offset - 1) - 0xc000))
|
---|
61 | offset++
|
---|
62 | break
|
---|
63 | }
|
---|
64 |
|
---|
65 | list.push(buf.toString('utf-8', offset, offset + len))
|
---|
66 | offset += len
|
---|
67 | len = buf[offset++]
|
---|
68 | }
|
---|
69 |
|
---|
70 | name.decode.bytes = offset - oldOffset
|
---|
71 | return list.join('.')
|
---|
72 | }
|
---|
73 |
|
---|
74 | name.decode.bytes = 0
|
---|
75 |
|
---|
76 | name.encodingLength = function (n) {
|
---|
77 | if (n === '.' || n === '..') return 1
|
---|
78 | return Buffer.byteLength(n.replace(/^\.|\.$/gm, '')) + 2
|
---|
79 | }
|
---|
80 |
|
---|
81 | var string = {}
|
---|
82 |
|
---|
83 | string.encode = function (s, buf, offset) {
|
---|
84 | if (!buf) buf = Buffer.alloc(string.encodingLength(s))
|
---|
85 | if (!offset) offset = 0
|
---|
86 |
|
---|
87 | var len = buf.write(s, offset + 1)
|
---|
88 | buf[offset] = len
|
---|
89 | string.encode.bytes = len + 1
|
---|
90 | return buf
|
---|
91 | }
|
---|
92 |
|
---|
93 | string.encode.bytes = 0
|
---|
94 |
|
---|
95 | string.decode = function (buf, offset) {
|
---|
96 | if (!offset) offset = 0
|
---|
97 |
|
---|
98 | var len = buf[offset]
|
---|
99 | var s = buf.toString('utf-8', offset + 1, offset + 1 + len)
|
---|
100 | string.decode.bytes = len + 1
|
---|
101 | return s
|
---|
102 | }
|
---|
103 |
|
---|
104 | string.decode.bytes = 0
|
---|
105 |
|
---|
106 | string.encodingLength = function (s) {
|
---|
107 | return Buffer.byteLength(s) + 1
|
---|
108 | }
|
---|
109 |
|
---|
110 | var header = {}
|
---|
111 |
|
---|
112 | header.encode = function (h, buf, offset) {
|
---|
113 | if (!buf) buf = header.encodingLength(h)
|
---|
114 | if (!offset) offset = 0
|
---|
115 |
|
---|
116 | var flags = (h.flags || 0) & 32767
|
---|
117 | var type = h.type === 'response' ? RESPONSE_FLAG : QUERY_FLAG
|
---|
118 |
|
---|
119 | buf.writeUInt16BE(h.id || 0, offset)
|
---|
120 | buf.writeUInt16BE(flags | type, offset + 2)
|
---|
121 | buf.writeUInt16BE(h.questions.length, offset + 4)
|
---|
122 | buf.writeUInt16BE(h.answers.length, offset + 6)
|
---|
123 | buf.writeUInt16BE(h.authorities.length, offset + 8)
|
---|
124 | buf.writeUInt16BE(h.additionals.length, offset + 10)
|
---|
125 |
|
---|
126 | return buf
|
---|
127 | }
|
---|
128 |
|
---|
129 | header.encode.bytes = 12
|
---|
130 |
|
---|
131 | header.decode = function (buf, offset) {
|
---|
132 | if (!offset) offset = 0
|
---|
133 | if (buf.length < 12) throw new Error('Header must be 12 bytes')
|
---|
134 | var flags = buf.readUInt16BE(offset + 2)
|
---|
135 |
|
---|
136 | return {
|
---|
137 | id: buf.readUInt16BE(offset),
|
---|
138 | type: flags & RESPONSE_FLAG ? 'response' : 'query',
|
---|
139 | flags: flags & 32767,
|
---|
140 | flag_qr: ((flags >> 15) & 0x1) === 1,
|
---|
141 | opcode: opcodes.toString((flags >> 11) & 0xf),
|
---|
142 | flag_auth: ((flags >> 10) & 0x1) === 1,
|
---|
143 | flag_trunc: ((flags >> 9) & 0x1) === 1,
|
---|
144 | flag_rd: ((flags >> 8) & 0x1) === 1,
|
---|
145 | flag_ra: ((flags >> 7) & 0x1) === 1,
|
---|
146 | flag_z: ((flags >> 6) & 0x1) === 1,
|
---|
147 | flag_ad: ((flags >> 5) & 0x1) === 1,
|
---|
148 | flag_cd: ((flags >> 4) & 0x1) === 1,
|
---|
149 | rcode: rcodes.toString(flags & 0xf),
|
---|
150 | questions: new Array(buf.readUInt16BE(offset + 4)),
|
---|
151 | answers: new Array(buf.readUInt16BE(offset + 6)),
|
---|
152 | authorities: new Array(buf.readUInt16BE(offset + 8)),
|
---|
153 | additionals: new Array(buf.readUInt16BE(offset + 10))
|
---|
154 | }
|
---|
155 | }
|
---|
156 |
|
---|
157 | header.decode.bytes = 12
|
---|
158 |
|
---|
159 | header.encodingLength = function () {
|
---|
160 | return 12
|
---|
161 | }
|
---|
162 |
|
---|
163 | var runknown = exports.unknown = {}
|
---|
164 |
|
---|
165 | runknown.encode = function (data, buf, offset) {
|
---|
166 | if (!buf) buf = Buffer.alloc(runknown.encodingLength(data))
|
---|
167 | if (!offset) offset = 0
|
---|
168 |
|
---|
169 | buf.writeUInt16BE(data.length, offset)
|
---|
170 | data.copy(buf, offset + 2)
|
---|
171 |
|
---|
172 | runknown.encode.bytes = data.length + 2
|
---|
173 | return buf
|
---|
174 | }
|
---|
175 |
|
---|
176 | runknown.encode.bytes = 0
|
---|
177 |
|
---|
178 | runknown.decode = function (buf, offset) {
|
---|
179 | if (!offset) offset = 0
|
---|
180 |
|
---|
181 | var len = buf.readUInt16BE(offset)
|
---|
182 | var data = buf.slice(offset + 2, offset + 2 + len)
|
---|
183 | runknown.decode.bytes = len + 2
|
---|
184 | return data
|
---|
185 | }
|
---|
186 |
|
---|
187 | runknown.decode.bytes = 0
|
---|
188 |
|
---|
189 | runknown.encodingLength = function (data) {
|
---|
190 | return data.length + 2
|
---|
191 | }
|
---|
192 |
|
---|
193 | var rns = exports.ns = {}
|
---|
194 |
|
---|
195 | rns.encode = function (data, buf, offset) {
|
---|
196 | if (!buf) buf = Buffer.alloc(rns.encodingLength(data))
|
---|
197 | if (!offset) offset = 0
|
---|
198 |
|
---|
199 | name.encode(data, buf, offset + 2)
|
---|
200 | buf.writeUInt16BE(name.encode.bytes, offset)
|
---|
201 | rns.encode.bytes = name.encode.bytes + 2
|
---|
202 | return buf
|
---|
203 | }
|
---|
204 |
|
---|
205 | rns.encode.bytes = 0
|
---|
206 |
|
---|
207 | rns.decode = function (buf, offset) {
|
---|
208 | if (!offset) offset = 0
|
---|
209 |
|
---|
210 | var len = buf.readUInt16BE(offset)
|
---|
211 | var dd = name.decode(buf, offset + 2)
|
---|
212 |
|
---|
213 | rns.decode.bytes = len + 2
|
---|
214 | return dd
|
---|
215 | }
|
---|
216 |
|
---|
217 | rns.decode.bytes = 0
|
---|
218 |
|
---|
219 | rns.encodingLength = function (data) {
|
---|
220 | return name.encodingLength(data) + 2
|
---|
221 | }
|
---|
222 |
|
---|
223 | var rsoa = exports.soa = {}
|
---|
224 |
|
---|
225 | rsoa.encode = function (data, buf, offset) {
|
---|
226 | if (!buf) buf = Buffer.alloc(rsoa.encodingLength(data))
|
---|
227 | if (!offset) offset = 0
|
---|
228 |
|
---|
229 | var oldOffset = offset
|
---|
230 | offset += 2
|
---|
231 | name.encode(data.mname, buf, offset)
|
---|
232 | offset += name.encode.bytes
|
---|
233 | name.encode(data.rname, buf, offset)
|
---|
234 | offset += name.encode.bytes
|
---|
235 | buf.writeUInt32BE(data.serial || 0, offset)
|
---|
236 | offset += 4
|
---|
237 | buf.writeUInt32BE(data.refresh || 0, offset)
|
---|
238 | offset += 4
|
---|
239 | buf.writeUInt32BE(data.retry || 0, offset)
|
---|
240 | offset += 4
|
---|
241 | buf.writeUInt32BE(data.expire || 0, offset)
|
---|
242 | offset += 4
|
---|
243 | buf.writeUInt32BE(data.minimum || 0, offset)
|
---|
244 | offset += 4
|
---|
245 |
|
---|
246 | buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
|
---|
247 | rsoa.encode.bytes = offset - oldOffset
|
---|
248 | return buf
|
---|
249 | }
|
---|
250 |
|
---|
251 | rsoa.encode.bytes = 0
|
---|
252 |
|
---|
253 | rsoa.decode = function (buf, offset) {
|
---|
254 | if (!offset) offset = 0
|
---|
255 |
|
---|
256 | var oldOffset = offset
|
---|
257 |
|
---|
258 | var data = {}
|
---|
259 | offset += 2
|
---|
260 | data.mname = name.decode(buf, offset)
|
---|
261 | offset += name.decode.bytes
|
---|
262 | data.rname = name.decode(buf, offset)
|
---|
263 | offset += name.decode.bytes
|
---|
264 | data.serial = buf.readUInt32BE(offset)
|
---|
265 | offset += 4
|
---|
266 | data.refresh = buf.readUInt32BE(offset)
|
---|
267 | offset += 4
|
---|
268 | data.retry = buf.readUInt32BE(offset)
|
---|
269 | offset += 4
|
---|
270 | data.expire = buf.readUInt32BE(offset)
|
---|
271 | offset += 4
|
---|
272 | data.minimum = buf.readUInt32BE(offset)
|
---|
273 | offset += 4
|
---|
274 |
|
---|
275 | rsoa.decode.bytes = offset - oldOffset
|
---|
276 | return data
|
---|
277 | }
|
---|
278 |
|
---|
279 | rsoa.decode.bytes = 0
|
---|
280 |
|
---|
281 | rsoa.encodingLength = function (data) {
|
---|
282 | return 22 + name.encodingLength(data.mname) + name.encodingLength(data.rname)
|
---|
283 | }
|
---|
284 |
|
---|
285 | var rtxt = exports.txt = exports.null = {}
|
---|
286 | var rnull = rtxt
|
---|
287 |
|
---|
288 | rtxt.encode = function (data, buf, offset) {
|
---|
289 | if (!buf) buf = Buffer.alloc(rtxt.encodingLength(data))
|
---|
290 | if (!offset) offset = 0
|
---|
291 |
|
---|
292 | if (typeof data === 'string') data = Buffer.from(data)
|
---|
293 | if (!data) data = Buffer.alloc(0)
|
---|
294 |
|
---|
295 | var oldOffset = offset
|
---|
296 | offset += 2
|
---|
297 |
|
---|
298 | var len = data.length
|
---|
299 | data.copy(buf, offset, 0, len)
|
---|
300 | offset += len
|
---|
301 |
|
---|
302 | buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
|
---|
303 | rtxt.encode.bytes = offset - oldOffset
|
---|
304 | return buf
|
---|
305 | }
|
---|
306 |
|
---|
307 | rtxt.encode.bytes = 0
|
---|
308 |
|
---|
309 | rtxt.decode = function (buf, offset) {
|
---|
310 | if (!offset) offset = 0
|
---|
311 | var oldOffset = offset
|
---|
312 | var len = buf.readUInt16BE(offset)
|
---|
313 |
|
---|
314 | offset += 2
|
---|
315 |
|
---|
316 | var data = buf.slice(offset, offset + len)
|
---|
317 | offset += len
|
---|
318 |
|
---|
319 | rtxt.decode.bytes = offset - oldOffset
|
---|
320 | return data
|
---|
321 | }
|
---|
322 |
|
---|
323 | rtxt.decode.bytes = 0
|
---|
324 |
|
---|
325 | rtxt.encodingLength = function (data) {
|
---|
326 | if (!data) return 2
|
---|
327 | return (Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data)) + 2
|
---|
328 | }
|
---|
329 |
|
---|
330 | var rhinfo = exports.hinfo = {}
|
---|
331 |
|
---|
332 | rhinfo.encode = function (data, buf, offset) {
|
---|
333 | if (!buf) buf = Buffer.alloc(rhinfo.encodingLength(data))
|
---|
334 | if (!offset) offset = 0
|
---|
335 |
|
---|
336 | var oldOffset = offset
|
---|
337 | offset += 2
|
---|
338 | string.encode(data.cpu, buf, offset)
|
---|
339 | offset += string.encode.bytes
|
---|
340 | string.encode(data.os, buf, offset)
|
---|
341 | offset += string.encode.bytes
|
---|
342 | buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
|
---|
343 | rhinfo.encode.bytes = offset - oldOffset
|
---|
344 | return buf
|
---|
345 | }
|
---|
346 |
|
---|
347 | rhinfo.encode.bytes = 0
|
---|
348 |
|
---|
349 | rhinfo.decode = function (buf, offset) {
|
---|
350 | if (!offset) offset = 0
|
---|
351 |
|
---|
352 | var oldOffset = offset
|
---|
353 |
|
---|
354 | var data = {}
|
---|
355 | offset += 2
|
---|
356 | data.cpu = string.decode(buf, offset)
|
---|
357 | offset += string.decode.bytes
|
---|
358 | data.os = string.decode(buf, offset)
|
---|
359 | offset += string.decode.bytes
|
---|
360 | rhinfo.decode.bytes = offset - oldOffset
|
---|
361 | return data
|
---|
362 | }
|
---|
363 |
|
---|
364 | rhinfo.decode.bytes = 0
|
---|
365 |
|
---|
366 | rhinfo.encodingLength = function (data) {
|
---|
367 | return string.encodingLength(data.cpu) + string.encodingLength(data.os) + 2
|
---|
368 | }
|
---|
369 |
|
---|
370 | var rptr = exports.ptr = {}
|
---|
371 | var rcname = exports.cname = rptr
|
---|
372 | var rdname = exports.dname = rptr
|
---|
373 |
|
---|
374 | rptr.encode = function (data, buf, offset) {
|
---|
375 | if (!buf) buf = Buffer.alloc(rptr.encodingLength(data))
|
---|
376 | if (!offset) offset = 0
|
---|
377 |
|
---|
378 | name.encode(data, buf, offset + 2)
|
---|
379 | buf.writeUInt16BE(name.encode.bytes, offset)
|
---|
380 | rptr.encode.bytes = name.encode.bytes + 2
|
---|
381 | return buf
|
---|
382 | }
|
---|
383 |
|
---|
384 | rptr.encode.bytes = 0
|
---|
385 |
|
---|
386 | rptr.decode = function (buf, offset) {
|
---|
387 | if (!offset) offset = 0
|
---|
388 |
|
---|
389 | var data = name.decode(buf, offset + 2)
|
---|
390 | rptr.decode.bytes = name.decode.bytes + 2
|
---|
391 | return data
|
---|
392 | }
|
---|
393 |
|
---|
394 | rptr.decode.bytes = 0
|
---|
395 |
|
---|
396 | rptr.encodingLength = function (data) {
|
---|
397 | return name.encodingLength(data) + 2
|
---|
398 | }
|
---|
399 |
|
---|
400 | var rsrv = exports.srv = {}
|
---|
401 |
|
---|
402 | rsrv.encode = function (data, buf, offset) {
|
---|
403 | if (!buf) buf = Buffer.alloc(rsrv.encodingLength(data))
|
---|
404 | if (!offset) offset = 0
|
---|
405 |
|
---|
406 | buf.writeUInt16BE(data.priority || 0, offset + 2)
|
---|
407 | buf.writeUInt16BE(data.weight || 0, offset + 4)
|
---|
408 | buf.writeUInt16BE(data.port || 0, offset + 6)
|
---|
409 | name.encode(data.target, buf, offset + 8)
|
---|
410 |
|
---|
411 | var len = name.encode.bytes + 6
|
---|
412 | buf.writeUInt16BE(len, offset)
|
---|
413 |
|
---|
414 | rsrv.encode.bytes = len + 2
|
---|
415 | return buf
|
---|
416 | }
|
---|
417 |
|
---|
418 | rsrv.encode.bytes = 0
|
---|
419 |
|
---|
420 | rsrv.decode = function (buf, offset) {
|
---|
421 | if (!offset) offset = 0
|
---|
422 |
|
---|
423 | var len = buf.readUInt16BE(offset)
|
---|
424 |
|
---|
425 | var data = {}
|
---|
426 | data.priority = buf.readUInt16BE(offset + 2)
|
---|
427 | data.weight = buf.readUInt16BE(offset + 4)
|
---|
428 | data.port = buf.readUInt16BE(offset + 6)
|
---|
429 | data.target = name.decode(buf, offset + 8)
|
---|
430 |
|
---|
431 | rsrv.decode.bytes = len + 2
|
---|
432 | return data
|
---|
433 | }
|
---|
434 |
|
---|
435 | rsrv.decode.bytes = 0
|
---|
436 |
|
---|
437 | rsrv.encodingLength = function (data) {
|
---|
438 | return 8 + name.encodingLength(data.target)
|
---|
439 | }
|
---|
440 |
|
---|
441 | var rcaa = exports.caa = {}
|
---|
442 |
|
---|
443 | rcaa.ISSUER_CRITICAL = 1 << 7
|
---|
444 |
|
---|
445 | rcaa.encode = function (data, buf, offset) {
|
---|
446 | var len = rcaa.encodingLength(data)
|
---|
447 |
|
---|
448 | if (!buf) buf = Buffer.alloc(rcaa.encodingLength(data))
|
---|
449 | if (!offset) offset = 0
|
---|
450 |
|
---|
451 | if (data.issuerCritical) {
|
---|
452 | data.flags = rcaa.ISSUER_CRITICAL
|
---|
453 | }
|
---|
454 |
|
---|
455 | buf.writeUInt16BE(len - 2, offset)
|
---|
456 | offset += 2
|
---|
457 | buf.writeUInt8(data.flags || 0, offset)
|
---|
458 | offset += 1
|
---|
459 | string.encode(data.tag, buf, offset)
|
---|
460 | offset += string.encode.bytes
|
---|
461 | buf.write(data.value, offset)
|
---|
462 | offset += Buffer.byteLength(data.value)
|
---|
463 |
|
---|
464 | rcaa.encode.bytes = len
|
---|
465 | return buf
|
---|
466 | }
|
---|
467 |
|
---|
468 | rcaa.encode.bytes = 0
|
---|
469 |
|
---|
470 | rcaa.decode = function (buf, offset) {
|
---|
471 | if (!offset) offset = 0
|
---|
472 |
|
---|
473 | var len = buf.readUInt16BE(offset)
|
---|
474 | offset += 2
|
---|
475 |
|
---|
476 | var oldOffset = offset
|
---|
477 | var data = {}
|
---|
478 | data.flags = buf.readUInt8(offset)
|
---|
479 | offset += 1
|
---|
480 | data.tag = string.decode(buf, offset)
|
---|
481 | offset += string.decode.bytes
|
---|
482 | data.value = buf.toString('utf-8', offset, oldOffset + len)
|
---|
483 |
|
---|
484 | data.issuerCritical = !!(data.flags & rcaa.ISSUER_CRITICAL)
|
---|
485 |
|
---|
486 | rcaa.decode.bytes = len + 2
|
---|
487 |
|
---|
488 | return data
|
---|
489 | }
|
---|
490 |
|
---|
491 | rcaa.decode.bytes = 0
|
---|
492 |
|
---|
493 | rcaa.encodingLength = function (data) {
|
---|
494 | return string.encodingLength(data.tag) + string.encodingLength(data.value) + 2
|
---|
495 | }
|
---|
496 |
|
---|
497 | var ra = exports.a = {}
|
---|
498 |
|
---|
499 | ra.encode = function (host, buf, offset) {
|
---|
500 | if (!buf) buf = Buffer.alloc(ra.encodingLength(host))
|
---|
501 | if (!offset) offset = 0
|
---|
502 |
|
---|
503 | buf.writeUInt16BE(4, offset)
|
---|
504 | offset += 2
|
---|
505 | ip.toBuffer(host, buf, offset)
|
---|
506 | ra.encode.bytes = 6
|
---|
507 | return buf
|
---|
508 | }
|
---|
509 |
|
---|
510 | ra.encode.bytes = 0
|
---|
511 |
|
---|
512 | ra.decode = function (buf, offset) {
|
---|
513 | if (!offset) offset = 0
|
---|
514 |
|
---|
515 | offset += 2
|
---|
516 | var host = ip.toString(buf, offset, 4)
|
---|
517 | ra.decode.bytes = 6
|
---|
518 | return host
|
---|
519 | }
|
---|
520 |
|
---|
521 | ra.decode.bytes = 0
|
---|
522 |
|
---|
523 | ra.encodingLength = function () {
|
---|
524 | return 6
|
---|
525 | }
|
---|
526 |
|
---|
527 | var raaaa = exports.aaaa = {}
|
---|
528 |
|
---|
529 | raaaa.encode = function (host, buf, offset) {
|
---|
530 | if (!buf) buf = Buffer.alloc(raaaa.encodingLength(host))
|
---|
531 | if (!offset) offset = 0
|
---|
532 |
|
---|
533 | buf.writeUInt16BE(16, offset)
|
---|
534 | offset += 2
|
---|
535 | ip.toBuffer(host, buf, offset)
|
---|
536 | raaaa.encode.bytes = 18
|
---|
537 | return buf
|
---|
538 | }
|
---|
539 |
|
---|
540 | raaaa.encode.bytes = 0
|
---|
541 |
|
---|
542 | raaaa.decode = function (buf, offset) {
|
---|
543 | if (!offset) offset = 0
|
---|
544 |
|
---|
545 | offset += 2
|
---|
546 | var host = ip.toString(buf, offset, 16)
|
---|
547 | raaaa.decode.bytes = 18
|
---|
548 | return host
|
---|
549 | }
|
---|
550 |
|
---|
551 | raaaa.decode.bytes = 0
|
---|
552 |
|
---|
553 | raaaa.encodingLength = function () {
|
---|
554 | return 18
|
---|
555 | }
|
---|
556 |
|
---|
557 | var renc = exports.record = function (type) {
|
---|
558 | switch (type.toUpperCase()) {
|
---|
559 | case 'A': return ra
|
---|
560 | case 'PTR': return rptr
|
---|
561 | case 'CNAME': return rcname
|
---|
562 | case 'DNAME': return rdname
|
---|
563 | case 'TXT': return rtxt
|
---|
564 | case 'NULL': return rnull
|
---|
565 | case 'AAAA': return raaaa
|
---|
566 | case 'SRV': return rsrv
|
---|
567 | case 'HINFO': return rhinfo
|
---|
568 | case 'CAA': return rcaa
|
---|
569 | case 'NS': return rns
|
---|
570 | case 'SOA': return rsoa
|
---|
571 | }
|
---|
572 | return runknown
|
---|
573 | }
|
---|
574 |
|
---|
575 | var answer = exports.answer = {}
|
---|
576 |
|
---|
577 | answer.encode = function (a, buf, offset) {
|
---|
578 | if (!buf) buf = Buffer.alloc(answer.encodingLength(a))
|
---|
579 | if (!offset) offset = 0
|
---|
580 |
|
---|
581 | var oldOffset = offset
|
---|
582 |
|
---|
583 | name.encode(a.name, buf, offset)
|
---|
584 | offset += name.encode.bytes
|
---|
585 |
|
---|
586 | buf.writeUInt16BE(types.toType(a.type), offset)
|
---|
587 |
|
---|
588 | var klass = a.class === undefined ? 1 : a.class
|
---|
589 | if (a.flush) klass |= FLUSH_MASK // the 1st bit of the class is the flush bit
|
---|
590 | buf.writeUInt16BE(klass, offset + 2)
|
---|
591 |
|
---|
592 | buf.writeUInt32BE(a.ttl || 0, offset + 4)
|
---|
593 |
|
---|
594 | var enc = renc(a.type)
|
---|
595 | enc.encode(a.data, buf, offset + 8)
|
---|
596 | offset += 8 + enc.encode.bytes
|
---|
597 |
|
---|
598 | answer.encode.bytes = offset - oldOffset
|
---|
599 | return buf
|
---|
600 | }
|
---|
601 |
|
---|
602 | answer.encode.bytes = 0
|
---|
603 |
|
---|
604 | answer.decode = function (buf, offset) {
|
---|
605 | if (!offset) offset = 0
|
---|
606 |
|
---|
607 | var a = {}
|
---|
608 | var oldOffset = offset
|
---|
609 |
|
---|
610 | a.name = name.decode(buf, offset)
|
---|
611 | offset += name.decode.bytes
|
---|
612 | a.type = types.toString(buf.readUInt16BE(offset))
|
---|
613 | a.class = buf.readUInt16BE(offset + 2)
|
---|
614 | a.ttl = buf.readUInt32BE(offset + 4)
|
---|
615 |
|
---|
616 | a.flush = !!(a.class & FLUSH_MASK)
|
---|
617 | if (a.flush) a.class &= NOT_FLUSH_MASK
|
---|
618 |
|
---|
619 | var enc = renc(a.type)
|
---|
620 | a.data = enc.decode(buf, offset + 8)
|
---|
621 | offset += 8 + enc.decode.bytes
|
---|
622 |
|
---|
623 | answer.decode.bytes = offset - oldOffset
|
---|
624 | return a
|
---|
625 | }
|
---|
626 |
|
---|
627 | answer.decode.bytes = 0
|
---|
628 |
|
---|
629 | answer.encodingLength = function (a) {
|
---|
630 | return name.encodingLength(a.name) + 8 + renc(a.type).encodingLength(a.data)
|
---|
631 | }
|
---|
632 |
|
---|
633 | var question = exports.question = {}
|
---|
634 |
|
---|
635 | question.encode = function (q, buf, offset) {
|
---|
636 | if (!buf) buf = Buffer.alloc(question.encodingLength(q))
|
---|
637 | if (!offset) offset = 0
|
---|
638 |
|
---|
639 | var oldOffset = offset
|
---|
640 |
|
---|
641 | name.encode(q.name, buf, offset)
|
---|
642 | offset += name.encode.bytes
|
---|
643 |
|
---|
644 | buf.writeUInt16BE(types.toType(q.type), offset)
|
---|
645 | offset += 2
|
---|
646 |
|
---|
647 | buf.writeUInt16BE(q.class === undefined ? 1 : q.class, offset)
|
---|
648 | offset += 2
|
---|
649 |
|
---|
650 | question.encode.bytes = offset - oldOffset
|
---|
651 | return q
|
---|
652 | }
|
---|
653 |
|
---|
654 | question.encode.bytes = 0
|
---|
655 |
|
---|
656 | question.decode = function (buf, offset) {
|
---|
657 | if (!offset) offset = 0
|
---|
658 |
|
---|
659 | var oldOffset = offset
|
---|
660 | var q = {}
|
---|
661 |
|
---|
662 | q.name = name.decode(buf, offset)
|
---|
663 | offset += name.decode.bytes
|
---|
664 |
|
---|
665 | q.type = types.toString(buf.readUInt16BE(offset))
|
---|
666 | offset += 2
|
---|
667 |
|
---|
668 | q.class = buf.readUInt16BE(offset)
|
---|
669 | offset += 2
|
---|
670 |
|
---|
671 | var qu = !!(q.class & QU_MASK)
|
---|
672 | if (qu) q.class &= NOT_QU_MASK
|
---|
673 |
|
---|
674 | question.decode.bytes = offset - oldOffset
|
---|
675 | return q
|
---|
676 | }
|
---|
677 |
|
---|
678 | question.decode.bytes = 0
|
---|
679 |
|
---|
680 | question.encodingLength = function (q) {
|
---|
681 | return name.encodingLength(q.name) + 4
|
---|
682 | }
|
---|
683 |
|
---|
684 | exports.AUTHORITATIVE_ANSWER = 1 << 10
|
---|
685 | exports.TRUNCATED_RESPONSE = 1 << 9
|
---|
686 | exports.RECURSION_DESIRED = 1 << 8
|
---|
687 | exports.RECURSION_AVAILABLE = 1 << 7
|
---|
688 | exports.AUTHENTIC_DATA = 1 << 5
|
---|
689 | exports.CHECKING_DISABLED = 1 << 4
|
---|
690 |
|
---|
691 | exports.encode = function (result, buf, offset) {
|
---|
692 | var allocing = !buf
|
---|
693 | if (allocing) buf = Buffer.alloc(exports.encodingLength(result))
|
---|
694 | if (!offset) offset = 0
|
---|
695 |
|
---|
696 | var oldOffset = offset
|
---|
697 |
|
---|
698 | if (!result.questions) result.questions = []
|
---|
699 | if (!result.answers) result.answers = []
|
---|
700 | if (!result.authorities) result.authorities = []
|
---|
701 | if (!result.additionals) result.additionals = []
|
---|
702 |
|
---|
703 | header.encode(result, buf, offset)
|
---|
704 | offset += header.encode.bytes
|
---|
705 |
|
---|
706 | offset = encodeList(result.questions, question, buf, offset)
|
---|
707 | offset = encodeList(result.answers, answer, buf, offset)
|
---|
708 | offset = encodeList(result.authorities, answer, buf, offset)
|
---|
709 | offset = encodeList(result.additionals, answer, buf, offset)
|
---|
710 |
|
---|
711 | exports.encode.bytes = offset - oldOffset
|
---|
712 |
|
---|
713 | // just a quick sanity check
|
---|
714 | if (allocing && exports.encode.bytes !== buf.length) {
|
---|
715 | return buf.slice(0, exports.encode.bytes)
|
---|
716 | }
|
---|
717 |
|
---|
718 | return buf
|
---|
719 | }
|
---|
720 |
|
---|
721 | exports.encode.bytes = 0
|
---|
722 |
|
---|
723 | exports.decode = function (buf, offset) {
|
---|
724 | if (!offset) offset = 0
|
---|
725 |
|
---|
726 | var oldOffset = offset
|
---|
727 | var result = header.decode(buf, offset)
|
---|
728 | offset += header.decode.bytes
|
---|
729 |
|
---|
730 | offset = decodeList(result.questions, question, buf, offset)
|
---|
731 | offset = decodeList(result.answers, answer, buf, offset)
|
---|
732 | offset = decodeList(result.authorities, answer, buf, offset)
|
---|
733 | offset = decodeList(result.additionals, answer, buf, offset)
|
---|
734 |
|
---|
735 | exports.decode.bytes = offset - oldOffset
|
---|
736 |
|
---|
737 | return result
|
---|
738 | }
|
---|
739 |
|
---|
740 | exports.decode.bytes = 0
|
---|
741 |
|
---|
742 | exports.encodingLength = function (result) {
|
---|
743 | return header.encodingLength(result) +
|
---|
744 | encodingLengthList(result.questions || [], question) +
|
---|
745 | encodingLengthList(result.answers || [], answer) +
|
---|
746 | encodingLengthList(result.authorities || [], answer) +
|
---|
747 | encodingLengthList(result.additionals || [], answer)
|
---|
748 | }
|
---|
749 |
|
---|
750 | function encodingLengthList (list, enc) {
|
---|
751 | var len = 0
|
---|
752 | for (var i = 0; i < list.length; i++) len += enc.encodingLength(list[i])
|
---|
753 | return len
|
---|
754 | }
|
---|
755 |
|
---|
756 | function encodeList (list, enc, buf, offset) {
|
---|
757 | for (var i = 0; i < list.length; i++) {
|
---|
758 | enc.encode(list[i], buf, offset)
|
---|
759 | offset += enc.encode.bytes
|
---|
760 | }
|
---|
761 | return offset
|
---|
762 | }
|
---|
763 |
|
---|
764 | function decodeList (list, enc, buf, offset) {
|
---|
765 | for (var i = 0; i < list.length; i++) {
|
---|
766 | list[i] = enc.decode(buf, offset)
|
---|
767 | offset += enc.decode.bytes
|
---|
768 | }
|
---|
769 | return offset
|
---|
770 | }
|
---|