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