123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- const opcode = {
- QUERY: 0,
- IQUERY: 1,
- STATUS: 2
- }
- const qtype = {
- A: 1,
- NS: 2,
- MD: 3,
- MF: 4,
- CNAME: 5,
- SOA: 6,
- MB: 7,
- MG: 8,
- MR: 9,
- NULL: 10,
- WKS: 11,
- PTR: 12,
- HINFO: 13,
- MINFO: 14,
- MX: 15,
- TXT: 16,
- // Additional
- AXFR: 252,
- MAILB: 253,
- MAILA: 254,
- ANY: 255
- }
- const qclass = {
- IN: 1,
- CS: 2,
- CH: 3,
- HS: 4,
- ANY: 255
- }
- const rcode = {
- NOERROR: 0,
- FORMAT: 1,
- SERVER: 2,
- NAME: 3,
- NOTIMPL: 4,
- REFUSED: 5
- }
- const types = { opcode, qtype, qclass, rcode }
- function readName (offset, buf, view) {
- let name = []
- let qnameSize = view.getUint8(offset++)
- while (qnameSize) {
- if ((qnameSize & 192) === 192) {
- let off = (qnameSize - 192) << 8
- off += view.getUint8(offset++)
- name = name.concat(readName(off, buf, view))
- qnameSize = 0
- } else {
- name.push(buf.readString(qnameSize, offset))
- offset += qnameSize
- qnameSize = view.getUint8(offset++)
- }
- }
- return name
- }
- const parse = (buf, len) => {
- const bytes = new Uint8Array(buf)
- const view = new DataView(buf)
- const id = view.getUint16(0)
- const flags = view.getUint16(2)
- const QR = (flags >> 15) & 0b1
- const opCode = (flags >> 11) & 0b1111
- const AA = (flags >> 10) & 0b1
- const TC = (flags >> 9) & 0b1
- const RD = (flags >> 8) & 0b1
- const RA = (flags >> 7) & 0b1
- const Z = (flags >> 4) & 0b111
- const RCODE = flags & 0b1111
- const qcount = view.getUint16(4)
- const ancount = view.getUint16(6)
- const nscount = view.getUint16(8)
- const arcount = view.getUint16(10)
- const question = []
- const answer = []
- const authority = []
- const additional = []
- const start = 12
- let off = start
- let i = off
- let counter = qcount
- while (counter--) {
- let size = 0
- const sections = []
- while (bytes[i++]) size++
- if (size > 0) {
- while (off - start < size) {
- const qnameSize = view.getUint8(off++)
- sections.push(buf.readString(qnameSize, off))
- off += qnameSize
- }
- }
- off++
- const qtype = view.getUint16(off)
- off += 2
- const qclass = view.getUint16(off)
- off += 2
- question.push({ qtype, qclass, name: sections })
- }
- counter = ancount
- while (counter--) {
- const next = view.getUint16(off)
- let name
- if ((0b1100000000000000 & next) === 0b1100000000000000) {
- name = readName(next & 0b11111111111111, buf, view)
- off += 2
- } else {
- name = readName(off, buf, view)
- off += name.length + (name.reduce((a, v) => a + v.length, 0)) + 1
- }
- const qtype = view.getUint16(off)
- off += 2
- const qclass = view.getUint16(off)
- off += 2
- const ttl = view.getUint32(off)
- off += 4
- const rdLength = view.getUint16(off)
- off += 2
- if (qtype === 5) {
- const cname = readName(off, buf, view)
- answer.push({ name, cname, qtype, qclass, ttl })
- } else if (qtype === 1) {
- answer.push({ name, qtype, qclass, ttl, ip: bytes.slice(off, off + rdLength) })
- }
- off += rdLength
- }
- return { bytes: bytes.slice(0, len), qcount, nscount, ancount, arcount, id, flags, QR, opCode, AA, TC, RD, RA, Z, RCODE, question, answer, authority, additional }
- }
- const create = (domain, buf, id, qtype = 1, qclass = 1) => {
- const view = new DataView(buf)
- const bytes = new Uint8Array(buf)
- view.setUint16(0, id)
- view.setUint16(2, 0b0000000101000000)
- view.setUint16(4, 1)
- view.setUint16(6, 0)
- view.setUint16(8, 0)
- view.setUint16(10, 0)
- let off = 12
- const parts = domain.split('.')
- for (const part of parts) {
- view.setUint8(off++, part.length)
- buf.writeString(part, off)
- off += part.length
- }
- bytes[off++] = 0
- view.setUint16(off, qtype)
- off += 2
- view.setUint16(off, qclass)
- off += 2
- return off
- }
- const qtypes = {}
- Object.keys(types.qtype).forEach(k => {
- qtypes[types.qtype[k]] = k
- })
- const qclasses = {}
- Object.keys(types.qclass).forEach(k => {
- qclasses[types.qclass[k]] = k
- })
- const opcodes = {}
- Object.keys(types.opcode).forEach(k => {
- opcodes[types.opcode[k]] = k
- })
- const rcodes = {}
- Object.keys(types.rcode).forEach(k => {
- rcodes[types.rcode[k]] = k
- })
- function getFlags (message) {
- const flags = []
- if (message.QR) flags.push('qr')
- if (message.AA) flags.push('aa')
- if (message.TC) flags.push('tc')
- if (message.RD) flags.push('rd')
- if (message.RA) flags.push('ra')
- if (message.Z) flags.push('z')
- return flags.join(' ')
- }
- module.exports = { getFlags, create, parse, types, qtypes, qclasses, opcodes, rcodes }
|