From b5b28e05a997d9cc103a6ddfe1eff6c89c397d94 Mon Sep 17 00:00:00 2001 From: XadillaX Date: Sat, 17 Jun 2017 01:27:21 +0800 Subject: [PATCH] dns: make `dns.setServers` support customized port Make `dns.setServers` parameter may be strings contain IP and port which split by `:`. eg. ``` dns.setServers([ "103.238.225.181:666" ]); ``` And `dns.getServers` will return IP with port if that server is not use default port. Refs: https://github.com/nodejs/node/issues/7903 --- lib/dns.js | 27 ++++++++++++++++++++------- src/cares_wrap.cc | 32 ++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/lib/dns.js b/lib/dns.js index e2af27863e7f67..6c12ea7ce35726 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -301,7 +301,13 @@ function resolve(hostname, rrtype, callback) { function getServers() { - return cares.getServers(); + const ret = cares.getServers(); + return ret.map((val) => { + if (!val[1] || val[1] === 53) return val[0]; + + const ipVersion = isIP(val[0]); + return ipVersion === 6 ? `[${val[0]}]:${val[1]}` : `${val[0]}:${val[1]}`; + }); } @@ -311,26 +317,33 @@ 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, 53]); 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 portMatch = serv.match(addrSplitRE) || []; + return newSet.push([ipVersion, match[1], parseInt(portMatch[1] || 53)]); + } } const s = serv.split(addrSplitRE)[0]; ipVersion = isIP(s); - if (ipVersion !== 0) - return newSet.push([ipVersion, s]); + if (ipVersion !== 0) { + return newSet.push([ + ipVersion, + s, + parseInt(serv.substr(serv.indexOf(':') + 1)) + ]); + } throw new Error(`IP address is not properly formatted: ${serv}`); }); diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index bd340f0d920a88..41a5633ee022f1 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -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& args) { Local 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& args) { int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip)); CHECK_EQ(err, 0); - Local addr = OneByteString(env->isolate(), ip); - server_array->Set(i, addr); + Local 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& 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& 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& 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;