summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/api/dns.md6
-rw-r--r--lib/dns.js4
-rw-r--r--src/cares_wrap.cc89
-rw-r--r--test/internet/test-dns.js2
4 files changed, 43 insertions, 58 deletions
diff --git a/doc/api/dns.md b/doc/api/dns.md
index 0d191af15e..46927e5f52 100644
--- a/doc/api/dns.md
+++ b/doc/api/dns.md
@@ -140,6 +140,12 @@ changes:
flags may be passed by bitwise `OR`ing their values.
- `all` {boolean} When `true`, the callback returns all resolved addresses in
an array. Otherwise, returns a single address. Defaults to `false`.
+ - `verbatim` {boolean} When `true`, the callback receives IPv4 and IPv6
+ addresses in the order the DNS resolver returned them. When `false`,
+ IPv4 addresses are placed before IPv6 addresses.
+ Default: currently `false` (addresses are reordered) but this is expected
+ to change in the not too distant future.
+ New code should use `{ verbatim: true }`.
- `callback` {Function}
- `err` {Error}
- `address` {string} A string representation of an IPv4 or IPv6 address.
diff --git a/lib/dns.js b/lib/dns.js
index 53e667565d..e536f1b4f9 100644
--- a/lib/dns.js
+++ b/lib/dns.js
@@ -131,6 +131,7 @@ function lookup(hostname, options, callback) {
var hints = 0;
var family = -1;
var all = false;
+ var verbatim = false;
// Parse arguments
if (hostname && typeof hostname !== 'string') {
@@ -145,6 +146,7 @@ function lookup(hostname, options, callback) {
hints = options.hints >>> 0;
family = options.family >>> 0;
all = options.all === true;
+ verbatim = options.verbatim === true;
if (hints !== 0 &&
hints !== cares.AI_ADDRCONFIG &&
@@ -185,7 +187,7 @@ function lookup(hostname, options, callback) {
req.hostname = hostname;
req.oncomplete = all ? onlookupall : onlookup;
- var err = cares.getaddrinfo(req, hostname, family, hints);
+ var err = cares.getaddrinfo(req, hostname, family, hints, verbatim);
if (err) {
process.nextTick(callback, errnoException(err, 'getaddrinfo', hostname));
return {};
diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc
index e881ff5173..e800e0f2fe 100644
--- a/src/cares_wrap.cc
+++ b/src/cares_wrap.cc
@@ -196,15 +196,23 @@ void ChannelWrap::New(const FunctionCallbackInfo<Value>& args) {
class GetAddrInfoReqWrap : public ReqWrap<uv_getaddrinfo_t> {
public:
- GetAddrInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
+ GetAddrInfoReqWrap(Environment* env,
+ Local<Object> req_wrap_obj,
+ bool verbatim);
~GetAddrInfoReqWrap();
size_t self_size() const override { return sizeof(*this); }
+ bool verbatim() const { return verbatim_; }
+
+ private:
+ const bool verbatim_;
};
GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env,
- Local<Object> req_wrap_obj)
- : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP) {
+ Local<Object> req_wrap_obj,
+ bool verbatim)
+ : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP)
+ , verbatim_(verbatim) {
Wrap(req_wrap_obj, this);
}
@@ -1811,70 +1819,38 @@ void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
};
if (status == 0) {
- // Success
- struct addrinfo *address;
int n = 0;
-
- // Create the response array.
Local<Array> results = Array::New(env->isolate());
- char ip[INET6_ADDRSTRLEN];
- const char *addr;
-
- // Iterate over the IPv4 responses again this time creating javascript
- // strings for each IP and filling the results array.
- address = res;
- while (address) {
- CHECK_EQ(address->ai_socktype, SOCK_STREAM);
-
- // Ignore random ai_family types.
- if (address->ai_family == AF_INET) {
- // Juggle pointers
- addr = reinterpret_cast<char*>(&(reinterpret_cast<struct sockaddr_in*>(
- address->ai_addr)->sin_addr));
- int err = uv_inet_ntop(address->ai_family,
- addr,
- ip,
- INET6_ADDRSTRLEN);
- if (err)
+ auto add = [&] (bool want_ipv4, bool want_ipv6) {
+ for (auto p = res; p != nullptr; p = p->ai_next) {
+ CHECK_EQ(p->ai_socktype, SOCK_STREAM);
+
+ const char* addr;
+ if (want_ipv4 && p->ai_family == AF_INET) {
+ addr = reinterpret_cast<char*>(
+ &(reinterpret_cast<struct sockaddr_in*>(p->ai_addr)->sin_addr));
+ } else if (want_ipv6 && p->ai_family == AF_INET6) {
+ addr = reinterpret_cast<char*>(
+ &(reinterpret_cast<struct sockaddr_in6*>(p->ai_addr)->sin6_addr));
+ } else {
continue;
+ }
- // Create JavaScript string
- Local<String> s = OneByteString(env->isolate(), ip);
- results->Set(n, s);
- n++;
- }
-
- // Increment
- address = address->ai_next;
- }
-
- // Iterate over the IPv6 responses putting them in the array.
- address = res;
- while (address) {
- CHECK_EQ(address->ai_socktype, SOCK_STREAM);
-
- // Ignore random ai_family types.
- if (address->ai_family == AF_INET6) {
- // Juggle pointers
- addr = reinterpret_cast<char*>(&(reinterpret_cast<struct sockaddr_in6*>(
- address->ai_addr)->sin6_addr));
- int err = uv_inet_ntop(address->ai_family,
- addr,
- ip,
- INET6_ADDRSTRLEN);
- if (err)
+ char ip[INET6_ADDRSTRLEN];
+ if (uv_inet_ntop(p->ai_family, addr, ip, sizeof(ip)))
continue;
- // Create JavaScript string
Local<String> s = OneByteString(env->isolate(), ip);
results->Set(n, s);
n++;
}
+ };
- // Increment
- address = address->ai_next;
- }
+ const bool verbatim = req_wrap->verbatim();
+ add(true, verbatim);
+ if (verbatim == false)
+ add(false, true);
// No responses were found to return
if (n == 0) {
@@ -1965,6 +1941,7 @@ void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
CHECK(args[0]->IsObject());
CHECK(args[1]->IsString());
CHECK(args[2]->IsInt32());
+ CHECK(args[4]->IsBoolean());
Local<Object> req_wrap_obj = args[0].As<Object>();
node::Utf8Value hostname(env->isolate(), args[1]);
@@ -1985,7 +1962,7 @@ void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
CHECK(0 && "bad address family");
}
- GetAddrInfoReqWrap* req_wrap = new GetAddrInfoReqWrap(env, req_wrap_obj);
+ auto req_wrap = new GetAddrInfoReqWrap(env, req_wrap_obj, args[4]->IsTrue());
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
diff --git a/test/internet/test-dns.js b/test/internet/test-dns.js
index 9e08770590..03bf4bb7f8 100644
--- a/test/internet/test-dns.js
+++ b/test/internet/test-dns.js
@@ -553,7 +553,7 @@ console.log('looking up nodejs.org...');
const cares = process.binding('cares_wrap');
const req = new cares.GetAddrInfoReqWrap();
-cares.getaddrinfo(req, 'nodejs.org', 4);
+cares.getaddrinfo(req, 'nodejs.org', 4, /* hints */ 0, /* verbatim */ true);
req.oncomplete = function(err, domains) {
assert.strictEqual(err, 0);