| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -117,6 +117,27 @@ added: v8.3.0 | |||
| 117 | 117 | Cancel all outstanding DNS queries made by this resolver. The corresponding | |
| 118 | 118 | callbacks will be called with an error with code `ECANCELLED`. | |
| 119 | 119 | ||
| 120 | + ### `resolver.setLocalAddress([ipv4][, ipv6])` | ||
| 121 | + <!-- YAML | ||
| 122 | + added: REPLACEME | ||
| 123 | + --> | ||
| 124 | + | ||
| 125 | + * `ipv4` {string} A string representation of an IPv4 address. | ||
| 126 | + **Default:** `'0.0.0.0'` | ||
| 127 | + * `ipv6` {string} A string representation of an IPv6 address. | ||
| 128 | + **Default:** `'::0'` | ||
| 129 | + | ||
| 130 | + The resolver instance will send its requests from the specified IP address. | ||
| 131 | + This allows programs to specify outbound interfaces when used on multi-homed | ||
| 132 | + systems. | ||
| 133 | + | ||
| 134 | + If a v4 or v6 address is not specified, it is set to the default, and the | ||
| 135 | + operating system will choose a local address automatically. | ||
| 136 | + | ||
| 137 | + The resolver will use the v4 local address when making requests to IPv4 DNS | ||
| 138 | + servers, and the v6 local address when making requests to IPv6 DNS servers. | ||
| 139 | + The `rrtype` of resolution requests has no impact on the local address used. | ||
| 140 | + | ||
| 120 | 141 | ## `dns.getServers()` | |
| 121 | 142 | <!-- YAML | |
| 122 | 143 | added: v0.11.3 | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -217,6 +217,7 @@ class Resolver { | |||
| 217 | 217 | ||
| 218 | 218 | Resolver.prototype.getServers = CallbackResolver.prototype.getServers; | |
| 219 | 219 | Resolver.prototype.setServers = CallbackResolver.prototype.setServers; | |
| 220 | + Resolver.prototype.setLocalAddress = CallbackResolver.prototype.setLocalAddress; | ||
| 220 | 221 | Resolver.prototype.resolveAny = resolveMap.ANY = resolver('queryAny'); | |
| 221 | 222 | Resolver.prototype.resolve4 = resolveMap.A = resolver('queryA'); | |
| 222 | 223 | Resolver.prototype.resolve6 = resolveMap.AAAA = resolver('queryAaaa'); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -114,6 +114,18 @@ class Resolver { | |||
| 114 | 114 | throw new ERR_DNS_SET_SERVERS_FAILED(err, servers); | |
| 115 | 115 | } | |
| 116 | 116 | } | |
| 117 | + | ||
| 118 | + setLocalAddress(ipv4, ipv6) { | ||
| 119 | + if (typeof ipv4 !== 'string') { | ||
| 120 | + throw new ERR_INVALID_ARG_TYPE('ipv4', 'String', ipv4); | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + if (typeof ipv6 !== 'string' && ipv6 !== undefined) { | ||
| 124 | + throw new ERR_INVALID_ARG_TYPE('ipv6', ['String', 'undefined'], ipv6); | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + this._handle.setLocalAddress(ipv4, ipv6); | ||
| 128 | + } | ||
| 117 | 129 | } | |
| 118 | 130 | ||
| 119 | 131 | let defaultResolver = new Resolver(); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -29,6 +29,7 @@ | |||
| 29 | 29 | #include "req_wrap-inl.h" | |
| 30 | 30 | #include "util-inl.h" | |
| 31 | 31 | #include "uv.h" | |
| 32 | + #include "node_errors.h" | ||
| 32 | 33 | ||
| 33 | 34 | #include <cerrno> | |
| 34 | 35 | #include <cstring> | |
@@ -2227,6 +2228,70 @@ void SetServers(const FunctionCallbackInfo<Value>& args) { | |||
| 2227 | 2228 | args.GetReturnValue().Set(err); | |
| 2228 | 2229 | } | |
| 2229 | 2230 | ||
| 2231 | + void SetLocalAddress(const FunctionCallbackInfo<Value>& args) { | ||
| 2232 | + Environment* env = Environment::GetCurrent(args); | ||
| 2233 | + ChannelWrap* channel; | ||
| 2234 | + ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder()); | ||
| 2235 | + | ||
| 2236 | + CHECK_EQ(args.Length(), 2); | ||
| 2237 | + CHECK(args[0]->IsString()); | ||
| 2238 | + | ||
| 2239 | + Isolate* isolate = args.GetIsolate(); | ||
| 2240 | + node::Utf8Value ip0(isolate, args[0]); | ||
| 2241 | + | ||
| 2242 | + unsigned char addr0[sizeof(struct in6_addr)]; | ||
| 2243 | + unsigned char addr1[sizeof(struct in6_addr)]; | ||
| 2244 | + int type0 = 0; | ||
| 2245 | + | ||
| 2246 | + // This function accepts 2 arguments. The first may be either an IPv4 | ||
| 2247 | + // address or an IPv6 address. If present, the second argument must be the | ||
| 2248 | + // other type of address. Otherwise, the unspecified type of IP is set | ||
| 2249 | + // to 0 (any). | ||
| 2250 | + | ||
| 2251 | + if (uv_inet_pton(AF_INET, *ip0, &addr0) == 0) { | ||
| 2252 | + ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr0)); | ||
| 2253 | + type0 = 4; | ||
| 2254 | + } else if (uv_inet_pton(AF_INET6, *ip0, &addr0) == 0) { | ||
| 2255 | + ares_set_local_ip6(channel->cares_channel(), addr0); | ||
| 2256 | + type0 = 6; | ||
| 2257 | + } else { | ||
| 2258 | + THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address."); | ||
| 2259 | + return; | ||
| 2260 | + } | ||
| 2261 | + | ||
| 2262 | + if (!args[1]->IsUndefined()) { | ||
| 2263 | + CHECK(args[1]->IsString()); | ||
| 2264 | + node::Utf8Value ip1(isolate, args[1]); | ||
| 2265 | + | ||
| 2266 | + if (uv_inet_pton(AF_INET, *ip1, &addr1) == 0) { | ||
| 2267 | + if (type0 == 4) { | ||
| 2268 | + THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv4 addresses."); | ||
| 2269 | + return; | ||
| 2270 | + } else { | ||
| 2271 | + ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr1)); | ||
| 2272 | + } | ||
| 2273 | + } else if (uv_inet_pton(AF_INET6, *ip1, &addr1) == 0) { | ||
| 2274 | + if (type0 == 6) { | ||
| 2275 | + THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv6 addresses."); | ||
| 2276 | + return; | ||
| 2277 | + } else { | ||
| 2278 | + ares_set_local_ip6(channel->cares_channel(), addr1); | ||
| 2279 | + } | ||
| 2280 | + } else { | ||
| 2281 | + THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address."); | ||
| 2282 | + return; | ||
| 2283 | + } | ||
| 2284 | + } else { | ||
| 2285 | + // No second arg specifed | ||
| 2286 | + if (type0 == 4) { | ||
| 2287 | + memset(&addr1, 0, sizeof(addr1)); | ||
| 2288 | + ares_set_local_ip6(channel->cares_channel(), addr1); | ||
| 2289 | + } else { | ||
| 2290 | + ares_set_local_ip4(channel->cares_channel(), 0); | ||
| 2291 | + } | ||
| 2292 | + } | ||
| 2293 | + } | ||
| 2294 | + | ||
| 2230 | 2295 | void Cancel(const FunctionCallbackInfo<Value>& args) { | |
| 2231 | 2296 | ChannelWrap* channel; | |
| 2232 | 2297 | ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder()); | |
@@ -2329,6 +2394,7 @@ void Initialize(Local<Object> target, | |||
| 2329 | 2394 | ||
| 2330 | 2395 | env->SetProtoMethodNoSideEffect(channel_wrap, "getServers", GetServers); | |
| 2331 | 2396 | env->SetProtoMethod(channel_wrap, "setServers", SetServers); | |
| 2397 | + env->SetProtoMethod(channel_wrap, "setLocalAddress", SetLocalAddress); | ||
| 2332 | 2398 | env->SetProtoMethod(channel_wrap, "cancel", Cancel); | |
| 2333 | 2399 | ||
| 2334 | 2400 | Local<String> channelWrapString = | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,37 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + require('../common'); | ||
| 3 | + const assert = require('assert'); | ||
| 4 | + | ||
| 5 | + const dns = require('dns'); | ||
| 6 | + const resolver = new dns.Resolver(); | ||
| 7 | + const promiseResolver = new dns.promises.Resolver(); | ||
| 8 | + | ||
| 9 | + // Verifies that setLocalAddress succeeds with IPv4 and IPv6 addresses | ||
| 10 | + { | ||
| 11 | + resolver.setLocalAddress('127.0.0.1'); | ||
| 12 | + resolver.setLocalAddress('::1'); | ||
| 13 | + resolver.setLocalAddress('127.0.0.1', '::1'); | ||
| 14 | + promiseResolver.setLocalAddress('127.0.0.1', '::1'); | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + // Verify that setLocalAddress throws if called with an invalid address | ||
| 18 | + { | ||
| 19 | + assert.throws(() => { | ||
| 20 | + resolver.setLocalAddress('127.0.0.1', '127.0.0.1'); | ||
| 21 | + }, Error); | ||
| 22 | + assert.throws(() => { | ||
| 23 | + resolver.setLocalAddress('::1', '::1'); | ||
| 24 | + }, Error); | ||
| 25 | + assert.throws(() => { | ||
| 26 | + resolver.setLocalAddress('bad'); | ||
| 27 | + }, Error); | ||
| 28 | + assert.throws(() => { | ||
| 29 | + resolver.setLocalAddress(123); | ||
| 30 | + }, Error); | ||
| 31 | + assert.throws(() => { | ||
| 32 | + resolver.setLocalAddress(); | ||
| 33 | + }, Error); | ||
| 34 | + assert.throws(() => { | ||
| 35 | + promiseResolver.setLocalAddress(); | ||
| 36 | + }, Error); | ||
| 37 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments