});
});
-## dns.lookup(hostname, [family], callback)
+## dns.lookup(hostname, [options], callback)
Resolves a hostname (e.g. `'google.com'`) into the first found A (IPv4) or
-AAAA (IPv6) record.
-The `family` can be the integer `4` or `6`. Defaults to `null` that indicates
-both Ip v4 and v6 address family.
+AAAA (IPv6) record. `options` can be an object or integer. If `options` is
+not provided, then IP v4 and v6 addresses are both valid. If `options` is
+an integer, then it must be `4` or `6`.
+
+Alternatively, `options` can be an object containing two properties,
+`family` and `hints`. Both properties are optional. If `family` is provided,
+it must be the integer `4` or `6`. If `family` is not provided then IP v4
+and v6 addresses are accepted. The `hints` field, if present, should be one
+or more of the supported `getaddrinfo` flags. If `hints` is not provided,
+then no flags are passed to `getaddrinfo`. Multiple flags can be passed
+through `hints` by logically `OR`ing their values. An example usage of
+`options` is shown below.
+
+```
+{
+ family: 4,
+ hints: dns.ADDRCONFIG | dns.V4MAPPED
+}
+```
+
+See [supported `getaddrinfo` flags](#dns_supported_getaddrinfo_flags) below for
+more information on supported flags.
The callback has arguments `(err, address, family)`. The `address` argument
is a string representation of a IP v4 or v6 address. The `family` argument
## dns.resolveSoa(hostname, callback)
-The same as `dns.resolve()`, but only for start of authority record queries
+The same as `dns.resolve()`, but only for start of authority record queries
(`SOA` record).
`addresses` is an object with the following structure:
- `dns.LOADIPHLPAPI`: Error loading iphlpapi.dll.
- `dns.ADDRGETNETWORKPARAMS`: Could not find GetNetworkParams function.
- `dns.CANCELLED`: DNS query cancelled.
+
+## Supported getaddrinfo flags
+
+The following flags can be passed as hints to `dns.lookup`.
+
+- `dns.ADDRCONFIG`: Returned address types are determined by the types
+of addresses supported by the current system. For example, IPv4 addresses
+are only returned if the current system has at least one IPv4 address
+configured. Loopback addresses are not considered.
+- `dns.V4MAPPED`: If the IPv6 family was specified, but no IPv6 addresses
+were found, then return IPv4 mapped IPv6 addresses.
// Easy DNS A/AAAA look up
-// lookup(hostname, [family,] callback)
-exports.lookup = function(hostname, family, callback) {
- // parse arguments
- if (arguments.length === 2) {
- callback = family;
+// lookup(hostname, [options,] callback)
+exports.lookup = function lookup(hostname, options, callback) {
+ var hints = 0;
+ var family;
+
+ // Parse arguments
+ if (typeof options === 'function') {
+ callback = options;
family = 0;
- } else if (!family) {
+ // Allow user to pass falsy values to options, and still pass callback.
+ } else if (typeof callback !== 'function') {
+ throw TypeError('invalid arguments: callback must be passed');
+ } else if (!options) {
family = 0;
- } else {
- family = +family;
- if (family !== 4 && family !== 6) {
- throw new Error('invalid argument: `family` must be 4 or 6');
+ } else if (util.isObject(options)) {
+ hints = options.hints >>> 0;
+ family = options.family >>> 0;
+
+ if (hints !== 0 &&
+ hints !== exports.ADDRCONFIG &&
+ hints !== exports.V4MAPPED &&
+ hints !== (exports.ADDRCONFIG | exports.V4MAPPED)) {
+ throw new TypeError('invalid argument: hints must use valid flags');
}
+ } else {
+ family = options >>> 0;
}
+
+ if (family !== 0 && family !== 4 && family !== 6)
+ throw new TypeError('invalid argument: family must be 4 or 6');
+
callback = makeAsync(callback);
if (!hostname) {
oncomplete: onlookup
};
- var err = cares.getaddrinfo(req, hostname, family);
+ var err = cares.getaddrinfo(req, hostname, family, hints);
if (err) {
callback(errnoException(err, 'getaddrinfo', hostname));
return {};
}
};
+// uv_getaddrinfo flags
+exports.ADDRCONFIG = cares.AI_ADDRCONFIG;
+exports.V4MAPPED = cares.AI_V4MAPPED;
// ERROR CODES
exports.NODATA = 'ENODATA';
connect(self, self._host, options.port, 4);
} else {
+ var dns = require('dns');
var host = options.host;
- var family = options.family || 4;
+ var dnsopts = {
+ family: options.family,
+ hints: 0
+ };
+
+ if (dnsopts.family !== 4 && dnsopts.family !== 6)
+ dnsopts.hints = dns.ADDRCONFIG | dns.V4MAPPED;
+
debug('connect: find host ' + host);
+ debug('connect: dns options ' + dnsopts);
self._host = host;
- require('dns').lookup(host, family, function(err, ip, addressType) {
+ dns.lookup(host, dnsopts, function(err, ip, addressType) {
self.emit('lookup', err, ip, addressType);
// It's possible we were destroyed while looking this up.
assert(args[0]->IsObject());
assert(args[1]->IsString());
assert(args[2]->IsInt32());
+ assert(args[3]->IsInt32());
Local<Object> req_wrap_obj = args[0].As<Object>();
node::Utf8Value hostname(args[1]);
int family;
+ int32_t flags = args[3]->Int32Value();
+
switch (args[2]->Int32Value()) {
case 0:
family = AF_UNSPEC;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = flags;
int err = uv_getaddrinfo(env->event_loop(),
&req_wrap->req_,
Integer::New(env->isolate(), AF_INET6));
target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AF_UNSPEC"),
Integer::New(env->isolate(), AF_UNSPEC));
+ target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AI_ADDRCONFIG"),
+ Integer::New(env->isolate(), AI_ADDRCONFIG));
+ target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AI_V4MAPPED"),
+ Integer::New(env->isolate(), AI_V4MAPPED));
}
} // namespace cares_wrap
});
+TEST(function test_lookup_ipv4_explicit_object(done) {
+ var req = dns.lookup('www.google.com', {
+ family: 4
+ }, function(err, ip, family) {
+ if (err) throw err;
+ assert.ok(net.isIPv4(ip));
+ assert.strictEqual(family, 4);
+
+ done();
+ });
+
+ checkWrap(req);
+});
+
+
+TEST(function test_lookup_ipv4_hint_addrconfig(done) {
+ var req = dns.lookup('www.google.com', {
+ hint: dns.ADDRCONFIG
+ }, function(err, ip, family) {
+ if (err) throw err;
+ assert.ok(net.isIPv4(ip));
+ assert.strictEqual(family, 4);
+
+ done();
+ });
+
+ checkWrap(req);
+});
+
+
TEST(function test_lookup_ipv6_explicit(done) {
var req = dns.lookup('ipv6.google.com', 6, function(err, ip, family) {
if (err) throw err;
*/
+TEST(function test_lookup_ipv6_explicit_object(done) {
+ var req = dns.lookup('ipv6.google.com', {
+ family: 6
+ }, function(err, ip, family) {
+ if (err) throw err;
+ assert.ok(net.isIPv6(ip));
+ assert.strictEqual(family, 6);
+
+ done();
+ });
+
+ checkWrap(req);
+});
+
+
+TEST(function test_lookup_ipv6_hint(done) {
+ var req = dns.lookup('ipv6.google.com', {
+ hint: dns.V4MAPPED
+ }, function(err, ip, family) {
+ if (err) throw err;
+ assert.ok(net.isIPv6(ip));
+ assert.strictEqual(family, 6);
+
+ done();
+ });
+
+ checkWrap(req);
+});
+
+
TEST(function test_lookup_failure(done) {
var req = dns.lookup('does.not.exist', 4, function(err, ip, family) {
assert.ok(err instanceof Error);
var existing = dns.getServers();
assert(existing.length);
+function noop() {}
+
var goog = [
'8.8.8.8',
'8.8.4.4',
assert.doesNotThrow(function () { dns.setServers([]); });
assert.deepEqual(dns.getServers(), []);
-assert.throws(
- function() {
- dns.resolve('test.com', [], new Function);
- },
- function(err) {
- return !(err instanceof TypeError);
- },
- "Unexpected error"
-);
+assert.throws(function() {
+ dns.resolve('test.com', [], noop);
+}, function(err) {
+ return !(err instanceof TypeError);
+}, 'Unexpected error');
+
+assert.throws(function() {
+ dns.lookup('www.google.com', { hints: 1 }, noop);
+});
+
+assert.throws(function() {
+ dns.lookup('www.google.com');
+}, 'invalid arguments: callback must be passed');
+
+assert.throws(function() {
+ dns.lookup('www.google.com', 4);
+}, 'invalid arguments: callback must be passed');
+
+assert.doesNotThrow(function() {
+ dns.lookup('www.google.com', 6, noop);
+});
+
+assert.doesNotThrow(function() {
+ dns.lookup('www.google.com', {}, noop);
+});
+
+assert.doesNotThrow(function() {
+ dns.lookup('www.google.com', {
+ family: 4,
+ hints: 0
+ }, noop);
+});
+
+assert.doesNotThrow(function() {
+ dns.lookup('www.google.com', {
+ family: 6,
+ hints: dns.ADDRCONFIG
+ }, noop);
+});
+
+assert.doesNotThrow(function() {
+ dns.lookup('www.google.com', {
+ hints: dns.V4MAPPED
+ }, noop);
+});
+
+assert.doesNotThrow(function() {
+ dns.lookup('www.google.com', {
+ hints: dns.ADDRCONFIG | dns.V4MAPPED
+ }, noop);
+});