bugfix: add null terminators for packing SOA records
This commit is contained in:
parent
98187043ec
commit
a538fa4f58
|
@ -35,7 +35,7 @@ var hexdump = require('hexdump.js').hexdump;
|
||||||
function testJsonAsync(nb) {
|
function testJsonAsync(nb) {
|
||||||
var packet = dnsjs.write(JSON.parse(nb.toString('ascii')));
|
var packet = dnsjs.write(JSON.parse(nb.toString('ascii')));
|
||||||
var str = hexdump(packet);
|
var str = hexdump(packet);
|
||||||
console.log(str);
|
console.info(str);
|
||||||
var json = dnsjs.parse(packet);
|
var json = dnsjs.parse(packet);
|
||||||
if (json.error) {
|
if (json.error) {
|
||||||
console.error(json);
|
console.error(json);
|
||||||
|
@ -43,7 +43,7 @@ function testJsonAsync(nb) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("[OK] JSON -> binary -> JSON");
|
console.info("[OK] JSON -> binary -> JSON");
|
||||||
|
|
||||||
if (!outname) {
|
if (!outname) {
|
||||||
console.warn('');
|
console.warn('');
|
||||||
|
@ -54,7 +54,7 @@ function testJsonAsync(nb) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync(path.basename(filename).replace(path.extname(filename), '.bin'), packet, null);
|
fs.writeFileSync(outname, packet, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBinAsync(nb) {
|
function testBinAsync(nb) {
|
||||||
|
@ -66,6 +66,8 @@ function testBinAsync(nb) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var bin2 = dnsjs.write(json);
|
var bin2 = dnsjs.write(json);
|
||||||
|
//var debugname = outname || path.basename(filename);
|
||||||
|
//fs.writeFileSync(debugname.replace(path.extname(debugname), '.bin'), bin2, null);
|
||||||
var json2 = dnsjs.parse(bin2);
|
var json2 = dnsjs.parse(bin2);
|
||||||
if (json2.error) {
|
if (json2.error) {
|
||||||
console.error(json2);
|
console.error(json2);
|
||||||
|
@ -86,12 +88,22 @@ function testBinAsync(nb) {
|
||||||
.replace(/,"cpcount":\d+/, '')
|
.replace(/,"cpcount":\d+/, '')
|
||||||
);
|
);
|
||||||
//json2 = JSON.parse(JSON.stringify(json2));
|
//json2 = JSON.parse(JSON.stringify(json2));
|
||||||
//console.log(json);
|
try {
|
||||||
//console.log(json2);
|
|
||||||
assert.deepEqual(json, json2);
|
assert.deepEqual(json, json2);
|
||||||
|
} catch(e) {
|
||||||
|
console.error('');
|
||||||
|
console.error('Original');
|
||||||
|
console.error(JSON.stringify(json, null, 2));
|
||||||
|
console.error('');
|
||||||
|
console.error('Converted');
|
||||||
|
console.error(JSON.stringify(json2, null, 2));
|
||||||
|
console.error('');
|
||||||
|
process.exit(422);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
console.log("[OK] binary -> JSON -> binary -> JSON");
|
console.info("[OK] binary -> JSON -> binary -> JSON");
|
||||||
console.log("(compression pointer support needs to be improved in order to support direct bin -> JSON -> bin testing)");
|
console.warn("(compression pointer support needs to be improved in order to support direct bin -> JSON -> bin testing)");
|
||||||
|
|
||||||
if (!outname) {
|
if (!outname) {
|
||||||
console.warn('');
|
console.warn('');
|
||||||
|
@ -102,7 +114,7 @@ function testBinAsync(nb) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync(path.basename(filename).replace(path.extname(filename), '.json'), JSON.stringify(json, null, 2), null);
|
fs.writeFileSync(outname, JSON.stringify(json, null, 2), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('json' === extname) {
|
if ('json' === extname) {
|
||||||
|
|
|
@ -46,6 +46,10 @@ exports.DNS_UNPACK_LABELS = function (ui8, ptr, q) {
|
||||||
|
|
||||||
//str.length = 0; // fast empty array
|
//str.length = 0; // fast empty array
|
||||||
if (ui8.byteLength - total < len) {
|
if (ui8.byteLength - total < len) {
|
||||||
|
//console.error('-1', ui8[total - 1]);
|
||||||
|
//console.error(' 0', ui8[total]);
|
||||||
|
//console.error(' 1', ui8[total + 1]);
|
||||||
|
//console.error(' 1', ui8[total + 2]);
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Expected a string of length " + len
|
"Expected a string of length " + len
|
||||||
+ " but packet itself has " + (ui8.byteLength - total) + " bytes remaining"
|
+ " but packet itself has " + (ui8.byteLength - total) + " bytes remaining"
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
(function (exports) {
|
(function (exports) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// http://www.zytrax.com/books/dns/ch8/soa.html
|
||||||
|
|
||||||
// Value Meaning/Use
|
// Value Meaning/Use
|
||||||
// Primary NS Variable length. The name of the Primary Master for the domain. May be a label, pointer, or any combination
|
// Primary NS Variable length. The name of the Primary Master for the domain. May be a label, pointer, or any combination
|
||||||
// Admin MB Variable length. The administrator's mailbox. May be a label, pointer, or any combination
|
// Admin MB Variable length. The administrator's mailbox. May be a label, pointer, or any combination
|
||||||
|
@ -10,8 +12,6 @@
|
||||||
// Expiration Limit Unsigned 32-bit integer
|
// Expiration Limit Unsigned 32-bit integer
|
||||||
// Minimum TTL Unsigned 32-bit integer
|
// Minimum TTL Unsigned 32-bit integer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
exports.DNS_PACKER_TYPE_SOA = function (ab, dv, total, record) {
|
exports.DNS_PACKER_TYPE_SOA = function (ab, dv, total, record) {
|
||||||
if(!record.name_server){
|
if(!record.name_server){
|
||||||
throw new Error("no name server for SOA record");
|
throw new Error("no name server for SOA record");
|
||||||
|
@ -23,16 +23,16 @@ exports.DNS_PACKER_TYPE_SOA = function (ab, dv, total, record) {
|
||||||
throw new Error("no serial number for SOA record");
|
throw new Error("no serial number for SOA record");
|
||||||
}
|
}
|
||||||
if(!record.ref){
|
if(!record.ref){
|
||||||
throw new Error("no serial number for SOA record");
|
throw new Error("no refresh for SOA record");
|
||||||
}
|
}
|
||||||
if(!record.ret){
|
if(!record.ret){
|
||||||
throw new Error("no serial number for SOA record");
|
throw new Error("no update retry for SOA record");
|
||||||
}
|
}
|
||||||
if(!record.ex){
|
if(!record.ex){
|
||||||
throw new Error("no serial number for SOA record");
|
throw new Error("no expiry for SOA record");
|
||||||
}
|
}
|
||||||
if(!record.nx){
|
if(!record.nx){
|
||||||
throw new Error("no serial number for SOA record");
|
throw new Error("no nxdomain for SOA record");
|
||||||
}
|
}
|
||||||
|
|
||||||
var soaLen = 20; // take into account sn, ref, ret, ex, and nx
|
var soaLen = 20; // take into account sn, ref, ret, ex, and nx
|
||||||
|
@ -40,9 +40,10 @@ exports.DNS_PACKER_TYPE_SOA = function (ab, dv, total, record) {
|
||||||
var rdLenIndex = total;
|
var rdLenIndex = total;
|
||||||
total += 2; // Save space for RDLENGTH
|
total += 2; // Save space for RDLENGTH
|
||||||
|
|
||||||
|
console.log('record.name_server', 1 + record.name_server.length, record.name_server);
|
||||||
// pack name_server which is a sequence of labels
|
// pack name_server which is a sequence of labels
|
||||||
record.name_server.split('.').forEach(function(label){
|
record.name_server.split('.').forEach(function (label) {
|
||||||
soaLen += 1 + label.length;
|
soaLen += (1 + label.length);
|
||||||
|
|
||||||
dv.setUint8(total, label.length, false);
|
dv.setUint8(total, label.length, false);
|
||||||
total += 1;
|
total += 1;
|
||||||
|
@ -52,9 +53,14 @@ exports.DNS_PACKER_TYPE_SOA = function (ab, dv, total, record) {
|
||||||
total += 1;
|
total += 1;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
// must be terminated by null when not using write null
|
||||||
|
dv.setUint8(total, 0, false);
|
||||||
|
total += 1;
|
||||||
|
soaLen += 1;
|
||||||
|
|
||||||
|
console.log('record.email_addr', 1 + record.email_addr.length, record.email_addr);
|
||||||
// pack email address which is a sequence of labels
|
// pack email address which is a sequence of labels
|
||||||
record.email_addr.split('.').forEach(function (label){
|
record.email_addr.split('.').forEach(function (label) {
|
||||||
soaLen += 1 + label.length;
|
soaLen += 1 + label.length;
|
||||||
|
|
||||||
dv.setUint8(total, label.length, false);
|
dv.setUint8(total, label.length, false);
|
||||||
|
@ -65,6 +71,10 @@ exports.DNS_PACKER_TYPE_SOA = function (ab, dv, total, record) {
|
||||||
total += 1;
|
total += 1;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
// must be terminated by null when not using write null
|
||||||
|
dv.setUint8(total, 0, false);
|
||||||
|
total += 1;
|
||||||
|
soaLen += 1;
|
||||||
|
|
||||||
// pack all 32-bit values
|
// pack all 32-bit values
|
||||||
dv.setUint32(total, parseInt(record.sn, 10), false);
|
dv.setUint32(total, parseInt(record.sn, 10), false);
|
||||||
|
@ -79,6 +89,8 @@ exports.DNS_PACKER_TYPE_SOA = function (ab, dv, total, record) {
|
||||||
total+=4;
|
total+=4;
|
||||||
|
|
||||||
// RDLENGTH
|
// RDLENGTH
|
||||||
|
console.log('rdAt', rdLenIndex);
|
||||||
|
console.log('soaLen (lables + 2 + 20)', soaLen);
|
||||||
dv.setUint16(rdLenIndex, soaLen, false);
|
dv.setUint16(rdLenIndex, soaLen, false);
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
|
|
|
@ -18,27 +18,31 @@ exports.DNS_PARSER_TYPE_SOA = function (ab, packet, record) {
|
||||||
var dv = new DataView(rdataAb);
|
var dv = new DataView(rdataAb);
|
||||||
|
|
||||||
// we need this information for this parser
|
// we need this information for this parser
|
||||||
var cpcount = unpackLabels(new Uint8Array(ab), record.rdstart, { byteLength: 0, cpcount: 0, labels: [], name: '' }).cpcount;
|
var labelInfo = unpackLabels(new Uint8Array(ab), record.rdstart, { byteLength: 0, cpcount: 0, labels: [], name: '' });
|
||||||
var offset = unpackLabels(new Uint8Array(ab), record.rdstart, { byteLength: 0, cpcount: 0, labels: [], name: '' }).byteLength;
|
var cpcount = labelInfo.cpcount;
|
||||||
var labels = unpackLabels(new Uint8Array(ab), record.rdstart, { byteLength: 0, cpcount: 0, labels: [], name: '' }).labels;
|
var offset = labelInfo.byteLength;
|
||||||
|
var labels = labelInfo.labels;
|
||||||
|
|
||||||
// Primary NS
|
// Primary NS
|
||||||
record.name_server = unpackLabels(new Uint8Array(ab), record.rdstart, { byteLength: 0, cpcount: 0, labels: [], name: '' }).name;
|
record.name_server = labelInfo.name;
|
||||||
|
|
||||||
|
// TODO delete this commented out code after some testing
|
||||||
|
// (pretty sure it was unnecessary and it seemed to work on code with compression pointers just fine)
|
||||||
|
/*
|
||||||
// if there exists compression pointers in the rdata
|
// if there exists compression pointers in the rdata
|
||||||
if (cpcount > 0){
|
if (cpcount > 0) {
|
||||||
// do something awesome with compression pointers to get the email address
|
// do something awesome with compression pointers to get the email address
|
||||||
// I need the length of all the data before the email address starts.
|
// I need the length of all the data before the email address starts.
|
||||||
// if there are compression pointers then there will be a byte to indicate the length of each label, the label,
|
// if there are compression pointers then there will be a byte to indicate the length of each label, the label,
|
||||||
// then there will be a compression pointer to grab the longest label.
|
// then there will be a compression pointer to grab the longest label.
|
||||||
|
|
||||||
var start = 2; // start or email_addr. take into account compression pointer and address length
|
var start = 2; // start or email_addr. take into account compression pointer and address length
|
||||||
for(var i = 0; i < labels.length; i++){
|
for (var i = 0; i < labels.length; i += 1) {
|
||||||
|
|
||||||
// increase start by the label length. the +1 is to take into account the next label size byte
|
// increase start by the label length. the +1 is to take into account the next label size byte
|
||||||
start = start + labels[i].length + 1;
|
start = start + labels[i].length + 1;
|
||||||
// check for cpcount. 2 counts behind
|
// check for cpcount. 2 counts behind
|
||||||
if(parseInt(dv.getUint8(start - 2), 10) === 192){
|
if (parseInt(dv.getUint8(start - 2), 10) === 192) {
|
||||||
record.email_addr = unpackLabels(new Uint8Array(ab), record.rdstart + start ,{ byteLength: 0, cpcount: 0, labels: [], name: '' }).name;
|
record.email_addr = unpackLabels(new Uint8Array(ab), record.rdstart + start ,{ byteLength: 0, cpcount: 0, labels: [], name: '' }).name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,6 +51,9 @@ exports.DNS_PARSER_TYPE_SOA = function (ab, packet, record) {
|
||||||
|
|
||||||
record.email_addr = unpackLabels(new Uint8Array(ab), record.rdstart + offset, { byteLength: 0, cpcount: 0, labels: [], name: '' }).name;
|
record.email_addr = unpackLabels(new Uint8Array(ab), record.rdstart + offset, { byteLength: 0, cpcount: 0, labels: [], name: '' }).name;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
record.email_addr = unpackLabels(new Uint8Array(ab), record.rdstart + offset, { byteLength: 0, cpcount: 0, labels: [], name: '' }).name;
|
||||||
|
|
||||||
// Serial Number
|
// Serial Number
|
||||||
record.sn = dv.getUint32(dv.byteLength - 20, false);
|
record.sn = dv.getUint32(dv.byteLength - 20, false);
|
||||||
// Refresh Interval
|
// Refresh Interval
|
||||||
|
@ -58,9 +65,7 @@ exports.DNS_PARSER_TYPE_SOA = function (ab, packet, record) {
|
||||||
// Minimum TTL
|
// Minimum TTL
|
||||||
record.nx = dv.getUint32(dv.byteLength - 4, false);
|
record.nx = dv.getUint32(dv.byteLength - 4, false);
|
||||||
|
|
||||||
|
|
||||||
return record;
|
return record;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}('undefined' !== typeof window ? window : exports));
|
}('undefined' !== typeof window ? window : exports));
|
||||||
|
|
Loading…
Reference in New Issue