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
|
||||
-->
|
||||
|
||||
Returns an array of IP address strings that are being used for name
|
||||
resolution.
|
||||
Returns an array of IP address strings, formatted according to [rfc5952][],
|
||||
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)
|
||||
<!-- YAML
|
||||
@ -482,12 +495,22 @@ one of the [DNS error codes][].
|
||||
<!-- YAML
|
||||
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`
|
||||
argument is an array of IPv4 or IPv6 addresses.
|
||||
Sets the IP address and port of servers to be used when performing DNS
|
||||
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.
|
||||
|
||||
@ -583,3 +606,4 @@ uses. For instance, _they do not use the configuration from `/etc/hosts`_.
|
||||
[supported `getaddrinfo` flags]: #dns_supported_getaddrinfo_flags
|
||||
[the official libuv documentation]: http://docs.libuv.org/en/latest/threadpool.html
|
||||
[`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;
|
||||
}
|
||||
|
||||
const IANA_DNS_PORT = 53;
|
||||
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, // 16-31
|
||||
@ -301,7 +302,13 @@ function resolve(hostname, rrtype, callback) {
|
||||
|
||||
|
||||
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 newSet = [];
|
||||
const IPv6RE = /\[(.*)\]/;
|
||||
const addrSplitRE = /:\d+$/;
|
||||
const addrSplitRE = /(^.+?)(?::(\d+))?$/;
|
||||
|
||||
servers.forEach((serv) => {
|
||||
var ipVersion = isIP(serv);
|
||||
if (ipVersion !== 0)
|
||||
return newSet.push([ipVersion, serv]);
|
||||
return newSet.push([ipVersion, serv, IANA_DNS_PORT]);
|
||||
|
||||
const match = serv.match(IPv6RE);
|
||||
// we have an IPv6 in brackets
|
||||
if (match) {
|
||||
ipVersion = isIP(match[1]);
|
||||
if (ipVersion !== 0)
|
||||
return newSet.push([ipVersion, match[1]]);
|
||||
if (ipVersion !== 0) {
|
||||
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);
|
||||
|
||||
if (ipVersion !== 0)
|
||||
return newSet.push([ipVersion, s]);
|
||||
if (ipVersion !== 0) {
|
||||
return newSet.push([ipVersion, s, parseInt(p)]);
|
||||
}
|
||||
|
||||
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_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 (servers == nullptr) return;
|
||||
@ -456,7 +456,9 @@ void AresEnsureServers(Environment* env) {
|
||||
|
||||
/* if the only server is not 127.0.0.1, ignore */
|
||||
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);
|
||||
env->set_cares_is_servers_default(false);
|
||||
return;
|
||||
@ -1924,12 +1926,12 @@ void GetServers(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
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);
|
||||
|
||||
ares_addr_node* cur = servers;
|
||||
ares_addr_port_node* cur = servers;
|
||||
|
||||
for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) {
|
||||
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));
|
||||
CHECK_EQ(err, 0);
|
||||
|
||||
Local<String> addr = OneByteString(env->isolate(), ip);
|
||||
server_array->Set(i, addr);
|
||||
Local<Array> ret = Array::New(env->isolate(), 2);
|
||||
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);
|
||||
@ -1962,8 +1967,8 @@ void SetServers(const FunctionCallbackInfo<Value>& args) {
|
||||
return args.GetReturnValue().Set(rv);
|
||||
}
|
||||
|
||||
ares_addr_node* servers = new ares_addr_node[len];
|
||||
ares_addr_node* last = nullptr;
|
||||
ares_addr_port_node* servers = new ares_addr_port_node[len];
|
||||
ares_addr_port_node* last = nullptr;
|
||||
|
||||
int err;
|
||||
|
||||
@ -1974,12 +1979,15 @@ void SetServers(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
CHECK(elm->Get(0)->Int32Value());
|
||||
CHECK(elm->Get(1)->IsString());
|
||||
CHECK(elm->Get(2)->Int32Value());
|
||||
|
||||
int fam = elm->Get(0)->Int32Value();
|
||||
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) {
|
||||
case 4:
|
||||
cur->family = AF_INET;
|
||||
@ -2005,7 +2013,7 @@ void SetServers(const FunctionCallbackInfo<Value>& args) {
|
||||
}
|
||||
|
||||
if (err == 0)
|
||||
err = ares_set_servers(env->cares_channel(), &servers[0]);
|
||||
err = ares_set_servers_ports(env->cares_channel(), &servers[0]);
|
||||
else
|
||||
err = ARES_EBADSTR;
|
||||
|
||||
|
@ -35,6 +35,8 @@ assert.doesNotThrow(() => {
|
||||
servers[0] = '127.0.0.1';
|
||||
servers[2] = '0.0.0.0';
|
||||
dns.setServers(servers);
|
||||
|
||||
assert.deepStrictEqual(dns.getServers(), ['127.0.0.1', '0.0.0.0']);
|
||||
});
|
||||
|
||||
assert.doesNotThrow(() => {
|
||||
@ -53,6 +55,11 @@ assert.doesNotThrow(() => {
|
||||
});
|
||||
|
||||
dns.setServers(servers);
|
||||
assert.deepStrictEqual(dns.getServers(), [
|
||||
'127.0.0.1',
|
||||
'192.168.1.1',
|
||||
'0.0.0.0'
|
||||
]);
|
||||
});
|
||||
|
||||
const goog = [
|
||||
@ -63,6 +70,8 @@ assert.doesNotThrow(() => dns.setServers(goog));
|
||||
assert.deepStrictEqual(dns.getServers(), goog);
|
||||
assert.throws(() => dns.setServers(['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);
|
||||
|
||||
const goog6 = [
|
||||
@ -79,10 +88,14 @@ assert.deepStrictEqual(dns.getServers(), goog6);
|
||||
const ports = [
|
||||
'4.4.4.4:53',
|
||||
'[2001:4860:4860::8888]:53',
|
||||
'103.238.225.181:666',
|
||||
'[fe80::483a:5aff:fee6:1f04]:666'
|
||||
];
|
||||
const portsExpected = [
|
||||
'4.4.4.4',
|
||||
'2001:4860:4860::8888',
|
||||
'103.238.225.181:666',
|
||||
'[fe80::483a:5aff:fee6:1f04]:666'
|
||||
];
|
||||
dns.setServers(ports);
|
||||
assert.deepStrictEqual(dns.getServers(), portsExpected);
|
||||
|
Loading…
x
Reference in New Issue
Block a user