2017-03-31 06:08:15 +00:00
'use strict' ;
var cli = require ( 'cli' ) ;
2017-09-20 18:29:43 +00:00
var dns = require ( 'dns' ) ;
2017-09-16 00:43:02 +00:00
var dgram = require ( 'dgram' ) ;
var dnsjs = require ( 'dns-suite' ) ;
2017-03-31 06:08:15 +00:00
var hexdump = require ( '../hexdump' ) ;
var crypto = require ( 'crypto' ) ;
2017-09-16 00:43:02 +00:00
var common = require ( '../common' ) ;
2017-09-20 18:29:43 +00:00
var defaultNameservers = require ( 'dns' ) . getServers ( ) ;
2017-09-16 00:43:02 +00:00
2017-03-31 06:08:15 +00:00
cli . parse ( {
// 'b': [ false, 'set source IP address (defaults to 0.0.0.0)', 'string' ]
2017-09-16 00:43:02 +00:00
'class' : [ 'c' , 'class (defaults to IN)' , 'string' , 'IN' ]
, 'debug' : [ false , 'more verbose output' , 'boolean' , false ]
2017-03-31 06:08:15 +00:00
//, 'insecure': [ false, 'turn off RaNDOm cAPS required for securing queries']
//, 'ipv4': [ '4', 'use ipv4 exclusively (defaults to false)', 'boolean', false ]
//, 'ipv6': [ '6', 'use ipv6 exclusively (defaults to false)', 'boolean', false ]
//, 'json': [ false, 'output results as json', 'string' ]
//, 'lint': [ false, 'attack (in the metaphorical sense) a nameserver with all sorts of queries to test for correct responses', 'string', false ]
, 'mdns' : [ false , "Alias for setting defaults to -p 5353 @224.0.0.251 -t PTR -q _services._dns-sd._udp.local and waiting for multiple responses" , 'boolean' , false ]
2017-09-16 00:43:02 +00:00
, 'timeout' : [ false , "How long, in milliseconds, to wait for a response. Alias of +time=" , 'int' , false ]
2017-03-31 06:08:15 +00:00
, 'output' : [ 'o' , 'output prefix to use for writing query and response(s) to disk' , 'file' ]
2017-09-16 00:43:02 +00:00
, 'address' : [ false , 'ip address(es) to listen on (defaults to 0.0.0.0,::0)' , 'string' ]
2017-03-31 06:08:15 +00:00
, 'port' : [ 'p' , 'port (defaults to 53 for dns and 5353 for mdns)' , 'int' ]
2017-09-20 18:29:43 +00:00
, 'nameserver' : [ false , 'the nameserver(s) to use for recursive lookups (defaults to ' + defaultNameservers . join ( ',' ) + ')' , 'string' ]
2017-03-31 06:08:15 +00:00
//, 'serve': [ 's', 'path to json file with array of responses to issue for given queries', 'string' ]
, 'type' : [ 't' , 'type (defaults to ANY for dns and PTR for mdns)' , 'string' ]
, 'query' : [ 'q' , 'a superfluous explicit option to set the query as a command line flag' ]
} ) ;
2017-09-16 00:43:02 +00:00
cli . main ( function ( args , cli ) {
args . forEach ( function ( arg ) {
if ( arg === '+norecurse' ) {
if ( cli . norecurse ) {
console . error ( "'+norecurse' was specified more than once" ) ;
process . exit ( 1 ) ;
return ;
}
cli . norecurse = true ;
return ;
}
2017-03-31 06:08:15 +00:00
} ) ;
2017-09-16 00:43:02 +00:00
if ( cli . mdns ) {
if ( ! cli . type ) {
cli . type = cli . t = 'PTR' ;
}
if ( ! cli . port ) {
cli . port = cli . p = 5353 ;
}
if ( ! cli . nameserver ) {
cli . nameserver = '224.0.0.251' ;
}
if ( ! cli . query ) {
cli . query = '_services._dns-sd._udp.local' ;
}
if ( ! ( 'timeout' in cli ) ) {
cli . timeout = 3000 ;
}
} else {
if ( ! cli . port ) {
cli . port = cli . p = 53 ;
}
2017-03-31 06:08:15 +00:00
}
var handlers = { } ;
var server = dgram . createSocket ( {
2017-09-16 00:43:02 +00:00
type : cli . udp6 ? 'udp6' : 'udp4'
//, reuseAddr: true
} ) ;
server . bind ( {
port : cli . port
, address : cli . address
2017-03-31 06:08:15 +00:00
} ) ;
handlers . onError = function ( err ) {
console . error ( "error:" , err . stack ) ;
server . close ( ) ;
} ;
handlers . onMessage = function ( nb ) {
2017-09-16 00:43:02 +00:00
var queryAb = nb . buffer . slice ( nb . byteOffset , nb . byteOffset + nb . byteLength ) ;
var query = dnsjs . DNSPacket . parse ( queryAb ) ;
2017-03-31 06:08:15 +00:00
2017-09-16 00:43:02 +00:00
if ( cli . debug ) {
console . log ( '' ) ;
console . log ( 'DNS Question:' ) ;
console . log ( '' ) ;
console . log ( query ) ;
console . log ( '' ) ;
console . log ( hexdump ( queryAb ) ) ;
2017-03-31 06:08:15 +00:00
console . log ( '' ) ;
}
2017-09-16 00:43:02 +00:00
console . log ( ';; Got question:' ) ;
2017-03-31 06:08:15 +00:00
console . log ( ';; ->>HEADER<<-' ) ;
2017-09-16 00:43:02 +00:00
console . log ( JSON . stringify ( query . header ) ) ;
2017-03-31 06:08:15 +00:00
console . log ( '' ) ;
console . log ( ';; QUESTION SECTION:' ) ;
2017-09-16 00:43:02 +00:00
query . question . forEach ( function ( q ) {
2017-03-31 06:08:15 +00:00
console . log ( ';' + q . name + '.' , ' ' , q . className , q . typeName ) ;
} ) ;
2017-09-16 00:43:02 +00:00
2017-03-31 06:08:15 +00:00
function print ( q ) {
2017-09-16 00:43:02 +00:00
var printer = common . printers [ q . typeName ] || common . printers . ANY ;
2017-03-31 06:08:15 +00:00
printer ( q ) ;
}
2017-09-16 00:43:02 +00:00
if ( query . answer . length ) {
console . error ( '[ERROR] Query contains an answer section:' ) ;
2017-03-31 06:08:15 +00:00
console . log ( ';; ANSWER SECTION:' ) ;
2017-09-16 00:43:02 +00:00
query . answer . forEach ( print ) ;
2017-03-31 06:08:15 +00:00
}
2017-09-16 00:43:02 +00:00
if ( query . authority . length ) {
2017-03-31 06:08:15 +00:00
console . log ( '' ) ;
2017-09-16 00:43:02 +00:00
console . error ( '[ERROR] Query contains an authority section:' ) ;
2017-03-31 06:08:15 +00:00
console . log ( ';; AUTHORITY SECTION:' ) ;
2017-09-16 00:43:02 +00:00
query . authority . forEach ( print ) ;
2017-03-31 06:08:15 +00:00
}
2017-09-16 00:43:02 +00:00
if ( query . additional . length ) {
2017-03-31 06:08:15 +00:00
console . log ( '' ) ;
2017-09-16 00:43:02 +00:00
console . error ( '[ERROR] Query contains an additional section:' ) ;
2017-03-31 06:08:15 +00:00
console . log ( ';; ADDITIONAL SECTION:' ) ;
2017-09-16 00:43:02 +00:00
query . additional . forEach ( print ) ;
2017-03-31 06:08:15 +00:00
}
console . log ( '' ) ;
console . log ( ';; MSG SIZE rcvd: ' + nb . byteLength ) ;
console . log ( '' ) ;
2017-09-16 00:43:02 +00:00
if ( cli . output ) {
2017-03-31 06:08:15 +00:00
console . log ( '' ) ;
2017-09-16 00:43:02 +00:00
common . writeQuery ( cli , query , queryAb ) ;
//common.writeResponse(opts, query, nb, packet);
2017-03-31 06:08:15 +00:00
}
2017-09-20 18:29:43 +00:00
if ( ! cli . norecurse ) {
// ANY, A, AAAA, CNAME, MX, NAPTR, NS, PTR, SOA, SRV, TXT
var count = query . question . length ;
query . question . forEach ( function ( q ) {
dns . resolve ( q . name , q . typeName , function ( ) {
count -= 1 ;
if ( ! count ) {
}
} ) ;
console . log ( ';' + q . name + '.' , ' ' , q . className , q . typeName ) ;
} ) ;
}
2017-03-31 06:08:15 +00:00
} ;
handlers . onListening = function ( ) {
/*jshint validthis:true*/
var server = this ;
2017-09-16 00:43:02 +00:00
var nameserver = cli . nameserver ;
2017-03-31 06:08:15 +00:00
var index ;
if ( ! nameserver ) {
2017-09-20 18:29:43 +00:00
index = crypto . randomBytes ( 2 ) . readUInt16BE ( 0 ) % defaultNameservers . length ;
nameserver = defaultNameservers [ index ] ;
2017-09-16 00:43:02 +00:00
if ( cli . debug ) {
2017-09-20 18:29:43 +00:00
console . log ( index , defaultNameservers ) ;
2017-03-31 06:08:15 +00:00
}
}
2017-09-16 00:43:02 +00:00
if ( cli . mdns || '224.0.0.251' === cli . nameserver ) {
2017-03-31 06:08:15 +00:00
server . setBroadcast ( true ) ;
2017-09-16 00:43:02 +00:00
server . addMembership ( cli . nameserver ) ;
2017-03-31 06:08:15 +00:00
}
2017-09-16 00:43:02 +00:00
console . log ( '' ) ;
console . log ( 'Bound and Listening:' ) ;
console . log ( server . address ( ) . address + '#' + server . address ( ) . port ) ;
2017-03-31 06:08:15 +00:00
} ;
2017-09-16 00:43:02 +00:00
console . log ( '' ) ;
if ( ! cli . nocmd ) {
console . log ( '; <<>> dig.js ' + 'v0.0.0' + ' <<>> ' + process . argv . slice ( 2 ) ) ;
console . log ( ';; global options: +cmd' ) ;
}
2017-03-31 06:08:15 +00:00
server . on ( 'error' , handlers . onError ) ;
server . on ( 'message' , handlers . onMessage ) ;
server . on ( 'listening' , handlers . onListening ) ;
} ) ;