over-the-wire
Version:
Network inspection library for Node
143 lines (122 loc) • 3.08 kB
JavaScript
const { compile } = require('struct-compile');
const { OsiModelLayers } = require('./osi');
const { DNSRecordType, DNSRecordClass } = require('./enums');
const mixins = require('./mixins');
const { DNSQuery, DNSAnswer, DNSAuthority, DNSAdditional } = require('./DNSRecord');
const { DNSHeader } = compile(`
//@NE
struct DNSHeader {
/** Transaction ID */
uint16_t id;
/** Flags */
uint16_t flags;
/** Number of questions */
uint16_t qdcount;
/** Number of answer RRs */
uint16_t ancount;
/** Number of authority RRs */
uint16_t nscount;
/** Number of additional RRs */
uint16_t arcount;
};
`);
const { length: baseLength } = DNSHeader.prototype.config;
/**
* DNS protocol layer
* @class
* @property {number} src - Source DNS port.
* @property {number} dst - Destination DNS port.
* @property {number} totalLength - This field specifies the length in bytes of the DNS datagram.
* @property {number} checksum - The 16-bit checksum field is used for error-checking of the header and data.
* @implements {Layer}
*/
class DNS extends DNSHeader {
name = 'DNS';
constructor(data = {}, opts = {}) {
super(data);
mixins.ctor(this, data, opts);
this.length = opts.allocated ?? this.totalLength * 4;
}
/**
* Whether this is a DNS query
* @type {boolean}
*/
get isQuery() {
return !(this.flags & 0x8000);
}
/**
* Whether this is a DNS response
* @type {boolean}
*/
get isResponse() {
return !!(this.flags & 0x8000);
}
/**
* DNS operation code
* @type {number}
*/
get opcode() {
return (this.flags >> 11) & 0xF;
}
/**
* Whether this is an authoritative answer
* @type {boolean}
*/
get authoritativeAnswer() {
return !!(this.flags & 0x0400);
}
/**
* Whether this is a truncated message
* @type {boolean}
*/
get truncation() {
return !!(this.flags & 0x0200);
}
/**
* Whether recursion is desired
* @type {boolean}
*/
get recursionDesired() {
return !!(this.flags & 0x0100);
}
/**
* Whether recursion is available
* @type {boolean}
*/
get recursionAvailable() {
return !!(this.flags & 0x0080);
}
/**
* DNS response code
* @type {number}
*/
get responseCode() {
return this.flags & 0xF;
}
static toAlloc = (data) => baseLength;
static osi = OsiModelLayers.Application;
osi = OsiModelLayers.Application;
/**
* Retrieves all fields of the DNS layer.
* @returns {Object} The DNS layer fields as an object.
*/
toObject() {
return {
...super.toObject(),
queries: this.queries,
answers: this.answers,
authorities: this.authorities,
additionals: this.additionals,
};
}
defaults(obj = {}, layers) {
if (!obj.totalLength) {
this.totalLength = this.length / 4;
}
}
nextProto(layers) {
return new layers.Payload(this._buf.subarray(this.length));
}
}
mixins.withOptions(DNS.prototype, { baseLength, skipTypes: [0x1, 0x0], lengthIsTotal: true });
module.exports = { DNS };