Skip to content

Commit ebe7bb2

Browse files
XadillaXaddaleax
authored andcommitted
dns: make dns.setServers support customized port
allow `dns.setServers` parameter to contain port e.g. ``` dns.setServers([ '103.238.225.181:666' ]); ``` And `dns.getServers` will return IP with port if not the default port. PR-URL: #13723 Refs: #7903 Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent 683f743 commit ebe7bb2

File tree

4 files changed

+83
-26
lines changed

4 files changed

+83
-26
lines changed

‎doc/api/dns.md‎

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,21 @@ the [Implementation considerations section][] for more information.
5959
added: v0.11.3
6060
-->
6161

62-
Returns an array of IP address strings that are being used for name
63-
resolution.
62+
Returns an array of IP address strings, formatted according to [rfc5952][],
63+
that are currently configured for DNS resolution. A string will include a port
64+
section if a custom port is used.
65+
66+
For example:
67+
68+
<!-- eslint-disable -->
69+
```js
70+
[
71+
'4.4.4.4',
72+
'2001:4860:4860::8888',
73+
'4.4.4.4:1053',
74+
'[2001:4860:4860::8888]:1053'
75+
]
76+
```
6477

6578
## dns.lookup(hostname[, options], callback)
6679
<!-- YAML
@@ -436,12 +449,22 @@ one of the [DNS error codes][].
436449
<!-- YAML
437450
added: v0.11.3
438451
-->
439-
-`servers`{string[]}
452+
-`servers`{string[]} array of [rfc5952][] formatted addresses
453+
454+
Sets the IP address and port of servers to be used when performing DNS
455+
resolution. The `servers` argument is an array of [rfc5952][] formatted
456+
addresses. If the port is the IANA default DNS port (53) it can be omitted.
440457

441-
Sets the IP addresses of the servers to be used when resolving. The `servers`
442-
argument is an array of IPv4 or IPv6 addresses.
458+
For example:
443459

444-
If a port is specified on the address, it will be removed.
460+
```js
461+
dns.setServers([
462+
'4.4.4.4',
463+
'[2001:4860:4860::8888]',
464+
'4.4.4.4:1053',
465+
'[2001:4860:4860::8888]:1053'
466+
]);
467+
```
445468

446469
An error will be thrown if an invalid address is provided.
447470

@@ -536,3 +559,4 @@ uses. For instance, _they do not use the configuration from `/etc/hosts`_.
536559
[supported `getaddrinfo` flags]: #dns_supported_getaddrinfo_flags
537560
[the official libuv documentation]: http://docs.libuv.org/en/latest/threadpool.html
538561
[`util.promisify()`]: util.html#util_util_promisify_original
562+
[rfc5952]: https://tools.ietf.org/html/rfc5952#section-6

‎lib/dns.js‎

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ function errnoException(err, syscall, hostname){
6060
returnex;
6161
}
6262

