diff --git a/lib/dns.js b/lib/dns.js index 92b55f03595f45..979d724c3e4aa5 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -24,7 +24,7 @@ const util = require('util'); const cares = process.binding('cares_wrap'); -const { isLegalPort } = require('internal/net'); +const { isIP, isIPv4, isLegalPort } = require('internal/net'); const { customPromisifyArgs } = require('internal/util'); const errors = require('internal/errors'); const { @@ -38,7 +38,6 @@ const { GetNameInfoReqWrap, QueryReqWrap, ChannelWrap, - isIP } = cares; function errnoException(err, syscall, hostname) { @@ -66,30 +65,6 @@ function errnoException(err, syscall, hostname) { } const IANA_DNS_PORT = 53; -const digits = [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48-63 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64-79 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-95 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 96-111 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 112-127 -]; -function isIPv4(str) { - if (!digits[str.charCodeAt(0)]) return false; - if (str.length === 1) return false; - if (str.charCodeAt(1) === 46/*'.'*/) - return true; - else if (!digits[str.charCodeAt(1)]) - return false; - if (str.length === 2) return false; - if (str.charCodeAt(2) === 46/*'.'*/) - return true; - else if (!digits[str.charCodeAt(2)]) - return false; - return (str.length > 3 && str.charCodeAt(3) === 46/*'.'*/); -} function onlookup(err, addresses) { diff --git a/lib/internal/net.js b/lib/internal/net.js index 847539d576906d..adaa4475b02232 100644 --- a/lib/internal/net.js +++ b/lib/internal/net.js @@ -1,8 +1,22 @@ 'use strict'; const Buffer = require('buffer').Buffer; +const { isIPv6 } = process.binding('cares_wrap'); const { writeBuffer } = process.binding('fs'); +const octet = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; +const re = new RegExp(`^${octet}[.]${octet}[.]${octet}[.]${octet}$`); + +function isIPv4(s) { + return re.test(s); +} + +function isIP(s) { + if (isIPv4(s)) return 4; + if (isIPv6(s)) return 6; + return 0; +} + // Check that the port number is not NaN when coerced to a number, // is an integer and that it falls within the legal range of port numbers. function isLegalPort(port) { @@ -33,6 +47,9 @@ function makeSyncWrite(fd) { } module.exports = { + isIP, + isIPv4, + isIPv6, isLegalPort, makeSyncWrite, normalizedArgsSymbol: Symbol('normalizedArgs') diff --git a/lib/net.js b/lib/net.js index 16d0b9605c594a..44a870fd209153 100644 --- a/lib/net.js +++ b/lib/net.js @@ -27,12 +27,14 @@ const timers = require('timers'); const util = require('util'); const internalUtil = require('internal/util'); const { + isIP, + isIPv4, + isIPv6, isLegalPort, normalizedArgsSymbol, makeSyncWrite } = require('internal/net'); const assert = require('assert'); -const cares = process.binding('cares_wrap'); const { UV_EADDRINUSE, UV_EINVAL, @@ -1066,7 +1068,7 @@ function lookupAndConnect(self, options) { var localAddress = options.localAddress; var localPort = options.localPort; - if (localAddress && !cares.isIP(localAddress)) { + if (localAddress && !isIP(localAddress)) { throw new errors.TypeError('ERR_INVALID_IP_ADDRESS', localAddress); } @@ -1091,7 +1093,7 @@ function lookupAndConnect(self, options) { port |= 0; // If host is an IP, skip performing a lookup - var addressType = cares.isIP(host); + var addressType = isIP(host); if (addressType) { nextTick(self[async_id_symbol], function() { if (self.connecting) @@ -1775,9 +1777,9 @@ module.exports = { connect, createConnection: connect, createServer, - isIP: cares.isIP, - isIPv4: cares.isIPv4, - isIPv6: cares.isIPv6, + isIP: isIP, + isIPv4: isIPv4, + isIPv6: isIPv6, Server, Socket, Stream: Socket, // Legacy naming diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index de3cb8f89c1ea2..191e3c92dcc308 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -1876,60 +1876,32 @@ void AfterGetNameInfo(uv_getnameinfo_t* req, delete req_wrap; } - -void IsIP(const FunctionCallbackInfo& args) { - node::Utf8Value ip(args.GetIsolate(), args[0]); - char address_buffer[sizeof(struct in6_addr)]; - - int rc = 0; - if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 0) - rc = 4; - else if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 0) - rc = 6; - - args.GetReturnValue().Set(rc); -} - -void IsIPv4(const FunctionCallbackInfo& args) { - node::Utf8Value ip(args.GetIsolate(), args[0]); - char address_buffer[sizeof(struct in_addr)]; - - if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 0) { - args.GetReturnValue().Set(true); - } else { - args.GetReturnValue().Set(false); - } +using ParseIPResult = decltype(static_cast(0)->addr); + +int ParseIP(const char* ip, ParseIPResult* result = nullptr) { + ParseIPResult tmp; + if (result == nullptr) result = &tmp; + if (0 == uv_inet_pton(AF_INET, ip, result)) return 4; + if (0 == uv_inet_pton(AF_INET6, ip, result)) return 6; + return 0; } void IsIPv6(const FunctionCallbackInfo& args) { node::Utf8Value ip(args.GetIsolate(), args[0]); - char address_buffer[sizeof(struct in6_addr)]; - - if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 0) { - args.GetReturnValue().Set(true); - } else { - args.GetReturnValue().Set(false); - } + args.GetReturnValue().Set(6 == ParseIP(*ip)); } void CanonicalizeIP(const FunctionCallbackInfo& args) { v8::Isolate* isolate = args.GetIsolate(); node::Utf8Value ip(isolate, args[0]); - char address_buffer[sizeof(struct in6_addr)]; - char canonical_ip[INET6_ADDRSTRLEN]; - int af; - if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 0) - af = AF_INET; - else if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 0) - af = AF_INET6; - else - return; - - int err = uv_inet_ntop(af, address_buffer, canonical_ip, - sizeof(canonical_ip)); - CHECK_EQ(err, 0); + ParseIPResult result; + const int rc = ParseIP(*ip, &result); + if (rc == 0) return; + char canonical_ip[INET6_ADDRSTRLEN]; + const int af = (rc == 4 ? AF_INET : AF_INET6); + CHECK_EQ(0, uv_inet_ntop(af, &result, canonical_ip, sizeof(canonical_ip))); args.GetReturnValue().Set(String::NewFromUtf8(isolate, canonical_ip)); } @@ -2156,8 +2128,6 @@ void Initialize(Local target, env->SetMethod(target, "getaddrinfo", GetAddrInfo); env->SetMethod(target, "getnameinfo", GetNameInfo); - env->SetMethod(target, "isIP", IsIP); - env->SetMethod(target, "isIPv4", IsIPv4); env->SetMethod(target, "isIPv6", IsIPv6); env->SetMethod(target, "canonicalizeIP", CanonicalizeIP);