Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dns: add order option and support ipv6first #52492

Merged
merged 4 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -594,16 +594,20 @@ added:
- v16.4.0
- v14.18.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/52492
description: The `ipv6first` is supported now.
- version: v17.0.0
pr-url: https://github.com/nodejs/node/pull/39987
description: Changed default value to `verbatim`.
-->

Set the default value of `verbatim` in [`dns.lookup()`][] and
Set the default value of `order` in [`dns.lookup()`][] and
[`dnsPromises.lookup()`][]. The value could be:

* `ipv4first`: sets default `verbatim` `false`.
* `verbatim`: sets default `verbatim` `true`.
* `ipv4first`: sets default `order` to `ipv4first`.
* `ipv6first`: sets default `order` to `ipv6first`.
* `verbatim`: sets default `order` to `verbatim`.

The default is `verbatim` and [`dns.setDefaultResultOrder()`][] have higher
priority than `--dns-result-order`.
Expand Down
62 changes: 50 additions & 12 deletions doc/api/dns.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ section if a custom port is used.
<!-- YAML
added: v0.1.90
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/52492
description: The `verbatim` option is now deprecated in favor of the new `order` option.
- version: v18.4.0
pr-url: https://github.com/nodejs/node/pull/43054
description: For compatibility with `node:net`, when passing an option
Expand Down Expand Up @@ -211,9 +214,18 @@ 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. **Default:** `false`.
* `order` {string} When `verbatim`, the resolved addresses are return
unsorted. When `ipv4first`, the resolved addresses are sorted by placing
IPv4 addresses before IPv6 addresses. When `ipv6first`, the resolved
addresses are sorted by placing IPv6 addresses before IPv4 addresses.
**Default:** `verbatim` (addresses are not reordered).
Default value is configurable using [`dns.setDefaultResultOrder()`][] or
[`--dns-result-order`][].
* `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.
This option will be deprecated in favor of `order`. When both are specified,
`order` has higher precedence. New code should only use `order`.
**Default:** `true` (addresses are not reordered). Default value is
configurable using [`dns.setDefaultResultOrder()`][] or
[`--dns-result-order`][].
Expand Down Expand Up @@ -775,18 +787,22 @@ added:
- v16.4.0
- v14.18.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/52492
description: The `ipv6first` value is supported now.
- version: v17.0.0
pr-url: https://github.com/nodejs/node/pull/39987
description: Changed default value to `verbatim`.
-->

* `order` {string} must be `'ipv4first'` or `'verbatim'`.
* `order` {string} must be `'ipv4first'`, `'ipv6first'` or `'verbatim'`.

Set the default value of `verbatim` in [`dns.lookup()`][] and
Set the default value of `order` in [`dns.lookup()`][] and
[`dnsPromises.lookup()`][]. The value could be:

* `ipv4first`: sets default `verbatim` `false`.
* `verbatim`: sets default `verbatim` `true`.
* `ipv4first`: sets default `order` to `ipv4first`.
* `ipv6first`: sets default `order` to `ipv6first`.
* `verbatim`: sets default `order` to `verbatim`.

The default is `verbatim` and [`dns.setDefaultResultOrder()`][] have higher
priority than [`--dns-result-order`][]. When using [worker threads][],
Expand All @@ -799,13 +815,18 @@ dns orders in workers.
added:
- v20.1.0
- v18.17.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/52492
description: The `ipv6first` value is supported now.
-->

Get the default value for `verbatim` in [`dns.lookup()`][] and
Get the default value for `order` in [`dns.lookup()`][] and
[`dnsPromises.lookup()`][]. The value could be:

* `ipv4first`: for `verbatim` defaulting to `false`.
* `verbatim`: for `verbatim` defaulting to `true`.
* `ipv4first`: for `order` defaulting to `ipv4first`.
* `ipv6first`: for `order` defaulting to `ipv6first`.
* `verbatim`: for `order` defaulting to `verbatim`.

## `dns.setServers(servers)`

Expand Down Expand Up @@ -949,6 +970,10 @@ section if a custom port is used.

<!-- YAML
added: v10.6.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/52492
description: The `verbatim` option is now deprecated in favor of the new `order` option.
-->

* `hostname` {string}
Expand All @@ -961,13 +986,22 @@ added: v10.6.0
flags may be passed by bitwise `OR`ing their values.
* `all` {boolean} When `true`, the `Promise` is resolved with all addresses in
an array. Otherwise, returns a single address. **Default:** `false`.
* `order` {string} When `verbatim`, the `Promise` is resolved with IPv4 and
IPv6 addresses in the order the DNS resolver returned them. When `ipv4first`,
IPv4 addresses are placed before IPv6 addresses. When `ipv6first`,
IPv6 addresses are placed before IPv4 addresses.
**Default:** `verbatim` (addresses are not reordered).
Default value is configurable using [`dns.setDefaultResultOrder()`][] or
[`--dns-result-order`][]. New code should use `{ order: 'verbatim' }`.
* `verbatim` {boolean} When `true`, the `Promise` is resolved with IPv4 and
IPv6 addresses in the order the DNS resolver returned them. When `false`,
IPv4 addresses are placed before IPv6 addresses.
This option will be deprecated in favor of `order`. When both are specified,
`order` has higher precedence. New code should only use `order`.
**Default:** currently `false` (addresses are reordered) but this is
expected to change in the not too distant future. Default value is
configurable using [`dns.setDefaultResultOrder()`][] or
[`--dns-result-order`][]. New code should use `{ verbatim: true }`.
[`--dns-result-order`][].

Resolves a host name (e.g. `'nodejs.org'`) into the first found A (IPv4) or
AAAA (IPv6) record. All `option` properties are optional. If `options` is an
Expand Down Expand Up @@ -1349,18 +1383,22 @@ added:
- v16.4.0
- v14.18.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/52492
description: The `ipv6first` value is supported now.
- version: v17.0.0
pr-url: https://github.com/nodejs/node/pull/39987
description: Changed default value to `verbatim`.
-->

* `order` {string} must be `'ipv4first'` or `'verbatim'`.
* `order` {string} must be `'ipv4first'`, `'ipv6first'` or `'verbatim'`.

Set the default value of `verbatim` in [`dns.lookup()`][] and
Set the default value of `order` in [`dns.lookup()`][] and
[`dnsPromises.lookup()`][]. The value could be:

* `ipv4first`: sets default `verbatim` `false`.
* `verbatim`: sets default `verbatim` `true`.
* `ipv4first`: sets default `order` to `ipv4first`.
* `ipv6first`: sets default `order` to `ipv6first`.
* `verbatim`: sets default `order` to `verbatim`.

The default is `verbatim` and [`dnsPromises.setDefaultResultOrder()`][] have
higher priority than [`--dns-result-order`][]. When using [worker threads][],
Expand Down
26 changes: 21 additions & 5 deletions lib/dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ const {
setDefaultResolver,
validateHints,
emitInvalidHostnameWarning,
getDefaultVerbatim,
getDefaultResultOrder,
setDefaultResultOrder,
errorCodes: dnsErrorCodes,
Expand Down Expand Up @@ -89,6 +88,9 @@ const {
const {
GetAddrInfoReqWrap,
GetNameInfoReqWrap,
DNS_ORDER_VERBATIM,
DNS_ORDER_IPV4_FIRST,
DNS_ORDER_IPV6_FIRST,
} = cares;

const kPerfHooksDnsLookupContext = Symbol('kPerfHooksDnsLookupContext');
Expand Down Expand Up @@ -141,7 +143,7 @@ function lookup(hostname, options, callback) {
let hints = 0;
let family = 0;
let all = false;
let verbatim = getDefaultVerbatim();
let dnsOrder = getDefaultResultOrder();

// Parse arguments
if (hostname) {
Expand Down Expand Up @@ -187,7 +189,11 @@ function lookup(hostname, options, callback) {
}
if (options?.verbatim != null) {
validateBoolean(options.verbatim, 'options.verbatim');
verbatim = options.verbatim;
dnsOrder = options.verbatim ? 'verbatim' : 'ipv4first';
}
if (options?.order != null) {
validateOneOf(options.order, 'options.order', ['ipv4first', 'ipv6first', 'verbatim']);
dnsOrder = options.dnsOrder;
}
}

Expand Down Expand Up @@ -218,8 +224,16 @@ function lookup(hostname, options, callback) {
req.hostname = hostname;
req.oncomplete = all ? onlookupall : onlookup;

let order = DNS_ORDER_VERBATIM;

if (dnsOrder === 'ipv4first') {
order = DNS_ORDER_IPV4_FIRST;
} else if (dnsOrder === 'ipv6first') {
order = DNS_ORDER_IPV6_FIRST;
}

const err = cares.getaddrinfo(
req, hostname, family, hints, verbatim,
req, hostname, family, hints, order,
);
if (err) {
process.nextTick(callback, new DNSException(err, 'getaddrinfo', hostname));
Expand All @@ -230,8 +244,10 @@ function lookup(hostname, options, callback) {
hostname,
family,
hints,
verbatim,
verbatim: order === DNS_ORDER_VERBATIM,
order: dnsOrder,
};

startPerf(req, kPerfHooksDnsLookupContext, { type: 'dns', name: 'lookup', detail });
}
return req;
Expand Down
36 changes: 26 additions & 10 deletions lib/internal/dns/promises.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ const {
createResolverClass,
validateHints,
emitInvalidHostnameWarning,
getDefaultVerbatim,
errorCodes: dnsErrorCodes,
getDefaultResultOrder,
setDefaultResultOrder,
Expand Down Expand Up @@ -53,6 +52,9 @@ const {
GetAddrInfoReqWrap,
GetNameInfoReqWrap,
QueryReqWrap,
DNS_ORDER_VERBATIM,
DNS_ORDER_IPV4_FIRST,
DNS_ORDER_IPV6_FIRST,
} = internalBinding('cares_wrap');
const {
ERR_INVALID_ARG_TYPE,
Expand Down Expand Up @@ -120,13 +122,13 @@ function onlookupall(err, addresses) {
* @param {boolean} all - Whether to resolve with all IP addresses for the hostname.
* @param {number} hints - One or more supported getaddrinfo flags (supply multiple via
* bitwise OR).
* @param {boolean} verbatim - Whether to use the hostname verbatim.
* @param {number} dnsOrder - How to sort results. Must be `ipv4first`, `ipv6first` or `verbatim`.
* @returns {Promise<DNSLookupResult | DNSLookupResult[]>} The IP address(es) of the hostname.
* @typedef {object} DNSLookupResult
* @property {string} address - The IP address.
* @property {0 | 4 | 6} family - The IP address type. 4 for IPv4 or 6 for IPv6, or 0 (for both).
*/
function createLookupPromise(family, hostname, all, hints, verbatim) {
function createLookupPromise(family, hostname, all, hints, dnsOrder) {
return new Promise((resolve, reject) => {
if (!hostname) {
emitInvalidHostnameWarning(hostname);
Expand All @@ -150,7 +152,15 @@ function createLookupPromise(family, hostname, all, hints, verbatim) {
req.resolve = resolve;
req.reject = reject;

const err = getaddrinfo(req, hostname, family, hints, verbatim);
let order = DNS_ORDER_VERBATIM;

if (dnsOrder === 'ipv4first') {
order = DNS_ORDER_IPV4_FIRST;
} else if (dnsOrder === 'ipv6first') {
order = DNS_ORDER_IPV6_FIRST;
}

const err = getaddrinfo(req, hostname, family, hints, order);

if (err) {
reject(new DNSException(err, 'getaddrinfo', hostname));
Expand All @@ -159,7 +169,8 @@ function createLookupPromise(family, hostname, all, hints, verbatim) {
hostname,
family,
hints,
verbatim,
verbatim: order === DNS_ORDER_VERBATIM,
order: dnsOrder,
};
startPerf(req, kPerfHooksDnsLookupContext, { type: 'dns', name: 'lookup', detail });
}
Expand All @@ -175,14 +186,15 @@ const validFamilies = [0, 4, 6];
* @param {0 | 4 | 6} [options.family=0] - The record family. Must be 4, 6, or 0 (for both).
* @param {number} [options.hints] - One or more supported getaddrinfo flags (supply multiple via
* bitwise OR).
* @param {boolean} [options.verbatim=false] - Return results in same order DNS resolved them;
* otherwise IPv4 then IPv6. New code should supply `true`.
* @param {string} [options.order='verbatim'] - Return results in same order DNS resolved them;
* Must be `ipv4first`, `ipv6first` or `verbatim`.
* New code should supply `verbatim`.
*/
function lookup(hostname, options) {
let hints = 0;
let family = 0;
let all = false;
let verbatim = getDefaultVerbatim();
let dnsOrder = getDefaultResultOrder();

// Parse arguments
if (hostname) {
Expand Down Expand Up @@ -210,11 +222,15 @@ function lookup(hostname, options) {
}
if (options?.verbatim != null) {
validateBoolean(options.verbatim, 'options.verbatim');
verbatim = options.verbatim;
dnsOrder = options.verbatim ? 'verbatim' : 'ipv4first';
}
if (options?.order != null) {
validateOneOf(options.order, 'options.order', ['ipv4first', 'ipv6first', 'verbatim']);
dnsOrder = options.order;
}
}

return createLookupPromise(family, hostname, all, hints, verbatim);
return createLookupPromise(family, hostname, all, hints, dnsOrder);
}


Expand Down
8 changes: 2 additions & 6 deletions lib/internal/dns/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ function initializeDns() {
dnsOrder ??= 'verbatim';
} else {
// Allow the deserialized application to override order from CLI.
validateOneOf(orderFromCLI, '--dns-result-order', ['verbatim', 'ipv4first', 'ipv6first']);
dnsOrder = orderFromCLI;
}

Expand Down Expand Up @@ -277,12 +278,8 @@ function emitInvalidHostnameWarning(hostname) {
}
}

function getDefaultVerbatim() {
return dnsOrder !== 'ipv4first';
}

function setDefaultResultOrder(value) {
validateOneOf(value, 'dnsOrder', ['verbatim', 'ipv4first']);
validateOneOf(value, 'dnsOrder', ['verbatim', 'ipv4first', 'ipv6first']);
dnsOrder = value;
}

Expand Down Expand Up @@ -351,7 +348,6 @@ module.exports = {
validateTimeout,
validateTries,
emitInvalidHostnameWarning,
getDefaultVerbatim,
getDefaultResultOrder,
setDefaultResultOrder,
errorCodes,
Expand Down
2 changes: 1 addition & 1 deletion lib/internal/modules/esm/fetch_module.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ async function isLocalAddress(hostname) {
) {
hostname = StringPrototypeSlice(hostname, 1, -1);
}
const addr = await dnsLookup(hostname, { verbatim: true });
const addr = await dnsLookup(hostname, { order: 'verbatim' });
const ipv = addr.family === 4 ? 'ipv4' : 'ipv6';
return allowList.check(addr.address, ipv);
} catch {
Expand Down
Loading