diff --git a/dns.packer.type.a.js b/dns.packer.type.a.js index 1d2d8a7..a901d5b 100644 --- a/dns.packer.type.a.js +++ b/dns.packer.type.a.js @@ -9,7 +9,8 @@ exports.DNS_PACKER_TYPE_A = function (ab, dv, total, record) { } // RDLENGTH - dv.setUint16(total, 4, false); + var IP_LEN = 4; + dv.setUint16(total, IP_LEN, false); total += 2; // RDATA diff --git a/dns.packer.type.aaaa.js b/dns.packer.type.aaaa.js index 7857453..ed7d27d 100644 --- a/dns.packer.type.aaaa.js +++ b/dns.packer.type.aaaa.js @@ -25,7 +25,8 @@ exports.DNS_PACKER_TYPE_AAAA = function (ab, dv, total, record) { }); // RDLENGTH - dv.setUint16(total, 16, false); + var IP_LEN = 16; + dv.setUint16(total, IP_LEN, false); total += 2; // RDATA diff --git a/dns.packer.type.cname.js b/dns.packer.type.cname.js new file mode 100644 index 0000000..70cd22c --- /dev/null +++ b/dns.packer.type.cname.js @@ -0,0 +1,35 @@ +(function (exports) { +'use strict'; + +// A 'CNAME' record is a 32-bit value representing the IP address + +exports.DNS_PACKER_TYPE_CNAME = function (ab, dv, total, record) { + if (!record.data) { + throw new Error("no data for CNAME record"); + } + + var cnameLen = 0; + var rdLenIndex = total; + total += 2; + + // RDATA + // i.e. 127.0.0.1 => 0x7F, 0x00, 0x00, 0x01 + record.data.split('.').forEach(function (label) { + cnameLen += 1 + label.length; + + dv.setUint8(total, label.length, false); + total += 1; + + label.split('').forEach(function (ch) { + dv.setUint8(total, ch.charCodeAt(0), false); + total += 1; + }); + }); + + // RDLENGTH + dv.setUint16(rdLenIndex, record.data.length + 1, false); + + return total; +}; + +}('undefined' !== typeof window ? window : exports)); diff --git a/test/packer.type.a.js b/test/packer.type.a.js index 4198fea..126c135 100644 --- a/test/packer.type.a.js +++ b/test/packer.type.a.js @@ -1,7 +1,7 @@ 'use strict'; var packer = require('../dns.packer.type.a.js').DNS_PACKER_TYPE_A; -var ab = new ArrayBuffer(4); +var ab = new ArrayBuffer(6); // 16-bit RDLENGTH + 32-bit address var dv = new DataView(ab); var total; @@ -16,11 +16,12 @@ dv.setUint32(0x0, 0xDDDDDDDD, false); ].forEach(function (ipv4) { total = 0; total = packer(ab, dv, total, { address: ipv4 }); - if (0x04 !== total) { + if (0x06 !== total) { console.error('unexpected total ' + total); process.exit(1); } - if (ipv4 !== new Uint8Array(ab).join('.')) { + // 0.4 is just a hacky way to account for the RDLENGTH + if ('0.4.' + ipv4 !== new Uint8Array(ab).join('.')) { console.error("expected: ", ipv4); console.error("actual: ", new Uint8Array(ab).join('.')); process.exit(1); diff --git a/test/packer.type.aaaa.js b/test/packer.type.aaaa.js index 75404fd..bbaedd0 100644 --- a/test/packer.type.aaaa.js +++ b/test/packer.type.aaaa.js @@ -1,7 +1,7 @@ 'use strict'; var packer = require('../dns.packer.type.aaaa.js').DNS_PACKER_TYPE_AAAA; -var ab = new ArrayBuffer(20); +var ab = new ArrayBuffer(22); var dv = new DataView(ab); var total = 0; @@ -16,18 +16,19 @@ dv.setUint16(0xC, 0xDDDD, false); dv.setUint16(0xE, 0xDDDD, false); dv.setUint16(0x10, 0xDDDD, false); dv.setUint16(0x12, 0xDDDD, false); +dv.setUint16(0x14, 0xDDDD, false); [ [ '::1' - , [ 0xDD, 0xDD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0xDD, 0xDD ].join(' ') ] + , [ 0xDD, 0xDD, 0x00, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0xDD, 0xDD ].join(' ') ] , [ 'fe80::1' - , [ 0xDD, 0xDD, 0xFE, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0xDD, 0xDD ].join(' ') ] + , [ 0xDD, 0xDD, 0x00, 0x10, 0xFE, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0xDD, 0xDD ].join(' ') ] , [ 'fd41:50ca:2169:f4e:5020:f756:ca4e:c3b5' - , [ 0xDD, 0xDD, 0xFD, 0x41, 0x50, 0xCA, 0x21, 0x69, 0x0F, 0x4E + , [ 0xDD, 0xDD, 0x00, 0x10, 0xFD, 0x41, 0x50, 0xCA, 0x21, 0x69, 0x0F, 0x4E , 0x50, 0x20, 0xF7, 0x56, 0xCA, 0x4E, 0xC3, 0xB5, 0xDD, 0xDD ].join(' ') ] ].forEach(function (ipv6) { - total = 2; // leave leading 0x00 + total = 2; // leave leading 0xDD total = packer(ab, dv, total, { address: ipv6[0] }); - if (0x12 !== total) { + if (0x14 !== total) { console.error('unexpected total ' + total); process.exit(1); } diff --git a/test/packer.type.cname.js b/test/packer.type.cname.js new file mode 100644 index 0000000..d18d8ee --- /dev/null +++ b/test/packer.type.cname.js @@ -0,0 +1,21 @@ +'use strict'; + +var packer = require('../dns.packer.type.cname.js').DNS_PACKER_TYPE_CNAME; +var ab = new ArrayBuffer(255); // max len per label is 63, max label sequence is 254 + null terminator +var dv = new DataView(ab); +var total = 0; + +[ [ 'www.example.com' + , [ 0x00, 0x10, 0x03, 119, 119, 119, 0x07, 101, 120, 97, 109, 112, 108, 101, 0x03, 99, 111, 109 ].join(' ') ] +].forEach(function (cname) { + total = packer(ab, dv, total, { data: cname[0] }); + ab = ab.slice(0, total); + // TODO: Check that total increments appropriately + if (cname[1] !== new Uint8Array(ab).join(' ')) { + console.error("expected: ", cname[1]); + console.error("actual: ", new Uint8Array(ab).join(' ')); + process.exit(1); + } +}); + +console.log('PASS');