diff --git a/bin/dns-test.js b/bin/dns-test.js index 4169245..6a7ac09 100755 --- a/bin/dns-test.js +++ b/bin/dns-test.js @@ -35,7 +35,7 @@ var hexdump = require('hexdump.js').hexdump; function testJsonAsync(nb) { var packet = dnsjs.write(JSON.parse(nb.toString('ascii'))); var str = hexdump(packet); - console.log(str); + console.info(str); var json = dnsjs.parse(packet); if (json.error) { console.error(json); @@ -43,7 +43,7 @@ function testJsonAsync(nb) { return; } - console.log("[OK] JSON -> binary -> JSON"); + console.info("[OK] JSON -> binary -> JSON"); if (!outname) { console.warn(''); @@ -54,7 +54,7 @@ function testJsonAsync(nb) { return; } - fs.writeFileSync(path.basename(filename).replace(path.extname(filename), '.bin'), packet, null); + fs.writeFileSync(outname, packet, null); } function testBinAsync(nb) { @@ -66,6 +66,8 @@ function testBinAsync(nb) { return; } 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); if (json2.error) { console.error(json2); @@ -86,12 +88,22 @@ function testBinAsync(nb) { .replace(/,"cpcount":\d+/, '') ); //json2 = JSON.parse(JSON.stringify(json2)); - //console.log(json); - //console.log(json2); - assert.deepEqual(json, json2); + try { + 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.log("(compression pointer support needs to be improved in order to support direct bin -> JSON -> bin testing)"); + console.info("[OK] binary -> JSON -> binary -> JSON"); + console.warn("(compression pointer support needs to be improved in order to support direct bin -> JSON -> bin testing)"); if (!outname) { console.warn(''); @@ -102,7 +114,7 @@ function testBinAsync(nb) { 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) { diff --git a/dns.unpack-labels.js b/dns.unpack-labels.js index 0956fc0..9a82d43 100644 --- a/dns.unpack-labels.js +++ b/dns.unpack-labels.js @@ -46,6 +46,10 @@ exports.DNS_UNPACK_LABELS = function (ui8, ptr, q) { //str.length = 0; // fast empty array 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( "Expected a string of length " + len + " but packet itself has " + (ui8.byteLength - total) + " bytes remaining" diff --git a/packer/type.soa.js b/packer/type.soa.js index d79a9f5..b33441a 100644 --- a/packer/type.soa.js +++ b/packer/type.soa.js @@ -1,6 +1,8 @@ (function (exports) { 'use strict'; +// http://www.zytrax.com/books/dns/ch8/soa.html + // Value Meaning/Use // 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 @@ -10,8 +12,6 @@ // Expiration Limit Unsigned 32-bit integer // Minimum TTL Unsigned 32-bit integer - - exports.DNS_PACKER_TYPE_SOA = function (ab, dv, total, record) { if(!record.name_server){ 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"); } if(!record.ref){ - throw new Error("no serial number for SOA record"); + throw new Error("no refresh for SOA record"); } if(!record.ret){ - throw new Error("no serial number for SOA record"); + throw new Error("no update retry for SOA record"); } if(!record.ex){ - throw new Error("no serial number for SOA record"); + throw new Error("no expiry for SOA record"); } 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 @@ -40,9 +40,10 @@ exports.DNS_PACKER_TYPE_SOA = function (ab, dv, total, record) { var rdLenIndex = total; 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 - record.name_server.split('.').forEach(function(label){ - soaLen += 1 + label.length; + record.name_server.split('.').forEach(function (label) { + soaLen += (1 + label.length); dv.setUint8(total, label.length, false); total += 1; @@ -52,9 +53,14 @@ exports.DNS_PACKER_TYPE_SOA = function (ab, dv, total, record) { 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 - record.email_addr.split('.').forEach(function (label){ + record.email_addr.split('.').forEach(function (label) { soaLen += 1 + label.length; dv.setUint8(total, label.length, false); @@ -65,6 +71,10 @@ exports.DNS_PACKER_TYPE_SOA = function (ab, dv, total, record) { 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 dv.setUint32(total, parseInt(record.sn, 10), false); @@ -79,6 +89,8 @@ exports.DNS_PACKER_TYPE_SOA = function (ab, dv, total, record) { total+=4; // RDLENGTH + console.log('rdAt', rdLenIndex); + console.log('soaLen (lables + 2 + 20)', soaLen); dv.setUint16(rdLenIndex, soaLen, false); return total; diff --git a/parser/type.soa.js b/parser/type.soa.js index 2ca64ff..eda05b8 100644 --- a/parser/type.soa.js +++ b/parser/type.soa.js @@ -18,27 +18,31 @@ exports.DNS_PARSER_TYPE_SOA = function (ab, packet, record) { var dv = new DataView(rdataAb); // we need this information for this parser - var cpcount = unpackLabels(new Uint8Array(ab), record.rdstart, { byteLength: 0, cpcount: 0, labels: [], name: '' }).cpcount; - var offset = unpackLabels(new Uint8Array(ab), record.rdstart, { byteLength: 0, cpcount: 0, labels: [], name: '' }).byteLength; - var labels = unpackLabels(new Uint8Array(ab), record.rdstart, { byteLength: 0, cpcount: 0, labels: [], name: '' }).labels; + var labelInfo = unpackLabels(new Uint8Array(ab), record.rdstart, { byteLength: 0, cpcount: 0, labels: [], name: '' }); + var cpcount = labelInfo.cpcount; + var offset = labelInfo.byteLength; + var labels = labelInfo.labels; // 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 (cpcount > 0){ + if (cpcount > 0) { // do something awesome with compression pointers to get the email address // 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, // 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 - 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 start = start + labels[i].length + 1; // 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; } } @@ -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; + // Serial Number record.sn = dv.getUint32(dv.byteLength - 20, false); // Refresh Interval @@ -58,9 +65,7 @@ exports.DNS_PARSER_TYPE_SOA = function (ab, packet, record) { // Minimum TTL record.nx = dv.getUint32(dv.byteLength - 4, false); - return record; - }; }('undefined' !== typeof window ? window : exports));