From 88093062a2441ff58adb0f888678d4a134188f65 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 28 Jan 2017 15:15:27 -0700 Subject: [PATCH] It's a Christmas miracle! refactored and got CNAME in one shot - W00T! --- dns.type.cname.js | 13 ++---- dns.unpack-labels.js | 61 ++++++++++++++++++++++++++ pure-parser.js | 100 ++++++++++++++----------------------------- 3 files changed, 96 insertions(+), 78 deletions(-) create mode 100644 dns.unpack-labels.js diff --git a/dns.type.cname.js b/dns.type.cname.js index 96b3d5e..f1d9770 100644 --- a/dns.type.cname.js +++ b/dns.type.cname.js @@ -1,18 +1,13 @@ (function (exports) { 'use strict'; -// TODO. Not yet implemented - -// A CNAME reocord maps a single alias or nickname to the real or +// A CNAME reocord maps a single alias or nickname to the real or // Canonical name which may lie outside the current zone. // Canonical simply means the expected or real name. - - -exports.DNS_TYPE_CNAME = function (rdata) { - - - +var unpackLabels = exports.DNS_UNPACK_LABELS || require('./dns.unpack-labels.js').DNS_UNPACK_LABELS; +exports.DNS_TYPE_CNAME = function (ab, packet, record) { + return unpackLabels(new Uint8Array(ab), record.rdstart, { byteLength: 0, cpcount: 0, labels: [], name: '' }).name; }; }('undefined' !== typeof window ? window : exports)); diff --git a/dns.unpack-labels.js b/dns.unpack-labels.js new file mode 100644 index 0000000..bd43172 --- /dev/null +++ b/dns.unpack-labels.js @@ -0,0 +1,61 @@ +(function (exports) { +'use strict'; + +// unpack labels with 0x20 compression pointer support + +// ui8 is the ArrayBuffer of the entire packet +// ptr is the current index of the packet +// q = { byteLength: 0, cpcount: 0, labels: [], name: '' } +exports.DNS_UNPACK_LABELS = function (ui8, ptr, q) { + if (q.cpcount > 25) { + throw new Error("compression pointer loop detected (over 25 pointers seems like a loop)"); + } + + var total = ptr; + var i; + + var len; + var label = []; + + do { + label.length = 0; + len = ui8[total]; + if (0xc0 === len) { + var cpptr = ui8[total + 1]; + + // we're not coming back! + ptr = cpptr; + q.cpcount += 1; + q.byteLength += 2; // cp and len + return exports.DNS_UNPACK_LABELS(ui8, ptr, q); + } + //str.length = 0; // fast empty array + if (ui8.byteLength - total < len) { + throw new Error( + "Expected a string of length " + len + + " but packet itself has " + (ui8.byteLength - total) + " bytes remaining" + ); + } + for (i = 0; i < len; i += 1) { + total += 1; + // TODO check url-allowable characters + label.push(String.fromCharCode(ui8[total])); + } + if (label.length) { + q.labels.push(label.join('')); + } + total += 1; + //console.log('total', total, ui8[total], String.fromCharCode(ui8[total])); + } while (len); + + //str.pop(); // remove trailing '.' + + q.name = q.labels.join('.'); + if (0 === q.cpcount) { + q.byteLength = total - ptr; + } + + return q; +}; + +}('undefined' !== typeof window ? window : exports)); diff --git a/pure-parser.js b/pure-parser.js index 7472420..2cdff6a 100644 --- a/pure-parser.js +++ b/pure-parser.js @@ -1,3 +1,4 @@ +;(function (exports) { 'use strict'; var pdns = module.exports; @@ -29,70 +30,7 @@ pdns.unpackHeader = function (i) { return header; }; -pdns.unpackQname = function (ui8, ptr, q) { - return pdns._unpackQname(ui8, ptr, q || { - name: '' - , type: 0 - , typeName: '' - , class: 0 - , className: '' - , byteLength: 0 - , labels: [] - , cpcount: 0 - }); -}; - -pdns._unpackQname = function (ui8, ptr, q) { - if (q.cpcount > 25) { - throw new Error("compression pointer loop detected (over 25 pointers seems like a loop)"); - } - - var total = ptr; - var i; - - var len; - var label = []; - - do { - label.length = 0; - len = ui8[total]; - if (0xc0 === len) { - var cpptr = ui8[total + 1]; - - // we're not coming back! - ptr = cpptr; - q.cpcount += 1; - q.byteLength += 2; // cp and len - return pdns.unpackQname(ui8, ptr, q); - } - //str.length = 0; // fast empty array - if (ui8.byteLength - total < len) { - throw new Error( - "Expected a string of length " + len - + " but packet itself has " + (ui8.byteLength - total) + " bytes remaining" - ); - } - for (i = 0; i < len; i += 1) { - total += 1; - // TODO check url-allowable characters - label.push(String.fromCharCode(ui8[total])); - } - if (label.length) { - q.labels.push(label.join('')); - } - total += 1; - //console.log('total', total, ui8[total], String.fromCharCode(ui8[total])); - } while (len); - - //str.pop(); // remove trailing '.' - - q.name = q.labels.join('.'); - if (0 === q.cpcount) { - q.byteLength = total - ptr; - } - - return q; -}; +pdns._unpackLabels = exports.DNS_UNPACK_LABELS || require('./dns.unpack-labels.js').DNS_UNPACK_LABELS; pdns.unpack = function (ab) { if (ab.buffer) { @@ -133,12 +71,21 @@ pdns.unpack = function (ab) { // TODO move to pdns.unpackQuestion to make testable function unpackQuestion(ab, dv, ui8, total) { var ototal = total; - var q = pdns.unpackQname(ui8, total); + var q = pdns._unpackLabels(ui8, total, { + name: '' + , type: 0 + , typeName: '' + , class: 0 + , className: '' + , byteLength: 0 + , labels: [] + , cpcount: 0 + }); //console.log('unpackQuestion QNAME:'); //console.log(q); total += q.byteLength; - + @@ -161,13 +108,26 @@ pdns.unpack = function (ab) { console.log('*********************'); console.log(q.typeName); - + return q; } function unpackAnswer(ab, dv, ui8, total) { var ototal = total; - var q = pdns.unpackQname(ui8, total); + var q = pdns._unpackLabels(ui8, total, { + name: '' + , type: 0 + , typeName: '' + , class: 0 + , className: '' + , byteLength: 0 + , labels: [] + , cpcount: 0 + + , rdstart: 0 + , rdata: 0 + , rdlength: 0 + }); //console.log('unpackAnswer QNAME:'); //console.log(q); total += q.byteLength; @@ -193,9 +153,10 @@ pdns.unpack = function (ab) { q.className = classes[q.class]; q.typeName = types[q.type]; - + // TODO actually parse RDATA + q.rdstart = total; q.rdata = new Uint8Array(ab).slice(total, total + q.rdlength); console.log('q.rdata', q.rdata.byteLength, 'bytes:'); console.log(q.rdata); @@ -250,3 +211,4 @@ pdns.unpack = function (ab) { return header; }; pdns.unpackRdata = require('./dns.rdata.parse.js').DNS_RDATA_PARSE; +}('undefined' !== typeof window ? window : exports));