summaryrefslogtreecommitdiff
path: root/ext/node/polyfills/dns.ts
diff options
context:
space:
mode:
Diffstat (limited to 'ext/node/polyfills/dns.ts')
-rw-r--r--ext/node/polyfills/dns.ts1012
1 files changed, 1012 insertions, 0 deletions
diff --git a/ext/node/polyfills/dns.ts b/ext/node/polyfills/dns.ts
new file mode 100644
index 000000000..7b8752e13
--- /dev/null
+++ b/ext/node/polyfills/dns.ts
@@ -0,0 +1,1012 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+import { nextTick } from "internal:deno_node/polyfills/_next_tick.ts";
+import { customPromisifyArgs } from "internal:deno_node/polyfills/internal/util.mjs";
+import {
+ validateBoolean,
+ validateFunction,
+ validateNumber,
+ validateOneOf,
+ validateString,
+} from "internal:deno_node/polyfills/internal/validators.mjs";
+import { isIP } from "internal:deno_node/polyfills/internal/net.ts";
+import {
+ emitInvalidHostnameWarning,
+ getDefaultResolver,
+ getDefaultVerbatim,
+ isFamily,
+ isLookupCallback,
+ isLookupOptions,
+ isResolveCallback,
+ Resolver as CallbackResolver,
+ setDefaultResolver,
+ setDefaultResultOrder,
+ validateHints,
+} from "internal:deno_node/polyfills/internal/dns/utils.ts";
+import type {
+ AnyAaaaRecord,
+ AnyARecord,
+ AnyCnameRecord,
+ AnyMxRecord,
+ AnyNaptrRecord,
+ AnyNsRecord,
+ AnyPtrRecord,
+ AnyRecord,
+ AnySoaRecord,
+ AnySrvRecord,
+ AnyTxtRecord,
+ CaaRecord,
+ LookupAddress,
+ LookupAllOptions,
+ LookupOneOptions,
+ LookupOptions,
+ MxRecord,
+ NaptrRecord,
+ Records,
+ RecordWithTtl,
+ ResolveCallback,
+ ResolveOptions,
+ ResolverOptions,
+ ResolveWithTtlOptions,
+ SoaRecord,
+ SrvRecord,
+} from "internal:deno_node/polyfills/internal/dns/utils.ts";
+import promisesBase from "internal:deno_node/polyfills/internal/dns/promises.ts";
+import type { ErrnoException } from "internal:deno_node/polyfills/internal/errors.ts";
+import {
+ dnsException,
+ ERR_INVALID_ARG_TYPE,
+ ERR_INVALID_ARG_VALUE,
+} from "internal:deno_node/polyfills/internal/errors.ts";
+import {
+ AI_ADDRCONFIG as ADDRCONFIG,
+ AI_ALL as ALL,
+ AI_V4MAPPED as V4MAPPED,
+} from "internal:deno_node/polyfills/internal_binding/ares.ts";
+import {
+ ChannelWrapQuery,
+ getaddrinfo,
+ GetAddrInfoReqWrap,
+ QueryReqWrap,
+} from "internal:deno_node/polyfills/internal_binding/cares_wrap.ts";
+import { toASCII } from "internal:deno_node/polyfills/internal/idna.ts";
+import { notImplemented } from "internal:deno_node/polyfills/_utils.ts";
+
+function onlookup(
+ this: GetAddrInfoReqWrap,
+ err: number | null,
+ addresses: string[],
+) {
+ if (err) {
+ return this.callback(dnsException(err, "getaddrinfo", this.hostname));
+ }
+
+ this.callback(null, addresses[0], this.family || isIP(addresses[0]));
+}
+
+function onlookupall(
+ this: GetAddrInfoReqWrap,
+ err: number | null,
+ addresses: string[],
+) {
+ if (err) {
+ return this.callback(dnsException(err, "getaddrinfo", this.hostname));
+ }
+
+ const family = this.family;
+ const parsedAddresses = [];
+
+ for (let i = 0; i < addresses.length; i++) {
+ const addr = addresses[i];
+ parsedAddresses[i] = {
+ address: addr,
+ family: family || isIP(addr),
+ };
+ }
+
+ this.callback(null, parsedAddresses);
+}
+
+type LookupCallback = (
+ err: ErrnoException | null,
+ addressOrAddresses?: string | LookupAddress[] | null,
+ family?: number,
+) => void;
+
+const validFamilies = [0, 4, 6];
+
+// Easy DNS A/AAAA look up
+// lookup(hostname, [options,] callback)
+export function lookup(
+ hostname: string,
+ family: number,
+ callback: (
+ err: ErrnoException | null,
+ address: string,
+ family: number,
+ ) => void,
+): GetAddrInfoReqWrap | Record<string, never>;
+export function lookup(
+ hostname: string,
+ options: LookupOneOptions,
+ callback: (
+ err: ErrnoException | null,
+ address: string,
+ family: number,
+ ) => void,
+): GetAddrInfoReqWrap | Record<string, never>;
+export function lookup(
+ hostname: string,
+ options: LookupAllOptions,
+ callback: (err: ErrnoException | null, addresses: LookupAddress[]) => void,
+): GetAddrInfoReqWrap | Record<string, never>;
+export function lookup(
+ hostname: string,
+ options: LookupOptions,
+ callback: (
+ err: ErrnoException | null,
+ address: string | LookupAddress[],
+ family: number,
+ ) => void,
+): GetAddrInfoReqWrap | Record<string, never>;
+export function lookup(
+ hostname: string,
+ callback: (
+ err: ErrnoException | null,
+ address: string,
+ family: number,
+ ) => void,
+): GetAddrInfoReqWrap | Record<string, never>;
+export function lookup(
+ hostname: string,
+ options: unknown,
+ callback?: unknown,
+): GetAddrInfoReqWrap | Record<string, never> {
+ let hints = 0;
+ let family = 0;
+ let all = false;
+ let verbatim = getDefaultVerbatim();
+
+ // Parse arguments
+ if (hostname) {
+ validateString(hostname, "hostname");
+ }
+
+ if (isLookupCallback(options)) {
+ callback = options;
+ family = 0;
+ } else if (isFamily(options)) {
+ validateFunction(callback, "callback");
+
+ validateOneOf(options, "family", validFamilies);
+ family = options;
+ } else if (!isLookupOptions(options)) {
+ validateFunction(arguments.length === 2 ? options : callback, "callback");
+
+ throw new ERR_INVALID_ARG_TYPE("options", ["integer", "object"], options);
+ } else {
+ validateFunction(callback, "callback");
+
+ if (options?.hints != null) {
+ validateNumber(options.hints, "options.hints");
+ hints = options.hints >>> 0;
+ validateHints(hints);
+ }
+
+ if (options?.family != null) {
+ validateOneOf(options.family, "options.family", validFamilies);
+ family = options.family;
+ }
+
+ if (options?.all != null) {
+ validateBoolean(options.all, "options.all");
+ all = options.all;
+ }
+
+ if (options?.verbatim != null) {
+ validateBoolean(options.verbatim, "options.verbatim");
+ verbatim = options.verbatim;
+ }
+ }
+
+ if (!hostname) {
+ emitInvalidHostnameWarning(hostname);
+
+ if (all) {
+ nextTick(callback as LookupCallback, null, []);
+ } else {
+ nextTick(callback as LookupCallback, null, null, family === 6 ? 6 : 4);
+ }
+
+ return {};
+ }
+
+ const matchedFamily = isIP(hostname);
+
+ if (matchedFamily) {
+ if (all) {
+ nextTick(callback as LookupCallback, null, [
+ { address: hostname, family: matchedFamily },
+ ]);
+ } else {
+ nextTick(callback as LookupCallback, null, hostname, matchedFamily);
+ }
+
+ return {};
+ }
+
+ const req = new GetAddrInfoReqWrap();
+ req.callback = callback as LookupCallback;
+ req.family = family;
+ req.hostname = hostname;
+ req.oncomplete = all ? onlookupall : onlookup;
+
+ const err = getaddrinfo(req, toASCII(hostname), family, hints, verbatim);
+
+ if (err) {
+ nextTick(
+ callback as LookupCallback,
+ dnsException(err, "getaddrinfo", hostname),
+ );
+
+ return {};
+ }
+
+ return req;
+}
+
+Object.defineProperty(lookup, customPromisifyArgs, {
+ value: ["address", "family"],
+ enumerable: false,
+});
+
+function onresolve(
+ this: QueryReqWrap,
+ err: number,
+ records: Records,
+ ttls?: number[],
+) {
+ if (err) {
+ this.callback(dnsException(err, this.bindingName, this.hostname));
+
+ return;
+ }
+
+ const parsedRecords = ttls && this.ttl
+ ? (records as string[]).map((address: string, index: number) => ({
+ address,
+ ttl: ttls[index],
+ }))
+ : records;
+
+ this.callback(null, parsedRecords);
+}
+
+function resolver(bindingName: keyof ChannelWrapQuery) {
+ function query(
+ this: Resolver,
+ name: string,
+ options: unknown,
+ callback?: unknown,
+ ): QueryReqWrap {
+ if (isResolveCallback(options)) {
+ callback = options;
+ options = {};
+ }
+
+ validateString(name, "name");
+ validateFunction(callback, "callback");
+
+ const req = new QueryReqWrap();
+ req.bindingName = bindingName;
+ req.callback = callback as ResolveCallback;
+ req.hostname = name;
+ req.oncomplete = onresolve;
+
+ if (options && (options as ResolveOptions).ttl) {
+ notImplemented("dns.resolve* with ttl option");
+ }
+
+ req.ttl = !!(options && (options as ResolveOptions).ttl);
+
+ const err = this._handle[bindingName](req, toASCII(name));
+
+ if (err) {
+ throw dnsException(err, bindingName, name);
+ }
+
+ return req;
+ }
+
+ Object.defineProperty(query, "name", { value: bindingName });
+
+ return query;
+}
+
+const resolveMap = Object.create(null);
+
+export class Resolver extends CallbackResolver {
+ constructor(options?: ResolverOptions) {
+ super(options);
+ }
+
+ // deno-lint-ignore no-explicit-any
+ [resolveMethod: string]: any;
+}
+
+Resolver.prototype.resolveAny = resolveMap.ANY = resolver("queryAny");
+Resolver.prototype.resolve4 = resolveMap.A = resolver("queryA");
+Resolver.prototype.resolve6 = resolveMap.AAAA = resolver("queryAaaa");
+Resolver.prototype.resolveCaa = resolveMap.CAA = resolver("queryCaa");
+Resolver.prototype.resolveCname = resolveMap.CNAME = resolver("queryCname");
+Resolver.prototype.resolveMx = resolveMap.MX = resolver("queryMx");
+Resolver.prototype.resolveNs = resolveMap.NS = resolver("queryNs");
+Resolver.prototype.resolveTxt = resolveMap.TXT = resolver("queryTxt");
+Resolver.prototype.resolveSrv = resolveMap.SRV = resolver("querySrv");
+Resolver.prototype.resolvePtr = resolveMap.PTR = resolver("queryPtr");
+Resolver.prototype.resolveNaptr = resolveMap.NAPTR = resolver("queryNaptr");
+Resolver.prototype.resolveSoa = resolveMap.SOA = resolver("querySoa");
+Resolver.prototype.reverse = resolver("getHostByAddr");
+Resolver.prototype.resolve = _resolve;
+
+function _resolve(
+ this: Resolver,
+ hostname: string,
+ rrtype: unknown,
+ callback?: unknown,
+): QueryReqWrap {
+ let resolver: Resolver;
+
+ if (typeof hostname !== "string") {
+ throw new ERR_INVALID_ARG_TYPE("name", "string", hostname);
+ }
+
+ if (typeof rrtype === "string") {
+ resolver = resolveMap[rrtype];
+ } else if (typeof rrtype === "function") {
+ resolver = resolveMap.A;
+ callback = rrtype;
+ } else {
+ throw new ERR_INVALID_ARG_TYPE("rrtype", "string", rrtype);
+ }
+
+ if (typeof resolver === "function") {
+ return Reflect.apply(resolver, this, [hostname, callback]);
+ }
+
+ throw new ERR_INVALID_ARG_VALUE("rrtype", rrtype);
+}
+
+/**
+ * Sets the IP address and port of servers to be used when performing DNS
+ * resolution. The `servers` argument is an array of [RFC 5952](https://tools.ietf.org/html/rfc5952#section-6) formatted
+ * addresses. If the port is the IANA default DNS port (53) it can be omitted.
+ *
+ * ```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.
+ *
+ * The `dns.setServers()` method must not be called while a DNS query is in
+ * progress.
+ *
+ * The `setServers` method affects only `resolve`,`dns.resolve*()` and `reverse` (and specifically _not_ `lookup`).
+ *
+ * This method works much like [resolve.conf](https://man7.org/linux/man-pages/man5/resolv.conf.5.html).
+ * That is, if attempting to resolve with the first server provided results in a
+ * `NOTFOUND` error, the `resolve()` method will _not_ attempt to resolve with
+ * subsequent servers provided. Fallback DNS servers will only be used if the
+ * earlier ones time out or result in some other error.
+ *
+ * @param servers array of `RFC 5952` formatted addresses
+ */
+export function setServers(servers: ReadonlyArray<string>) {
+ const resolver = new Resolver();
+
+ resolver.setServers(servers);
+ setDefaultResolver(resolver);
+}
+
+// The Node implementation uses `bindDefaultResolver` to set the follow methods
+// on `module.exports` bound to the current `defaultResolver`. We don't have
+// the same ability in ESM but can simulate this (at some cost) by explicitly
+// exporting these methods which dynamically bind to the default resolver when
+// called.
+
+/**
+ * Returns an array of IP address strings, formatted according to [RFC 5952](https://tools.ietf.org/html/rfc5952#section-6),
+ * that are currently configured for DNS resolution. A string will include a port
+ * section if a custom port is used.
+ *
+ * ```js
+ * [
+ * '4.4.4.4',
+ * '2001:4860:4860::8888',
+ * '4.4.4.4:1053',
+ * '[2001:4860:4860::8888]:1053',
+ * ]
+ * ```
+ */
+export function getServers(): string[] {
+ return Resolver.prototype.getServers.bind(getDefaultResolver())();
+}
+
+/**
+ * Uses the DNS protocol to resolve all records (also known as `ANY` or `*` query).
+ * The `ret` argument passed to the `callback` function will be an array containing
+ * various types of records. Each object has a property `type` that indicates the
+ * type of the current record. And depending on the `type`, additional properties
+ * will be present on the object.
+ *
+ * Here is an example of the `ret` object passed to the callback:
+ *
+ * ```js
+ * [ { type: 'A', address: '127.0.0.1', ttl: 299 },
+ * { type: 'CNAME', value: 'example.com' },
+ * { type: 'MX', exchange: 'alt4.aspmx.l.example.com', priority: 50 },
+ * { type: 'NS', value: 'ns1.example.com' },
+ * { type: 'TXT', entries: [ 'v=spf1 include:_spf.example.com ~all' ] },
+ * { type: 'SOA',
+ * nsname: 'ns1.example.com',
+ * hostmaster: 'admin.example.com',
+ * serial: 156696742,
+ * refresh: 900,
+ * retry: 900,
+ * expire: 1800,
+ * minttl: 60 } ]
+ * ```
+ *
+ * DNS server operators may choose not to respond to `ANY` queries. It may be
+ * better to call individual methods like `resolve4`, `resolveMx`, and so on.
+ * For more details, see [RFC 8482](https://tools.ietf.org/html/rfc8482).
+ */
+export function resolveAny(
+ hostname: string,
+ callback: (err: ErrnoException | null, addresses: AnyRecord[]) => void,
+): QueryReqWrap;
+export function resolveAny(...args: unknown[]): QueryReqWrap {
+ return Resolver.prototype.resolveAny.bind(getDefaultResolver() as Resolver)(
+ ...args,
+ );
+}
+
+/**
+ * Uses the DNS protocol to resolve a IPv4 addresses (`A` records) for the
+ * `hostname`. The `addresses` argument passed to the `callback` function will
+ * contain an array of IPv4 addresses (e.g. `['74.125.79.104', '74.125.79.105','74.125.79.106']`).
+ *
+ * @param hostname Host name to resolve.
+ */
+export function resolve4(
+ hostname: string,
+ callback: (err: ErrnoException | null, addresses: string[]) => void,
+): void;
+export function resolve4(
+ hostname: string,
+ options: ResolveWithTtlOptions,
+ callback: (err: ErrnoException | null, addresses: RecordWithTtl[]) => void,
+): void;
+export function resolve4(
+ hostname: string,
+ options: ResolveOptions,
+ callback: (
+ err: ErrnoException | null,
+ addresses: string[] | RecordWithTtl[],
+ ) => void,
+): void;
+export function resolve4(
+ hostname: string,
+ options: unknown,
+ callback?: unknown,
+) {
+ return Resolver.prototype.resolve4.bind(getDefaultResolver() as Resolver)(
+ hostname,
+ options,
+ callback,
+ );
+}
+
+/**
+ * Uses the DNS protocol to resolve a IPv6 addresses (`AAAA` records) for the
+ * `hostname`. The `addresses` argument passed to the `callback` function
+ * will contain an array of IPv6 addresses.
+ *
+ * @param hostname Host name to resolve.
+ */
+export function resolve6(
+ hostname: string,
+ callback: (err: ErrnoException | null, addresses: string[]) => void,
+): void;
+export function resolve6(
+ hostname: string,
+ options: ResolveWithTtlOptions,
+ callback: (err: ErrnoException | null, addresses: RecordWithTtl[]) => void,
+): void;
+export function resolve6(
+ hostname: string,
+ options: ResolveOptions,
+ callback: (
+ err: ErrnoException | null,
+ addresses: string[] | RecordWithTtl[],
+ ) => void,
+): void;
+export function resolve6(
+ hostname: string,
+ options: unknown,
+ callback?: unknown,
+) {
+ return Resolver.prototype.resolve6.bind(getDefaultResolver() as Resolver)(
+ hostname,
+ options,
+ callback,
+ );
+}
+
+/**
+ * Uses the DNS protocol to resolve `CAA` records for the `hostname`. The
+ * `addresses` argument passed to the `callback` function will contain an array
+ * of certification authority authorization records available for the
+ * `hostname` (e.g. `[{critical: 0, iodef: 'mailto:pki@example.com'}, {critical: 128, issue: 'pki.example.com'}]`).
+ */
+export function resolveCaa(
+ hostname: string,
+ callback: (err: ErrnoException | null, records: CaaRecord[]) => void,
+): QueryReqWrap;
+export function resolveCaa(...args: unknown[]): QueryReqWrap {
+ return Resolver.prototype.resolveCaa.bind(getDefaultResolver() as Resolver)(
+ ...args,
+ );
+}
+
+/**
+ * Uses the DNS protocol to resolve `CNAME` records for the `hostname`. The
+ * `addresses` argument passed to the `callback` function will contain an array
+ * of canonical name records available for the `hostname`(e.g. `['bar.example.com']`).
+ */
+export function resolveCname(
+ hostname: string,
+ callback: (err: ErrnoException | null, addresses: string[]) => void,
+): QueryReqWrap;
+export function resolveCname(...args: unknown[]): QueryReqWrap {
+ return Resolver.prototype.resolveCname.bind(getDefaultResolver() as Resolver)(
+ ...args,
+ );
+}
+
+/**
+ * Uses the DNS protocol to resolve mail exchange records (`MX` records) for the
+ * `hostname`. The `addresses` argument passed to the `callback` function will
+ * contain an array of objects containing both a `priority` and `exchange`
+ * property (e.g. `[{priority: 10, exchange: 'mx.example.com'}, ...]`).
+ */
+export function resolveMx(
+ hostname: string,
+ callback: (err: ErrnoException | null, addresses: MxRecord[]) => void,
+): QueryReqWrap;
+export function resolveMx(...args: unknown[]): QueryReqWrap {
+ return Resolver.prototype.resolveMx.bind(getDefaultResolver() as Resolver)(
+ ...args,
+ );
+}
+
+/**
+ * Uses the DNS protocol to resolve name server records (`NS` records) for the
+ * `hostname`. The `addresses` argument passed to the `callback` function will
+ * contain an array of name server records available for `hostname`
+ * (e.g. `['ns1.example.com', 'ns2.example.com']`).
+ */
+export function resolveNs(
+ hostname: string,
+ callback: (err: ErrnoException | null, addresses: string[]) => void,
+): QueryReqWrap;
+export function resolveNs(...args: unknown[]): QueryReqWrap {
+ return Resolver.prototype.resolveNs.bind(getDefaultResolver() as Resolver)(
+ ...args,
+ );
+}
+
+/**
+ * Uses the DNS protocol to resolve text queries (`TXT` records) for the
+ * `hostname`. The `records` argument passed to the `callback` function is a
+ * two-dimensional array of the text records available for `hostname`
+ * (e.g.`[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]`). Each sub-array contains TXT
+ * chunks of one record. Depending on the use case, these could be either
+ * joined together or treated separately.
+ */
+export function resolveTxt(
+ hostname: string,
+ callback: (err: ErrnoException | null, addresses: string[][]) => void,
+): QueryReqWrap;
+export function resolveTxt(...args: unknown[]): QueryReqWrap {
+ return Resolver.prototype.resolveTxt.bind(getDefaultResolver() as Resolver)(
+ ...args,
+ );
+}
+
+/**
+ * Uses the DNS protocol to resolve service records (`SRV` records) for the
+ * `hostname`. The `addresses` argument passed to the `callback` function will
+ * be an array of objects with the following properties:
+ *
+ * - `priority`
+ * - `weight`
+ * - `port`
+ * - `name`
+ *
+ * ```js
+ * {
+ * priority: 10,
+ * weight: 5,
+ * port: 21223,
+ * name: 'service.example.com'
+ * }
+ * ```
+ */
+export function resolveSrv(
+ hostname: string,
+ callback: (err: ErrnoException | null, addresses: SrvRecord[]) => void,
+): QueryReqWrap;
+export function resolveSrv(...args: unknown[]): QueryReqWrap {
+ return Resolver.prototype.resolveSrv.bind(getDefaultResolver() as Resolver)(
+ ...args,
+ );
+}
+
+/**
+ * Uses the DNS protocol to resolve pointer records (`PTR` records) for the
+ * `hostname`. The `addresses` argument passed to the `callback` function will
+ * be an array of strings containing the reply records.
+ */
+export function resolvePtr(
+ hostname: string,
+ callback: (err: ErrnoException | null, addresses: string[]) => void,
+): QueryReqWrap;
+export function resolvePtr(...args: unknown[]): QueryReqWrap {
+ return Resolver.prototype.resolvePtr.bind(getDefaultResolver() as Resolver)(
+ ...args,
+ );
+}
+
+/**
+ * Uses the DNS protocol to resolve regular expression based records (`NAPTR`
+ * records) for the `hostname`. The `addresses` argument passed to the
+ * `callback` function will contain an array of objects with the following
+ * properties:
+ *
+ * - `flags`
+ * - `service`
+ * - `regexp`
+ * - `replacement`
+ * - `order`
+ * - `preference`
+ *
+ * ```js
+ * {
+ * flags: 's',
+ * service: 'SIP+D2U',
+ * regexp: '',
+ * replacement: '_sip._udp.example.com',
+ * order: 30,
+ * preference: 100
+ * }
+ * ```
+ */
+export function resolveNaptr(
+ hostname: string,
+ callback: (err: ErrnoException | null, addresses: NaptrRecord[]) => void,
+): QueryReqWrap;
+export function resolveNaptr(...args: unknown[]): QueryReqWrap {
+ return Resolver.prototype.resolveNaptr.bind(getDefaultResolver() as Resolver)(
+ ...args,
+ );
+}
+
+/**
+ * Uses the DNS protocol to resolve a start of authority record (`SOA` record) for
+ * the `hostname`. The `address` argument passed to the `callback` function will
+ * be an object with the following properties:
+ *
+ * - `nsname`
+ * - `hostmaster`
+ * - `serial`
+ * - `refresh`
+ * - `retry`
+ * - `expire`
+ * - `minttl`
+ *
+ * ```js
+ * {
+ * nsname: 'ns.example.com',
+ * hostmaster: 'root.example.com',
+ * serial: 2013101809,
+ * refresh: 10000,
+ * retry: 2400,
+ * expire: 604800,
+ * minttl: 3600
+ * }
+ * ```
+ */
+export function resolveSoa(
+ hostname: string,
+ callback: (err: ErrnoException | null, address: SoaRecord) => void,
+): QueryReqWrap;
+export function resolveSoa(...args: unknown[]): QueryReqWrap {
+ return Resolver.prototype.resolveSoa.bind(getDefaultResolver() as Resolver)(
+ ...args,
+ );
+}
+
+/**
+ * Performs a reverse DNS query that resolves an IPv4 or IPv6 address to an
+ * array of host names.
+ *
+ * On error, `err` is an `Error` object, where `err.code` is
+ * one of the `DNS error codes`.
+ */
+export function reverse(
+ ip: string,
+ callback: (err: ErrnoException | null, hostnames: string[]) => void,
+): QueryReqWrap;
+export function reverse(...args: unknown[]): QueryReqWrap {
+ return Resolver.prototype.reverse.bind(getDefaultResolver() as Resolver)(
+ ...args,
+ );
+}
+
+/**
+ * Uses the DNS protocol to resolve a host name (e.g. `'nodejs.org'`) into an array
+ * of the resource records. The `callback` function has arguments`(err, records)`.]
+ * When successful, `records` will be an array of resource
+ * records. The type and structure of individual results varies based on `rrtype`.
+ *
+ * On error, `err` is an `Error` object, where `err.code` is one of the DNS error codes.
+ *
+ * @param hostname Host name to resolve.
+ * @param [rrtype='A'] Resource record type.
+ */
+export function resolve(
+ hostname: string,
+ callback: (err: ErrnoException | null, addresses: string[]) => void,
+): QueryReqWrap;
+export function resolve(
+ hostname: string,
+ rrtype: "A",
+ callback: (err: ErrnoException | null, addresses: string[]) => void,
+): QueryReqWrap;
+export function resolve(
+ hostname: string,
+ rrtype: "AAAA",
+ callback: (err: ErrnoException | null, addresses: string[]) => void,
+): QueryReqWrap;
+export function resolve(
+ hostname: string,
+ rrtype: "ANY",
+ callback: (err: ErrnoException | null, addresses: AnyRecord[]) => void,
+): QueryReqWrap;
+export function resolve(
+ hostname: string,
+ rrtype: "CNAME",
+ callback: (err: ErrnoException | null, addresses: string[]) => void,
+): QueryReqWrap;
+export function resolve(
+ hostname: string,
+ rrtype: "MX",
+ callback: (err: ErrnoException | null, addresses: MxRecord[]) => void,
+): QueryReqWrap;
+export function resolve(
+ hostname: string,
+ rrtype: "NAPTR",
+ callback: (err: ErrnoException | null, addresses: NaptrRecord[]) => void,
+): QueryReqWrap;
+export function resolve(
+ hostname: string,
+ rrtype: "NS",
+ callback: (err: ErrnoException | null, addresses: string[]) => void,
+): QueryReqWrap;
+export function resolve(
+ hostname: string,
+ rrtype: "PTR",
+ callback: (err: ErrnoException | null, addresses: string[]) => void,
+): QueryReqWrap;
+export function resolve(
+ hostname: string,
+ rrtype: "SOA",
+ callback: (err: ErrnoException | null, addresses: SoaRecord) => void,
+): QueryReqWrap;
+export function resolve(
+ hostname: string,
+ rrtype: "SRV",
+ callback: (err: ErrnoException | null, addresses: SrvRecord[]) => void,
+): QueryReqWrap;
+export function resolve(
+ hostname: string,
+ rrtype: "TXT",
+ callback: (err: ErrnoException | null, addresses: string[][]) => void,
+): QueryReqWrap;
+export function resolve(
+ hostname: string,
+ rrtype: string,
+ callback: (
+ err: ErrnoException | null,
+ addresses:
+ | string[]
+ | MxRecord[]
+ | NaptrRecord[]
+ | SoaRecord
+ | SrvRecord[]
+ | string[][]
+ | AnyRecord[],
+ ) => void,
+): QueryReqWrap;
+export function resolve(hostname: string, rrtype: unknown, callback?: unknown) {
+ return Resolver.prototype.resolve.bind(getDefaultResolver() as Resolver)(
+ hostname,
+ rrtype,
+ callback,
+ );
+}
+
+// ERROR CODES
+export const NODATA = "ENODATA";
+export const FORMERR = "EFORMERR";
+export const SERVFAIL = "ESERVFAIL";
+export const NOTFOUND = "ENOTFOUND";
+export const NOTIMP = "ENOTIMP";
+export const REFUSED = "EREFUSED";
+export const BADQUERY = "EBADQUERY";
+export const BADNAME = "EBADNAME";
+export const BADFAMILY = "EBADFAMILY";
+export const BADRESP = "EBADRESP";
+export const CONNREFUSED = "ECONNREFUSED";
+export const TIMEOUT = "ETIMEOUT";
+export const EOF = "EOF";
+export const FILE = "EFILE";
+export const NOMEM = "ENOMEM";
+export const DESTRUCTION = "EDESTRUCTION";
+export const BADSTR = "EBADSTR";
+export const BADFLAGS = "EBADFLAGS";
+export const NONAME = "ENONAME";
+export const BADHINTS = "EBADHINTS";
+export const NOTINITIALIZED = "ENOTINITIALIZED";
+export const LOADIPHLPAPI = "ELOADIPHLPAPI";
+export const ADDRGETNETWORKPARAMS = "EADDRGETNETWORKPARAMS";
+export const CANCELLED = "ECANCELLED";
+
+const promises = {
+ ...promisesBase,
+ setDefaultResultOrder,
+ setServers,
+
+ // ERROR CODES
+ NODATA,
+ FORMERR,
+ SERVFAIL,
+ NOTFOUND,
+ NOTIMP,
+ REFUSED,
+ BADQUERY,
+ BADNAME,
+ BADFAMILY,
+ BADRESP,
+ CONNREFUSED,
+ TIMEOUT,
+ EOF,
+ FILE,
+ NOMEM,
+ DESTRUCTION,
+ BADSTR,
+ BADFLAGS,
+ NONAME,
+ BADHINTS,
+ NOTINITIALIZED,
+ LOADIPHLPAPI,
+ ADDRGETNETWORKPARAMS,
+ CANCELLED,
+};
+
+export { ADDRCONFIG, ALL, promises, setDefaultResultOrder, V4MAPPED };
+
+export type {
+ AnyAaaaRecord,
+ AnyARecord,
+ AnyCnameRecord,
+ AnyMxRecord,
+ AnyNaptrRecord,
+ AnyNsRecord,
+ AnyPtrRecord,
+ AnyRecord,
+ AnySoaRecord,
+ AnySrvRecord,
+ AnyTxtRecord,
+ CaaRecord,
+ LookupAddress,
+ LookupAllOptions,
+ LookupOneOptions,
+ LookupOptions,
+ MxRecord,
+ NaptrRecord,
+ Records,
+ RecordWithTtl,
+ ResolveCallback,
+ ResolveOptions,
+ ResolverOptions,
+ ResolveWithTtlOptions,
+ SoaRecord,
+ SrvRecord,
+};
+
+export default {
+ ADDRCONFIG,
+ ALL,
+ V4MAPPED,
+ lookup,
+ getServers,
+ resolveAny,
+ resolve4,
+ resolve6,
+ resolveCaa,
+ resolveCname,
+ resolveMx,
+ resolveNs,
+ resolveTxt,
+ resolveSrv,
+ resolvePtr,
+ resolveNaptr,
+ resolveSoa,
+ resolve,
+ Resolver,
+ reverse,
+ setServers,
+ setDefaultResultOrder,
+ promises,
+ NODATA,
+ FORMERR,
+ SERVFAIL,
+ NOTFOUND,
+ NOTIMP,
+ REFUSED,
+ BADQUERY,
+ BADNAME,
+ BADFAMILY,
+ BADRESP,
+ CONNREFUSED,
+ TIMEOUT,
+ EOF,
+ FILE,
+ NOMEM,
+ DESTRUCTION,
+ BADSTR,
+ BADFLAGS,
+ NONAME,
+ BADHINTS,
+ NOTINITIALIZED,
+ LOADIPHLPAPI,
+ ADDRGETNETWORKPARAMS,
+ CANCELLED,
+};