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: https://github.com/nodejs/node/pull/13723 Refs: https://github.com/nodejs/node/issues/7903 Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
parent
1fcb76e8f2
commit
330349f706
@ -59,8 +59,21 @@ the [Implementation considerations section][] for more information.
|
|||||||
added: v0.11.3
|
added: v0.11.3
|
||||||
-->
|
-->
|
||||||
|
|
||||||
Returns an array of IP address strings that are being used for name
|
Returns an array of IP address strings, formatted according to [rfc5952][],
|
||||||
resolution.
|
that are currently configured for DNS resolution. A string will include a port
|
||||||
|
section if a custom port is used.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
<!-- eslint-disable -->
|
||||||
|
```js
|
||||||
|
[
|
||||||
|
'4.4.4.4',
|
||||||
|
'2001:4860:4860::8888',
|
||||||
|
'4.4.4.4:1053',
|
||||||
|
'[2001:4860:4860::8888]:1053'
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
## dns.lookup(hostname[, options], callback)
|
## dns.lookup(hostname[, options], callback)
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
@ -482,12 +495,22 @@ one of the [DNS error codes][].
|
|||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.11.3
|
added: v0.11.3
|
||||||
-->
|
-->
|
||||||
- `servers` {string[]}
|
- `servers` {string[]} array of [rfc5952][] formatted addresses
|
||||||
|
|
||||||
Sets the IP addresses of the servers to be used when resolving. The `servers`
|
Sets the IP address and port of servers to be used when performing DNS
|
||||||
argument is an array of IPv4 or IPv6 addresses.
|
resolution. The `servers` argument is an array of [rfc5952][] formatted
|
||||||
|
addresses. If the port is the IANA default DNS port (53) it can be omitted.
|
||||||
|
|
||||||
If a port is specified on the address, it will be removed.
|
For example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
dns.setServers([
|
||||||
|
'4.4.4.4',
|
||||||
|
'[2001:4860:4860::8888]',
|
||||||
|
'4.4.4.4:1053',
|
||||||
|
'[2001:4860:4860::8888]:1053'
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
An error will be thrown if an invalid address is provided.
|
An error will be thrown if an invalid address is provided.
|
||||||
|
|
||||||
@ -583,3 +606,4 @@ uses. For instance, _they do not use the configuration from `/etc/hosts`_.
|
|||||||
[supported `getaddrinfo` flags]: #dns_supported_getaddrinfo_flags
|
[supported `getaddrinfo` flags]: #dns_supported_getaddrinfo_flags
|
||||||
[the official libuv documentation]: http://docs.libuv.org/en/latest/threadpool.html
|
[the official libuv documentation]: http://docs.libuv.org/en/latest/threadpool.html
|
||||||
[`util.promisify()`]: util.html#util_util_promisify_original
|
[`util.promisify()`]: util.html#util_util_promisify_original
|
||||||
|
[rfc5952]: https://tools.ietf.org/html/rfc5952#section-6
|
||||||
|
28
lib/dns.js
28
lib/dns.js
@ -60,6 +60,7 @@ function errnoException(err, syscall, hostname) {
|
|||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const IANA_DNS_PORT = 53;
|
||||||
const digits = [
|
const digits = [
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31
|
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, rrtype, callback) {
|
|||||||
|
|
||||||
|
|
||||||
function getServers() {
|
function getServers() {
|
||||||
return cares.getServers();
|
const ret = cares.getServers();
|
||||||
|
return ret.map((val) => {
|
||||||
|
if (!val[1] || val[1] === IANA_DNS_PORT) return val[0];
|
||||||
|
|
||||||
|
const host = isIP(val[0]) === 6 ? `[${val[0]}]` : val[0];
|
||||||
|
return `${host}:${val[1]}`;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -311,26 +318,31 @@ function setServers(servers) {
|
|||||||
const orig = cares.getServers();
|
const orig = cares.getServers();
|
||||||
const newSet = [];
|
const newSet = [];
|
||||||
const IPv6RE = /\[(.*)\]/;
|
const IPv6RE = /\[(.*)\]/;
|
||||||
const addrSplitRE = /:\d+$/;
|
const addrSplitRE = /(^.+?)(?::(\d+))?$/;
|
||||||
|
|
||||||
servers.forEach((serv) => {
|
servers.forEach((serv) => {
|
||||||
var ipVersion = isIP(serv);
|
var ipVersion = isIP(serv);
|
||||||
if (ipVersion !== 0)
|
if (ipVersion !== 0)
|
||||||
return newSet.push([ipVersion, serv]);
|
return newSet.push([ipVersion, serv, IANA_DNS_PORT]);
|
||||||
|
|
||||||
const match = serv.match(IPv6RE);
|
const match = serv.match(IPv6RE);
|
||||||
// we have an IPv6 in brackets
|
// we have an IPv6 in brackets
|
||||||
if (match) {
|
if (match) {
|
||||||
ipVersion = isIP(match[1]);
|
ipVersion = isIP(match[1]);
|
||||||
if (ipVersion !== 0)
|
if (ipVersion !== 0) {
|
||||||
return newSet.push([ipVersion, match[1]]);
|
const port =
|
||||||
|
parseInt(serv.replace(addrSplitRE, '$2')) ||
|
||||||
|
IANA_DNS_PORT;
|
||||||
|
return newSet.push([ipVersion, match[1], port]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const s = serv.split(addrSplitRE)[0];
|
const [, s, p] = serv.match(addrSplitRE);
|
||||||
ipVersion = isIP(s);
|
ipVersion = isIP(s);
|
||||||
|
|
||||||
if (ipVersion !== 0)
|
if (ipVersion !== 0) {
|
||||||
return newSet.push([ipVersion, s]);
|
return newSet.push([ipVersion, s, parseInt(p)]);
|
||||||
|
}
|
||||||
|
|
||||||
throw new Error(`IP address is not properly formatted: ${serv}`);
|
throw new Error(`IP address is not properly formatted: ${serv}`);
|
||||||
});
|
});
|
||||||
|
@ -442,9 +442,9 @@ void AresEnsureServers(Environment* env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ares_channel channel = env->cares_channel();
|
ares_channel channel = env->cares_channel();
|
||||||
ares_addr_node* servers = nullptr;
|
ares_addr_port_node* servers = nullptr;
|
||||||
|
|
||||||
ares_get_servers(channel, &servers);
|
ares_get_servers_ports(channel, &servers);
|
||||||
|
|
||||||
/* if no server or multi-servers, ignore */
|
/* if no server or multi-servers, ignore */
|
||||||
if (servers == nullptr) return;
|
if (servers == nullptr) return;
|
||||||
@ -456,7 +456,9 @@ void AresEnsureServers(Environment* env) {
|
|||||||
|
|
||||||
/* if the only server is not 127.0.0.1, ignore */
|
/* if the only server is not 127.0.0.1, ignore */
|
||||||
if (servers[0].family != AF_INET ||
|
if (servers[0].family != AF_INET ||
|
||||||
servers[0].addr.addr4.s_addr != htonl(INADDR_LOOPBACK)) {
|
servers[0].addr.addr4.s_addr != htonl(INADDR_LOOPBACK) ||
|
||||||
|
servers[0].tcp_port != 0 ||
|
||||||
|
servers[0].udp_port != 0) {
|
||||||
ares_free_data(servers);
|
ares_free_data(servers);
|
||||||
env->set_cares_is_servers_default(false);
|
env->set_cares_is_servers_default(false);
|
||||||
return;
|
return;
|
||||||
@ -1924,12 +1926,12 @@ void GetServers(const FunctionCallbackInfo<Value>& args) {
|
|||||||
|
|
||||||
Local<Array> server_array = Array::New(env->isolate());
|
Local<Array> server_array = Array::New(env->isolate());
|
||||||
|
|
||||||
ares_addr_node* servers;
|
ares_addr_port_node* servers;
|
||||||
|
|
||||||
int r = ares_get_servers(env->cares_channel(), &servers);
|
int r = ares_get_servers_ports(env->cares_channel(), &servers);
|
||||||
CHECK_EQ(r, ARES_SUCCESS);
|
CHECK_EQ(r, ARES_SUCCESS);
|
||||||
|
|
||||||
ares_addr_node* cur = servers;
|
ares_addr_port_node* cur = servers;
|
||||||
|
|
||||||
for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) {
|
for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) {
|
||||||
char ip[INET6_ADDRSTRLEN];
|
char ip[INET6_ADDRSTRLEN];
|
||||||
@ -1938,8 +1940,11 @@ void GetServers(const FunctionCallbackInfo<Value>& args) {
|
|||||||
int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip));
|
int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip));
|
||||||
CHECK_EQ(err, 0);
|
CHECK_EQ(err, 0);
|
||||||
|
|
||||||
Local<String> addr = OneByteString(env->isolate(), ip);
|
Local<Array> ret = Array::New(env->isolate(), 2);
|
||||||
server_array->Set(i, addr);
|
ret->Set(0, OneByteString(env->isolate(), ip));
|
||||||
|
ret->Set(1, Integer::New(env->isolate(), cur->udp_port));
|
||||||
|
|
||||||
|
server_array->Set(i, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
ares_free_data(servers);
|
ares_free_data(servers);
|
||||||
@ -1962,8 +1967,8 @@ void SetServers(const FunctionCallbackInfo<Value>& args) {
|
|||||||
return args.GetReturnValue().Set(rv);
|
return args.GetReturnValue().Set(rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
ares_addr_node* servers = new ares_addr_node[len];
|
ares_addr_port_node* servers = new ares_addr_port_node[len];
|
||||||
ares_addr_node* last = nullptr;
|
ares_addr_port_node* last = nullptr;
|
||||||
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -1974,12 +1979,15 @@ void SetServers(const FunctionCallbackInfo<Value>& args) {
|
|||||||
|
|
||||||
CHECK(elm->Get(0)->Int32Value());
|
CHECK(elm->Get(0)->Int32Value());
|
||||||
CHECK(elm->Get(1)->IsString());
|
CHECK(elm->Get(1)->IsString());
|
||||||
|
CHECK(elm->Get(2)->Int32Value());
|
||||||
|
|
||||||
int fam = elm->Get(0)->Int32Value();
|
int fam = elm->Get(0)->Int32Value();
|
||||||
node::Utf8Value ip(env->isolate(), elm->Get(1));
|
node::Utf8Value ip(env->isolate(), elm->Get(1));
|
||||||
|
int port = elm->Get(2)->Int32Value();
|
||||||
|
|
||||||
ares_addr_node* cur = &servers[i];
|
ares_addr_port_node* cur = &servers[i];
|
||||||
|
|
||||||
|
cur->tcp_port = cur->udp_port = port;
|
||||||
switch (fam) {
|
switch (fam) {
|
||||||
case 4:
|
case 4:
|
||||||
cur->family = AF_INET;
|
cur->family = AF_INET;
|
||||||
@ -2005,7 +2013,7 @@ void SetServers(const FunctionCallbackInfo<Value>& args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
err = ares_set_servers(env->cares_channel(), &servers[0]);
|
err = ares_set_servers_ports(env->cares_channel(), &servers[0]);
|
||||||
else
|
else
|
||||||
err = ARES_EBADSTR;
|
err = ARES_EBADSTR;
|
||||||
|
|
||||||
|
@ -35,6 +35,8 @@ assert.doesNotThrow(() => {
|
|||||||
servers[0] = '127.0.0.1';
|
servers[0] = '127.0.0.1';
|
||||||
servers[2] = '0.0.0.0';
|
servers[2] = '0.0.0.0';
|
||||||
dns.setServers(servers);
|
dns.setServers(servers);
|
||||||
|
|
||||||
|
assert.deepStrictEqual(dns.getServers(), ['127.0.0.1', '0.0.0.0']);
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.doesNotThrow(() => {
|
assert.doesNotThrow(() => {
|
||||||
@ -53,6 +55,11 @@ assert.doesNotThrow(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
dns.setServers(servers);
|
dns.setServers(servers);
|
||||||
|
assert.deepStrictEqual(dns.getServers(), [
|
||||||
|
'127.0.0.1',
|
||||||
|
'192.168.1.1',
|
||||||
|
'0.0.0.0'
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
const goog = [
|
const goog = [
|
||||||
@ -63,6 +70,8 @@ assert.doesNotThrow(() => dns.setServers(goog));
|
|||||||
assert.deepStrictEqual(dns.getServers(), goog);
|
assert.deepStrictEqual(dns.getServers(), goog);
|
||||||
assert.throws(() => dns.setServers(['foobar']),
|
assert.throws(() => dns.setServers(['foobar']),
|
||||||
/^Error: IP address is not properly formatted: foobar$/);
|
/^Error: IP address is not properly formatted: foobar$/);
|
||||||
|
assert.throws(() => dns.setServers(['127.0.0.1:va']),
|
||||||
|
/^Error: IP address is not properly formatted: 127\.0\.0\.1:va$/);
|
||||||
assert.deepStrictEqual(dns.getServers(), goog);
|
assert.deepStrictEqual(dns.getServers(), goog);
|
||||||
|
|
||||||
const goog6 = [
|
const goog6 = [
|
||||||
@ -79,10 +88,14 @@ assert.deepStrictEqual(dns.getServers(), goog6);
|
|||||||
const ports = [
|
const ports = [
|
||||||
'4.4.4.4:53',
|
'4.4.4.4:53',
|
||||||
'[2001:4860:4860::8888]:53',
|
'[2001:4860:4860::8888]:53',
|
||||||
|
'103.238.225.181:666',
|
||||||
|
'[fe80::483a:5aff:fee6:1f04]:666'
|
||||||
];
|
];
|
||||||
const portsExpected = [
|
const portsExpected = [
|
||||||
'4.4.4.4',
|
'4.4.4.4',
|
||||||
'2001:4860:4860::8888',
|
'2001:4860:4860::8888',
|
||||||
|
'103.238.225.181:666',
|
||||||
|
'[fe80::483a:5aff:fee6:1f04]:666'
|
||||||
];
|
];
|
||||||
dns.setServers(ports);
|
dns.setServers(ports);
|
||||||
assert.deepStrictEqual(dns.getServers(), portsExpected);
|
assert.deepStrictEqual(dns.getServers(), portsExpected);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user