source: frontend/node_modules/dns-packet/index.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 43.6 KB
Line 
1'use strict'
2
3const Buffer = require('buffer').Buffer
4const types = require('./types')
5const rcodes = require('./rcodes')
6const opcodes = require('./opcodes')
7const classes = require('./classes')
8const optioncodes = require('./optioncodes')
9const ip = require('@leichtgewicht/ip-codec')
10
11const QUERY_FLAG = 0
12const RESPONSE_FLAG = 1 << 15
13const FLUSH_MASK = 1 << 15
14const NOT_FLUSH_MASK = ~FLUSH_MASK
15const QU_MASK = 1 << 15
16const NOT_QU_MASK = ~QU_MASK
17
18const name = exports.name = {}
19
20name.encode = function (str, buf, offset, { mail = false } = {}) {
21 if (!buf) buf = Buffer.alloc(name.encodingLength(str))
22 if (!offset) offset = 0
23 const oldOffset = offset
24
25 // strip leading and trailing .
26 const n = str.replace(/^\.|\.$/gm, '')
27 if (n.length) {
28 let list = []
29 if (mail) {
30 let localPart = ''
31 n.split('.').forEach(label => {
32 if (label.endsWith('\\')) {
33 localPart += (localPart.length ? '.' : '') + label.slice(0, -1)
34 } else {
35 if (list.length === 0 && localPart.length) {
36 list.push(localPart + '.' + label)
37 } else {
38 list.push(label)
39 }
40 }
41 })
42 } else {
43 list = n.split('.')
44 }
45
46 for (let i = 0; i < list.length; i++) {
47 const len = buf.write(list[i], offset + 1)
48 buf[offset] = len
49 offset += len + 1
50 }
51 }
52
53 buf[offset++] = 0
54
55 name.encode.bytes = offset - oldOffset
56 return buf
57}
58
59name.encode.bytes = 0
60
61name.decode = function (buf, offset, { mail = false } = {}) {
62 if (!offset) offset = 0
63
64 const list = []
65 let oldOffset = offset
66 let totalLength = 0
67 let consumedBytes = 0
68 let jumped = false
69
70 while (true) {
71 if (offset >= buf.length) {
72 throw new Error('Cannot decode name (buffer overflow)')
73 }
74 const len = buf[offset++]
75 consumedBytes += jumped ? 0 : 1
76
77 if (len === 0) {
78 break
79 } else if ((len & 0xc0) === 0) {
80 if (offset + len > buf.length) {
81 throw new Error('Cannot decode name (buffer overflow)')
82 }
83 totalLength += len + 1
84 if (totalLength > 254) {
85 throw new Error('Cannot decode name (name too long)')
86 }
87 let label = buf.toString('utf-8', offset, offset + len)
88 if (mail) {
89 label = label.replace(/\./g, '\\.')
90 }
91 list.push(label)
92 offset += len
93 consumedBytes += jumped ? 0 : len
94 } else if ((len & 0xc0) === 0xc0) {
95 if (offset + 1 > buf.length) {
96 throw new Error('Cannot decode name (buffer overflow)')
97 }
98 const jumpOffset = buf.readUInt16BE(offset - 1) - 0xc000
99 if (jumpOffset >= oldOffset) {
100 // Allow only pointers to prior data. RFC 1035, section 4.1.4 states:
101 // "[...] an entire domain name or a list of labels at the end of a domain name
102 // is replaced with a pointer to a prior occurance (sic) of the same name."
103 throw new Error('Cannot decode name (bad pointer)')
104 }
105 offset = jumpOffset
106 oldOffset = jumpOffset
107 consumedBytes += jumped ? 0 : 1
108 jumped = true
109 } else {
110 throw new Error('Cannot decode name (bad label)')
111 }
112 }
113
114 name.decode.bytes = consumedBytes
115 return list.length === 0 ? '.' : list.join('.')
116}
117
118name.decode.bytes = 0
119
120name.encodingLength = function (n) {
121 if (n === '.' || n === '..') return 1
122 return Buffer.byteLength(n.replace(/^\.|\.$/gm, '')) + 2
123}
124
125const string = {}
126
127string.encode = function (s, buf, offset) {
128 if (!buf) buf = Buffer.alloc(string.encodingLength(s))
129 if (!offset) offset = 0
130
131 const len = buf.write(s, offset + 1)
132 buf[offset] = len
133 string.encode.bytes = len + 1
134 return buf
135}
136
137string.encode.bytes = 0
138
139string.decode = function (buf, offset) {
140 if (!offset) offset = 0
141
142 const len = buf[offset]
143 const s = buf.toString('utf-8', offset + 1, offset + 1 + len)
144 string.decode.bytes = len + 1
145 return s
146}
147
148string.decode.bytes = 0
149
150string.encodingLength = function (s) {
151 return Buffer.byteLength(s) + 1
152}
153
154const header = {}
155
156header.encode = function (h, buf, offset) {
157 if (!buf) buf = header.encodingLength(h)
158 if (!offset) offset = 0
159
160 const flags = (h.flags || 0) & 32767
161 const type = h.type === 'response' ? RESPONSE_FLAG : QUERY_FLAG
162
163 buf.writeUInt16BE(h.id || 0, offset)
164 buf.writeUInt16BE(flags | type, offset + 2)
165 buf.writeUInt16BE(h.questions.length, offset + 4)
166 buf.writeUInt16BE(h.answers.length, offset + 6)
167 buf.writeUInt16BE(h.authorities.length, offset + 8)
168 buf.writeUInt16BE(h.additionals.length, offset + 10)
169
170 return buf
171}
172
173header.encode.bytes = 12
174
175header.decode = function (buf, offset) {
176 if (!offset) offset = 0
177 if (buf.length < 12) throw new Error('Header must be 12 bytes')
178 const flags = buf.readUInt16BE(offset + 2)
179
180 return {
181 id: buf.readUInt16BE(offset),
182 type: flags & RESPONSE_FLAG ? 'response' : 'query',
183 flags: flags & 32767,
184 flag_qr: ((flags >> 15) & 0x1) === 1,
185 opcode: opcodes.toString((flags >> 11) & 0xf),
186 flag_aa: ((flags >> 10) & 0x1) === 1,
187 flag_tc: ((flags >> 9) & 0x1) === 1,
188 flag_rd: ((flags >> 8) & 0x1) === 1,
189 flag_ra: ((flags >> 7) & 0x1) === 1,
190 flag_z: ((flags >> 6) & 0x1) === 1,
191 flag_ad: ((flags >> 5) & 0x1) === 1,
192 flag_cd: ((flags >> 4) & 0x1) === 1,
193 rcode: rcodes.toString(flags & 0xf),
194 questions: new Array(buf.readUInt16BE(offset + 4)),
195 answers: new Array(buf.readUInt16BE(offset + 6)),
196 authorities: new Array(buf.readUInt16BE(offset + 8)),
197 additionals: new Array(buf.readUInt16BE(offset + 10))
198 }
199}
200
201header.decode.bytes = 12
202
203header.encodingLength = function () {
204 return 12
205}
206
207const runknown = exports.unknown = {}
208
209runknown.encode = function (data, buf, offset) {
210 if (!buf) buf = Buffer.alloc(runknown.encodingLength(data))
211 if (!offset) offset = 0
212
213 buf.writeUInt16BE(data.length, offset)
214 data.copy(buf, offset + 2)
215
216 runknown.encode.bytes = data.length + 2
217 return buf
218}
219
220runknown.encode.bytes = 0
221
222runknown.decode = function (buf, offset) {
223 if (!offset) offset = 0
224
225 const len = buf.readUInt16BE(offset)
226 const data = buf.slice(offset + 2, offset + 2 + len)
227 runknown.decode.bytes = len + 2
228 return data
229}
230
231runknown.decode.bytes = 0
232
233runknown.encodingLength = function (data) {
234 return data.length + 2
235}
236
237const rns = exports.ns = {}
238
239rns.encode = function (data, buf, offset) {
240 if (!buf) buf = Buffer.alloc(rns.encodingLength(data))
241 if (!offset) offset = 0
242
243 name.encode(data, buf, offset + 2)
244 buf.writeUInt16BE(name.encode.bytes, offset)
245 rns.encode.bytes = name.encode.bytes + 2
246 return buf
247}
248
249rns.encode.bytes = 0
250
251rns.decode = function (buf, offset) {
252 if (!offset) offset = 0
253
254 const len = buf.readUInt16BE(offset)
255 const dd = name.decode(buf, offset + 2)
256
257 rns.decode.bytes = len + 2
258 return dd
259}
260
261rns.decode.bytes = 0
262
263rns.encodingLength = function (data) {
264 return name.encodingLength(data) + 2
265}
266
267const rsoa = exports.soa = {}
268
269rsoa.encode = function (data, buf, offset) {
270 if (!buf) buf = Buffer.alloc(rsoa.encodingLength(data))
271 if (!offset) offset = 0
272
273 const oldOffset = offset
274 offset += 2
275 name.encode(data.mname, buf, offset)
276 offset += name.encode.bytes
277 name.encode(data.rname, buf, offset, { mail: true })
278 offset += name.encode.bytes
279 buf.writeUInt32BE(data.serial || 0, offset)
280 offset += 4
281 buf.writeUInt32BE(data.refresh || 0, offset)
282 offset += 4
283 buf.writeUInt32BE(data.retry || 0, offset)
284 offset += 4
285 buf.writeUInt32BE(data.expire || 0, offset)
286 offset += 4
287 buf.writeUInt32BE(data.minimum || 0, offset)
288 offset += 4
289
290 buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
291 rsoa.encode.bytes = offset - oldOffset
292 return buf
293}
294
295rsoa.encode.bytes = 0
296
297rsoa.decode = function (buf, offset) {
298 if (!offset) offset = 0
299
300 const oldOffset = offset
301
302 const data = {}
303 offset += 2
304 data.mname = name.decode(buf, offset)
305 offset += name.decode.bytes
306 data.rname = name.decode(buf, offset, { mail: true })
307 offset += name.decode.bytes
308 data.serial = buf.readUInt32BE(offset)
309 offset += 4
310 data.refresh = buf.readUInt32BE(offset)
311 offset += 4
312 data.retry = buf.readUInt32BE(offset)
313 offset += 4
314 data.expire = buf.readUInt32BE(offset)
315 offset += 4
316 data.minimum = buf.readUInt32BE(offset)
317 offset += 4
318
319 rsoa.decode.bytes = offset - oldOffset
320 return data
321}
322
323rsoa.decode.bytes = 0
324
325rsoa.encodingLength = function (data) {
326 return 22 + name.encodingLength(data.mname) + name.encodingLength(data.rname)
327}
328
329const rtxt = exports.txt = {}
330
331rtxt.encode = function (data, buf, offset) {
332 if (!Array.isArray(data)) data = [data]
333 for (let i = 0; i < data.length; i++) {
334 if (typeof data[i] === 'string') {
335 data[i] = Buffer.from(data[i])
336 }
337 if (!Buffer.isBuffer(data[i])) {
338 throw new Error('Must be a Buffer')
339 }
340 }
341
342 if (!buf) buf = Buffer.alloc(rtxt.encodingLength(data))
343 if (!offset) offset = 0
344
345 const oldOffset = offset
346 offset += 2
347
348 data.forEach(function (d) {
349 buf[offset++] = d.length
350 d.copy(buf, offset, 0, d.length)
351 offset += d.length
352 })
353
354 buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
355 rtxt.encode.bytes = offset - oldOffset
356 return buf
357}
358
359rtxt.encode.bytes = 0
360
361rtxt.decode = function (buf, offset) {
362 if (!offset) offset = 0
363 const oldOffset = offset
364 let remaining = buf.readUInt16BE(offset)
365 offset += 2
366
367 let data = []
368 while (remaining > 0) {
369 const len = buf[offset++]
370 --remaining
371 if (remaining < len) {
372 throw new Error('Buffer overflow')
373 }
374 data.push(buf.slice(offset, offset + len))
375 offset += len
376 remaining -= len
377 }
378
379 rtxt.decode.bytes = offset - oldOffset
380 return data
381}
382
383rtxt.decode.bytes = 0
384
385rtxt.encodingLength = function (data) {
386 if (!Array.isArray(data)) data = [data]
387 let length = 2
388 data.forEach(function (buf) {
389 if (typeof buf === 'string') {
390 length += Buffer.byteLength(buf) + 1
391 } else {
392 length += buf.length + 1
393 }
394 })
395 return length
396}
397
398const rnull = exports.null = {}
399
400rnull.encode = function (data, buf, offset) {
401 if (!buf) buf = Buffer.alloc(rnull.encodingLength(data))
402 if (!offset) offset = 0
403
404 if (typeof data === 'string') data = Buffer.from(data)
405 if (!data) data = Buffer.alloc(0)
406
407 const oldOffset = offset
408 offset += 2
409
410 const len = data.length
411 data.copy(buf, offset, 0, len)
412 offset += len
413
414 buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
415 rnull.encode.bytes = offset - oldOffset
416 return buf
417}
418
419rnull.encode.bytes = 0
420
421rnull.decode = function (buf, offset) {
422 if (!offset) offset = 0
423 const oldOffset = offset
424 const len = buf.readUInt16BE(offset)
425
426 offset += 2
427
428 const data = buf.slice(offset, offset + len)
429 offset += len
430
431 rnull.decode.bytes = offset - oldOffset
432 return data
433}
434
435rnull.decode.bytes = 0
436
437rnull.encodingLength = function (data) {
438 if (!data) return 2
439 return (Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data)) + 2
440}
441
442const rhinfo = exports.hinfo = {}
443
444rhinfo.encode = function (data, buf, offset) {
445 if (!buf) buf = Buffer.alloc(rhinfo.encodingLength(data))
446 if (!offset) offset = 0
447
448 const oldOffset = offset
449 offset += 2
450 string.encode(data.cpu, buf, offset)
451 offset += string.encode.bytes
452 string.encode(data.os, buf, offset)
453 offset += string.encode.bytes
454 buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
455 rhinfo.encode.bytes = offset - oldOffset
456 return buf
457}
458
459rhinfo.encode.bytes = 0
460
461rhinfo.decode = function (buf, offset) {
462 if (!offset) offset = 0
463
464 const oldOffset = offset
465
466 const data = {}
467 offset += 2
468 data.cpu = string.decode(buf, offset)
469 offset += string.decode.bytes
470 data.os = string.decode(buf, offset)
471 offset += string.decode.bytes
472 rhinfo.decode.bytes = offset - oldOffset
473 return data
474}
475
476rhinfo.decode.bytes = 0
477
478rhinfo.encodingLength = function (data) {
479 return string.encodingLength(data.cpu) + string.encodingLength(data.os) + 2
480}
481
482const rptr = exports.ptr = {}
483const rcname = exports.cname = rptr
484const rdname = exports.dname = rptr
485
486rptr.encode = function (data, buf, offset) {
487 if (!buf) buf = Buffer.alloc(rptr.encodingLength(data))
488 if (!offset) offset = 0
489
490 name.encode(data, buf, offset + 2)
491 buf.writeUInt16BE(name.encode.bytes, offset)
492 rptr.encode.bytes = name.encode.bytes + 2
493 return buf
494}
495
496rptr.encode.bytes = 0
497
498rptr.decode = function (buf, offset) {
499 if (!offset) offset = 0
500
501 const data = name.decode(buf, offset + 2)
502 rptr.decode.bytes = name.decode.bytes + 2
503 return data
504}
505
506rptr.decode.bytes = 0
507
508rptr.encodingLength = function (data) {
509 return name.encodingLength(data) + 2
510}
511
512const rsrv = exports.srv = {}
513
514rsrv.encode = function (data, buf, offset) {
515 if (!buf) buf = Buffer.alloc(rsrv.encodingLength(data))
516 if (!offset) offset = 0
517
518 buf.writeUInt16BE(data.priority || 0, offset + 2)
519 buf.writeUInt16BE(data.weight || 0, offset + 4)
520 buf.writeUInt16BE(data.port || 0, offset + 6)
521 name.encode(data.target, buf, offset + 8)
522
523 const len = name.encode.bytes + 6
524 buf.writeUInt16BE(len, offset)
525
526 rsrv.encode.bytes = len + 2
527 return buf
528}
529
530rsrv.encode.bytes = 0
531
532rsrv.decode = function (buf, offset) {
533 if (!offset) offset = 0
534
535 const len = buf.readUInt16BE(offset)
536
537 const data = {}
538 data.priority = buf.readUInt16BE(offset + 2)
539 data.weight = buf.readUInt16BE(offset + 4)
540 data.port = buf.readUInt16BE(offset + 6)
541 data.target = name.decode(buf, offset + 8)
542
543 rsrv.decode.bytes = len + 2
544 return data
545}
546
547rsrv.decode.bytes = 0
548
549rsrv.encodingLength = function (data) {
550 return 8 + name.encodingLength(data.target)
551}
552
553const rcaa = exports.caa = {}
554
555rcaa.ISSUER_CRITICAL = 1 << 7
556
557rcaa.encode = function (data, buf, offset) {
558 const len = rcaa.encodingLength(data)
559
560 if (!buf) buf = Buffer.alloc(rcaa.encodingLength(data))
561 if (!offset) offset = 0
562
563 if (data.issuerCritical) {
564 data.flags = rcaa.ISSUER_CRITICAL
565 }
566
567 buf.writeUInt16BE(len - 2, offset)
568 offset += 2
569 buf.writeUInt8(data.flags || 0, offset)
570 offset += 1
571 string.encode(data.tag, buf, offset)
572 offset += string.encode.bytes
573 buf.write(data.value, offset)
574 offset += Buffer.byteLength(data.value)
575
576 rcaa.encode.bytes = len
577 return buf
578}
579
580rcaa.encode.bytes = 0
581
582rcaa.decode = function (buf, offset) {
583 if (!offset) offset = 0
584
585 const len = buf.readUInt16BE(offset)
586 offset += 2
587
588 const oldOffset = offset
589 const data = {}
590 data.flags = buf.readUInt8(offset)
591 offset += 1
592 data.tag = string.decode(buf, offset)
593 offset += string.decode.bytes
594 data.value = buf.toString('utf-8', offset, oldOffset + len)
595
596 data.issuerCritical = !!(data.flags & rcaa.ISSUER_CRITICAL)
597
598 rcaa.decode.bytes = len + 2
599
600 return data
601}
602
603rcaa.decode.bytes = 0
604
605rcaa.encodingLength = function (data) {
606 return string.encodingLength(data.tag) + string.encodingLength(data.value) + 2
607}
608
609const rmx = exports.mx = {}
610
611rmx.encode = function (data, buf, offset) {
612 if (!buf) buf = Buffer.alloc(rmx.encodingLength(data))
613 if (!offset) offset = 0
614
615 const oldOffset = offset
616 offset += 2
617 buf.writeUInt16BE(data.preference || 0, offset)
618 offset += 2
619 name.encode(data.exchange, buf, offset)
620 offset += name.encode.bytes
621
622 buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
623 rmx.encode.bytes = offset - oldOffset
624 return buf
625}
626
627rmx.encode.bytes = 0
628
629rmx.decode = function (buf, offset) {
630 if (!offset) offset = 0
631
632 const oldOffset = offset
633
634 const data = {}
635 offset += 2
636 data.preference = buf.readUInt16BE(offset)
637 offset += 2
638 data.exchange = name.decode(buf, offset)
639 offset += name.decode.bytes
640
641 rmx.decode.bytes = offset - oldOffset
642 return data
643}
644
645rmx.encodingLength = function (data) {
646 return 4 + name.encodingLength(data.exchange)
647}
648
649const ra = exports.a = {}
650
651ra.encode = function (host, buf, offset) {
652 if (!buf) buf = Buffer.alloc(ra.encodingLength(host))
653 if (!offset) offset = 0
654
655 buf.writeUInt16BE(4, offset)
656 offset += 2
657 ip.v4.encode(host, buf, offset)
658 ra.encode.bytes = 6
659 return buf
660}
661
662ra.encode.bytes = 0
663
664ra.decode = function (buf, offset) {
665 if (!offset) offset = 0
666
667 offset += 2
668 const host = ip.v4.decode(buf, offset)
669 ra.decode.bytes = 6
670 return host
671}
672
673ra.decode.bytes = 0
674
675ra.encodingLength = function () {
676 return 6
677}
678
679const raaaa = exports.aaaa = {}
680
681raaaa.encode = function (host, buf, offset) {
682 if (!buf) buf = Buffer.alloc(raaaa.encodingLength(host))
683 if (!offset) offset = 0
684
685 buf.writeUInt16BE(16, offset)
686 offset += 2
687 ip.v6.encode(host, buf, offset)
688 raaaa.encode.bytes = 18
689 return buf
690}
691
692raaaa.encode.bytes = 0
693
694raaaa.decode = function (buf, offset) {
695 if (!offset) offset = 0
696
697 offset += 2
698 const host = ip.v6.decode(buf, offset)
699 raaaa.decode.bytes = 18
700 return host
701}
702
703raaaa.decode.bytes = 0
704
705raaaa.encodingLength = function () {
706 return 18
707}
708
709const roption = exports.option = {}
710
711roption.encode = function (option, buf, offset) {
712 if (!buf) buf = Buffer.alloc(roption.encodingLength(option))
713 if (!offset) offset = 0
714 const oldOffset = offset
715
716 const code = optioncodes.toCode(option.code)
717 buf.writeUInt16BE(code, offset)
718 offset += 2
719 if (option.data) {
720 buf.writeUInt16BE(option.data.length, offset)
721 offset += 2
722 option.data.copy(buf, offset)
723 offset += option.data.length
724 } else {
725 switch (code) {
726 // case 3: NSID. No encode makes sense.
727 // case 5,6,7: Not implementable
728 case 8: // ECS
729 // note: do IP math before calling
730 const spl = option.sourcePrefixLength || 0
731 const fam = option.family || ip.familyOf(option.ip)
732 const ipBuf = ip.encode(option.ip, Buffer.alloc)
733 const ipLen = Math.ceil(spl / 8)
734 buf.writeUInt16BE(ipLen + 4, offset)
735 offset += 2
736 buf.writeUInt16BE(fam, offset)
737 offset += 2
738 buf.writeUInt8(spl, offset++)
739 buf.writeUInt8(option.scopePrefixLength || 0, offset++)
740
741 ipBuf.copy(buf, offset, 0, ipLen)
742 offset += ipLen
743 break
744 // case 9: EXPIRE (experimental)
745 // case 10: COOKIE. No encode makes sense.
746 case 11: // KEEP-ALIVE
747 if (option.timeout) {
748 buf.writeUInt16BE(2, offset)
749 offset += 2
750 buf.writeUInt16BE(option.timeout, offset)
751 offset += 2
752 } else {
753 buf.writeUInt16BE(0, offset)
754 offset += 2
755 }
756 break
757 case 12: // PADDING
758 const len = option.length || 0
759 buf.writeUInt16BE(len, offset)
760 offset += 2
761 buf.fill(0, offset, offset + len)
762 offset += len
763 break
764 // case 13: CHAIN. Experimental.
765 case 14: // KEY-TAG
766 const tagsLen = option.tags.length * 2
767 buf.writeUInt16BE(tagsLen, offset)
768 offset += 2
769 for (const tag of option.tags) {
770 buf.writeUInt16BE(tag, offset)
771 offset += 2
772 }
773 break
774 default:
775 throw new Error(`Unknown roption code: ${option.code}`)
776 }
777 }
778
779 roption.encode.bytes = offset - oldOffset
780 return buf
781}
782
783roption.encode.bytes = 0
784
785roption.decode = function (buf, offset) {
786 if (!offset) offset = 0
787 const option = {}
788 option.code = buf.readUInt16BE(offset)
789 option.type = optioncodes.toString(option.code)
790 offset += 2
791 const len = buf.readUInt16BE(offset)
792 offset += 2
793 option.data = buf.slice(offset, offset + len)
794 switch (option.code) {
795 // case 3: NSID. No decode makes sense.
796 case 8: // ECS
797 option.family = buf.readUInt16BE(offset)
798 offset += 2
799 option.sourcePrefixLength = buf.readUInt8(offset++)
800 option.scopePrefixLength = buf.readUInt8(offset++)
801 const padded = Buffer.alloc((option.family === 1) ? 4 : 16)
802 buf.copy(padded, 0, offset, offset + len - 4)
803 option.ip = ip.decode(padded)
804 break
805 // case 12: Padding. No decode makes sense.
806 case 11: // KEEP-ALIVE
807 if (len > 0) {
808 option.timeout = buf.readUInt16BE(offset)
809 offset += 2
810 }
811 break
812 case 14:
813 option.tags = []
814 for (let i = 0; i < len; i += 2) {
815 option.tags.push(buf.readUInt16BE(offset))
816 offset += 2
817 }
818 // don't worry about default. caller will use data if desired
819 }
820
821 roption.decode.bytes = len + 4
822 return option
823}
824
825roption.decode.bytes = 0
826
827roption.encodingLength = function (option) {
828 if (option.data) {
829 return option.data.length + 4
830 }
831 const code = optioncodes.toCode(option.code)
832 switch (code) {
833 case 8: // ECS
834 const spl = option.sourcePrefixLength || 0
835 return Math.ceil(spl / 8) + 8
836 case 11: // KEEP-ALIVE
837 return (typeof option.timeout === 'number') ? 6 : 4
838 case 12: // PADDING
839 return option.length + 4
840 case 14: // KEY-TAG
841 return 4 + (option.tags.length * 2)
842 }
843 throw new Error(`Unknown roption code: ${option.code}`)
844}
845
846const ropt = exports.opt = {}
847
848ropt.encode = function (options, buf, offset) {
849 if (!buf) buf = Buffer.alloc(ropt.encodingLength(options))
850 if (!offset) offset = 0
851 const oldOffset = offset
852
853 const rdlen = encodingLengthList(options, roption)
854 buf.writeUInt16BE(rdlen, offset)
855 offset = encodeList(options, roption, buf, offset + 2)
856
857 ropt.encode.bytes = offset - oldOffset
858 return buf
859}
860
861ropt.encode.bytes = 0
862
863ropt.decode = function (buf, offset) {
864 if (!offset) offset = 0
865 const oldOffset = offset
866
867 const options = []
868 let rdlen = buf.readUInt16BE(offset)
869 offset += 2
870 let o = 0
871 while (rdlen > 0) {
872 options[o++] = roption.decode(buf, offset)
873 offset += roption.decode.bytes
874 rdlen -= roption.decode.bytes
875 }
876 ropt.decode.bytes = offset - oldOffset
877 return options
878}
879
880ropt.decode.bytes = 0
881
882ropt.encodingLength = function (options) {
883 return 2 + encodingLengthList(options || [], roption)
884}
885
886const rdnskey = exports.dnskey = {}
887
888rdnskey.PROTOCOL_DNSSEC = 3
889rdnskey.ZONE_KEY = 0x80
890rdnskey.SECURE_ENTRYPOINT = 0x8000
891
892rdnskey.encode = function (key, buf, offset) {
893 if (!buf) buf = Buffer.alloc(rdnskey.encodingLength(key))
894 if (!offset) offset = 0
895 const oldOffset = offset
896
897 const keydata = key.key
898 if (!Buffer.isBuffer(keydata)) {
899 throw new Error('Key must be a Buffer')
900 }
901
902 offset += 2 // Leave space for length
903 buf.writeUInt16BE(key.flags, offset)
904 offset += 2
905 buf.writeUInt8(rdnskey.PROTOCOL_DNSSEC, offset)
906 offset += 1
907 buf.writeUInt8(key.algorithm, offset)
908 offset += 1
909 keydata.copy(buf, offset, 0, keydata.length)
910 offset += keydata.length
911
912 rdnskey.encode.bytes = offset - oldOffset
913 buf.writeUInt16BE(rdnskey.encode.bytes - 2, oldOffset)
914 return buf
915}
916
917rdnskey.encode.bytes = 0
918
919rdnskey.decode = function (buf, offset) {
920 if (!offset) offset = 0
921 const oldOffset = offset
922
923 var key = {}
924 var length = buf.readUInt16BE(offset)
925 offset += 2
926 key.flags = buf.readUInt16BE(offset)
927 offset += 2
928 if (buf.readUInt8(offset) !== rdnskey.PROTOCOL_DNSSEC) {
929 throw new Error('Protocol must be 3')
930 }
931 offset += 1
932 key.algorithm = buf.readUInt8(offset)
933 offset += 1
934 key.key = buf.slice(offset, oldOffset + length + 2)
935 offset += key.key.length
936 rdnskey.decode.bytes = offset - oldOffset
937 return key
938}
939
940rdnskey.decode.bytes = 0
941
942rdnskey.encodingLength = function (key) {
943 return 6 + Buffer.byteLength(key.key)
944}
945
946const rrrsig = exports.rrsig = {}
947
948rrrsig.encode = function (sig, buf, offset) {
949 if (!buf) buf = Buffer.alloc(rrrsig.encodingLength(sig))
950 if (!offset) offset = 0
951 const oldOffset = offset
952
953 const signature = sig.signature
954 if (!Buffer.isBuffer(signature)) {
955 throw new Error('Signature must be a Buffer')
956 }
957
958 offset += 2 // Leave space for length
959 buf.writeUInt16BE(types.toType(sig.typeCovered), offset)
960 offset += 2
961 buf.writeUInt8(sig.algorithm, offset)
962 offset += 1
963 buf.writeUInt8(sig.labels, offset)
964 offset += 1
965 buf.writeUInt32BE(sig.originalTTL, offset)
966 offset += 4
967 buf.writeUInt32BE(sig.expiration, offset)
968 offset += 4
969 buf.writeUInt32BE(sig.inception, offset)
970 offset += 4
971 buf.writeUInt16BE(sig.keyTag, offset)
972 offset += 2
973 name.encode(sig.signersName, buf, offset)
974 offset += name.encode.bytes
975 signature.copy(buf, offset, 0, signature.length)
976 offset += signature.length
977
978 rrrsig.encode.bytes = offset - oldOffset
979 buf.writeUInt16BE(rrrsig.encode.bytes - 2, oldOffset)
980 return buf
981}
982
983rrrsig.encode.bytes = 0
984
985rrrsig.decode = function (buf, offset) {
986 if (!offset) offset = 0
987 const oldOffset = offset
988
989 var sig = {}
990 var length = buf.readUInt16BE(offset)
991 offset += 2
992 sig.typeCovered = types.toString(buf.readUInt16BE(offset))
993 offset += 2
994 sig.algorithm = buf.readUInt8(offset)
995 offset += 1
996 sig.labels = buf.readUInt8(offset)
997 offset += 1
998 sig.originalTTL = buf.readUInt32BE(offset)
999 offset += 4
1000 sig.expiration = buf.readUInt32BE(offset)
1001 offset += 4
1002 sig.inception = buf.readUInt32BE(offset)
1003 offset += 4
1004 sig.keyTag = buf.readUInt16BE(offset)
1005 offset += 2
1006 sig.signersName = name.decode(buf, offset)
1007 offset += name.decode.bytes
1008 sig.signature = buf.slice(offset, oldOffset + length + 2)
1009 offset += sig.signature.length
1010 rrrsig.decode.bytes = offset - oldOffset
1011 return sig
1012}
1013
1014rrrsig.decode.bytes = 0
1015
1016rrrsig.encodingLength = function (sig) {
1017 return 20 +
1018 name.encodingLength(sig.signersName) +
1019 Buffer.byteLength(sig.signature)
1020}
1021
1022const rrp = exports.rp = {}
1023
1024rrp.encode = function (data, buf, offset) {
1025 if (!buf) buf = Buffer.alloc(rrp.encodingLength(data))
1026 if (!offset) offset = 0
1027 const oldOffset = offset
1028
1029 offset += 2 // Leave space for length
1030 name.encode(data.mbox || '.', buf, offset, { mail: true })
1031 offset += name.encode.bytes
1032 name.encode(data.txt || '.', buf, offset)
1033 offset += name.encode.bytes
1034 rrp.encode.bytes = offset - oldOffset
1035 buf.writeUInt16BE(rrp.encode.bytes - 2, oldOffset)
1036 return buf
1037}
1038
1039rrp.encode.bytes = 0
1040
1041rrp.decode = function (buf, offset) {
1042 if (!offset) offset = 0
1043 const oldOffset = offset
1044
1045 const data = {}
1046 offset += 2
1047 data.mbox = name.decode(buf, offset, { mail: true }) || '.'
1048 offset += name.decode.bytes
1049 data.txt = name.decode(buf, offset) || '.'
1050 offset += name.decode.bytes
1051 rrp.decode.bytes = offset - oldOffset
1052 return data
1053}
1054
1055rrp.decode.bytes = 0
1056
1057rrp.encodingLength = function (data) {
1058 return 2 + name.encodingLength(data.mbox || '.') + name.encodingLength(data.txt || '.')
1059}
1060
1061const typebitmap = {}
1062
1063typebitmap.encode = function (typelist, buf, offset) {
1064 if (!buf) buf = Buffer.alloc(typebitmap.encodingLength(typelist))
1065 if (!offset) offset = 0
1066 const oldOffset = offset
1067
1068 var typesByWindow = []
1069 for (var i = 0; i < typelist.length; i++) {
1070 var typeid = types.toType(typelist[i])
1071 if (typesByWindow[typeid >> 8] === undefined) {
1072 typesByWindow[typeid >> 8] = []
1073 }
1074 typesByWindow[typeid >> 8][(typeid >> 3) & 0x1F] |= 1 << (7 - (typeid & 0x7))
1075 }
1076
1077 for (i = 0; i < typesByWindow.length; i++) {
1078 if (typesByWindow[i] !== undefined) {
1079 var windowBuf = Buffer.from(typesByWindow[i])
1080 buf.writeUInt8(i, offset)
1081 offset += 1
1082 buf.writeUInt8(windowBuf.length, offset)
1083 offset += 1
1084 windowBuf.copy(buf, offset)
1085 offset += windowBuf.length
1086 }
1087 }
1088
1089 typebitmap.encode.bytes = offset - oldOffset
1090 return buf
1091}
1092
1093typebitmap.encode.bytes = 0
1094
1095typebitmap.decode = function (buf, offset, length) {
1096 if (!offset) offset = 0
1097 const oldOffset = offset
1098
1099 var typelist = []
1100 while (offset - oldOffset < length) {
1101 var window = buf.readUInt8(offset)
1102 offset += 1
1103 var windowLength = buf.readUInt8(offset)
1104 offset += 1
1105 for (var i = 0; i < windowLength; i++) {
1106 var b = buf.readUInt8(offset + i)
1107 for (var j = 0; j < 8; j++) {
1108 if (b & (1 << (7 - j))) {
1109 var typeid = types.toString((window << 8) | (i << 3) | j)
1110 typelist.push(typeid)
1111 }
1112 }
1113 }
1114 offset += windowLength
1115 }
1116
1117 typebitmap.decode.bytes = offset - oldOffset
1118 return typelist
1119}
1120
1121typebitmap.decode.bytes = 0
1122
1123typebitmap.encodingLength = function (typelist) {
1124 var extents = []
1125 for (var i = 0; i < typelist.length; i++) {
1126 var typeid = types.toType(typelist[i])
1127 extents[typeid >> 8] = Math.max(extents[typeid >> 8] || 0, typeid & 0xFF)
1128 }
1129
1130 var len = 0
1131 for (i = 0; i < extents.length; i++) {
1132 if (extents[i] !== undefined) {
1133 len += 2 + Math.ceil((extents[i] + 1) / 8)
1134 }
1135 }
1136
1137 return len
1138}
1139
1140const rnsec = exports.nsec = {}
1141
1142rnsec.encode = function (record, buf, offset) {
1143 if (!buf) buf = Buffer.alloc(rnsec.encodingLength(record))
1144 if (!offset) offset = 0
1145 const oldOffset = offset
1146
1147 offset += 2 // Leave space for length
1148 name.encode(record.nextDomain, buf, offset)
1149 offset += name.encode.bytes
1150 typebitmap.encode(record.rrtypes, buf, offset)
1151 offset += typebitmap.encode.bytes
1152
1153 rnsec.encode.bytes = offset - oldOffset
1154 buf.writeUInt16BE(rnsec.encode.bytes - 2, oldOffset)
1155 return buf
1156}
1157
1158rnsec.encode.bytes = 0
1159
1160rnsec.decode = function (buf, offset) {
1161 if (!offset) offset = 0
1162 const oldOffset = offset
1163
1164 var record = {}
1165 var length = buf.readUInt16BE(offset)
1166 offset += 2
1167 record.nextDomain = name.decode(buf, offset)
1168 offset += name.decode.bytes
1169 record.rrtypes = typebitmap.decode(buf, offset, length - (offset - oldOffset))
1170 offset += typebitmap.decode.bytes
1171
1172 rnsec.decode.bytes = offset - oldOffset
1173 return record
1174}
1175
1176rnsec.decode.bytes = 0
1177
1178rnsec.encodingLength = function (record) {
1179 return 2 +
1180 name.encodingLength(record.nextDomain) +
1181 typebitmap.encodingLength(record.rrtypes)
1182}
1183
1184const rnsec3 = exports.nsec3 = {}
1185
1186rnsec3.encode = function (record, buf, offset) {
1187 if (!buf) buf = Buffer.alloc(rnsec3.encodingLength(record))
1188 if (!offset) offset = 0
1189 const oldOffset = offset
1190
1191 const salt = record.salt
1192 if (!Buffer.isBuffer(salt)) {
1193 throw new Error('salt must be a Buffer')
1194 }
1195
1196 const nextDomain = record.nextDomain
1197 if (!Buffer.isBuffer(nextDomain)) {
1198 throw new Error('nextDomain must be a Buffer')
1199 }
1200
1201 offset += 2 // Leave space for length
1202 buf.writeUInt8(record.algorithm, offset)
1203 offset += 1
1204 buf.writeUInt8(record.flags, offset)
1205 offset += 1
1206 buf.writeUInt16BE(record.iterations, offset)
1207 offset += 2
1208 buf.writeUInt8(salt.length, offset)
1209 offset += 1
1210 salt.copy(buf, offset, 0, salt.length)
1211 offset += salt.length
1212 buf.writeUInt8(nextDomain.length, offset)
1213 offset += 1
1214 nextDomain.copy(buf, offset, 0, nextDomain.length)
1215 offset += nextDomain.length
1216 typebitmap.encode(record.rrtypes, buf, offset)
1217 offset += typebitmap.encode.bytes
1218
1219 rnsec3.encode.bytes = offset - oldOffset
1220 buf.writeUInt16BE(rnsec3.encode.bytes - 2, oldOffset)
1221 return buf
1222}
1223
1224rnsec3.encode.bytes = 0
1225
1226rnsec3.decode = function (buf, offset) {
1227 if (!offset) offset = 0
1228 const oldOffset = offset
1229
1230 var record = {}
1231 var length = buf.readUInt16BE(offset)
1232 offset += 2
1233 record.algorithm = buf.readUInt8(offset)
1234 offset += 1
1235 record.flags = buf.readUInt8(offset)
1236 offset += 1
1237 record.iterations = buf.readUInt16BE(offset)
1238 offset += 2
1239 const saltLength = buf.readUInt8(offset)
1240 offset += 1
1241 record.salt = buf.slice(offset, offset + saltLength)
1242 offset += saltLength
1243 const hashLength = buf.readUInt8(offset)
1244 offset += 1
1245 record.nextDomain = buf.slice(offset, offset + hashLength)
1246 offset += hashLength
1247 record.rrtypes = typebitmap.decode(buf, offset, length - (offset - oldOffset))
1248 offset += typebitmap.decode.bytes
1249
1250 rnsec3.decode.bytes = offset - oldOffset
1251 return record
1252}
1253
1254rnsec3.decode.bytes = 0
1255
1256rnsec3.encodingLength = function (record) {
1257 return 8 +
1258 record.salt.length +
1259 record.nextDomain.length +
1260 typebitmap.encodingLength(record.rrtypes)
1261}
1262
1263const rds = exports.ds = {}
1264
1265rds.encode = function (digest, buf, offset) {
1266 if (!buf) buf = Buffer.alloc(rds.encodingLength(digest))
1267 if (!offset) offset = 0
1268 const oldOffset = offset
1269
1270 const digestdata = digest.digest
1271 if (!Buffer.isBuffer(digestdata)) {
1272 throw new Error('Digest must be a Buffer')
1273 }
1274
1275 offset += 2 // Leave space for length
1276 buf.writeUInt16BE(digest.keyTag, offset)
1277 offset += 2
1278 buf.writeUInt8(digest.algorithm, offset)
1279 offset += 1
1280 buf.writeUInt8(digest.digestType, offset)
1281 offset += 1
1282 digestdata.copy(buf, offset, 0, digestdata.length)
1283 offset += digestdata.length
1284
1285 rds.encode.bytes = offset - oldOffset
1286 buf.writeUInt16BE(rds.encode.bytes - 2, oldOffset)
1287 return buf
1288}
1289
1290rds.encode.bytes = 0
1291
1292rds.decode = function (buf, offset) {
1293 if (!offset) offset = 0
1294 const oldOffset = offset
1295
1296 var digest = {}
1297 var length = buf.readUInt16BE(offset)
1298 offset += 2
1299 digest.keyTag = buf.readUInt16BE(offset)
1300 offset += 2
1301 digest.algorithm = buf.readUInt8(offset)
1302 offset += 1
1303 digest.digestType = buf.readUInt8(offset)
1304 offset += 1
1305 digest.digest = buf.slice(offset, oldOffset + length + 2)
1306 offset += digest.digest.length
1307 rds.decode.bytes = offset - oldOffset
1308 return digest
1309}
1310
1311rds.decode.bytes = 0
1312
1313rds.encodingLength = function (digest) {
1314 return 6 + Buffer.byteLength(digest.digest)
1315}
1316
1317const rsshfp = exports.sshfp = {}
1318
1319rsshfp.getFingerprintLengthForHashType = function getFingerprintLengthForHashType (hashType) {
1320 switch (hashType) {
1321 case 1: return 20
1322 case 2: return 32
1323 }
1324}
1325
1326rsshfp.encode = function encode (record, buf, offset) {
1327 if (!buf) buf = Buffer.alloc(rsshfp.encodingLength(record))
1328 if (!offset) offset = 0
1329 const oldOffset = offset
1330
1331 offset += 2 // The function call starts with the offset pointer at the RDLENGTH field, not the RDATA one
1332 buf[offset] = record.algorithm
1333 offset += 1
1334 buf[offset] = record.hash
1335 offset += 1
1336
1337 const fingerprintBuf = Buffer.from(record.fingerprint.toUpperCase(), 'hex')
1338 if (fingerprintBuf.length !== rsshfp.getFingerprintLengthForHashType(record.hash)) {
1339 throw new Error('Invalid fingerprint length')
1340 }
1341 fingerprintBuf.copy(buf, offset)
1342 offset += fingerprintBuf.byteLength
1343
1344 rsshfp.encode.bytes = offset - oldOffset
1345 buf.writeUInt16BE(rsshfp.encode.bytes - 2, oldOffset)
1346
1347 return buf
1348}
1349
1350rsshfp.encode.bytes = 0
1351
1352rsshfp.decode = function decode (buf, offset) {
1353 if (!offset) offset = 0
1354 const oldOffset = offset
1355
1356 const record = {}
1357 offset += 2 // Account for the RDLENGTH field
1358 record.algorithm = buf[offset]
1359 offset += 1
1360 record.hash = buf[offset]
1361 offset += 1
1362
1363 const fingerprintLength = rsshfp.getFingerprintLengthForHashType(record.hash)
1364 record.fingerprint = buf.slice(offset, offset + fingerprintLength).toString('hex').toUpperCase()
1365 offset += fingerprintLength
1366 rsshfp.decode.bytes = offset - oldOffset
1367 return record
1368}
1369
1370rsshfp.decode.bytes = 0
1371
1372rsshfp.encodingLength = function (record) {
1373 return 4 + Buffer.from(record.fingerprint, 'hex').byteLength
1374}
1375
1376const rnaptr = exports.naptr = {}
1377
1378rnaptr.encode = function (data, buf, offset) {
1379 if (!buf) buf = Buffer.alloc(rnaptr.encodingLength(data))
1380 if (!offset) offset = 0
1381 const oldOffset = offset
1382 offset += 2
1383 buf.writeUInt16BE(data.order || 0, offset)
1384 offset += 2
1385 buf.writeUInt16BE(data.preference || 0, offset)
1386 offset += 2
1387 string.encode(data.flags, buf, offset)
1388 offset += string.encode.bytes
1389 string.encode(data.services, buf, offset)
1390 offset += string.encode.bytes
1391 string.encode(data.regexp, buf, offset)
1392 offset += string.encode.bytes
1393 name.encode(data.replacement, buf, offset)
1394 offset += name.encode.bytes
1395 rnaptr.encode.bytes = offset - oldOffset
1396 buf.writeUInt16BE(rnaptr.encode.bytes - 2, oldOffset)
1397 return buf
1398}
1399
1400rnaptr.encode.bytes = 0
1401
1402rnaptr.decode = function (buf, offset) {
1403 if (!offset) offset = 0
1404 const oldOffset = offset
1405 const data = {}
1406 offset += 2
1407 data.order = buf.readUInt16BE(offset)
1408 offset += 2
1409 data.preference = buf.readUInt16BE(offset)
1410 offset += 2
1411 data.flags = string.decode(buf, offset)
1412 offset += string.decode.bytes
1413 data.services = string.decode(buf, offset)
1414 offset += string.decode.bytes
1415 data.regexp = string.decode(buf, offset)
1416 offset += string.decode.bytes
1417 data.replacement = name.decode(buf, offset)
1418 offset += name.decode.bytes
1419 rnaptr.decode.bytes = offset - oldOffset
1420 return data
1421}
1422
1423rnaptr.decode.bytes = 0
1424
1425rnaptr.encodingLength = function (data) {
1426 return string.encodingLength(data.flags) +
1427 string.encodingLength(data.services) +
1428 string.encodingLength(data.regexp) +
1429 name.encodingLength(data.replacement) + 6
1430}
1431
1432const rtlsa = exports.tlsa = {}
1433
1434rtlsa.encode = function (cert, buf, offset) {
1435 if (!buf) buf = Buffer.alloc(rtlsa.encodingLength(cert))
1436 if (!offset) offset = 0
1437 const oldOffset = offset
1438
1439 const certdata = cert.certificate
1440 if (!Buffer.isBuffer(certdata)) {
1441 throw new Error('Certificate must be a Buffer')
1442 }
1443
1444 offset += 2 // Leave space for length
1445 buf.writeUInt8(cert.usage, offset)
1446 offset += 1
1447 buf.writeUInt8(cert.selector, offset)
1448 offset += 1
1449 buf.writeUInt8(cert.matchingType, offset)
1450 offset += 1
1451 certdata.copy(buf, offset, 0, certdata.length)
1452 offset += certdata.length
1453
1454 rtlsa.encode.bytes = offset - oldOffset
1455 buf.writeUInt16BE(rtlsa.encode.bytes - 2, oldOffset)
1456 return buf
1457}
1458
1459rtlsa.encode.bytes = 0
1460
1461rtlsa.decode = function (buf, offset) {
1462 if (!offset) offset = 0
1463 const oldOffset = offset
1464
1465 const cert = {}
1466 const length = buf.readUInt16BE(offset)
1467 offset += 2
1468 cert.usage = buf.readUInt8(offset)
1469 offset += 1
1470 cert.selector = buf.readUInt8(offset)
1471 offset += 1
1472 cert.matchingType = buf.readUInt8(offset)
1473 offset += 1
1474 cert.certificate = buf.slice(offset, oldOffset + length + 2)
1475 offset += cert.certificate.length
1476 rtlsa.decode.bytes = offset - oldOffset
1477 return cert
1478}
1479
1480rtlsa.decode.bytes = 0
1481
1482rtlsa.encodingLength = function (cert) {
1483 return 5 + Buffer.byteLength(cert.certificate)
1484}
1485
1486const renc = exports.record = function (type) {
1487 switch (type.toUpperCase()) {
1488 case 'A': return ra
1489 case 'PTR': return rptr
1490 case 'CNAME': return rcname
1491 case 'DNAME': return rdname
1492 case 'TXT': return rtxt
1493 case 'NULL': return rnull
1494 case 'AAAA': return raaaa
1495 case 'SRV': return rsrv
1496 case 'HINFO': return rhinfo
1497 case 'CAA': return rcaa
1498 case 'NS': return rns
1499 case 'SOA': return rsoa
1500 case 'MX': return rmx
1501 case 'OPT': return ropt
1502 case 'DNSKEY': return rdnskey
1503 case 'RRSIG': return rrrsig
1504 case 'RP': return rrp
1505 case 'NSEC': return rnsec
1506 case 'NSEC3': return rnsec3
1507 case 'SSHFP': return rsshfp
1508 case 'DS': return rds
1509 case 'NAPTR': return rnaptr
1510 case 'TLSA': return rtlsa
1511 }
1512 return runknown
1513}
1514
1515const answer = exports.answer = {}
1516
1517answer.encode = function (a, buf, offset) {
1518 if (!buf) buf = Buffer.alloc(answer.encodingLength(a))
1519 if (!offset) offset = 0
1520
1521 const oldOffset = offset
1522
1523 name.encode(a.name, buf, offset)
1524 offset += name.encode.bytes
1525
1526 buf.writeUInt16BE(types.toType(a.type), offset)
1527
1528 if (a.type.toUpperCase() === 'OPT') {
1529 if (a.name !== '.') {
1530 throw new Error('OPT name must be root.')
1531 }
1532 buf.writeUInt16BE(a.udpPayloadSize || 4096, offset + 2)
1533 buf.writeUInt8(a.extendedRcode || 0, offset + 4)
1534 buf.writeUInt8(a.ednsVersion || 0, offset + 5)
1535 buf.writeUInt16BE(a.flags || 0, offset + 6)
1536
1537 offset += 8
1538 ropt.encode(a.options || [], buf, offset)
1539 offset += ropt.encode.bytes
1540 } else {
1541 let klass = classes.toClass(a.class === undefined ? 'IN' : a.class)
1542 if (a.flush) klass |= FLUSH_MASK // the 1st bit of the class is the flush bit
1543 buf.writeUInt16BE(klass, offset + 2)
1544 buf.writeUInt32BE(a.ttl || 0, offset + 4)
1545
1546 offset += 8
1547 const enc = renc(a.type)
1548 enc.encode(a.data, buf, offset)
1549 offset += enc.encode.bytes
1550 }
1551
1552 answer.encode.bytes = offset - oldOffset
1553 return buf
1554}
1555
1556answer.encode.bytes = 0
1557
1558answer.decode = function (buf, offset) {
1559 if (!offset) offset = 0
1560
1561 const a = {}
1562 const oldOffset = offset
1563
1564 a.name = name.decode(buf, offset)
1565 offset += name.decode.bytes
1566 a.type = types.toString(buf.readUInt16BE(offset))
1567 if (a.type === 'OPT') {
1568 a.udpPayloadSize = buf.readUInt16BE(offset + 2)
1569 a.extendedRcode = buf.readUInt8(offset + 4)
1570 a.ednsVersion = buf.readUInt8(offset + 5)
1571 a.flags = buf.readUInt16BE(offset + 6)
1572 a.flag_do = ((a.flags >> 15) & 0x1) === 1
1573 a.options = ropt.decode(buf, offset + 8)
1574 offset += 8 + ropt.decode.bytes
1575 } else {
1576 const klass = buf.readUInt16BE(offset + 2)
1577 a.ttl = buf.readUInt32BE(offset + 4)
1578
1579 a.class = classes.toString(klass & NOT_FLUSH_MASK)
1580 a.flush = !!(klass & FLUSH_MASK)
1581
1582 const enc = renc(a.type)
1583 a.data = enc.decode(buf, offset + 8)
1584 offset += 8 + enc.decode.bytes
1585 }
1586
1587 answer.decode.bytes = offset - oldOffset
1588 return a
1589}
1590
1591answer.decode.bytes = 0
1592
1593answer.encodingLength = function (a) {
1594 const data = (a.data !== null && a.data !== undefined) ? a.data : a.options
1595 return name.encodingLength(a.name) + 8 + renc(a.type).encodingLength(data)
1596}
1597
1598const question = exports.question = {}
1599
1600question.encode = function (q, buf, offset) {
1601 if (!buf) buf = Buffer.alloc(question.encodingLength(q))
1602 if (!offset) offset = 0
1603
1604 const oldOffset = offset
1605
1606 name.encode(q.name, buf, offset)
1607 offset += name.encode.bytes
1608
1609 buf.writeUInt16BE(types.toType(q.type), offset)
1610 offset += 2
1611
1612 buf.writeUInt16BE(classes.toClass(q.class === undefined ? 'IN' : q.class), offset)
1613 offset += 2
1614
1615 question.encode.bytes = offset - oldOffset
1616 return q
1617}
1618
1619question.encode.bytes = 0
1620
1621question.decode = function (buf, offset) {
1622 if (!offset) offset = 0
1623
1624 const oldOffset = offset
1625 const q = {}
1626
1627 q.name = name.decode(buf, offset)
1628 offset += name.decode.bytes
1629
1630 q.type = types.toString(buf.readUInt16BE(offset))
1631 offset += 2
1632
1633 q.class = classes.toString(buf.readUInt16BE(offset))
1634 offset += 2
1635
1636 const qu = !!(q.class & QU_MASK)
1637 if (qu) q.class &= NOT_QU_MASK
1638
1639 question.decode.bytes = offset - oldOffset
1640 return q
1641}
1642
1643question.decode.bytes = 0
1644
1645question.encodingLength = function (q) {
1646 return name.encodingLength(q.name) + 4
1647}
1648
1649exports.AUTHORITATIVE_ANSWER = 1 << 10
1650exports.TRUNCATED_RESPONSE = 1 << 9
1651exports.RECURSION_DESIRED = 1 << 8
1652exports.RECURSION_AVAILABLE = 1 << 7
1653exports.AUTHENTIC_DATA = 1 << 5
1654exports.CHECKING_DISABLED = 1 << 4
1655exports.DNSSEC_OK = 1 << 15
1656
1657exports.encode = function (result, buf, offset) {
1658 const allocing = !buf
1659
1660 if (allocing) buf = Buffer.alloc(exports.encodingLength(result))
1661 if (!offset) offset = 0
1662
1663 const oldOffset = offset
1664
1665 if (!result.questions) result.questions = []
1666 if (!result.answers) result.answers = []
1667 if (!result.authorities) result.authorities = []
1668 if (!result.additionals) result.additionals = []
1669
1670 header.encode(result, buf, offset)
1671 offset += header.encode.bytes
1672
1673 offset = encodeList(result.questions, question, buf, offset)
1674 offset = encodeList(result.answers, answer, buf, offset)
1675 offset = encodeList(result.authorities, answer, buf, offset)
1676 offset = encodeList(result.additionals, answer, buf, offset)
1677
1678 exports.encode.bytes = offset - oldOffset
1679
1680 // just a quick sanity check
1681 if (allocing && exports.encode.bytes !== buf.length) {
1682 return buf.slice(0, exports.encode.bytes)
1683 }
1684
1685 return buf
1686}
1687
1688exports.encode.bytes = 0
1689
1690exports.decode = function (buf, offset) {
1691 if (!offset) offset = 0
1692
1693 const oldOffset = offset
1694 const result = header.decode(buf, offset)
1695 offset += header.decode.bytes
1696
1697 offset = decodeList(result.questions, question, buf, offset)
1698 offset = decodeList(result.answers, answer, buf, offset)
1699 offset = decodeList(result.authorities, answer, buf, offset)
1700 offset = decodeList(result.additionals, answer, buf, offset)
1701
1702 exports.decode.bytes = offset - oldOffset
1703
1704 return result
1705}
1706
1707exports.decode.bytes = 0
1708
1709exports.encodingLength = function (result) {
1710 return header.encodingLength(result) +
1711 encodingLengthList(result.questions || [], question) +
1712 encodingLengthList(result.answers || [], answer) +
1713 encodingLengthList(result.authorities || [], answer) +
1714 encodingLengthList(result.additionals || [], answer)
1715}
1716
1717exports.streamEncode = function (result) {
1718 const buf = exports.encode(result)
1719 const sbuf = Buffer.alloc(2)
1720 sbuf.writeUInt16BE(buf.byteLength)
1721 const combine = Buffer.concat([sbuf, buf])
1722 exports.streamEncode.bytes = combine.byteLength
1723 return combine
1724}
1725
1726exports.streamEncode.bytes = 0
1727
1728exports.streamDecode = function (sbuf) {
1729 const len = sbuf.readUInt16BE(0)
1730 if (sbuf.byteLength < len + 2) {
1731 // not enough data
1732 return null
1733 }
1734 const result = exports.decode(sbuf.slice(2))
1735 exports.streamDecode.bytes = exports.decode.bytes
1736 return result
1737}
1738
1739exports.streamDecode.bytes = 0
1740
1741function encodingLengthList (list, enc) {
1742 let len = 0
1743 for (let i = 0; i < list.length; i++) len += enc.encodingLength(list[i])
1744 return len
1745}
1746
1747function encodeList (list, enc, buf, offset) {
1748 for (let i = 0; i < list.length; i++) {
1749 enc.encode(list[i], buf, offset)
1750 offset += enc.encode.bytes
1751 }
1752 return offset
1753}
1754
1755function decodeList (list, enc, buf, offset) {
1756 for (let i = 0; i < list.length; i++) {
1757 list[i] = enc.decode(buf, offset)
1758 offset += enc.decode.bytes
1759 }
1760 return offset
1761}
Note: See TracBrowser for help on using the repository browser.