Skip to content

Commit dbdbdd4

Browse files
dturingsilverwind
authored andcommitted
dns: add resolvePtr to query plain DNS PTR records
Resolving plain PTR records is used beyond reverse DNS, most prominently with DNS-SD (RFC6763). This adds dns.resolvePtr(), and uses it (instead of dns.reverse()) in dns.resolve(). PR-URL: #4921 Reviewed-By: Roman Reiss <[email protected]> Reviewed-By: Brian White <[email protected]>
1 parent c4ab861 commit dbdbdd4

File tree

6 files changed

+86
-3
lines changed

6 files changed

+86
-3
lines changed

doc/api/dns.markdown

+7-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ Valid values for `rrtype` are:
155155
* `'MX'` - mail exchange records
156156
* `'TXT'` - text records
157157
* `'SRV'` - SRV records
158-
* `'PTR'` - used for reverse IP lookups
158+
* `'PTR'` - PTR records
159159
* `'NS'` - name server records
160160
* `'CNAME'` - canonical name records
161161
* `'SOA'` - start of authority record
@@ -248,6 +248,12 @@ be an array of objects with the following properties:
248248
}
249249
```
250250

251+
## dns.resolvePtr(hostname, callback)
252+
253+
Uses the DNS protocol to resolve pointer records (`PTR` records) for the
254+
`hostname`. The `addresses` argument passed to the `callback` function will
255+
be an array of strings containing the reply records.
256+
251257
## dns.resolveTxt(hostname, callback)
252258

253259
Uses the DNS protocol to resolve text queries (`TXT` records) for the

lib/dns.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,10 @@ exports.resolveMx = resolveMap.MX = resolver('queryMx');
251251
exports.resolveNs = resolveMap.NS = resolver('queryNs');
252252
exports.resolveTxt = resolveMap.TXT = resolver('queryTxt');
253253
exports.resolveSrv = resolveMap.SRV = resolver('querySrv');
254+
exports.resolvePtr = resolveMap.PTR = resolver('queryPtr');
254255
exports.resolveNaptr = resolveMap.NAPTR = resolver('queryNaptr');
255256
exports.resolveSoa = resolveMap.SOA = resolver('querySoa');
256-
exports.reverse = resolveMap.PTR = resolver('getHostByAddr');
257+
exports.reverse = resolver('getHostByAddr');
257258

258259

259260
exports.resolve = function(hostname, type_, callback_) {

src/cares_wrap.cc

+44
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,49 @@ class QuerySrvWrap: public QueryWrap {
698698
}
699699
};
700700

701+
class QueryPtrWrap: public QueryWrap {
702+
public:
703+
explicit QueryPtrWrap(Environment* env, Local<Object> req_wrap_obj)
704+
: QueryWrap(env, req_wrap_obj) {
705+
}
706+
707+
int Send(const char* name) override {
708+
ares_query(env()->cares_channel(),
709+
name,
710+
ns_c_in,
711+
ns_t_ptr,
712+
Callback,
713+
GetQueryArg());
714+
return 0;
715+
}
716+
717+
size_t self_size() const override { return sizeof(*this); }
718+
719+
protected:
720+
void Parse(unsigned char* buf, int len) override {
721+
HandleScope handle_scope(env()->isolate());
722+
Context::Scope context_scope(env()->context());
723+
724+
struct hostent* host;
725+
726+
int status = ares_parse_ptr_reply(buf, len, NULL, 0, AF_INET, &host);
727+
if (status != ARES_SUCCESS) {
728+
ParseError(status);
729+
return;
730+
}
731+
732+
Local<Array> aliases = Array::New(env()->isolate());
733+
734+
for (uint32_t i = 0; host->h_aliases[i] != NULL; i++) {
735+
aliases->Set(i, OneByteString(env()->isolate(), host->h_aliases[i]));
736+
}
737+
738+
ares_free_hostent(host);
739+
740+
this->CallOnComplete(aliases);
741+
}
742+
};
743+
701744
class QueryNaptrWrap: public QueryWrap {
702745
public:
703746
explicit QueryNaptrWrap(Environment* env, Local<Object> req_wrap_obj)
@@ -1276,6 +1319,7 @@ static void Initialize(Local<Object> target,
12761319
env->SetMethod(target, "queryNs", Query<QueryNsWrap>);
12771320
env->SetMethod(target, "queryTxt", Query<QueryTxtWrap>);
12781321
env->SetMethod(target, "querySrv", Query<QuerySrvWrap>);
1322+
env->SetMethod(target, "queryPtr", Query<QueryPtrWrap>);
12791323
env->SetMethod(target, "queryNaptr", Query<QueryNaptrWrap>);
12801324
env->SetMethod(target, "querySoa", Query<QuerySoaWrap>);
12811325
env->SetMethod(target, "getHostByAddr", Query<GetHostByAddrWrap>);

test/internet/test-dns.js

+31
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,37 @@ TEST(function test_resolveSrv_failure(done) {
166166
checkWrap(req);
167167
});
168168

169+
TEST(function test_resolvePtr(done) {
170+
var req = dns.resolvePtr('8.8.8.8.in-addr.arpa', function(err, result) {
171+
if (err) throw err;
172+
173+
assert.ok(result.length > 0);
174+
175+
for (var i = 0; i < result.length; i++) {
176+
var item = result[i];
177+
assert.ok(item);
178+
assert.ok(typeof item === 'string');
179+
}
180+
181+
done();
182+
});
183+
184+
checkWrap(req);
185+
});
186+
187+
TEST(function test_resolvePtr_failure(done) {
188+
var req = dns.resolvePtr('something.invalid', function(err, result) {
189+
assert.ok(err instanceof Error);
190+
assert.strictEqual(err.errno, 'ENOTFOUND');
191+
192+
assert.ok(result == undefined);
193+
194+
done();
195+
});
196+
197+
checkWrap(req);
198+
});
199+
169200
TEST(function test_resolveNaptr(done) {
170201
var req = dns.resolveNaptr('sip2sip.info', function(err, result) {
171202
if (err) throw err;

test/parallel/test-c-ares.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ assert.throws(function() {
3131
// C:\Windows\System32\drivers\etc\hosts
3232
// so we disable this test on Windows.
3333
if (!common.isWindows) {
34-
dns.resolve('127.0.0.1', 'PTR', function(error, domains) {
34+
dns.reverse('127.0.0.1', function(error, domains) {
3535
if (error) throw error;
3636
assert.ok(Array.isArray(domains));
3737
});

test/parallel/test-dns-cares-domains.js

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ var methods = [
1212
'resolveNs',
1313
'resolveTxt',
1414
'resolveSrv',
15+
'resolvePtr',
1516
'resolveNaptr',
1617
'resolveSoa'
1718
];

0 commit comments

Comments
 (0)