Support CNAME lookups in DNS module.
authorBen Noordhuis <info@bnoordhuis.nl>
Tue, 16 Nov 2010 20:50:24 +0000 (21:50 +0100)
committerRyan Dahl <ry@tinyclouds.org>
Mon, 22 Nov 2010 04:53:57 +0000 (20:53 -0800)
lib/dns.js
src/node_cares.cc
test/disabled/test-dns.js

index f9b0da228846acd34ae96ecf61b732d2a1f420be..66bb6ca23bd2253f0fde9c2bbae74695eb58b730 100644 (file)
@@ -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
index ea227a88407ff4adfb282823204a9d82cff3623d..4f5383ebb2f53c5f477b5f8e171f799022e9a212 100644 (file)
@@ -98,6 +98,7 @@ void Cares::Initialize(Handle<Object> 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<Array> addresses = Array::New(1);
+  addresses->Set(0, String::New(host->h_name));
+  ares_free_hostent(host);
+
+  Local<Value> argv[2] = { Local<Value>::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<Value> Channel::Query(const Arguments& args) {
       parse_cb = ParseAnswerSRV;
       break;
 
+    case ns_t_cname:
+      parse_cb = ParseAnswerCNAME;
+      break;
+
     case ns_t_ptr:
 
       int length, family;
index c5c2795781ea666de58f79e998aadbfcfe82f287..1599a17dbabd6d26bf92554c1de0c8753a3595c6 100644 (file)
@@ -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;