From bddea032b7f2b0f2854faa18855249286bd99428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tu=C4=9Frul=20Topuz?= Date: Mon, 21 Oct 2013 16:47:57 +0300 Subject: [PATCH] dns: add resolveSoa and 'SOA' rrtype You can now query for SOA records by either passing 'SOA' to `resolve` or by using the new `resolveSoa` --- doc/api/dns.markdown | 36 +++++++++++++++++++++++--- lib/dns.js | 1 + src/cares_wrap.cc | 54 +++++++++++++++++++++++++++++++++++++++ test/internet/test-dns.js | 34 ++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 4 deletions(-) diff --git a/doc/api/dns.markdown b/doc/api/dns.markdown index 60dbfe2062..b9b1502a23 100644 --- a/doc/api/dns.markdown +++ b/doc/api/dns.markdown @@ -52,10 +52,19 @@ such as no available file descriptors. ## dns.resolve(hostname, [rrtype], callback) Resolves a hostname (e.g. `'google.com'`) into an array of the record types -specified by rrtype. Valid rrtypes are `'A'` (IPV4 addresses, default), -`'AAAA'` (IPV6 addresses), `'MX'` (mail exchange records), `'TXT'` (text -records), `'SRV'` (SRV records), `'PTR'` (used for reverse IP lookups), -`'NS'` (name server records) and `'CNAME'` (canonical name records). +specified by rrtype. + +Valid rrtypes are: + + * `'A'` (IPV4 addresses, default) + * `'AAAA'` (IPV6 addresses) + * `'MX'` (mail exchange records) + * `'TXT'` (text records) + * `'SRV'` (SRV records) + * `'PTR'` (used for reverse IP lookups) + * `'NS'` (name server records) + * `'CNAME'` (canonical name records) + * `'SOA'` (start of authority record) The callback has arguments `(err, addresses)`. The type of each item in `addresses` is determined by the record type, and described in the @@ -96,6 +105,25 @@ The same as `dns.resolve()`, but only for service records (`SRV` records). of SRV records are priority, weight, port, and name (e.g., `[{'priority': 10, {'weight': 5, 'port': 21223, 'name': 'service.example.com'}, ...]`). +## dns.resolveSoa(hostname, callback) + +The same as `dns.resolve()`, but only for start of authority record queries +(`SOA` record). + +`addresses` is an object with the following structure: + +``` +{ + nsname: 'ns.example.com', + hostmaster: 'root.example.com', + serial: 2013101809, + refresh: 10000, + retry: 2400, + expire: 604800, + minttl: 3600 +} +``` + ## dns.resolveNs(hostname, callback) The same as `dns.resolve()`, but only for name server records (`NS` records). diff --git a/lib/dns.js b/lib/dns.js index 34545e835a..cbba372584 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -176,6 +176,7 @@ exports.resolveNs = resolveMap.NS = resolver('queryNs'); exports.resolveTxt = resolveMap.TXT = resolver('queryTxt'); exports.resolveSrv = resolveMap.SRV = resolver('querySrv'); exports.resolveNaptr = resolveMap.NAPTR = resolver('queryNaptr'); +exports.resolveSoa = resolveMap.SOA = resolver('querySoa'); exports.reverse = resolveMap.PTR = resolver('getHostByAddr'); diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index d7669c2770..ade6f1382a 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -717,6 +717,59 @@ class QueryNaptrWrap: public QueryWrap { }; +class QuerySoaWrap: public QueryWrap { + public: + QuerySoaWrap(Environment* env, Local req_wrap_obj) + : QueryWrap(env, req_wrap_obj) { + } + + int Send(const char* name) { + ares_query(env()->cares_channel(), + name, + ns_c_in, + ns_t_soa, + Callback, + GetQueryArg()); + return 0; + } + + protected: + void Parse(unsigned char* buf, int len) { + HandleScope handle_scope(env()->isolate()); + Context::Scope context_scope(env()->context()); + + ares_soa_reply* soa_out; + int status = ares_parse_soa_reply(buf, len, &soa_out); + + if (status != ARES_SUCCESS) { + ParseError(status); + return; + } + + Local soa_record = Object::New(); + + soa_record->Set(FIXED_ONE_BYTE_STRING(node_isolate, "nsname"), + OneByteString(node_isolate, soa_out->nsname)); + soa_record->Set(FIXED_ONE_BYTE_STRING(node_isolate, "hostmaster"), + OneByteString(node_isolate, soa_out->hostmaster)); + soa_record->Set(FIXED_ONE_BYTE_STRING(node_isolate, "serial"), + Integer::New(soa_out->serial, node_isolate)); + soa_record->Set(FIXED_ONE_BYTE_STRING(node_isolate, "refresh"), + Integer::New(soa_out->refresh, node_isolate)); + soa_record->Set(FIXED_ONE_BYTE_STRING(node_isolate, "retry"), + Integer::New(soa_out->retry, node_isolate)); + soa_record->Set(FIXED_ONE_BYTE_STRING(node_isolate, "expire"), + Integer::New(soa_out->expire, node_isolate)); + soa_record->Set(FIXED_ONE_BYTE_STRING(node_isolate, "minttl"), + Integer::New(soa_out->minttl, node_isolate)); + + ares_free_data(soa_out); + + this->CallOnComplete(soa_record); + } +}; + + class GetHostByAddrWrap: public QueryWrap { public: explicit GetHostByAddrWrap(Environment* env, Local req_wrap_obj) @@ -1103,6 +1156,7 @@ static void Initialize(Handle target, NODE_SET_METHOD(target, "queryTxt", Query); NODE_SET_METHOD(target, "querySrv", Query); NODE_SET_METHOD(target, "queryNaptr", Query); + NODE_SET_METHOD(target, "querySoa", Query); NODE_SET_METHOD(target, "getHostByAddr", Query); NODE_SET_METHOD(target, "getaddrinfo", GetAddrInfo); diff --git a/test/internet/test-dns.js b/test/internet/test-dns.js index cc69106c52..bb55aeca60 100644 --- a/test/internet/test-dns.js +++ b/test/internet/test-dns.js @@ -244,6 +244,40 @@ TEST(function test_resolveNaptr(done) { checkWrap(req); }); +TEST(function test_resolveSoa(done) { + var req = dns.resolveSoa('nodejs.org', function(err, result) { + if (err) throw err; + + assert.ok(result); + assert.ok(typeof result === 'object'); + + assert.ok(typeof result.nsname === 'string'); + assert.ok(result.nsname.length > 0); + + assert.ok(typeof result.hostmaster === 'string'); + assert.ok(result.hostmaster.length > 0); + + assert.ok(typeof result.serial === 'number'); + assert.ok((result.serial > 0) && (result.serial < 4294967295)); + + assert.ok(typeof result.refresh === 'number'); + assert.ok((result.refresh > 0) && (result.refresh < 2147483647)); + + assert.ok(typeof result.retry === 'number'); + assert.ok((result.retry > 0) && (result.retry < 2147483647)); + + assert.ok(typeof result.expire === 'number'); + assert.ok((result.expire > 0) && (result.expire < 2147483647)); + + assert.ok(typeof result.minttl === 'number'); + assert.ok((result.minttl >= 0) && (result.minttl < 2147483647)); + + done(); + }); + + checkWrap(req); +}); + TEST(function test_resolveCname(done) { var req = dns.resolveCname('www.microsoft.com', function(err, names) { if (err) throw err;