diff --git a/lib/dns.js b/lib/dns.js index f9b0da2288..66bb6ca23b 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -199,15 +199,19 @@ exports.reverse = function(domain, callback) { exports.resolveNs = function(domain, callback) { channel.query(domain, dns.NS, callback); }; +exports.resolveCname = function(domain, callback) { + channel.query(domain, dns.CNAME, callback); +}; var resolveMap = { - 'A' : exports.resolve4, - 'AAAA': exports.resolve6, - 'MX' : exports.resolveMx, - 'TXT' : exports.resolveTxt, - 'SRV' : exports.resolveSrv, - 'PTR' : exports.resolvePtr, - 'NS' : exports.resolveNs + 'A' : exports.resolve4, + 'AAAA' : exports.resolve6, + 'MX' : exports.resolveMx, + 'TXT' : exports.resolveTxt, + 'SRV' : exports.resolveSrv, + 'PTR' : exports.resolvePtr, + 'NS' : exports.resolveNs, + 'CNAME' : exports.resolveCname }; // ERROR CODES diff --git a/src/node_cares.cc b/src/node_cares.cc index ea227a8840..4f5383ebb2 100644 --- a/src/node_cares.cc +++ b/src/node_cares.cc @@ -98,6 +98,7 @@ void Cares::Initialize(Handle target) { target->Set(String::NewSymbol("PTR"), Integer::New(ns_t_ptr)); target->Set(String::NewSymbol("TXT"), Integer::New(ns_t_txt)); target->Set(String::NewSymbol("SRV"), Integer::New(ns_t_srv)); + target->Set(String::NewSymbol("CNAME"), Integer::New(ns_t_cname)); target->Set(String::NewSymbol("NODATA"), Integer::New(ARES_ENODATA)); target->Set(String::NewSymbol("FORMERR"), Integer::New(ARES_EFORMERR)); @@ -312,6 +313,29 @@ static void ParseAnswerAAAA(QueryArg *arg, unsigned char* abuf, int alen) { cb_call(arg->js_cb, 2, argv); } + +static void ParseAnswerCNAME(QueryArg *arg, unsigned char* abuf, int alen) { + HandleScope scope; + + hostent* host; + + int status = ares_parse_a_reply(abuf, alen, &host, NULL, NULL); + if (status != ARES_SUCCESS) { + ResolveError(arg->js_cb, status); + return; + } + + // a CNAME lookup always returns a single record but + // it's probably best to follow the common API here + Local addresses = Array::New(1); + addresses->Set(0, String::New(host->h_name)); + ares_free_hostent(host); + + Local argv[2] = { Local::New(Null()), addresses }; + cb_call(arg->js_cb, 2, argv); +} + + static void ParseAnswerMX(QueryArg *arg, unsigned char* abuf, int alen) { HandleScope scope; @@ -543,6 +567,10 @@ Handle Channel::Query(const Arguments& args) { parse_cb = ParseAnswerSRV; break; + case ns_t_cname: + parse_cb = ParseAnswerCNAME; + break; + case ns_t_ptr: int length, family; diff --git a/test/disabled/test-dns.js b/test/disabled/test-dns.js index c5c2795781..1599a17dba 100644 --- a/test/disabled/test-dns.js +++ b/test/disabled/test-dns.js @@ -38,6 +38,16 @@ while (i--) { } } +// CNAME should resolve +dns.resolve('labs.nrcmedia.nl', 'CNAME', function(err, result) { + assert.deepEqual(result, ['nrcmedia.nl']); +}); + +// CNAME should not resolve +dns.resolve('nrcmedia.nl', 'CNAME', function(err, result) { + assert.ok(err.errno, dns.NODATA); +}); + function checkDnsRecord(host, record) { var myHost = host, myRecord = record;