63+
constIANA_DNS_PORT=53;
6364
constdigits=[
6465
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,// 0-15
6566
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,// 16-31
@@ -301,7 +302,13 @@ function resolve(hostname, type_, callback_){
301302

302303

303304
functiongetServers(){
304-
returncares.getServers();
305+
constret=cares.getServers();
306+
returnret.map((val)=>{
307+
if(!val[1]||val[1]===IANA_DNS_PORT)returnval[0];
308+
309+
consthost=isIP(val[0])===6 ? `[${val[0]}]` : val[0];
310+
return`${host}:${val[1]}`;
311+
});
305312
}
306313

307314

@@ -311,26 +318,31 @@ function setServers(servers){
311318
constorig=cares.getServers();
312319
constnewSet=[];
313320
constIPv6RE=/\[(.*)\]/;
314-
constaddrSplitRE=/:\d+$/;
321+
constaddrSplitRE=/(^.+?)(?::(\d+))?$/;
315322

316323
servers.forEach((serv)=>{
317324
varipVersion=isIP(serv);
318325
if(ipVersion!==0)
319-
returnnewSet.push([ipVersion,serv]);
326+
returnnewSet.push([ipVersion,serv,IANA_DNS_PORT]);
320327

321328
constmatch=serv.match(IPv6RE);
322329
// we have an IPv6 in brackets
323330
if(match){
324331
ipVersion=isIP(match[1]);
325-
if(ipVersion!==0)
326-
returnnewSet.push([ipVersion,match[1]]);
332+
if(ipVersion!==0){
333+
constport=
334+
parseInt(serv.replace(addrSplitRE,'$2'))||
335+
IANA_DNS_PORT;
336+
returnnewSet.push([ipVersion,match[1],port]);
337+
}
327338
}
328339

329-
consts=serv.split(addrSplitRE)[0];
340+
const[,s,p]=serv.match(addrSplitRE);
330341
ipVersion=isIP(s);
331342

332-
if(ipVersion!==0)
333-
returnnewSet.push([ipVersion,s]);
343+
if(ipVersion!==0){
344+
returnnewSet.push([ipVersion,s,parseInt(p)]);
345+
}
334346

335347
thrownewError(`IP address is not properly formatted: ${serv}`);
336348
});

‎src/cares_wrap.cc‎

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -419,9 +419,9 @@ void AresEnsureServers(Environment* env){
419419
}
420420

421421
ares_channel channel = env->cares_channel();
422-
ares_addr_node* servers = nullptr;
422+
ares_addr_port_node* servers = nullptr;
423423

424-
ares_get_servers(channel, &servers);
424+
ares_get_servers_ports(channel, &servers);
425425

426426
/* if no server or multi-servers, ignore */
427427
if (servers == nullptr) return;
@@ -433,7 +433,9 @@ void AresEnsureServers(Environment* env){
433433

434434
/* if the only server is not 127.0.0.1, ignore */
435435
if (servers[0].family != AF_INET ||
436-
servers[0].addr.addr4.s_addr != htonl(INADDR_LOOPBACK)){
436+
servers[0].addr.addr4.s_addr != htonl(INADDR_LOOPBACK) ||
437+
servers[0].tcp_port != 0 ||
438+
servers[0].udp_port != 0){
437439
ares_free_data(servers);
438440
env->set_cares_is_servers_default(false);
439441
return;
@@ -1384,12 +1386,12 @@ void GetServers(const FunctionCallbackInfo<Value>& args){
13841386

13851387
Local<Array> server_array = Array::New(env->isolate());
13861388

1387-
ares_addr_node* servers;
1389+
ares_addr_port_node* servers;
13881390

1389-
int r = ares_get_servers(env->cares_channel(), &servers);
1391+
int r = ares_get_servers_ports(env->cares_channel(), &servers);
13901392
CHECK_EQ(r, ARES_SUCCESS);
13911393

1392-
ares_addr_node* cur = servers;
1394+
ares_addr_port_node* cur = servers;
13931395

13941396
for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next){
13951397
char ip[INET6_ADDRSTRLEN];
@@ -1398,8 +1400,11 @@ void GetServers(const FunctionCallbackInfo<Value>& args){
13981400
int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip));
13991401
CHECK_EQ(err, 0);
14001402

1401-
Local<String> addr = OneByteString(env->isolate(), ip);
1402-
server_array->Set(i, addr);
1403+
Local<Array> ret = Array::New(env->isolate(), 2);
1404+
ret->Set(0, OneByteString(env->isolate(), ip));
1405+
ret->Set(1, Integer::New(env->isolate(), cur->udp_port));
1406+
1407+
server_array->Set(i, ret);
14031408
}
14041409

14051410
ares_free_data(servers);
@@ -1422,8 +1427,8 @@ void SetServers(const FunctionCallbackInfo<Value>& args){
14221427
return args.GetReturnValue().Set(rv);
14231428
}
14241429

1425-
ares_addr_node* servers = newares_addr_node[len];
1426-
ares_addr_node* last = nullptr;
1430+
ares_addr_port_node* servers = newares_addr_port_node[len];
1431+
ares_addr_port_node* last = nullptr;
14271432

14281433
int err;
14291434

@@ -1434,12 +1439,15 @@ void SetServers(const FunctionCallbackInfo<Value>& args){
14341439

14351440
CHECK(elm->Get(0)->Int32Value());
14361441
CHECK(elm->Get(1)->IsString());
1442+
CHECK(elm->Get(2)->Int32Value());
14371443

14381444
int fam = elm->Get(0)->Int32Value();
14391445
node::Utf8Value ip(env->isolate(), elm->Get(1));
1446+
int port = elm->Get(2)->Int32Value();
14401447

1441-
ares_addr_node* cur = &servers[i];
1448+
ares_addr_port_node* cur = &servers[i];
14421449

1450+
cur->tcp_port = cur->udp_port = port;
14431451
switch (fam){
14441452
case4:
14451453
cur->family = AF_INET;
@@ -1465,7 +1473,7 @@ void SetServers(const FunctionCallbackInfo<Value>& args){
14651473
}
14661474

14671475
if (err == 0)
1468-
err = ares_set_servers(env->cares_channel(), &servers[0]);
1476+
err = ares_set_servers_ports(env->cares_channel(), &servers[0]);
14691477
else
14701478
err = ARES_EBADSTR;
14711479

‎test/parallel/test-dns.js‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ assert.doesNotThrow(() =>{
3535
servers[0]='127.0.0.1';
3636
servers[2]='0.0.0.0';
3737
dns.setServers(servers);
38+
39+
assert.deepStrictEqual(dns.getServers(),['127.0.0.1','0.0.0.0']);
3840
});
3941

4042
assert.doesNotThrow(()=>{
@@ -53,6 +55,11 @@ assert.doesNotThrow(() =>{
5355
});
5456

5557
dns.setServers(servers);
58+
assert.deepStrictEqual(dns.getServers(),[
59+
'127.0.0.1',
60+
'192.168.1.1',
61+
'0.0.0.0'
62+
]);
5663
});
5764

5865
constgoog=[
@@ -63,6 +70,8 @@ assert.doesNotThrow(() => dns.setServers(goog));
6370
assert.deepStrictEqual(dns.getServers(),goog);
6471
assert.throws(()=>dns.setServers(['foobar']),
6572
/^Error:IPaddressisnotproperlyformatted:foobar$/);
73+
assert.throws(()=>dns.setServers(['127.0.0.1:va']),
74+
/^Error:IPaddressisnotproperlyformatted:127\.0\.0\.1:va$/);
6675
assert.deepStrictEqual(dns.getServers(),goog);
6776

6877
constgoog6=[
@@ -79,10 +88,14 @@ assert.deepStrictEqual(dns.getServers(), goog6);
7988
constports=[
8089
'4.4.4.4:53',
8190
'[2001:4860:4860::8888]:53',
91+
'103.238.225.181:666',
92+
'[fe80::483a:5aff:fee6:1f04]:666'
8293
];
8394
constportsExpected=[
8495
'4.4.4.4',
8596
'2001:4860:4860::8888',
97+
'103.238.225.181:666',
98+
'[fe80::483a:5aff:fee6:1f04]:666'
8699
];
87100
dns.setServers(ports);
88101
assert.deepStrictEqual(dns.getServers(),portsExpected);

0 commit comments

Comments
(0)