WIP dns server, mov hexdump.js to own repo, add aaonly flag
This commit is contained in:
		
							parent
							
								
									cdd490ec42
								
							
						
					
					
						commit
						6d0f9b1588
					
				
							
								
								
									
										23
									
								
								bin/dig.js
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								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);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										156
									
								
								bin/digd.js
									
									
									
									
									
								
							
							
						
						
									
										156
									
								
								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;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										27
									
								
								hexdump.js
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								hexdump.js
									
									
									
									
									
								
							@ -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;
 | 
			
		||||
};
 | 
			
		||||
@ -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"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user