dns-suite.js/dns.type.TEMPLATE.js

117 lines
4.3 KiB
JavaScript

(function (exports) {
'use strict';
// Put some documentation here in these comments.
// See examples of documentation in dns.type.a.js
// and dns.type.mx.js
// If the data type you're wanting to unpack contains labels
// (meaning text that will be represented as a period-separated
// domain name, i.e. www.google.com) then you will need to use
// `unpackLabels`, which has compression pointer support
var unpackLabels = exports.DNS_UNPACK_LABELS || require('./dns.unpack-labels.js').DNS_UNPACK_LABELS;
// The parser receives exactly 3 parameters as follows:
//
// ab - an ArrayBuffer containing the whole of the packet as binary
// you will use Uint8Array (for which endianness doesn't matter)
// and DataView (with wich you MUST always specify 'false' for
// Big Endian, which is "network byte order")
//
// packet - a plain javascript value object (i.e. to/from JSON) that
// has all of the currently parsed fields (generally not used),
// containing meta data in `header`, and arrays of potentially
// parsed (or not yet parsed) records in `question`, `answer`,
// `authority`, `additional`
//
// record - an element of an array in packet (meaning one of `question`,
// `answer`, `authority`, `additional`) which has potentially
// helpful data about the record such as `rdstart` and `rdlength`,
// signifying the type at which the binary segment for this record
// begins and its length
//
exports.DNS_TYPE_MX = function (ab, packet, record) {
//
// Slicing RData
//
// For various reasons it may be easier to work with a slice of the
// ArrayBuffer container the binary packet that just represents the
// RData you want to work with starting at 0 and ending at the end of
// the Resource Record (aka RData) rather than always adding `rdstart`
// to some offset and checking that you don't read past the record's
// end (`rdstart + rdlength`)
var rdataAb = ab.slice(record.rdstart, record.rdstart + record.rdlength);
//
// Using Uint8Array
//
// it's very likely that you'll want to process individual bytes,
// for which you would use Uint8Array - for example, if some significant
// portion of the record is to be read as a non-label string
var ui8 = new Uint8Array(rdataAb);
// Example: reading a string whose length is defined by the first byte
var len = ui8[0];
var i;
record.value = '';
for (i = 0; i < len; i += 1) {
record.value += String.fromCharCode(ui8[i]);
}
// Example: reading a string whose length is terminated with 0
var i;
record.value = '';
for (i = 0; i < len; i += 1) {
if (0 === ui8[i]) {
break;
}
record.value += String.fromCharCode(ui8[i]);
}
//
// Using DataView
//
// it's also very likely that you'll want to interpret some variable
// byte-width data, such as an id or type number, something of that nature
var dv = new DataView(rdataAb);
// Example: reading a single-octet type, a sexdectet id, and quad-octet date
record.rtype = dv.getUint8(0, false); // start at 0
record.rid = dv.getUint16(1, false); // next is at 1
record.date = new Date(dv.getUint32(3, false) * 1000); // advance 2 more bytes to 3
// the next read, if any, would be at 7
//
// Unpacking Labels
//
// if your data type contains labels (i.e. www.google.com would be represented
// as 3 labels and would have the byte sequence 0x03"www"0x06"google"0x03"com),
// they may contain compression pointers (represented as 0xc0, meaning 192 in
// decimal - outside the ascii range) and they may be terminated either by 0x00
// or by the end of the record, so you should use unpackLabels and provide an
// ArrayBuffer that is sliced to the end of your record (otherwise record-length
// terminated strings would be misinterpretted overflow)
// Example: assuming some label started at the 7th byte
var truncatedAb = new Uint8Array(ab.slice(0, record.rdstart + record.rdlength));
var labelData = unpackLabels(truncatedAb, record.rdstart+7, { byteLength: 0, cpcount: 0, labels: [], name: '' });
record.deviceName = labelData.name;
// finally, return the record
return record;
};
}('undefined' !== typeof window ? window : exports));