diff --git a/bin/dig.js b/bin/dig.js index 17baffc..bf99fdf 100755 --- a/bin/dig.js +++ b/bin/dig.js @@ -38,6 +38,16 @@ cli.main(function (args, cli) { return; } + if (arg === '+aaonly' || arg === '+aaflag') { + if (cli.aaonly) { + console.error("'+aaonly' was specified more than once"); + process.exit(1); + return; + } + cli.aaonly = true; + return; + } + if (arg === '+norecurse') { if (cli.norecurse) { console.error("'+norecurse' was specified more than once"); @@ -69,7 +79,7 @@ cli.main(function (args, cli) { } if (cli.query) { - console.error("'query' was specified more than once"); + console.error("'query' was specified more than once or unrecognized flag: " + cli.query + ", " + arg); process.exit(1); return; } @@ -124,11 +134,11 @@ cli.main(function (args, cli) { id: require('crypto').randomBytes(2).readUInt16BE(0) , qr: 0 , opcode: 0 - , aa: 0 // NA - , tc: 0 // NA + , aa: cli.aaonly ? 1 : 0 // NA + , tc: 0 // NA , rd: cli.norecurse ? 0 : 1 - , ra: 0 // NA - , rcode: 0 // NA + , ra: 0 // NA + , rcode: 0 // NA } , question: [ { name: cli.query @@ -140,7 +150,7 @@ cli.main(function (args, cli) { var dnsjs = require('dns-suite'); var queryAb = dnsjs.DNSPacket.write(query); - var hexdump = require('../hexdump'); + var hexdump = require('hexdump.js').hexdump; if (cli.debug) { console.log(''); @@ -254,5 +264,6 @@ cli.main(function (args, cli) { , port: cli.port , timeout: cli.timeout }; + dig.resolve(queryAb, opts); }); diff --git a/bin/digd.js b/bin/digd.js index de3f662..4143653 100644 --- a/bin/digd.js +++ b/bin/digd.js @@ -1,10 +1,10 @@ 'use strict'; var cli = require('cli'); -var dns = require('dns'); +var dig = require('../dns-request'); var dgram = require('dgram'); var dnsjs = require('dns-suite'); -var hexdump = require('../hexdump'); +var hexdump = require('hexdump.js').hexdump; var crypto = require('crypto'); var common = require('../common'); var defaultNameservers = require('dns').getServers(); @@ -78,9 +78,12 @@ cli.main(function (args, cli) { console.error("error:", err.stack); server.close(); }; - handlers.onMessage = function (nb) { + + handlers.onMessage = function (nb, rinfo) { var queryAb = nb.buffer.slice(nb.byteOffset, nb.byteOffset + nb.byteLength); var query = dnsjs.DNSPacket.parse(queryAb); + var newQuery; + var count; if (cli.debug) { console.log(''); @@ -92,6 +95,8 @@ cli.main(function (args, cli) { console.log(''); } + dig.logQuestion(query); + /* console.log(';; Got question:'); console.log(';; ->>HEADER<<-'); console.log(JSON.stringify(query.header)); @@ -100,6 +105,7 @@ cli.main(function (args, cli) { query.question.forEach(function (q) { console.log(';' + q.name + '.', ' ', q.className, q.typeName); }); + */ function print(q) { var printer = common.printers[q.typeName] || common.printers.ANY; @@ -132,19 +138,147 @@ cli.main(function (args, cli) { //common.writeResponse(opts, query, nb, packet); } - if (!cli.norecurse) { - // ANY, A, AAAA, CNAME, MX, NAPTR, NS, PTR, SOA, SRV, TXT - var count = query.question.length; + function sendEmptyResponse(query) { + var newQuery = { + header: { + id: query.header.id // require('crypto').randomBytes(2).readUInt16BE(0) + , qr: 1 + , opcode: 0 + , aa: 0 // TODO maybe + , tc: 0 + , rd: query.header.rd + , ra: cli.norecurse ? 0 : 1 + , rcode: 0 // no error + } + , question: [] + , answer: [] + , authority: [] + , additional: [] + }; query.question.forEach(function (q) { - dns.resolve(q.name, q.typeName, function () { - count -= 1; - if (!count) { - } + newQuery.question.push({ + name: q.name + , type: q.type + , typeName: q.typeName + , class: q.class + , className: q.className }); - console.log(';' + q.name + '.', ' ', q.className, q.typeName); + }); + server.send(dnsjs.DNSPacket.write(newQuery), rinfo.port, rinfo.address, function () { + console.log('[DEV] response sent'); }); } + + count = query.question.length; + if (!count) { + sendEmptyResponse(query); + return; + } + + // TODO get local answer first, if available + + if (query.header.rd) { + if (cli.norecurse) { + console.log("[Could not answer. Sent empty response.]"); + sendEmptyResponse(query); + return; + } else { + // ANY, A, AAAA, CNAME, MX, NAPTR, NS, PTR, SOA, SRV, TXT + newQuery = { + header: { + id: query.header.id // require('crypto').randomBytes(2).readUInt16BE(0) + , qr: 0 + , opcode: 0 + , aa: query.header.aa ? 1 : 0 // NA? not sure what this would do + , tc: 0 // NA + , rd: 1 + , ra: 0 // NA + , rcode: 0 // NA + } + , question: [ + /* + { name: cli.query + , typeName: cli.type + , className: cli.class + } + */ + ] + , answer: [] + , authority: [] + , additional: [] + }; + query.question.forEach(function (q) { + newQuery.question.push({ + name: q.name + , type: q.type + , typeName: q.typeName + , class: q.class + , className: q.className + }); + + function updateCount() { + count -= 1; + if (!count) { + server.send(dnsjs.DNSPacket.write(newQuery), rinfo.port, rinfo.address, function () { + console.log('[DEV] response sent'); + }); + } + } + + var opts = { + onError: function () { + updateCount(); + } + , onMessage: function (packet) { + + (packet.answer||[]).forEach(function (a) { + // TODO copy each relevant property + console.log('ans', a); + newQuery.answer.push(a); + }); + (packet.authority||[]).forEach(function (a) { + // TODO copy each relevant property + console.log('auth', a); + newQuery.authority.push(a); + }); + (packet.additional||[]).forEach(function (a) { + // TODO copy each relevant property + console.log('add', a); + newQuery.additional.push(a); + }); + + updateCount(); + + } + , onListening: function () {} + , onSent: function (res) { + if (cli.debug) { + console.log(''); + console.log('request sent to', res.nameserver); + } + } + , onTimeout: function (res) { + console.log(";; [" + q.name + "] connection timed out; no servers could be reached"); + console.log(";; [timed out after " + res.timeout + "ms and 1 tries]"); + } + , onClose: function () { + console.log(''); + } + , mdns: cli.mdns + , nameserver: cli.nameserver + , port: cli.port + , timeout: cli.timeout + }; + + //dig.resolve(queryAb, opts); + dig.resolveJson(query, opts); + + console.log(';' + q.name + '.', ' ', q.className, q.typeName); + }); + } + } }; + handlers.onListening = function () { /*jshint validthis:true*/ var server = this; diff --git a/hexdump.js b/hexdump.js deleted file mode 100644 index 0d057fc..0000000 --- a/hexdump.js +++ /dev/null @@ -1,27 +0,0 @@ -module.exports = function hexdump(ab) { - var ui8 = new Uint8Array(ab); - var bytecount = 0; - var head = ' 0 1 2 3 4 5 6 7 8 9 A B C D E F'; - var trail; - var str = [].slice.call(ui8).map(function (i) { - var h = i.toString(16); - if (h.length < 2) { - h = '0' + h; - } - return h; - }).join('').match(/.{1,2}/g).join(' ').match(/.{1,48}/g).map(function (str) { - var lead = bytecount.toString(16); - bytecount += 16; - - while (lead.length < 7) { - lead = '0' + lead; - } - - return lead + ' ' + str; - }).join('\n'); - trail = ab.byteLength.toString(16); - while (trail.length < 7) { - trail = '0' + trail; - } - return head + '\n' + str + '\n' + trail; -}; diff --git a/package.json b/package.json index bff9245..f2c2249 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "homepage": "https://git.daplie.com/Daplie/dig.js", "dependencies": { "cli": "^1.0.1", - "dns-suite": "git+https://git@git.daplie.com/Daplie/dns-suite#v1.1.0" + "dns-suite": "git+https://git@git.daplie.com/Daplie/dns-suite#v1.1.0", + "hexdump.js": "^1.0.2" } }