You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

763 lines
17 KiB

4 years ago
  1. var types = require('./types')
  2. var rcodes = require('./rcodes')
  3. var opcodes = require('./opcodes')
  4. var ip = require('ip')
  5. var Buffer = require('safe-buffer').Buffer
  6. var QUERY_FLAG = 0
  7. var RESPONSE_FLAG = 1 << 15
  8. var FLUSH_MASK = 1 << 15
  9. var NOT_FLUSH_MASK = ~FLUSH_MASK
  10. var QU_MASK = 1 << 15
  11. var NOT_QU_MASK = ~QU_MASK
  12. var name = exports.txt = exports.name = {}
  13. name.encode = function (str, buf, offset) {
  14. if (!buf) buf = Buffer.allocUnsafe(name.encodingLength(str))
  15. if (!offset) offset = 0
  16. var oldOffset = offset
  17. // strip leading and trailing .
  18. var n = str.replace(/^\.|\.$/gm, '')
  19. if (n.length) {
  20. var list = n.split('.')
  21. for (var i = 0; i < list.length; i++) {
  22. var len = buf.write(list[i], offset + 1)
  23. buf[offset] = len
  24. offset += len + 1
  25. }
  26. }
  27. buf[offset++] = 0
  28. name.encode.bytes = offset - oldOffset
  29. return buf
  30. }
  31. name.encode.bytes = 0
  32. name.decode = function (buf, offset) {
  33. if (!offset) offset = 0
  34. var list = []
  35. var oldOffset = offset
  36. var len = buf[offset++]
  37. if (len === 0) {
  38. name.decode.bytes = 1
  39. return '.'
  40. }
  41. if (len >= 0xc0) {
  42. var res = name.decode(buf, buf.readUInt16BE(offset - 1) - 0xc000)
  43. name.decode.bytes = 2
  44. return res
  45. }
  46. while (len) {
  47. if (len >= 0xc0) {
  48. list.push(name.decode(buf, buf.readUInt16BE(offset - 1) - 0xc000))
  49. offset++
  50. break
  51. }
  52. list.push(buf.toString('utf-8', offset, offset + len))
  53. offset += len
  54. len = buf[offset++]
  55. }
  56. name.decode.bytes = offset - oldOffset
  57. return list.join('.')
  58. }
  59. name.decode.bytes = 0
  60. name.encodingLength = function (n) {
  61. return Buffer.byteLength(n) + 2
  62. }
  63. var string = {}
  64. string.encode = function (s, buf, offset) {
  65. if (!buf) buf = Buffer.allocUnsafe(string.encodingLength(s))
  66. if (!offset) offset = 0
  67. var len = buf.write(s, offset + 1)
  68. buf[offset] = len
  69. string.encode.bytes = len + 1
  70. return buf
  71. }
  72. string.encode.bytes = 0
  73. string.decode = function (buf, offset) {
  74. if (!offset) offset = 0
  75. var len = buf[offset]
  76. var s = buf.toString('utf-8', offset + 1, offset + 1 + len)
  77. string.decode.bytes = len + 1
  78. return s
  79. }
  80. string.decode.bytes = 0
  81. string.encodingLength = function (s) {
  82. return Buffer.byteLength(s) + 1
  83. }
  84. var header = {}
  85. header.encode = function (h, buf, offset) {
  86. if (!buf) buf = header.encodingLength(h)
  87. if (!offset) offset = 0
  88. var flags = (h.flags || 0) & 32767
  89. var type = h.type === 'response' ? RESPONSE_FLAG : QUERY_FLAG
  90. buf.writeUInt16BE(h.id || 0, offset)
  91. buf.writeUInt16BE(flags | type, offset + 2)
  92. buf.writeUInt16BE(h.questions.length, offset + 4)
  93. buf.writeUInt16BE(h.answers.length, offset + 6)
  94. buf.writeUInt16BE(h.authorities.length, offset + 8)
  95. buf.writeUInt16BE(h.additionals.length, offset + 10)
  96. return buf
  97. }
  98. header.encode.bytes = 12
  99. header.decode = function (buf, offset) {
  100. if (!offset) offset = 0
  101. if (buf.length < 12) throw new Error('Header must be 12 bytes')
  102. var flags = buf.readUInt16BE(offset + 2)
  103. return {
  104. id: buf.readUInt16BE(offset),
  105. type: flags & RESPONSE_FLAG ? 'response' : 'query',
  106. flags: flags & 32767,
  107. flag_qr: ((flags >> 15) & 0x1) === 1,
  108. opcode: opcodes.toString((flags >> 11) & 0xf),
  109. flag_auth: ((flags >> 10) & 0x1) === 1,
  110. flag_trunc: ((flags >> 9) & 0x1) === 1,
  111. flag_rd: ((flags >> 8) & 0x1) === 1,
  112. flag_ra: ((flags >> 7) & 0x1) === 1,
  113. flag_z: ((flags >> 6) & 0x1) === 1,
  114. flag_ad: ((flags >> 5) & 0x1) === 1,
  115. flag_cd: ((flags >> 4) & 0x1) === 1,
  116. rcode: rcodes.toString(flags & 0xf),
  117. questions: new Array(buf.readUInt16BE(offset + 4)),
  118. answers: new Array(buf.readUInt16BE(offset + 6)),
  119. authorities: new Array(buf.readUInt16BE(offset + 8)),
  120. additionals: new Array(buf.readUInt16BE(offset + 10))
  121. }
  122. }
  123. header.decode.bytes = 12
  124. header.encodingLength = function () {
  125. return 12
  126. }
  127. var runknown = exports.unknown = {}
  128. runknown.encode = function (data, buf, offset) {
  129. if (!buf) buf = Buffer.allocUnsafe(runknown.encodingLength(data))
  130. if (!offset) offset = 0
  131. buf.writeUInt16BE(data.length, offset)
  132. data.copy(buf, offset + 2)
  133. runknown.encode.bytes = data.length + 2
  134. return buf
  135. }
  136. runknown.encode.bytes = 0
  137. runknown.decode = function (buf, offset) {
  138. if (!offset) offset = 0
  139. var len = buf.readUInt16BE(offset)
  140. var data = buf.slice(offset + 2, offset + 2 + len)
  141. runknown.decode.bytes = len + 2
  142. return data
  143. }
  144. runknown.decode.bytes = 0
  145. runknown.encodingLength = function (data) {
  146. return data.length + 2
  147. }
  148. var rns = exports.ns = {}
  149. rns.encode = function (data, buf, offset) {
  150. if (!buf) buf = Buffer.allocUnsafe(rns.encodingLength(data))
  151. if (!offset) offset = 0
  152. name.encode(data, buf, offset + 2)
  153. buf.writeUInt16BE(name.encode.bytes, offset)
  154. rns.encode.bytes = name.encode.bytes + 2
  155. return buf
  156. }
  157. rns.encode.bytes = 0
  158. rns.decode = function (buf, offset) {
  159. if (!offset) offset = 0
  160. var len = buf.readUInt16BE(offset)
  161. var dd = name.decode(buf, offset + 2)
  162. rns.decode.bytes = len + 2
  163. return dd
  164. }
  165. rns.decode.bytes = 0
  166. rns.encodingLength = function (data) {
  167. return name.encodingLength(data) + 2
  168. }
  169. var rsoa = exports.soa = {}
  170. rsoa.encode = function (data, buf, offset) {
  171. if (!buf) buf = Buffer.allocUnsafe(rsoa.encodingLength(data))
  172. if (!offset) offset = 0
  173. var oldOffset = offset
  174. offset += 2
  175. name.encode(data.mname, buf, offset)
  176. offset += name.encode.bytes
  177. name.encode(data.rname, buf, offset)
  178. offset += name.encode.bytes
  179. buf.writeUInt32BE(data.serial || 0, offset)
  180. offset += 4
  181. buf.writeUInt32BE(data.refresh || 0, offset)
  182. offset += 4
  183. buf.writeUInt32BE(data.retry || 0, offset)
  184. offset += 4
  185. buf.writeUInt32BE(data.expire || 0, offset)
  186. offset += 4
  187. buf.writeUInt32BE(data.minimum || 0, offset)
  188. offset += 4
  189. buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
  190. rsoa.encode.bytes = offset - oldOffset
  191. return buf
  192. }
  193. rsoa.encode.bytes = 0
  194. rsoa.decode = function (buf, offset) {
  195. if (!offset) offset = 0
  196. var oldOffset = offset
  197. var data = {}
  198. offset += 2
  199. data.mname = name.decode(buf, offset)
  200. offset += name.decode.bytes
  201. data.rname = name.decode(buf, offset)
  202. offset += name.decode.bytes
  203. data.serial = buf.readUInt32BE(offset)
  204. offset += 4
  205. data.refresh = buf.readUInt32BE(offset)
  206. offset += 4
  207. data.retry = buf.readUInt32BE(offset)
  208. offset += 4
  209. data.expire = buf.readUInt32BE(offset)
  210. offset += 4
  211. data.minimum = buf.readUInt32BE(offset)
  212. offset += 4
  213. rsoa.decode.bytes = offset - oldOffset
  214. return data
  215. }
  216. rsoa.decode.bytes = 0
  217. rsoa.encodingLength = function (data) {
  218. return 22 + name.encodingLength(data.mname) + name.encodingLength(data.rname)
  219. }
  220. var rtxt = exports.txt = exports.null = {}
  221. var rnull = rtxt
  222. rtxt.encode = function (data, buf, offset) {
  223. if (!buf) buf = Buffer.allocUnsafe(rtxt.encodingLength(data))
  224. if (!offset) offset = 0
  225. if (typeof data === 'string') data = Buffer.from(data)
  226. if (!data) data = Buffer.allocUnsafe(0)
  227. var oldOffset = offset
  228. offset += 2
  229. var len = data.length
  230. data.copy(buf, offset, 0, len)
  231. offset += len
  232. buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
  233. rtxt.encode.bytes = offset - oldOffset
  234. return buf
  235. }
  236. rtxt.encode.bytes = 0
  237. rtxt.decode = function (buf, offset) {
  238. if (!offset) offset = 0
  239. var oldOffset = offset
  240. var len = buf.readUInt16BE(offset)
  241. offset += 2
  242. var data = buf.slice(offset, offset + len)
  243. offset += len
  244. rtxt.decode.bytes = offset - oldOffset
  245. return data
  246. }
  247. rtxt.decode.bytes = 0
  248. rtxt.encodingLength = function (data) {
  249. if (!data) return 2
  250. return (Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data)) + 2
  251. }
  252. var rhinfo = exports.hinfo = {}
  253. rhinfo.encode = function (data, buf, offset) {
  254. if (!buf) buf = Buffer.allocUnsafe(rhinfo.encodingLength(data))
  255. if (!offset) offset = 0
  256. var oldOffset = offset
  257. offset += 2
  258. string.encode(data.cpu, buf, offset)
  259. offset += string.encode.bytes
  260. string.encode(data.os, buf, offset)
  261. offset += string.encode.bytes
  262. buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
  263. rhinfo.encode.bytes = offset - oldOffset
  264. return buf
  265. }
  266. rhinfo.encode.bytes = 0
  267. rhinfo.decode = function (buf, offset) {
  268. if (!offset) offset = 0
  269. var oldOffset = offset
  270. var data = {}
  271. offset += 2
  272. data.cpu = string.decode(buf, offset)
  273. offset += string.decode.bytes
  274. data.os = string.decode(buf, offset)
  275. offset += string.decode.bytes
  276. rhinfo.decode.bytes = offset - oldOffset
  277. return data
  278. }
  279. rhinfo.decode.bytes = 0
  280. rhinfo.encodingLength = function (data) {
  281. return string.encodingLength(data.cpu) + string.encodingLength(data.os) + 2
  282. }
  283. var rptr = exports.ptr = {}
  284. var rcname = exports.cname = rptr
  285. var rdname = exports.dname = rptr
  286. rptr.encode = function (data, buf, offset) {
  287. if (!buf) buf = Buffer.allocUnsafe(rptr.encodingLength(data))
  288. if (!offset) offset = 0
  289. name.encode(data, buf, offset + 2)
  290. buf.writeUInt16BE(name.encode.bytes, offset)
  291. rptr.encode.bytes = name.encode.bytes + 2
  292. return buf
  293. }
  294. rptr.encode.bytes = 0
  295. rptr.decode = function (buf, offset) {
  296. if (!offset) offset = 0
  297. var data = name.decode(buf, offset + 2)
  298. rptr.decode.bytes = name.decode.bytes + 2
  299. return data
  300. }
  301. rptr.decode.bytes = 0
  302. rptr.encodingLength = function (data) {
  303. return name.encodingLength(data) + 2
  304. }
  305. var rsrv = exports.srv = {}
  306. rsrv.encode = function (data, buf, offset) {
  307. if (!buf) buf = Buffer.allocUnsafe(rsrv.encodingLength(data))
  308. if (!offset) offset = 0
  309. buf.writeUInt16BE(data.priority || 0, offset + 2)
  310. buf.writeUInt16BE(data.weight || 0, offset + 4)
  311. buf.writeUInt16BE(data.port || 0, offset + 6)
  312. name.encode(data.target, buf, offset + 8)
  313. var len = name.encode.bytes + 6
  314. buf.writeUInt16BE(len, offset)
  315. rsrv.encode.bytes = len + 2
  316. return buf
  317. }
  318. rsrv.encode.bytes = 0
  319. rsrv.decode = function (buf, offset) {
  320. if (!offset) offset = 0
  321. var len = buf.readUInt16BE(offset)
  322. var data = {}
  323. data.priority = buf.readUInt16BE(offset + 2)
  324. data.weight = buf.readUInt16BE(offset + 4)
  325. data.port = buf.readUInt16BE(offset + 6)
  326. data.target = name.decode(buf, offset + 8)
  327. rsrv.decode.bytes = len + 2
  328. return data
  329. }
  330. rsrv.decode.bytes = 0
  331. rsrv.encodingLength = function (data) {
  332. return 8 + name.encodingLength(data.target)
  333. }
  334. var rcaa = exports.caa = {}
  335. rcaa.ISSUER_CRITICAL = 1 << 7
  336. rcaa.encode = function (data, buf, offset) {
  337. var len = rcaa.encodingLength(data)
  338. if (!buf) buf = Buffer.allocUnsafe(rcaa.encodingLength(data))
  339. if (!offset) offset = 0
  340. if (data.issuerCritical) {
  341. data.flags = rcaa.ISSUER_CRITICAL
  342. }
  343. buf.writeUInt16BE(len - 2, offset)
  344. offset += 2
  345. buf.writeUInt8(data.flags || 0, offset)
  346. offset += 1
  347. string.encode(data.tag, buf, offset)
  348. offset += string.encode.bytes
  349. buf.write(data.value, offset)
  350. offset += Buffer.byteLength(data.value)
  351. rcaa.encode.bytes = len
  352. return buf
  353. }
  354. rcaa.encode.bytes = 0
  355. rcaa.decode = function (buf, offset) {
  356. if (!offset) offset = 0
  357. var len = buf.readUInt16BE(offset)
  358. offset += 2
  359. var oldOffset = offset
  360. var data = {}
  361. data.flags = buf.readUInt8(offset)
  362. offset += 1
  363. data.tag = string.decode(buf, offset)
  364. offset += string.decode.bytes
  365. data.value = buf.toString('utf-8', offset, oldOffset + len)
  366. data.issuerCritical = !!(data.flags & rcaa.ISSUER_CRITICAL)
  367. rcaa.decode.bytes = len + 2
  368. return data
  369. }
  370. rcaa.decode.bytes = 0
  371. rcaa.encodingLength = function (data) {
  372. return string.encodingLength(data.tag) + string.encodingLength(data.value) + 2
  373. }
  374. var ra = exports.a = {}
  375. ra.encode = function (host, buf, offset) {
  376. if (!buf) buf = Buffer.allocUnsafe(ra.encodingLength(host))
  377. if (!offset) offset = 0
  378. buf.writeUInt16BE(4, offset)
  379. offset += 2
  380. ip.toBuffer(host, buf, offset)
  381. ra.encode.bytes = 6
  382. return buf
  383. }
  384. ra.encode.bytes = 0
  385. ra.decode = function (buf, offset) {
  386. if (!offset) offset = 0
  387. offset += 2
  388. var host = ip.toString(buf, offset, 4)
  389. ra.decode.bytes = 6
  390. return host
  391. }
  392. ra.decode.bytes = 0
  393. ra.encodingLength = function () {
  394. return 6
  395. }
  396. var raaaa = exports.aaaa = {}
  397. raaaa.encode = function (host, buf, offset) {
  398. if (!buf) buf = Buffer.allocUnsafe(raaaa.encodingLength(host))
  399. if (!offset) offset = 0
  400. buf.writeUInt16BE(16, offset)
  401. offset += 2
  402. ip.toBuffer(host, buf, offset)
  403. raaaa.encode.bytes = 18
  404. return buf
  405. }
  406. raaaa.encode.bytes = 0
  407. raaaa.decode = function (buf, offset) {
  408. if (!offset) offset = 0
  409. offset += 2
  410. var host = ip.toString(buf, offset, 16)
  411. raaaa.decode.bytes = 18
  412. return host
  413. }
  414. raaaa.decode.bytes = 0
  415. raaaa.encodingLength = function () {
  416. return 18
  417. }
  418. var renc = exports.record = function (type) {
  419. switch (type.toUpperCase()) {
  420. case 'A': return ra
  421. case 'PTR': return rptr
  422. case 'CNAME': return rcname
  423. case 'DNAME': return rdname
  424. case 'TXT': return rtxt
  425. case 'NULL': return rnull
  426. case 'AAAA': return raaaa
  427. case 'SRV': return rsrv
  428. case 'HINFO': return rhinfo
  429. case 'CAA': return rcaa
  430. case 'NS': return rns
  431. case 'SOA': return rsoa
  432. }
  433. return runknown
  434. }
  435. var answer = exports.answer = {}
  436. answer.encode = function (a, buf, offset) {
  437. if (!buf) buf = Buffer.allocUnsafe(answer.encodingLength(a))
  438. if (!offset) offset = 0
  439. var oldOffset = offset
  440. name.encode(a.name, buf, offset)
  441. offset += name.encode.bytes
  442. buf.writeUInt16BE(types.toType(a.type), offset)
  443. var klass = a.class === undefined ? 1 : a.class
  444. if (a.flush) klass |= FLUSH_MASK // the 1st bit of the class is the flush bit
  445. buf.writeUInt16BE(klass, offset + 2)
  446. buf.writeUInt32BE(a.ttl || 0, offset + 4)
  447. var enc = renc(a.type)
  448. enc.encode(a.data, buf, offset + 8)
  449. offset += 8 + enc.encode.bytes
  450. answer.encode.bytes = offset - oldOffset
  451. return buf
  452. }
  453. answer.encode.bytes = 0
  454. answer.decode = function (buf, offset) {
  455. if (!offset) offset = 0
  456. var a = {}
  457. var oldOffset = offset
  458. a.name = name.decode(buf, offset)
  459. offset += name.decode.bytes
  460. a.type = types.toString(buf.readUInt16BE(offset))
  461. a.class = buf.readUInt16BE(offset + 2)
  462. a.ttl = buf.readUInt32BE(offset + 4)
  463. a.flush = !!(a.class & FLUSH_MASK)
  464. if (a.flush) a.class &= NOT_FLUSH_MASK
  465. var enc = renc(a.type)
  466. a.data = enc.decode(buf, offset + 8)
  467. offset += 8 + enc.decode.bytes
  468. answer.decode.bytes = offset - oldOffset
  469. return a
  470. }
  471. answer.decode.bytes = 0
  472. answer.encodingLength = function (a) {
  473. return name.encodingLength(a.name) + 8 + renc(a.type).encodingLength(a.data)
  474. }
  475. var question = exports.question = {}
  476. question.encode = function (q, buf, offset) {
  477. if (!buf) buf = Buffer.allocUnsafe(question.encodingLength(q))
  478. if (!offset) offset = 0
  479. var oldOffset = offset
  480. name.encode(q.name, buf, offset)
  481. offset += name.encode.bytes
  482. buf.writeUInt16BE(types.toType(q.type), offset)
  483. offset += 2
  484. buf.writeUInt16BE(q.class === undefined ? 1 : q.class, offset)
  485. offset += 2
  486. question.encode.bytes = offset - oldOffset
  487. return q
  488. }
  489. question.encode.bytes = 0
  490. question.decode = function (buf, offset) {
  491. if (!offset) offset = 0
  492. var oldOffset = offset
  493. var q = {}
  494. q.name = name.decode(buf, offset)
  495. offset += name.decode.bytes
  496. q.type = types.toString(buf.readUInt16BE(offset))
  497. offset += 2
  498. q.class = buf.readUInt16BE(offset)
  499. offset += 2
  500. var qu = !!(q.class & QU_MASK)
  501. if (qu) q.class &= NOT_QU_MASK
  502. question.decode.bytes = offset - oldOffset
  503. return q
  504. }
  505. question.decode.bytes = 0
  506. question.encodingLength = function (q) {
  507. return name.encodingLength(q.name) + 4
  508. }
  509. exports.AUTHORITATIVE_ANSWER = 1 << 10
  510. exports.TRUNCATED_RESPONSE = 1 << 9
  511. exports.RECURSION_DESIRED = 1 << 8
  512. exports.RECURSION_AVAILABLE = 1 << 7
  513. exports.AUTHENTIC_DATA = 1 << 5
  514. exports.CHECKING_DISABLED = 1 << 4
  515. exports.encode = function (result, buf, offset) {
  516. if (!buf) buf = Buffer.allocUnsafe(exports.encodingLength(result))
  517. if (!offset) offset = 0
  518. var oldOffset = offset
  519. if (!result.questions) result.questions = []
  520. if (!result.answers) result.answers = []
  521. if (!result.authorities) result.authorities = []
  522. if (!result.additionals) result.additionals = []
  523. header.encode(result, buf, offset)
  524. offset += header.encode.bytes
  525. offset = encodeList(result.questions, question, buf, offset)
  526. offset = encodeList(result.answers, answer, buf, offset)
  527. offset = encodeList(result.authorities, answer, buf, offset)
  528. offset = encodeList(result.additionals, answer, buf, offset)
  529. exports.encode.bytes = offset - oldOffset
  530. return buf
  531. }
  532. exports.encode.bytes = 0
  533. exports.decode = function (buf, offset) {
  534. if (!offset) offset = 0
  535. var oldOffset = offset
  536. var result = header.decode(buf, offset)
  537. offset += header.decode.bytes
  538. offset = decodeList(result.questions, question, buf, offset)
  539. offset = decodeList(result.answers, answer, buf, offset)
  540. offset = decodeList(result.authorities, answer, buf, offset)
  541. offset = decodeList(result.additionals, answer, buf, offset)
  542. exports.decode.bytes = offset - oldOffset
  543. return result
  544. }
  545. exports.decode.bytes = 0
  546. exports.encodingLength = function (result) {
  547. return header.encodingLength(result) +
  548. encodingLengthList(result.questions || [], question) +
  549. encodingLengthList(result.answers || [], answer) +
  550. encodingLengthList(result.authorities || [], answer) +
  551. encodingLengthList(result.additionals || [], answer)
  552. }
  553. function encodingLengthList (list, enc) {
  554. var len = 0
  555. for (var i = 0; i < list.length; i++) len += enc.encodingLength(list[i])
  556. return len
  557. }
  558. function encodeList (list, enc, buf, offset) {
  559. for (var i = 0; i < list.length; i++) {
  560. enc.encode(list[i], buf, offset)
  561. offset += enc.encode.bytes
  562. }
  563. return offset
  564. }
  565. function decodeList (list, enc, buf, offset) {
  566. for (var i = 0; i < list.length; i++) {
  567. list[i] = enc.decode(buf, offset)
  568. offset += enc.decode.bytes
  569. }
  570. return offset
  571. }