diff --git a/.codeclimate.yml b/.codeclimate.yml
index d44ff41..de2068e 100644
--- a/.codeclimate.yml
+++ b/.codeclimate.yml
@@ -1,13 +1,13 @@
engines:
eslint:
enabled: true
- channel: "eslint-8"
+ channel: 'eslint-8'
config:
- config: ".eslintrc.yaml"
+ config: '.eslintrc.yaml'
ratings:
- paths:
- - "**.js"
+ paths:
+ - '**.js'
checks:
return-statements:
diff --git a/.eslintrc.yaml b/.eslintrc.yaml
index 6313e7c..035a400 100644
--- a/.eslintrc.yaml
+++ b/.eslintrc.yaml
@@ -2,16 +2,6 @@ env:
node: true
es6: true
mocha: true
- es2020: true
+ es2022: true
-plugins:
- - haraka
-
-extends:
- - eslint:recommended
- - plugin:haraka/recommended
-
-root: true
-
-rules:
- indent: [2, 2, { SwitchCase: 1 } ]
\ No newline at end of file
+extends: ['@haraka']
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index c05ac3b..b969775 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,10 +1,10 @@
version: 2
updates:
- - package-ecosystem: "npm"
+ - package-ecosystem: 'npm'
# Look for `package.json` and `lock` files in the `root` directory
- directory: "/"
+ directory: '/'
# Check the npm registry for updates every day (weekdays)
schedule:
- interval: "monthly"
+ interval: 'monthly'
allow:
- - dependency-type: "production"
\ No newline at end of file
+ - dependency-type: 'production'
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 752f845..7034b75 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,6 +1,6 @@
name: CI
-on: [ pull_request, push ]
+on: [pull_request, push]
env:
CI: true
@@ -14,9 +14,9 @@ jobs:
secrets: inherit
test:
- needs: [ lint ]
+ needs: [lint]
uses: haraka/.github/.github/workflows/ubuntu.yml@master
windows:
- needs: [ lint ]
+ needs: [lint]
uses: haraka/.github/.github/workflows/windows.yml@master
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 3627451..8314a66 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -2,10 +2,10 @@ name: CodeQL
on:
push:
- branches: [ master ]
+ branches: [master]
pull_request:
# The branches below must be a subset of the branches above
- branches: [ master ]
+ branches: [master]
schedule:
- cron: '18 7 * * 4'
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index d489fbd..e81c15f 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -13,4 +13,4 @@ env:
jobs:
publish:
uses: haraka/.github/.github/workflows/publish.yml@master
- secrets: inherit
\ No newline at end of file
+ secrets: inherit
diff --git a/.npmignore b/.npmignore
deleted file mode 100644
index fa00e1b..0000000
--- a/.npmignore
+++ /dev/null
@@ -1,59 +0,0 @@
-# Logs
-logs
-*.log
-npm-debug.log*
-
-# Runtime data
-pids
-*.pid
-*.seed
-
-# Directory for instrumented libs generated by jscoverage/JSCover
-lib-cov
-
-# Coverage directory used by tools like istanbul
-coverage
-
-# nyc test coverage
-.nyc_output
-
-# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
-.grunt
-
-# node-waf configuration
-.lock-wscript
-
-# Compiled binary addons (http://nodejs.org/api/addons.html)
-build/Release
-
-# Dependency directories
-node_modules
-jspm_packages
-
-# Optional npm cache directory
-.npm
-
-# Optional REPL history
-.node_repl_history
-
-package-lock.json
-bower_components
-# Optional npm cache directory
-.npmrc
-.idea
-.DS_Store
-haraka-update.sh
-
-.github
-.release
-.codeclimate.yml
-.editorconfig
-.gitignore
-.gitmodules
-.lgtm.yml
-appveyor.yml
-codecov.yml
-.travis.yml
-.eslintrc.yaml
-.eslintrc.json
-test
\ No newline at end of file
diff --git a/.prettierrc.yml b/.prettierrc.yml
new file mode 100644
index 0000000..8ded5e0
--- /dev/null
+++ b/.prettierrc.yml
@@ -0,0 +1,2 @@
+singleQuote: true
+semi: false
diff --git a/.release b/.release
index 954197d..36bb27a 160000
--- a/.release
+++ b/.release
@@ -1 +1 @@
-Subproject commit 954197dae07b32c4476ff87ec9ae7371311ec97d
+Subproject commit 36bb27a93862517943e04f24fd67b0df2da6cbbe
diff --git a/Changes.md b/CHANGELOG.md
similarity index 68%
rename from Changes.md
rename to CHANGELOG.md
index 7a3383c..761abc0 100644
--- a/Changes.md
+++ b/CHANGELOG.md
@@ -1,39 +1,50 @@
+# Changelog
-#### N.N.N - YYYY-MM-DD
+The format is based on [Keep a Changelog](https://keepachangelog.com/).
+
+### Unreleased
+
+### [1.6.0] - 2024-04-17
+
+- feat: normalizeDomain, for punycode/IDN names
+- feat: get_mx now _also_ returns implicit MX records
+- feat: added get_implicit_mx
+- feat: added resolve_mx_hosts
+- doc(Changes): fixed broken tag version links
+- doc(CONTRIBUTORS): added
+- chore: populate [files] in package.json. Delete .npmignore
+- chore(lint): remove duplicate / stale rules from .eslintrc
+- dep(punycode): punycode -> punycode.js (avoid name collission)
+- chore: refactored get_ips_by_host using Promise.allSettled
### [1.5.4] - 2024-04-02
- Add timeout to DNS Resolver (#83)
-
### [1.5.3] - 2023-12-15
- dep(punycode): override built-in with trailing /
-
### [1.5.2] - 2023-12-11
- dep(stun): use updated @msimerson/stun
-
### [1.5.1] - 2023-12-03
- feat(is_local_host): also match when
- - the mx dest is a hostname that matches our hostname
- - the mx dest matches our public IP (may not be locally bound)
+ - the mx dest is a hostname that matches our hostname
+ - the mx dest matches our public IP (may not be locally bound)
- bump dep versions #78
- test update for node v20 #78
- ci: enable CI tests on PRs #77
- test: increase DNS timeouts from 3s to 5s #77
-
### [1.5.0] - 2022-12-20
- feat: add async support for get_public_ip #75
- dep: replace vs-stun with stun
- doc: use async/await syntax in examples #74
-
### [1.4.1] - 2022-07-22
- feat(get_mx): use async/await
@@ -41,137 +52,113 @@
- test(get_mx): expand and improve test coverage
- chore(ci): use more shared haraka/.github workflows
-
### [1.3.7] - 2022-06-03
- ci: fix the dependabot allow syntax
-
### [1.3.6] - 2022-06-01
- chore: replace .release with submodule
- chore(ci): populate test matrix with Node.js LTS versions
- chore(ci): limit dependabot updates to production deps
-
-#### 1.3.5 - 2022-05-27
+#### [1.3.5] - 2022-05-27
- chore(ci): use shared GHA workflows
- style(es6): use dns.promises internally
- dep(async): replace async dependency with Promise.all
- doc(README): use code fences around examples (vs indention)
-
-#### 1.3.4 - 2022-01-05
+#### [1.3.4] - 2022-01-05
- promisify get_ips_by_host (backwards compatible)
-
-#### 1.3.3 - 2020-01-05
+#### [1.3.3] - 2020-01-05
- refactored is_local_host function to return a promise instead of using a callback #65
-
-#### 1.3.2 - 2021-12-20
+#### [1.3.2] - 2021-12-20
- add is_local_host function #63
-
-#### 1.3.1 - 2021-10-13
+#### [1.3.1] - 2021-10-13
- get_mx: wrap dns.resolveMx in a try haraka/Haraka#2985
- add .release scripts
- add GH workflow, publish release to NPM upon merge to master
-
#### 1.3.0 - 2021-01-23
- Support passing an array to ip_in_list #60
-
#### 1.2.4 - 2021-01-14
- add "any" IP to is_local_ip
- add TEST-NET-[1-3] to is_private_ip
-
#### 1.2.3 - 2020-12-19
- fix: restore the tests wrapping the resolveMX iterable
-
#### 1.2.2 - 2020-12-15
- get_mx: do not include implicit MX
-
-#### 1.2.1 - 2020-11-17
+#### [1.2.1] - 2020-11-17
- bump ipaddr.js to 2.0.0 #56
-
-#### 1.2.0 - 2020-06-23
+#### [1.2.0] - 2020-06-23
- added get_mx
- remove deprecated load_tls_ini
- remove deprecated tls_ini_section_with_defaults
-
#### 1.1.5 - 2020-04-11
- ipv6_bogus: handle parsing broken ipv6 addresses #49
- update async to version 3.0.1 #43
-
#### 1.1.4 - 2019-04-04
- stop is_private_ip from checking if the IP is bound to a local network interface
-
#### 1.1.3 - 2019-03-01
- is_local_ip checks local network interfaces too
-
#### 1.1.2 - 2018-11-03
- add is_local_ip
-
#### 1.1.1 - 2018-07-19
- ip_in_list doesn't throw on empty list
-
#### 1.1.0 - 2018-04-11
- add get_primary_host_name haraka/Haraka#2380
-
#### 1.0.14 - 2018-01-25
- restore tls_ini_section_with_defaults function (deprecated since Haraka 2.0.17)
-
#### 1.0.13 - 2018-01-19
- get_public_ip: assign timer before calling connect #29
- - avoid race where timeout isn't cleared because stun connect errors immediately
+ - avoid race where timeout isn't cleared because stun connect errors immediately
- remove TLS functions that have been subsumed into Haraka/tls_socket: tls_ini_section_with_defaults, parse_x509_names, parse_x509_expire, parse_x509, load_tls_dir
- convert concatenated strings to template literals #28
- eslint updates #25, #27
- improved x509 parser #22
-
#### 1.0.10 - 2017-07-27
- added vs-stun as optional dep (from Haraka) #21
-
#### 1.0.9 - 2017-06-16
-- lint fixes for compat with eslint 4 #18
-
+- lint fixes for compat with eslint 4 #18
#### 1.0.8 - 2017-03-08
@@ -180,39 +167,42 @@
- rename certs -> cert (be consistent with haraka/plugins/tls)
- store cert/key as buffers (was strings)
-
#### 1.0.7 - 2017-03-08
- handle undefined tls.ini section
-
#### 1.0.6 - 2017-03-04
- add tls_ini_section_with_defaults()
- add load_tls_dir()
- add parse_x509_names()
-
#### 1.0.5 - 2016-11-20
-* add enableSNI TLS option
-
+- add enableSNI TLS option
#### 1.0.4 - 2016-10-25
-* initialize TLS opts in (section != main) as booleans
-
+- initialize TLS opts in (section != main) as booleans
#### 1.0.3 - 2016-10-25
-* added tls.ini loading
-
+- added tls.ini loading
+[1.2.0]: https://github.com/haraka/haraka-net-utils/releases/tag/1.2.0
+[1.2.1]: https://github.com/haraka/haraka-net-utils/releases/tag/1.2.1
+[1.3.1]: https://github.com/haraka/haraka-net-utils/releases/tag/1.3.1
+[1.3.2]: https://github.com/haraka/haraka-net-utils/releases/tag/1.3.2
+[1.3.3]: https://github.com/haraka/haraka-net-utils/releases/tag/1.3.3
+[1.3.4]: https://github.com/haraka/haraka-net-utils/releases/tag/1.3.4
+[1.3.5]: https://github.com/haraka/haraka-net-utils/releases/tag/1.3.5
[1.3.6]: https://github.com/haraka/haraka-net-utils/releases/tag/1.3.6
-[1.3.7]: https://github.com/haraka/haraka-net-utils/releases/tag/1.3.7
-[1.4.1]: https://github.com/haraka/haraka-net-utils/releases/tag/1.4.1
-[1.5.0]: https://github.com/haraka/haraka-net-utils/releases/tag/1.5.0
-[1.5.1]: https://github.com/haraka/haraka-net-utils/releases/tag/1.5.1
-[1.5.2]: https://github.com/haraka/haraka-net-utils/releases/tag/1.5.2
-[1.5.3]: https://github.com/haraka/haraka-net-utils/releases/tag/1.5.3
-[1.5.4]: https://github.com/haraka/haraka-net-utils/releases/tag/1.5.4
+[1.3.7]: https://github.com/haraka/haraka-net-utils/releases/tag/v1.3.7
+[1.4.0]: https://github.com/haraka/haraka-net-utils/releases/tag/v1.4.0
+[1.4.1]: https://github.com/haraka/haraka-net-utils/releases/tag/v1.4.1
+[1.5.0]: https://github.com/haraka/haraka-net-utils/releases/tag/v1.5.0
+[1.5.1]: https://github.com/haraka/haraka-net-utils/releases/tag/v1.5.1
+[1.5.2]: https://github.com/haraka/haraka-net-utils/releases/tag/v1.5.2
+[1.5.3]: https://github.com/haraka/haraka-net-utils/releases/tag/v1.5.3
+[1.5.4]: https://github.com/haraka/haraka-net-utils/releases/tag/v1.5.4
+[1.6.0]: https://github.com/haraka/haraka-net-utils/releases/tag/v1.6.0
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
new file mode 100644
index 0000000..ac187dd
--- /dev/null
+++ b/CONTRIBUTORS.md
@@ -0,0 +1,8 @@
+# Contributors
+
+This handcrafted artisinal software is brought to you by:
+
+|
msimerson (57) |
baudehlo (4) |
DoobleD (2) |
lnedry (2) |
Juerd (1) |
olsonpm (1) |
typingArtist (1) |
+| :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
+
+this file is maintained by [.release](https://github.com/msimerson/.release)
diff --git a/README.md b/README.md
index 639fab3..96ee3d8 100644
--- a/README.md
+++ b/README.md
@@ -16,56 +16,56 @@ This module provides network utility functions.
```js
// Convert IPv4 to long
-const long = net_utils.ip_to_long('11.22.33.44'); // 185999660
+const long = net_utils.ip_to_long('11.22.33.44') // 185999660
```
### long_to_ip
```js
// Convert long to IPv4
-const ip = net_utils.long_to_ip(185999660); // 11.22.33.44
+const ip = net_utils.long_to_ip(185999660) // 11.22.33.44
```
### dec_to_hex
```js
// Convert decimal to hex
-const hex = net_utils.dec_to_hex(20111104); // 132df00
+const hex = net_utils.dec_to_hex(20111104) // 132df00
```
### hex_to_dec
```js
// Convert hex to decimal
-const dec = net_utils.hex_to_dec('132df00'); // 20111104
+const dec = net_utils.hex_to_dec('132df00') // 20111104
```
### is_local_ipv4
```js
// Is IPv4 address on a local network?
-net_utils.is_local_ipv4('127.0.0.200'); // true (localhost)
-net_utils.is_local_ipv4('169.254.0.0'); // true (link local)
-net_utils.is_local_ipv4('226.0.0.1'); // false
+net_utils.is_local_ipv4('127.0.0.200') // true (localhost)
+net_utils.is_local_ipv4('169.254.0.0') // true (link local)
+net_utils.is_local_ipv4('226.0.0.1') // false
```
### is_private_ipv4
```js
// Is IPv4 address in RFC 1918 reserved private address space?
-net_utils.is_private_ipv4('10.0.0.0'); // true
-net_utils.is_private_ipv4('192.168.0.0'); // true
-net_utils.is_private_ipv4('172.16.0.0'); // true
+net_utils.is_private_ipv4('10.0.0.0') // true
+net_utils.is_private_ipv4('192.168.0.0') // true
+net_utils.is_private_ipv4('172.16.0.0') // true
```
### is_local_ipv6
```js
// Is IPv6 addr on local network?
-net_utils.is_local_ipv6('::1'); // true (localhost)
-net_utils.is_local_ipv6('fe80::') // true (link local)
-net_utils.is_local_ipv6('fc00::') // true (unique local)
-net_utils.is_local_ipv6('fd00::') // true (unique local)
+net_utils.is_local_ipv6('::1') // true (localhost)
+net_utils.is_local_ipv6('fe80::') // true (link local)
+net_utils.is_local_ipv6('fc00::') // true (unique local)
+net_utils.is_local_ipv6('fd00::') // true (unique local)
```
### is_private_ip
@@ -87,9 +87,9 @@ Checks to see if an IP is bound locally or an IPv4 or IPv6 localhost address.
```js
// searches for 'ip' as a hash key in the list object or array
// ip can be a host, an IP, or an IPv4 or IPv6 range
-net_utils.ip_in_list(object, ip);
-net_utils.ip_in_list(array, ip);
-net_utils.ip_in_list(tls.no_tls_hosts, '127.0.0.5');
+net_utils.ip_in_list(object, ip)
+net_utils.ip_in_list(array, ip)
+net_utils.ip_in_list(tls.no_tls_hosts, '127.0.0.5')
```
### get_ips_by_host
@@ -98,13 +98,12 @@ Returns an array of all the IPv4 and IPv6 addresses of the provided hostname.
```js
try {
- const ips = await net_utils.get_ips_by_host(domain)
- for (const ip of ips) {
- // do something with the IPs
- }
-}
-catch (err) {
- // handle any errors
+ const ips = await net_utils.get_ips_by_host(domain)
+ for (const ip of ips) {
+ // do something with the IPs
+ }
+} catch (err) {
+ // handle any errors
}
```
@@ -112,13 +111,12 @@ catch (err) {
```js
try {
- const mxList = await net_utils.get_mx(domain)
- for (const mx of mxList) {
- // do something with each mx
- }
-}
-catch (err) {
- // handle any errors
+ const mxList = await net_utils.get_mx(domain)
+ for (const mx of mxList) {
+ // do something with each mx
+ }
+} catch (err) {
+ // handle any errors
}
```
diff --git a/index.js b/index.js
index 739b230..77955e7 100644
--- a/index.js
+++ b/index.js
@@ -1,168 +1,167 @@
-'use strict';
+'use strict'
// node.js built-ins
-const {Resolver} = require('dns').promises;
-const dns = new Resolver({timeout: 25000, tries: 1});
-const net = require('net');
-const os = require('os');
-const punycode = require('punycode/')
+const { Resolver } = require('dns').promises
+const dns = new Resolver({ timeout: 25000, tries: 1 })
+const net = require('net')
+const os = require('os')
+const punycode = require('punycode.js')
// npm modules
-const ipaddr = require('ipaddr.js');
-const sprintf = require('sprintf-js').sprintf;
-const tlds = require('haraka-tld');
+const ipaddr = require('ipaddr.js')
+const sprintf = require('sprintf-js').sprintf
+const tlds = require('haraka-tld')
-const locallyBoundIPs = [];
+const locallyBoundIPs = []
// export config, so config base path can be overloaded by tests
-exports.config = require('haraka-config');
+exports.config = require('haraka-config')
exports.long_to_ip = function (n) {
- let d = n%256;
- for (let i=3; i>0; i--) {
- n = Math.floor(n/256);
- d = `${n%256}.${d}`;
+ let d = n % 256
+ for (let i = 3; i > 0; i--) {
+ n = Math.floor(n / 256)
+ d = `${n % 256}.${d}`
}
- return d;
+ return d
}
exports.dec_to_hex = function (d) {
- return d.toString(16);
+ return d.toString(16)
}
exports.hex_to_dec = function (h) {
- return parseInt(h, 16);
+ return parseInt(h, 16)
}
exports.ip_to_long = function (ip) {
- if (!net.isIPv4(ip)) { return false; }
+ if (!net.isIPv4(ip)) return false
- const d = ip.split('.');
- return ((((((+d[0])*256)+(+d[1]))*256)+(+d[2]))*256)+(+d[3]);
+ const d = ip.split('.')
+ return ((+d[0] * 256 + +d[1]) * 256 + +d[2]) * 256 + +d[3]
}
exports.octets_in_string = function (str, oct1, oct2) {
- let oct1_idx;
- let oct2_idx;
+ let oct1_idx
+ let oct2_idx
// test the largest of the two octets first
if (oct2.length >= oct1.length) {
- oct2_idx = str.lastIndexOf(oct2);
- if (oct2_idx === -1) return false;
+ oct2_idx = str.lastIndexOf(oct2)
+ if (oct2_idx === -1) return false
- oct1_idx = (str.substring(0, oct2_idx) +
- str.substring(oct2_idx + oct2.length)).lastIndexOf(oct1);
- if (oct1_idx === -1) return false;
+ oct1_idx = (
+ str.substring(0, oct2_idx) + str.substring(oct2_idx + oct2.length)
+ ).lastIndexOf(oct1)
+ if (oct1_idx === -1) return false
- return true; // both were found
+ return true // both were found
}
- oct1_idx = str.indexOf(oct1);
- if (oct1_idx === -1) return false;
+ oct1_idx = str.indexOf(oct1)
+ if (oct1_idx === -1) return false
- oct2_idx = (str.substring(0, oct1_idx) +
- str.substring(oct1_idx + oct1.length)).lastIndexOf(oct2);
- if (oct2_idx === -1) return false;
+ oct2_idx = (
+ str.substring(0, oct1_idx) + str.substring(oct1_idx + oct1.length)
+ ).lastIndexOf(oct2)
+ if (oct2_idx === -1) return false
- return true;
+ return true
}
exports.is_ip_in_str = function (ip, str) {
- if (!str) return false;
- if (!ip) return false;
- if (!net.isIPv4(ip)) return false; // IPv4 only, for now
+ if (!str) return false
+ if (!ip) return false
+ if (!net.isIPv4(ip)) return false // IPv4 only, for now
- const host_part = (tlds.split_hostname(str,1))[0].toString();
- const octets = ip.split('.');
+ const host_part = tlds.split_hostname(str, 1)[0].toString()
+ const octets = ip.split('.')
// See if the 3rd and 4th octets appear in the string
if (this.octets_in_string(host_part, octets[2], octets[3])) {
- return true;
+ return true
}
// then the 1st and 2nd octets
if (this.octets_in_string(host_part, octets[0], octets[1])) {
- return true;
+ return true
}
// Whole IP in hex
- let host_part_copy = host_part;
- const ip_hex = this.dec_to_hex(this.ip_to_long(ip));
- for (let i=0; i<4; i++) {
- const part = host_part_copy.indexOf(ip_hex.substring(i*2, (i*2)+2));
- if (part === -1) break;
- if (i === 3) return true;
- host_part_copy = host_part_copy.substring(0, part) +
- host_part_copy.substring(part+2);
+ let host_part_copy = host_part
+ const ip_hex = this.dec_to_hex(this.ip_to_long(ip))
+ for (let i = 0; i < 4; i++) {
+ const part = host_part_copy.indexOf(ip_hex.substring(i * 2, i * 2 + 2))
+ if (part === -1) break
+ if (i === 3) return true
+ host_part_copy =
+ host_part_copy.substring(0, part) + host_part_copy.substring(part + 2)
}
- return false;
+ return false
}
const re_ipv4 = {
loopback: /^127\./,
link_local: /^169\.254\./,
- private10: /^10\./, // 10/8
- private192: /^192\.168\./, // 192.168/16
+ private10: /^10\./, // 10/8
+ private192: /^192\.168\./, // 192.168/16
// 172.16/16 .. 172.31/16
- private172: /^172\.(1[6-9]|2[0-9]|3[01])\./, // 172.16/12
+ private172: /^172\.(1[6-9]|2[0-9]|3[01])\./, // 172.16/12
// RFC 5735
- testnet1: /^192\.0\.2\./, // 192.0.2.0/24
+ testnet1: /^192\.0\.2\./, // 192.0.2.0/24
testnet2: /^198\.51\.100\./, // 198.51.100.0/24
- testnet3: /^203\.0\.113\./, // 203.0.113.0/24
+ testnet3: /^203\.0\.113\./, // 203.0.113.0/24
}
exports.is_private_ipv4 = function (ip) {
-
// RFC 1918, reserved as "private" IP space
- if (re_ipv4.private10.test(ip)) return true;
- if (re_ipv4.private192.test(ip)) return true;
- if (re_ipv4.private172.test(ip)) return true;
+ if (re_ipv4.private10.test(ip)) return true
+ if (re_ipv4.private192.test(ip)) return true
+ if (re_ipv4.private172.test(ip)) return true
- if (re_ipv4.testnet1.test(ip)) return true;
- if (re_ipv4.testnet2.test(ip)) return true;
- if (re_ipv4.testnet3.test(ip)) return true;
+ if (re_ipv4.testnet1.test(ip)) return true
+ if (re_ipv4.testnet2.test(ip)) return true
+ if (re_ipv4.testnet3.test(ip)) return true
- return false;
+ return false
}
exports.on_local_interface = function (ip) {
-
if (locallyBoundIPs.length === 0) {
- const ifList = os.networkInterfaces();
+ const ifList = os.networkInterfaces()
for (const ifName of Object.keys(ifList)) {
for (const addr of ifList[ifName]) {
- locallyBoundIPs.push(addr.address);
+ locallyBoundIPs.push(addr.address)
}
}
}
- return locallyBoundIPs.includes(ip);
+ return locallyBoundIPs.includes(ip)
}
exports.is_local_host = async function (dst_host) {
-
// Is the destination hostname/IP delivered to a hostname or IP
// that's local to _this_ mail server?
- const local_ips = [];
- const dest_ips = [];
+ const local_ips = []
+ const dest_ips = []
try {
const public_ip = await this.get_public_ip()
if (public_ip) local_ips.push(public_ip)
const local_hostname = this.get_primary_host_name()
- local_ips.push(...await this.get_ips_by_host(local_hostname));
+ local_ips.push(...(await this.get_ips_by_host(local_hostname)))
- if (net.isIP(dst_host)) { // an IP address
+ if (net.isIP(dst_host)) {
+ // an IP address
dest_ips.push(dst_host)
- }
- else { // a hostname
+ } else {
+ // a hostname
if (dst_host === local_hostname) return true
- dest_ips.push(...await this.get_ips_by_host(dst_host));
+ dest_ips.push(...(await this.get_ips_by_host(dst_host)))
}
- }
- catch (e) {
+ } catch (e) {
// console.error(e)
return false
}
@@ -175,119 +174,117 @@ exports.is_local_host = async function (dst_host) {
}
exports.is_local_ip = function (ip) {
+ if (this.on_local_interface(ip)) return true
- if (this.on_local_interface(ip)) return true;
-
- if (net.isIPv4(ip)) return this.is_local_ipv4(ip);
- if (net.isIPv6(ip)) return this.is_local_ipv6(ip);
+ if (net.isIPv4(ip)) return this.is_local_ipv4(ip)
+ if (net.isIPv6(ip)) return this.is_local_ipv6(ip)
// console.error(`invalid IP address: ${ip}`);
- return false;
+ return false
}
exports.is_local_ipv4 = function (ip) {
- if ('0.0.0.0' === ip) return true; // RFC 5735
+ if ('0.0.0.0' === ip) return true // RFC 5735
// 127/8 (loopback) # RFC 1122
- if (re_ipv4.loopback.test(ip)) return true;
+ if (re_ipv4.loopback.test(ip)) return true
// link local: 169.254/16 RFC 3927
- if (re_ipv4.link_local.test(ip)) return true;
+ if (re_ipv4.link_local.test(ip)) return true
- return false;
+ return false
}
const re_ipv6 = {
- loopback: /^(0{1,4}:){7}0{0,3}1$/,
- link_local: /^fe80::/i,
+ loopback: /^(0{1,4}:){7}0{0,3}1$/,
+ link_local: /^fe80::/i,
unique_local: /^f(c|d)[a-f0-9]{2}:/i,
}
exports.is_local_ipv6 = function (ip) {
- if (ip === '::') return true; // RFC 5735
- if (ip === '::1') return true; // RFC 4291
+ if (ip === '::') return true // RFC 5735
+ if (ip === '::1') return true // RFC 4291
// 2 more IPv6 notations for ::1
// 0:0:0:0:0:0:0:1 or 0000:0000:0000:0000:0000:0000:0000:0001
- if (re_ipv6.loopback.test(ip)) return true;
+ if (re_ipv6.loopback.test(ip)) return true
// link local: fe80::/10, RFC 4862
- if (re_ipv6.link_local.test(ip)) return true;
+ if (re_ipv6.link_local.test(ip)) return true
// unique local (fc00::/7) -> fc00: - fd00:
- if (re_ipv6.unique_local.test(ip)) return true;
+ if (re_ipv6.unique_local.test(ip)) return true
- return false;
+ return false
}
exports.is_private_ip = function (ip) {
- if (net.isIPv4(ip)) return this.is_local_ipv4(ip) || this.is_private_ipv4(ip);
- if (net.isIPv6(ip)) return this.is_local_ipv6(ip);
- return false;
+ if (net.isIPv4(ip)) return this.is_local_ipv4(ip) || this.is_private_ipv4(ip)
+ if (net.isIPv6(ip)) return this.is_local_ipv6(ip)
+ return false
}
// backwards compatibility for non-public modules. Sunset: v3.0
-exports.is_rfc1918 = exports.is_private_ip;
+exports.is_rfc1918 = exports.is_private_ip
exports.is_ip_literal = function (host) {
- return exports.get_ipany_re('^\\[(IPv6:)?','\\]$','').test(host) ? true : false;
+ return exports.get_ipany_re('^\\[(IPv6:)?', '\\]$', '').test(host)
+ ? true
+ : false
}
exports.is_ipv4_literal = function (host) {
- return /^\[(\d{1,3}\.){3}\d{1,3}\]$/.test(host) ? true : false;
+ return /^\[(\d{1,3}\.){3}\d{1,3}\]$/.test(host) ? true : false
}
exports.same_ipv4_network = function (ip, ipList) {
if (!ipList || !ipList.length) {
- console.error('same_ipv4_network, no ip list!');
- return false;
+ console.error('same_ipv4_network, no ip list!')
+ return false
}
if (!net.isIPv4(ip)) {
- console.error('same_ipv4_network, IP is not IPv4!');
- return false;
+ console.error('same_ipv4_network, IP is not IPv4!')
+ return false
}
- const first3 = ip.split('.').slice(0,3).join('.');
+ const first3 = ip.split('.').slice(0, 3).join('.')
- for (let i=0; i < ipList.length; i++) {
+ for (let i = 0; i < ipList.length; i++) {
if (!net.isIPv4(ipList[i])) {
- console.error('same_ipv4_network, IP in list is not IPv4!');
- continue;
+ console.error('same_ipv4_network, IP in list is not IPv4!')
+ continue
}
- if (first3 === ipList[i].split('.').slice(0,3).join('.'))
- return true;
+ if (first3 === ipList[i].split('.').slice(0, 3).join('.')) return true
}
- return false;
+ return false
}
exports.get_public_ip_async = async function () {
-
- if (this.public_ip !== undefined) return this.public_ip; // cache
+ if (this.public_ip !== undefined) return this.public_ip // cache
// manual config override, for the cases where we can't figure it out
- const smtpIni = exports.config.get('smtp.ini').main;
+ const smtpIni = exports.config.get('smtp.ini').main
if (smtpIni.public_ip) {
- this.public_ip = smtpIni.public_ip;
- return this.public_ip;
+ this.public_ip = smtpIni.public_ip
+ return this.public_ip
}
// Initialise cache value to null to prevent running
// should we hit a timeout or the module isn't installed.
- this.public_ip = null;
+ this.public_ip = null
try {
- this.stun = require('@msimerson/stun');
- }
- catch (e) {
- e.install = 'Please install stun: "npm install -g stun"';
- console.error(`${e.msg}\n${e.install}`);
+ this.stun = require('@msimerson/stun')
+ } catch (e) {
+ e.install = 'Please install stun: "npm install -g stun"'
+ console.error(`${e.msg}\n${e.install}`)
return
}
- const timeout = 10;
+ const timeout = 10
const timer = setTimeout(() => {
return new Error('STUN timeout')
- }, timeout * 1000);
+ }, timeout * 1000)
// Connect to STUN Server
const res = await this.stun.request(get_stun_server())
@@ -299,45 +296,44 @@ exports.get_public_ip_async = async function () {
exports.get_public_ip = async function (cb) {
if (!cb) return exports.get_public_ip_async()
- const nu = this;
- if (nu.public_ip !== undefined) return cb(null, nu.public_ip); // cache
+ const nu = this
+ if (nu.public_ip !== undefined) return cb(null, nu.public_ip) // cache
// manual config override, for the cases where we can't figure it out
- const smtpIni = exports.config.get('smtp.ini').main;
+ const smtpIni = exports.config.get('smtp.ini').main
if (smtpIni.public_ip) {
- nu.public_ip = smtpIni.public_ip;
- return cb(null, nu.public_ip);
+ nu.public_ip = smtpIni.public_ip
+ return cb(null, nu.public_ip)
}
// Initialise cache value to null to prevent running
// should we hit a timeout or the module isn't installed.
- nu.public_ip = null;
+ nu.public_ip = null
try {
- nu.stun = require('@msimerson/stun');
- }
- catch (e) {
- e.install = 'Please install stun: "npm install -g stun"';
- console.error(`${e.msg}\n${e.install}`);
- return cb(e);
+ nu.stun = require('@msimerson/stun')
+ } catch (e) {
+ e.install = 'Please install stun: "npm install -g stun"'
+ console.error(`${e.msg}\n${e.install}`)
+ return cb(e)
}
- const timeout = 10;
+ const timeout = 10
const timer = setTimeout(() => {
- return cb(new Error('STUN timeout'));
- }, timeout * 1000);
+ return cb(new Error('STUN timeout'))
+ }, timeout * 1000)
// Connect to STUN Server
nu.stun.request(get_stun_server(), (error, res) => {
- if (timer) clearTimeout(timer);
- if (error) return cb(error);
+ if (timer) clearTimeout(timer)
+ if (error) return cb(error)
nu.public_ip = res.getXorAddress().address
- cb(null, nu.public_ip);
+ cb(null, nu.public_ip)
})
}
-function get_stun_server () {
+function get_stun_server() {
// STUN servers by Google
const servers = [
'stun.l.google.com:19302',
@@ -345,126 +341,130 @@ function get_stun_server () {
'stun2.l.google.com:19302',
'stun3.l.google.com:19302',
'stun4.l.google.com:19302',
- ];
- return servers[Math.floor(Math.random()*servers.length)];
+ ]
+ return servers[Math.floor(Math.random() * servers.length)]
}
exports.get_ipany_re = function (prefix, suffix, modifier) {
- if (prefix === undefined) prefix = '';
- if (suffix === undefined) suffix = '';
- if (modifier === undefined) modifier = 'mg';
+ if (prefix === undefined) prefix = ''
+ if (suffix === undefined) suffix = ''
+ if (modifier === undefined) modifier = 'mg'
/* eslint-disable prefer-template */
return new RegExp(
prefix +
- `(` + // capture group
- `(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(?:(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-fA-F]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,1}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,2}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,3}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:[0-9a-fA-F]{1,4})):)(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,4}(?:(?:[0-9a-fA-F]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,5}(?:(?:[0-9a-fA-F]{1,4})))?::)(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,6}(?:(?:[0-9a-fA-F]{1,4})))?::))))` + // complex ipv4 + ipv6
- `)` + // end capture
- `${suffix}`,
- modifier
- );
+ `(` + // capture group
+ `(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(?:(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-fA-F]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,1}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,2}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:(?:[0-9a-fA-F]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,3}(?:(?:[0-9a-fA-F]{1,4})))?::(?:(?:[0-9a-fA-F]{1,4})):)(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,4}(?:(?:[0-9a-fA-F]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,5}(?:(?:[0-9a-fA-F]{1,4})))?::)(?:(?:[0-9a-fA-F]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-fA-F]{1,4})):){0,6}(?:(?:[0-9a-fA-F]{1,4})))?::))))` + // complex ipv4 + ipv6
+ `)` + // end capture
+ `${suffix}`,
+ modifier,
+ )
}
exports.get_ips_by_host = function (hostname, done) {
const ips = new Set()
const errors = []
- const promises = []
- async function resolveAny (ver) {
- try {
- const addrs = await dns[`resolve${ver}`](hostname)
- for (const a of addrs) {
- ips.add(a);
- }
- return addrs
- }
- catch (err) {
- errors.push(err);
- }
- }
+ return Promise.allSettled([
+ dns.resolve6(hostname),
+ dns.resolve4(hostname),
+ ]).then((res) => {
+ res.filter((a) => a.status === 'rejected').map((a) => errors.push(a.reason))
- promises.push(resolveAny('4'))
- promises.push(resolveAny('6'))
+ res
+ .filter((a) => a.status === 'fulfilled')
+ .map((a) => a.value.map((ip) => ips.add(ip)))
- if (done) { // legacy callback API
- Promise.all(promises).then((r) => { done(errors, Array.from(ips)) })
- }
- else { // promise API
- // if (process.env.DEBUG && errors.length) console.error(errors)
- return Promise.all(promises).then(r => { return Array.from(ips) })
- }
+ if (done) done(errors, Array.from(ips))
+ return Array.from(ips)
+ })
}
exports.ipv6_reverse = function (ipv6) {
- ipv6 = ipaddr.parse(ipv6);
- return ipv6.toNormalizedString()
+ ipv6 = ipaddr.parse(ipv6)
+ return ipv6
+ .toNormalizedString()
.split(':')
.map(function (n) {
- return sprintf('%04x', parseInt(n, 16));
+ return sprintf('%04x', parseInt(n, 16))
})
.join('')
.split('')
.reverse()
- .join('.');
+ .join('.')
}
exports.ipv6_bogus = function (ipv6) {
try {
- const ipCheck = ipaddr.parse(ipv6);
- if (ipCheck.range() !== 'unicast') return true;
- return false;
- }
- catch (e) {
+ const ipCheck = ipaddr.parse(ipv6)
+ if (ipCheck.range() !== 'unicast') return true
+ return false
+ } catch (e) {
// If we get an error from parsing, return true for bogus.
- console.error(e);
- return true;
+ console.error(e)
+ return true
}
}
exports.ip_in_list = function (list, ip) {
- if (list === undefined) return false;
+ if (list === undefined) return false
- const isHostname = !net.isIP(ip);
- const isArray = Array.isArray(list);
+ const isHostname = !net.isIP(ip)
+ const isArray = Array.isArray(list)
// Quick lookup
if (!isArray) {
- if (ip in list) return true; // domain or literal IP
- if (isHostname) return false; // skip CIDR match
+ if (ip in list) return true // domain or literal IP
+ if (isHostname) return false // skip CIDR match
}
// Iterate: arrays and CIDR matches
for (let item in list) {
if (isArray) {
- item = list[item]; // item is index
- if (item === ip) return true; // exact match
+ item = list[item] // item is index
+ if (item === ip) return true // exact match
}
- if (isHostname) continue; // skip CIDR match
+ if (isHostname) continue // skip CIDR match
- const cidr = item.split('/');
- const c_net = cidr[0];
+ const cidr = item.split('/')
+ const c_net = cidr[0]
- if (!net.isIP(c_net)) continue; // bad config entry
- if (net.isIPv4(ip) && net.isIPv6(c_net)) continue;
- if (net.isIPv6(ip) && net.isIPv4(c_net)) continue;
+ if (!net.isIP(c_net)) continue // bad config entry
+ if (net.isIPv4(ip) && net.isIPv6(c_net)) continue
+ if (net.isIPv6(ip) && net.isIPv4(c_net)) continue
- const c_mask = parseInt(cidr[1], 10) || (net.isIPv6(c_net) ? 128 : 32);
+ const c_mask = parseInt(cidr[1], 10) || (net.isIPv6(c_net) ? 128 : 32)
if (ipaddr.parse(ip).match(ipaddr.parse(c_net), c_mask)) {
- return true;
+ return true
}
}
- return false;
+ return false
}
exports.get_primary_host_name = function () {
- return exports.config.get('me') || os.hostname();
+ return exports.config.get('me') || os.hostname()
}
-exports.get_mx = async function get_mx (raw_domain, cb) {
- let domain = raw_domain;
- const mxs = [];
+function normalizeDomain(raw_domain) {
+ let domain = raw_domain
+
+ if (/@/.test(domain)) {
+ domain = domain.split('@').pop()
+ // console.log(`\treduced ${raw_domain} to ${domain}.`)
+ }
+
+ if (/^xn--/.test(domain)) {
+ // is punycode IDN with ACE, ASCII Compatible Encoding
+ } else if (domain !== punycode.toASCII(domain)) {
+ domain = punycode.toASCII(domain)
+ console.log(`\tACE encoded '${raw_domain}' to '${domain}'`)
+ }
+
+ return domain
+}
+function fatal_mx_err(err) {
// Possible DNS errors
// NODATA
// FORMERR
@@ -479,36 +479,94 @@ exports.get_mx = async function get_mx (raw_domain, cb) {
// EREFUSED
// SERVFAIL
- if ( /@/.test(domain) ) {
- domain = domain.split('@').pop();
- // console.log(`\treduced ${raw_domain} to ${domain}.`)
+ switch (err.code) {
+ case 'ENODATA':
+ case 'ENOTFOUND':
+ // likely a hostname with no MX record, drop through
+ return false
+ default:
+ return err
}
+}
- if ( /^xn--/.test(domain) ) {
- // is punycode IDN with ACE, ASCII Compatible Encoding
- }
- else if (domain !== punycode.toASCII(domain)) {
- domain = punycode.toASCII(domain);
- console.log(`\tACE encoded '${raw_domain}' to '${domain}'`)
- }
+exports.get_mx = async (raw_domain, cb) => {
+ const domain = normalizeDomain(raw_domain)
- // wrap_mx returns our object with "priority" and "exchange" keys
- const wrap_mx = a => a;
- let err = null
+ try {
+ const exchanges = await dns.resolveMx(domain)
+ if (exchanges && exchanges.length) {
+ exchanges.map((e) => (e.from_dns = domain))
+ if (cb) return cb(null, exchanges)
+ return exchanges
+ }
+ } catch (err) {
+ // console.error(err.message)
+ if (fatal_mx_err(err)) {
+ if (cb) return cb(err, [])
+ throw err
+ }
+ }
+ // no MX or non-fatal DNS failure
try {
- const addresses = await dns.resolveMx(domain)
- if (addresses?.length) {
- for (const addr of addresses) {
- mxs.push(wrap_mx(addr));
- }
+ const exchanges = await this.get_implicit_mx(domain)
+ if (cb) return cb(null, exchanges)
+ return exchanges
+ } catch (err) {
+ if (fatal_mx_err(err)) {
+ if (cb) return cb(err, [])
+ throw err
}
}
- catch (e) {
- // console.error(e.message)
- err = e
+}
+
+exports.get_implicit_mx = async (domain) => {
+ // console.log(`No MX for ${domain}, trying AAAA & A records`)
+
+ const promises = [dns.resolve6(domain), dns.resolve4(domain)]
+ const r = await Promise.allSettled(promises)
+
+ return r
+ .filter((a) => a.status === 'fulfilled')
+ .flatMap((a) =>
+ a.value.map((ip) => ({ priority: 0, exchange: ip, from_dns: domain })),
+ )
+}
+
+exports.resolve_mx_hosts = async (mxes) => {
+ // for the given list of MX exchanges, resolve the hostnames to IPs
+ const promises = []
+
+ for (const mx of mxes) {
+ if (!mx.exchange) {
+ promises.push(mx)
+ continue
+ }
+
+ if (net.isIP(mx.exchange)) {
+ promises.push(mx) // already resolved
+ continue
+ }
+
+ // resolve AAAA and A since mx.exchange is a hostname
+ promises.push(
+ dns
+ .resolve6(mx.exchange)
+ .then((ips) =>
+ ips.map((ip) => ({ ...mx, exchange: ip, from_dns: mx.exchange })),
+ ),
+ )
+
+ promises.push(
+ dns
+ .resolve4(mx.exchange)
+ .then((ips) =>
+ ips.map((ip) => ({ ...mx, exchange: ip, from_dns: mx.exchange })),
+ ),
+ )
}
- if (cb) return cb(err, mxs)
- return mxs
+ const settled = await Promise.allSettled(promises)
+
+ return settled.filter((s) => s.status === 'fulfilled').flatMap((s) => s.value)
}
diff --git a/package.json b/package.json
index e5e06ee..dd51bb9 100644
--- a/package.json
+++ b/package.json
@@ -1,13 +1,20 @@
{
"name": "haraka-net-utils",
- "version": "1.5.4",
+ "version": "1.6.0",
"description": "haraka network utilities",
"main": "index.js",
+ "files": [
+ "CHANGELOG.md"
+ ],
"scripts": {
- "test": "npx mocha",
- "lint": "npx eslint *.js test",
- "lintfix": "npx eslint --fix *.js test",
- "versions": "npx dependency-version-checker check"
+ "format": "npm run prettier:fix && npm run lint:fix",
+ "lint": "npx eslint@^8 *.js test",
+ "lint:fix": "npx eslint@^8 *.js test --fix",
+ "prettier": "npx prettier . --check",
+ "prettier:fix": "npx prettier . --write --log-level=warn",
+ "test": "npx mocha@10",
+ "versions": "npx dependency-version-checker check",
+ "versions:fix": "npx dependency-version-checker update && npm run prettier:fix"
},
"repository": {
"type": "git",
@@ -29,15 +36,13 @@
},
"homepage": "https://github.com/haraka/haraka-net-utils#readme",
"devDependencies": {
- "eslint": "^8.57.0",
- "mocha": "^10.4.0",
- "eslint-plugin-haraka": "1.0.15"
+ "@haraka/eslint-config": "^1.1.3"
},
"dependencies": {
"haraka-config": "^1.1.0",
- "haraka-tld": "^1.2.0",
+ "haraka-tld": "^1.2.1",
"ipaddr.js": "^2.1.0",
- "punycode": "^2.3.1",
+ "punycode.js": "^2.3.1",
"openssl-wrapper": "^0.3.4",
"sprintf-js": "^1.1.3"
},
diff --git a/test/net_utils.js b/test/net_utils.js
index 71f28af..a547a83 100644
--- a/test/net_utils.js
+++ b/test/net_utils.js
@@ -1,1053 +1,1096 @@
-
const assert = require('assert')
-const net = require('net')
-const os = require('os')
-const path = require('path')
+const net = require('net')
+const os = require('os')
+const path = require('path')
-require('haraka-config').watch_files = false;
-const net_utils = require('../index');
+require('haraka-config').watch_files = false
+const net_utils = require('../index')
-function _check (done, ip, host, res) {
- assert.equal(net_utils.is_ip_in_str(ip, host), res);
- done();
+function _check(done, ip, host, res) {
+ assert.equal(net_utils.is_ip_in_str(ip, host), res)
+ done()
}
describe('long_to_ip', function () {
it('185999660', function (done) {
- assert.equal(net_utils.long_to_ip(185999660), '11.22.33.44');
- done();
+ assert.equal(net_utils.long_to_ip(185999660), '11.22.33.44')
+ done()
})
})
describe('static_rdns', function () {
it('74.125.82.182', function (done) {
- _check(done, '74.125.82.182', 'mail-we0-f182.google.com', false);
+ _check(done, '74.125.82.182', 'mail-we0-f182.google.com', false)
})
it('74.125.82.53', function (done) {
- _check(done, '74.125.82.53', 'mail-ww0-f53.google.com', false);
+ _check(done, '74.125.82.53', 'mail-ww0-f53.google.com', false)
})
})
describe('dynamic_rdns', function () {
-
it('109.168.232.131', function (done) {
- _check(done, '109.168.232.131', 'host-109-168-232-131.stv.ru', true);
+ _check(done, '109.168.232.131', 'host-109-168-232-131.stv.ru', true)
})
it('62.198.236.129', function (done) {
- _check(done, '62.198.236.129', '0x3ec6ec81.inet.dsl.telianet.dk', true);
+ _check(done, '62.198.236.129', '0x3ec6ec81.inet.dsl.telianet.dk', true)
})
it('123.58.178.17', function (done) {
- _check(done, '123.58.178.17', 'm17-178.vip.126.com', true);
+ _check(done, '123.58.178.17', 'm17-178.vip.126.com', true)
})
it('100.42.67.92', function (done) {
- _check(done, '100.42.67.92', '92-67-42-100-dedicated.multacom.com',
- true);
+ _check(done, '100.42.67.92', '92-67-42-100-dedicated.multacom.com', true)
})
it('101.0.57.5', function (done) {
- _check(done, '101.0.57.5', 'static-bpipl-101.0.57-5.com', true);
+ _check(done, '101.0.57.5', 'static-bpipl-101.0.57-5.com', true)
})
})
-function _same_ipv4_network (done, addr, addrList, expected) {
- assert.equal(expected, net_utils.same_ipv4_network(addr, addrList));
- done();
+function _same_ipv4_network(done, addr, addrList, expected) {
+ assert.equal(expected, net_utils.same_ipv4_network(addr, addrList))
+ done()
}
describe('same_ipv4_network', function () {
it('199.176.179.3 <-> [199.176.179.4]', function (done) {
- _same_ipv4_network(done, '199.176.179.3', ['199.176.179.4'], true);
+ _same_ipv4_network(done, '199.176.179.3', ['199.176.179.4'], true)
})
it('199.176.179.3 <-> [199.177.179.4', function (done) {
- _same_ipv4_network(done, '199.176.179.3', ['199.177.179.4'], false);
+ _same_ipv4_network(done, '199.176.179.3', ['199.177.179.4'], false)
})
it('199.176.179 <-> [199.176.179.4] (missing octet)', function (done) {
- _same_ipv4_network(done, '199.176.179', ['199.176.179.4'], false);
+ _same_ipv4_network(done, '199.176.179', ['199.176.179.4'], false)
})
it('199.176.179.3.5 <-> [199.176.179.4] (extra octet)', function (done) {
- _same_ipv4_network(done, '199.176.179.3.5', ['199.176.179.4'], false);
+ _same_ipv4_network(done, '199.176.179.3.5', ['199.176.179.4'], false)
})
})
describe('is_ipv4_literal', function () {
it('3 ways', function (done) {
- assert.equal(true, net_utils.is_ipv4_literal('[127.0.0.1]'));
- assert.equal(false, net_utils.is_ipv4_literal('127.0.0.1'));
- assert.equal(false, net_utils.is_ipv4_literal('test.host'));
- done();
+ assert.equal(true, net_utils.is_ipv4_literal('[127.0.0.1]'))
+ assert.equal(false, net_utils.is_ipv4_literal('127.0.0.1'))
+ assert.equal(false, net_utils.is_ipv4_literal('test.host'))
+ done()
})
})
-async function _is_local_host (done, host, expected) {
- const is_local_host = await net_utils.is_local_host(host);
- assert.strictEqual(expected, is_local_host);
- done();
+async function _is_local_host(done, host, expected) {
+ const is_local_host = await net_utils.is_local_host(host)
+ assert.strictEqual(expected, is_local_host)
+ done()
}
-function _is_private_ip (done, ip, expected) {
- assert.equal(expected, net_utils.is_private_ip(ip));
- done();
+function _is_private_ip(done, ip, expected) {
+ assert.equal(expected, net_utils.is_private_ip(ip))
+ done()
}
-function _is_local_ip (done, ip, expected) {
- assert.equal(expected, net_utils.is_local_ip(ip));
- done();
+function _is_local_ip(done, ip, expected) {
+ assert.equal(expected, net_utils.is_local_ip(ip))
+ done()
}
describe('is_local_host', function () {
it('127.0.0.1', function (done) {
- _is_local_host(done, '127.0.0.1', true);
+ _is_local_host(done, '127.0.0.1', true)
})
it('0.0.0.0', function (done) {
- _is_local_host(done, '0.0.0.0', true);
+ _is_local_host(done, '0.0.0.0', true)
})
it('::1', function (done) {
- _is_local_host(done, '::1', true);
+ _is_local_host(done, '::1', true)
})
it('self hostname', function (done) {
if (/^win/.test(process.platform)) return done()
- const hostname = require('../index').get_primary_host_name();
- _is_local_host(done, hostname, true);
+ const hostname = require('../index').get_primary_host_name()
+ _is_local_host(done, hostname, true)
})
it('self ip', function (done) {
- require('../index').get_public_ip().then(ip => {
- _is_local_host(done, ip, true);
- });
+ require('../index')
+ .get_public_ip()
+ .then((ip) => {
+ _is_local_host(done, ip, true)
+ })
})
it('google.com', function (done) {
- _is_local_host(done, 'google.com', false);
+ _is_local_host(done, 'google.com', false)
})
it('8.8.8.8', function (done) {
- _is_local_host(done, '8.8.8.8', false);
+ _is_local_host(done, '8.8.8.8', false)
})
it('invalid host string', async function () {
const r = await net_utils.is_local_host('invalid host string')
- assert.ok(!r);
+ assert.ok(!r)
})
})
describe('is_local_ip', function () {
it('127.0.0.1', function (done) {
- _is_local_ip(done, '127.0.0.1', true);
+ _is_local_ip(done, '127.0.0.1', true)
})
it('::1', function (done) {
- _is_local_ip(done, '::1', true);
+ _is_local_ip(done, '::1', true)
})
it('0:0:0:0:0:0:0:1', function (done) {
- _is_local_ip(done, '0:0:0:0:0:0:0:1', true);
+ _is_local_ip(done, '0:0:0:0:0:0:0:1', true)
})
it('0000:0000:0000:0000:0000:0000:0000:0001', function (done) {
- _is_local_ip(done, '0000:0000:0000:0000:0000:0000:0000:0001', true);
+ _is_local_ip(done, '0000:0000:0000:0000:0000:0000:0000:0001', true)
})
it('123.123.123.123 (!)', function (done) {
- _is_local_ip(done, '123.123.123.123', false);
+ _is_local_ip(done, '123.123.123.123', false)
})
it('dead::beef (!)', function (done) {
- _is_local_ip(done, 'dead::beef', false);
+ _is_local_ip(done, 'dead::beef', false)
})
it('192.168.1 (missing octet)', function (done) {
- _is_local_ip(done, '192.168.1', false);
+ _is_local_ip(done, '192.168.1', false)
})
it('239.0.0.1 (multicast; not currently considered rfc1918)', function (done) {
- _is_local_ip(done, '239.0.0.1', false);
+ _is_local_ip(done, '239.0.0.1', false)
})
it('0.0.0.0', function (done) {
- _is_local_ip(done, '0.0.0.0', true);
+ _is_local_ip(done, '0.0.0.0', true)
})
it('::', function (done) {
- _is_local_ip(done, '::', true);
+ _is_local_ip(done, '::', true)
})
})
describe('is_private_ip', function () {
it('127.0.0.1', function (done) {
- _is_private_ip(done, '127.0.0.1', true);
+ _is_private_ip(done, '127.0.0.1', true)
})
it('10.255.31.23', function (done) {
- _is_private_ip(done, '10.255.31.23', true);
+ _is_private_ip(done, '10.255.31.23', true)
})
it('172.16.255.254', function (done) {
- _is_private_ip(done, '172.16.255.254', true);
+ _is_private_ip(done, '172.16.255.254', true)
})
it('192.168.123.123', function (done) {
- _is_private_ip(done, '192.168.123.123', true);
+ _is_private_ip(done, '192.168.123.123', true)
})
it('169.254.23.54 (APIPA)', function (done) {
- _is_private_ip(done, '169.254.23.54', true);
+ _is_private_ip(done, '169.254.23.54', true)
})
it('::1', function (done) {
- _is_private_ip(done, '::1', true);
+ _is_private_ip(done, '::1', true)
})
it('0:0:0:0:0:0:0:1', function (done) {
- _is_private_ip(done, '0:0:0:0:0:0:0:1', true);
+ _is_private_ip(done, '0:0:0:0:0:0:0:1', true)
})
it('0000:0000:0000:0000:0000:0000:0000:0001', function (done) {
- _is_private_ip(done, '0000:0000:0000:0000:0000:0000:0000:0001', true);
+ _is_private_ip(done, '0000:0000:0000:0000:0000:0000:0000:0001', true)
})
it('123.123.123.123', function (done) {
- _is_private_ip(done, '123.123.123.123', false);
+ _is_private_ip(done, '123.123.123.123', false)
})
it('dead::beef', function (done) {
- _is_private_ip(done, 'dead::beef', false);
+ _is_private_ip(done, 'dead::beef', false)
})
it('192.168.1 (missing octet)', function (done) {
- _is_private_ip(done, '192.168.1', false);
+ _is_private_ip(done, '192.168.1', false)
})
it('239.0.0.1 (multicast; not currently considered rfc1918)', function (done) {
- _is_private_ip(done, '239.0.0.1', false);
+ _is_private_ip(done, '239.0.0.1', false)
})
it('192.0.2.1 TEST-NET-1', function (done) {
- _is_private_ip(done, '192.0.2.1', true);
+ _is_private_ip(done, '192.0.2.1', true)
})
it('198.51.100.0 TEST-NET-2', function (done) {
- _is_private_ip(done, '198.51.100.0', true);
+ _is_private_ip(done, '198.51.100.0', true)
})
it('203.0.113.0 TEST-NET-3', function (done) {
- _is_private_ip(done, '203.0.113.0', true);
+ _is_private_ip(done, '203.0.113.0', true)
})
})
describe('get_public_ip', function () {
-
beforeEach(function (done) {
- this.net_utils = require('../index');
- this.net_utils.config = this.net_utils.config.module_config(path.resolve('test'));
- done();
+ this.net_utils = require('../index')
+ this.net_utils.config = this.net_utils.config.module_config(
+ path.resolve('test'),
+ )
+ done()
})
- function has_stun () {
+ function has_stun() {
try {
- require('stun');
- }
- catch (e) {
- return false;
+ require('stun')
+ } catch (e) {
+ return false
}
- return true;
+ return true
}
it('cached', function (done) {
- this.net_utils.public_ip='1.1.1.1';
+ this.net_utils.public_ip = '1.1.1.1'
const cb = function (err, ip) {
- assert.equal(null, err);
- assert.equal('1.1.1.1', ip);
- done();
- };
- this.net_utils.get_public_ip(cb);
+ assert.equal(null, err)
+ assert.equal('1.1.1.1', ip)
+ done()
+ }
+ this.net_utils.get_public_ip(cb)
})
it('normal', function (done) {
- this.net_utils.public_ip=undefined;
+ this.net_utils.public_ip = undefined
const cb = function (err, ip) {
// console.log(`ip: ${ip}`);
// console.log(`err: ${err}`);
if (has_stun()) {
if (err) {
- console.log(err);
+ console.log(err)
+ } else {
+ console.log(`stun success: ${ip}`)
+ assert.equal(null, err)
+ assert.ok(ip, ip)
}
- else {
- console.log(`stun success: ${ip}`);
- assert.equal(null, err);
- assert.ok(ip, ip);
- }
- }
- else {
- console.log("stun skipped");
+ } else {
+ console.log('stun skipped')
}
- done();
- };
- this.net_utils.get_public_ip(cb);
+ done()
+ }
+ this.net_utils.get_public_ip(cb)
})
})
describe('get_public_ip_async', function () {
-
beforeEach(() => {
- this.net_utils = require('../index');
- this.net_utils.config = this.net_utils.config.module_config(path.resolve('test'));
+ this.net_utils = require('../index')
+ this.net_utils.config = this.net_utils.config.module_config(
+ path.resolve('test'),
+ )
})
- function has_stun () {
+ function has_stun() {
try {
- require('stun');
- }
- catch (e) {
- return false;
+ require('stun')
+ } catch (e) {
+ return false
}
- return true;
+ return true
}
it('cached', async () => {
- this.net_utils.public_ip='1.1.1.1';
+ this.net_utils.public_ip = '1.1.1.1'
const ip = await this.net_utils.get_public_ip()
- assert.equal('1.1.1.1', ip);
+ assert.equal('1.1.1.1', ip)
})
it('normal', async () => {
- this.net_utils.public_ip=undefined;
+ this.net_utils.public_ip = undefined
if (!has_stun()) {
- console.log("stun skipped");
+ console.log('stun skipped')
return
}
try {
const ip = await this.net_utils.get_public_ip()
- console.log(`stun success: ${ip}`);
- assert.ok(ip, ip);
- }
- catch (e) {
- console.error(e);
+ console.log(`stun success: ${ip}`)
+ assert.ok(ip, ip)
+ } catch (e) {
+ console.error(e)
}
})
})
describe('octets_in_string', function () {
it('c-24-18-98-14.hsd1.wa.comcast.net', function (done) {
- const str = 'c-24-18-98-14.hsd1.wa.comcast.net';
- assert.equal(net_utils.octets_in_string(str, 98, 14), true );
- assert.equal(net_utils.octets_in_string(str, 24, 18), true );
- assert.equal(net_utils.octets_in_string(str, 2, 7), false );
- done();
+ const str = 'c-24-18-98-14.hsd1.wa.comcast.net'
+ assert.equal(net_utils.octets_in_string(str, 98, 14), true)
+ assert.equal(net_utils.octets_in_string(str, 24, 18), true)
+ assert.equal(net_utils.octets_in_string(str, 2, 7), false)
+ done()
})
it('149.213.210.203.in-addr.arpa', function (done) {
- const str = '149.213.210.203.in-addr.arpa';
- assert.equal(net_utils.octets_in_string(str, 149, 213), true );
- assert.equal(net_utils.octets_in_string(str, 210, 20), true );
- assert.equal(net_utils.octets_in_string(str, 2, 7), false );
- done();
+ const str = '149.213.210.203.in-addr.arpa'
+ assert.equal(net_utils.octets_in_string(str, 149, 213), true)
+ assert.equal(net_utils.octets_in_string(str, 210, 20), true)
+ assert.equal(net_utils.octets_in_string(str, 2, 7), false)
+ done()
})
})
describe('is_ip_literal', function () {
it('ipv4 is_ip_literal', function (done) {
- assert.equal(net_utils.is_ip_literal('[127.0.0.0]'), true);
- assert.equal(net_utils.is_ip_literal('[127.0.0.1]'), true);
- assert.equal(net_utils.is_ip_literal('[127.1.0.255]'), true);
- assert.equal(net_utils.is_ip_literal('127.0.0.0'), false);
- assert.equal(net_utils.is_ip_literal('127.0.0.1'), false);
- assert.equal(net_utils.is_ip_literal('127.1.0.255'), false);
+ assert.equal(net_utils.is_ip_literal('[127.0.0.0]'), true)
+ assert.equal(net_utils.is_ip_literal('[127.0.0.1]'), true)
+ assert.equal(net_utils.is_ip_literal('[127.1.0.255]'), true)
+ assert.equal(net_utils.is_ip_literal('127.0.0.0'), false)
+ assert.equal(net_utils.is_ip_literal('127.0.0.1'), false)
+ assert.equal(net_utils.is_ip_literal('127.1.0.255'), false)
- done();
+ done()
})
it('ipv6 is_ip_literal', function (done) {
- assert.equal(net_utils.is_ip_literal('[::5555:6666:7777:8888]'), true);
- assert.equal(net_utils.is_ip_literal('[1111::4444:5555:6666:7777:8888]'), true);
- assert.equal(net_utils.is_ip_literal('[2001:0:1234::C1C0:ABCD:876]'), true);
- assert.equal(net_utils.is_ip_literal('[IPv6:2607:fb90:4c28:f9e9:4ca2:2658:db85:f1a]'), true);
- assert.equal(net_utils.is_ip_literal('::5555:6666:7777:8888'), false);
- assert.equal(net_utils.is_ip_literal('1111::4444:5555:6666:7777:8888'), false);
- assert.equal(net_utils.is_ip_literal('2001:0:1234::C1C0:ABCD:876'), false);
-
- done();
+ assert.equal(net_utils.is_ip_literal('[::5555:6666:7777:8888]'), true)
+ assert.equal(
+ net_utils.is_ip_literal('[1111::4444:5555:6666:7777:8888]'),
+ true,
+ )
+ assert.equal(net_utils.is_ip_literal('[2001:0:1234::C1C0:ABCD:876]'), true)
+ assert.equal(
+ net_utils.is_ip_literal('[IPv6:2607:fb90:4c28:f9e9:4ca2:2658:db85:f1a]'),
+ true,
+ )
+ assert.equal(net_utils.is_ip_literal('::5555:6666:7777:8888'), false)
+ assert.equal(
+ net_utils.is_ip_literal('1111::4444:5555:6666:7777:8888'),
+ false,
+ )
+ assert.equal(net_utils.is_ip_literal('2001:0:1234::C1C0:ABCD:876'), false)
+
+ done()
})
})
describe('is_local_ipv4', function () {
it('127/8', function (done) {
- assert.equal(net_utils.is_local_ipv4('127.0.0.0'), true);
- assert.equal(net_utils.is_local_ipv4('127.0.0.1'), true);
- assert.equal(net_utils.is_local_ipv4('127.1.0.255'), true);
+ assert.equal(net_utils.is_local_ipv4('127.0.0.0'), true)
+ assert.equal(net_utils.is_local_ipv4('127.0.0.1'), true)
+ assert.equal(net_utils.is_local_ipv4('127.1.0.255'), true)
- done();
+ done()
})
it('0/8', function (done) {
- assert.equal(net_utils.is_local_ipv4('0.0.0.1'), false);
- assert.equal(net_utils.is_local_ipv4('0.255.0.1'), false);
- assert.equal(net_utils.is_local_ipv4('1.255.0.1'), false);
- assert.equal(net_utils.is_local_ipv4('10.255.0.1'), false);
- done();
+ assert.equal(net_utils.is_local_ipv4('0.0.0.1'), false)
+ assert.equal(net_utils.is_local_ipv4('0.255.0.1'), false)
+ assert.equal(net_utils.is_local_ipv4('1.255.0.1'), false)
+ assert.equal(net_utils.is_local_ipv4('10.255.0.1'), false)
+ done()
})
})
describe('is_private_ipv4', function () {
it('10/8', function (done) {
- assert.equal(net_utils.is_private_ipv4('10.0.0.0'), true);
- assert.equal(net_utils.is_private_ipv4('10.255.0.0'), true);
- assert.equal(net_utils.is_private_ipv4('9.255.0.0'), false);
- assert.equal(net_utils.is_private_ipv4('11.255.0.0'), false);
- done();
+ assert.equal(net_utils.is_private_ipv4('10.0.0.0'), true)
+ assert.equal(net_utils.is_private_ipv4('10.255.0.0'), true)
+ assert.equal(net_utils.is_private_ipv4('9.255.0.0'), false)
+ assert.equal(net_utils.is_private_ipv4('11.255.0.0'), false)
+ done()
})
it('192.168/16', function (done) {
- assert.equal(net_utils.is_private_ipv4('192.168.0.0'), true);
- assert.equal(net_utils.is_private_ipv4('192.169.0.0'), false);
- assert.equal(net_utils.is_private_ipv4('192.167.0.0'), false);
- done();
+ assert.equal(net_utils.is_private_ipv4('192.168.0.0'), true)
+ assert.equal(net_utils.is_private_ipv4('192.169.0.0'), false)
+ assert.equal(net_utils.is_private_ipv4('192.167.0.0'), false)
+ done()
})
it('172.16-31', function (done) {
- assert.equal(net_utils.is_private_ipv4('172.16.0.0'), true);
- assert.equal(net_utils.is_private_ipv4('172.20.0.0'), true);
- assert.equal(net_utils.is_private_ipv4('172.31.0.0'), true);
- assert.equal(net_utils.is_private_ipv4('172.15.0.0'), false);
- assert.equal(net_utils.is_private_ipv4('172.32.0.0'), false);
- done();
+ assert.equal(net_utils.is_private_ipv4('172.16.0.0'), true)
+ assert.equal(net_utils.is_private_ipv4('172.20.0.0'), true)
+ assert.equal(net_utils.is_private_ipv4('172.31.0.0'), true)
+ assert.equal(net_utils.is_private_ipv4('172.15.0.0'), false)
+ assert.equal(net_utils.is_private_ipv4('172.32.0.0'), false)
+ done()
})
})
describe('is_local_ipv6', function () {
it('::', function (done) {
- assert.equal(net_utils.is_local_ipv6('::'), true);
- done();
+ assert.equal(net_utils.is_local_ipv6('::'), true)
+ done()
})
it('::1', function (done) {
- assert.equal(net_utils.is_local_ipv6('::1'), true);
- assert.equal(net_utils.is_local_ipv6('0:0:0:0:0:0:0:1'), true);
- assert.equal(net_utils.is_local_ipv6(
- '0000:0000:0000:0000:0000:0000:0000:0001'), true);
- done();
+ assert.equal(net_utils.is_local_ipv6('::1'), true)
+ assert.equal(net_utils.is_local_ipv6('0:0:0:0:0:0:0:1'), true)
+ assert.equal(
+ net_utils.is_local_ipv6('0000:0000:0000:0000:0000:0000:0000:0001'),
+ true,
+ )
+ done()
})
it('fe80::/10', function (done) {
- assert.equal(net_utils.is_local_ipv6('fe80::'), true);
- assert.equal(net_utils.is_local_ipv6('fe80:'), false);
- assert.equal(net_utils.is_local_ipv6('fe8:'), false);
- assert.equal(net_utils.is_local_ipv6(':fe80:'), false);
- done();
+ assert.equal(net_utils.is_local_ipv6('fe80::'), true)
+ assert.equal(net_utils.is_local_ipv6('fe80:'), false)
+ assert.equal(net_utils.is_local_ipv6('fe8:'), false)
+ assert.equal(net_utils.is_local_ipv6(':fe80:'), false)
+ done()
})
it('fc80::/7', function (done) {
- assert.equal(net_utils.is_local_ipv6('fc00:'), true);
- assert.equal(net_utils.is_local_ipv6('fcff:'), true);
+ assert.equal(net_utils.is_local_ipv6('fc00:'), true)
+ assert.equal(net_utils.is_local_ipv6('fcff:'), true)
// examples from https://en.wikipedia.org/wiki/Unique_local_address
- assert.equal(net_utils.is_local_ipv6('fde4:8dba:82e1::'), true);
- assert.equal(net_utils.is_local_ipv6('fde4:8dba:82e1:ffff::'), true);
+ assert.equal(net_utils.is_local_ipv6('fde4:8dba:82e1::'), true)
+ assert.equal(net_utils.is_local_ipv6('fde4:8dba:82e1:ffff::'), true)
- assert.equal(net_utils.is_local_ipv6('fd00:'), true);
- assert.equal(net_utils.is_local_ipv6('fdff:'), true);
+ assert.equal(net_utils.is_local_ipv6('fd00:'), true)
+ assert.equal(net_utils.is_local_ipv6('fdff:'), true)
- assert.equal(net_utils.is_local_ipv6('fb00:'), false);
- assert.equal(net_utils.is_local_ipv6('fe00:'), false);
+ assert.equal(net_utils.is_local_ipv6('fb00:'), false)
+ assert.equal(net_utils.is_local_ipv6('fe00:'), false)
- assert.equal(net_utils.is_local_ipv6('fe8:'), false);
- assert.equal(net_utils.is_local_ipv6(':fe80:'), false);
- done();
+ assert.equal(net_utils.is_local_ipv6('fe8:'), false)
+ assert.equal(net_utils.is_local_ipv6(':fe80:'), false)
+ done()
})
})
const ip_fixtures = [
- [false , " 2001:0000:1234:0000:0000:C1C0:ABCD:0876 "],
- [false , " 2001:0000:1234:0000:0000:C1C0:ABCD:0876 0"],
- [false , " 2001:0000:1234:0000:0000:C1C0:ABCD:0876"],
- [false , " 2001:0:1234::C1C0:ABCD:876 "],
- [false , " 2001:0:1234::C1C0:ABCD:876"],
- [false , ""],
- [false , "':10.0.0.1"],
- [false , "---"],
- [false , "02001:0000:1234:0000:0000:C1C0:ABCD:0876"],
- [false , "1.2.3.4:1111:2222:3333:4444::5555"],
- [false , "1.2.3.4:1111:2222:3333::5555"],
- [false , "1.2.3.4:1111:2222::5555"],
- [false , "1.2.3.4:1111::5555"],
- [false , "1.2.3.4::"],
- [false , "1.2.3.4::5555"],
- [false , "1111"],
- [false , "11112222:3333:4444:5555:6666:1.2.3.4"],
- [false , "11112222:3333:4444:5555:6666:7777:8888"],
- [false , "1111:"],
- [false , "1111:1.2.3.4"],
- [false , "1111:2222"],
- [false , "1111:22223333:4444:5555:6666:1.2.3.4"],
- [false , "1111:22223333:4444:5555:6666:7777:8888"],
- [false , "1111:2222:"],
- [false , "1111:2222:1.2.3.4"],
- [false , "1111:2222:3333"],
- [false , "1111:2222:33334444:5555:6666:1.2.3.4"],
- [false , "1111:2222:33334444:5555:6666:7777:8888"],
- [false , "1111:2222:3333:"],
- [false , "1111:2222:3333:1.2.3.4"],
- [false , "1111:2222:3333:4444"],
- [false , "1111:2222:3333:44445555:6666:1.2.3.4"],
- [false , "1111:2222:3333:44445555:6666:7777:8888"],
- [false , "1111:2222:3333:4444:"],
- [false , "1111:2222:3333:4444:1.2.3.4"],
- [false , "1111:2222:3333:4444:5555"],
- [false , "1111:2222:3333:4444:55556666:1.2.3.4"],
- [false , "1111:2222:3333:4444:55556666:7777:8888"],
- [false , "1111:2222:3333:4444:5555:"],
- [false , "1111:2222:3333:4444:5555:1.2.3.4"],
- [false , "1111:2222:3333:4444:5555:6666"],
- [false , "1111:2222:3333:4444:5555:66661.2.3.4"],
- [false , "1111:2222:3333:4444:5555:66667777:8888"],
- [false , "1111:2222:3333:4444:5555:6666:"],
- [false , "1111:2222:3333:4444:5555:6666:00.00.00.00"],
- [false , "1111:2222:3333:4444:5555:6666:000.000.000.000"],
- [false , "1111:2222:3333:4444:5555:6666:1.2.3.4.5"],
- [false , "1111:2222:3333:4444:5555:6666:255.255.255255"],
- [false , "1111:2222:3333:4444:5555:6666:255.255255.255"],
- [false , "1111:2222:3333:4444:5555:6666:255255.255.255"],
- [false , "1111:2222:3333:4444:5555:6666:256.256.256.256"],
- [false , "1111:2222:3333:4444:5555:6666:7777"],
- [false , "1111:2222:3333:4444:5555:6666:77778888"],
- [false , "1111:2222:3333:4444:5555:6666:7777:"],
- [false , "1111:2222:3333:4444:5555:6666:7777:1.2.3.4"],
- [false , "1111:2222:3333:4444:5555:6666:7777:8888:"],
- [false , "1111:2222:3333:4444:5555:6666:7777:8888:1.2.3.4"],
- [false , "1111:2222:3333:4444:5555:6666:7777:8888:9999"],
- [false , "1111:2222:3333:4444:5555:6666:7777:8888::"],
- [false , "1111:2222:3333:4444:5555:6666:7777:::"],
- [false , "1111:2222:3333:4444:5555:6666::1.2.3.4"],
- [false , "1111:2222:3333:4444:5555:6666::8888:"],
- [false , "1111:2222:3333:4444:5555:6666:::"],
- [false , "1111:2222:3333:4444:5555:6666:::8888"],
- [false , "1111:2222:3333:4444:5555::7777:8888:"],
- [false , "1111:2222:3333:4444:5555::7777::"],
- [false , "1111:2222:3333:4444:5555::8888:"],
- [false , "1111:2222:3333:4444:5555:::"],
- [false , "1111:2222:3333:4444:5555:::1.2.3.4"],
- [false , "1111:2222:3333:4444:5555:::7777:8888"],
- [false , "1111:2222:3333:4444::5555:"],
- [false , "1111:2222:3333:4444::6666:7777:8888:"],
- [false , "1111:2222:3333:4444::6666:7777::"],
- [false , "1111:2222:3333:4444::6666::8888"],
- [false , "1111:2222:3333:4444::7777:8888:"],
- [false , "1111:2222:3333:4444::8888:"],
- [false , "1111:2222:3333:4444:::"],
- [false , "1111:2222:3333:4444:::6666:1.2.3.4"],
- [false , "1111:2222:3333:4444:::6666:7777:8888"],
- [false , "1111:2222:3333::5555:"],
- [false , "1111:2222:3333::5555:6666:7777:8888:"],
- [false , "1111:2222:3333::5555:6666:7777::"],
- [false , "1111:2222:3333::5555:6666::8888"],
- [false , "1111:2222:3333::5555::1.2.3.4"],
- [false , "1111:2222:3333::5555::7777:8888"],
- [false , "1111:2222:3333::6666:7777:8888:"],
- [false , "1111:2222:3333::7777:8888:"],
- [false , "1111:2222:3333::8888:"],
- [false , "1111:2222:3333:::"],
- [false , "1111:2222:3333:::5555:6666:1.2.3.4"],
- [false , "1111:2222:3333:::5555:6666:7777:8888"],
- [false , "1111:2222::4444:5555:6666:7777:8888:"],
- [false , "1111:2222::4444:5555:6666:7777::"],
- [false , "1111:2222::4444:5555:6666::8888"],
- [false , "1111:2222::4444:5555::1.2.3.4"],
- [false , "1111:2222::4444:5555::7777:8888"],
- [false , "1111:2222::4444::6666:1.2.3.4"],
- [false , "1111:2222::4444::6666:7777:8888"],
- [false , "1111:2222::5555:"],
- [false , "1111:2222::5555:6666:7777:8888:"],
- [false , "1111:2222::6666:7777:8888:"],
- [false , "1111:2222::7777:8888:"],
- [false , "1111:2222::8888:"],
- [false , "1111:2222:::"],
- [false , "1111:2222:::4444:5555:6666:1.2.3.4"],
- [false , "1111:2222:::4444:5555:6666:7777:8888"],
- [false , "1111::3333:4444:5555:6666:7777:8888:"],
- [false , "1111::3333:4444:5555:6666:7777::"],
- [false , "1111::3333:4444:5555:6666::8888"],
- [false , "1111::3333:4444:5555::1.2.3.4"],
- [false , "1111::3333:4444:5555::7777:8888"],
- [false , "1111::3333:4444::6666:1.2.3.4"],
- [false , "1111::3333:4444::6666:7777:8888"],
- [false , "1111::3333::5555:6666:1.2.3.4"],
- [false , "1111::3333::5555:6666:7777:8888"],
- [false , "1111::4444:5555:6666:7777:8888:"],
- [false , "1111::5555:"],
- [false , "1111::5555:6666:7777:8888:"],
- [false , "1111::6666:7777:8888:"],
- [false , "1111::7777:8888:"],
- [false , "1111::8888:"],
- [false , "1111:::"],
- [false , "1111:::3333:4444:5555:6666:1.2.3.4"],
- [false , "1111:::3333:4444:5555:6666:7777:8888"],
- [false , "123"],
- [false , "12345::6:7:8"],
- [false , "192.168.0.256"],
- [false , "192.168.256.0"],
- [false , "1:2:3:4:5:6:7:8:9"],
- [false , "1:2:3::4:5:6:7:8:9"],
- [false , "1:2:3::4:5::7:8"],
- [false , "1::1.2.256.4"],
- [false , "1::1.2.3.256"],
- [false , "1::1.2.3.300"],
- [false , "1::1.2.3.900"],
- [false , "1::1.2.300.4"],
- [false , "1::1.2.900.4"],
- [false , "1::1.256.3.4"],
- [false , "1::1.300.3.4"],
- [false , "1::1.900.3.4"],
- [false , "1::256.2.3.4"],
- [false , "1::260.2.3.4"],
- [false , "1::2::3"],
- [false , "1::300.2.3.4"],
- [false , "1::300.300.300.300"],
- [false , "1::3000.30.30.30"],
- [false , "1::400.2.3.4"],
- [false , "1::5:1.2.256.4"],
- [false , "1::5:1.2.3.256"],
- [false , "1::5:1.2.3.300"],
- [false , "1::5:1.2.3.900"],
- [false , "1::5:1.2.300.4"],
- [false , "1::5:1.2.900.4"],
- [false , "1::5:1.256.3.4"],
- [false , "1::5:1.300.3.4"],
- [false , "1::5:1.900.3.4"],
- [false , "1::5:256.2.3.4"],
- [false , "1::5:260.2.3.4"],
- [false , "1::5:300.2.3.4"],
- [false , "1::5:300.300.300.300"],
- [false , "1::5:3000.30.30.30"],
- [false , "1::5:400.2.3.4"],
- [false , "1::5:900.2.3.4"],
- [false , "1::900.2.3.4"],
- [false , "1:::3:4:5"],
- [false , "2001:0000:1234: 0000:0000:C1C0:ABCD:0876"],
- [false , "2001:0000:1234:0000:00001:C1C0:ABCD:0876"],
- [false , "2001:0000:1234:0000:0000:C1C0:ABCD:0876 0"],
- [false , "2001:1:1:1:1:1:255Z255X255Y255"],
- [false , "2001::FFD3::57ab"],
- [false , "2001:DB8:0:0:8:800:200C:417A:221"],
- [false , "2001:db8:85a3::8a2e:37023:7334"],
- [false , "2001:db8:85a3::8a2e:370k:7334"],
- [false , "255.256.255.255"],
- [false , "256.255.255.255"],
- [false , "3ffe:0b00:0000:0001:0000:0000:000a"],
- [false , "3ffe:b00::1::a"],
- [false , ":"],
- [false , ":1.2.3.4"],
- [false , ":1111:2222:3333:4444:5555:6666:1.2.3.4"],
- [false , ":1111:2222:3333:4444:5555:6666:7777:8888"],
- [false , ":1111:2222:3333:4444:5555:6666:7777::"],
- [false , ":1111:2222:3333:4444:5555:6666::"],
- [false , ":1111:2222:3333:4444:5555:6666::8888"],
- [false , ":1111:2222:3333:4444:5555::"],
- [false , ":1111:2222:3333:4444:5555::1.2.3.4"],
- [false , ":1111:2222:3333:4444:5555::7777:8888"],
- [false , ":1111:2222:3333:4444:5555::8888"],
- [false , ":1111:2222:3333:4444::"],
- [false , ":1111:2222:3333:4444::1.2.3.4"],
- [false , ":1111:2222:3333:4444::5555"],
- [false , ":1111:2222:3333:4444::6666:1.2.3.4"],
- [false , ":1111:2222:3333:4444::6666:7777:8888"],
- [false , ":1111:2222:3333:4444::7777:8888"],
- [false , ":1111:2222:3333:4444::8888"],
- [false , ":1111:2222:3333::"],
- [false , ":1111:2222:3333::1.2.3.4"],
- [false , ":1111:2222:3333::5555"],
- [false , ":1111:2222:3333::5555:6666:1.2.3.4"],
- [false , ":1111:2222:3333::5555:6666:7777:8888"],
- [false , ":1111:2222:3333::6666:1.2.3.4"],
- [false , ":1111:2222:3333::6666:7777:8888"],
- [false , ":1111:2222:3333::7777:8888"],
- [false , ":1111:2222:3333::8888"],
- [false , ":1111:2222::"],
- [false , ":1111:2222::1.2.3.4"],
- [false , ":1111:2222::4444:5555:6666:1.2.3.4"],
- [false , ":1111:2222::4444:5555:6666:7777:8888"],
- [false , ":1111:2222::5555"],
- [false , ":1111:2222::5555:6666:1.2.3.4"],
- [false , ":1111:2222::5555:6666:7777:8888"],
- [false , ":1111:2222::6666:1.2.3.4"],
- [false , ":1111:2222::6666:7777:8888"],
- [false , ":1111:2222::7777:8888"],
- [false , ":1111:2222::8888"],
- [false , ":1111::"],
- [false , ":1111::1.2.3.4"],
- [false , ":1111::3333:4444:5555:6666:1.2.3.4"],
- [false , ":1111::3333:4444:5555:6666:7777:8888"],
- [false , ":1111::4444:5555:6666:1.2.3.4"],
- [false , ":1111::4444:5555:6666:7777:8888"],
- [false , ":1111::5555"],
- [false , ":1111::5555:6666:1.2.3.4"],
- [false , ":1111::5555:6666:7777:8888"],
- [false , ":1111::6666:1.2.3.4"],
- [false , ":1111::6666:7777:8888"],
- [false , ":1111::7777:8888"],
- [false , ":1111::8888"],
- [false , ":2222:3333:4444:5555:6666:1.2.3.4"],
- [false , ":2222:3333:4444:5555:6666:7777:8888"],
- [false , ":3333:4444:5555:6666:1.2.3.4"],
- [false , ":3333:4444:5555:6666:7777:8888"],
- [false , ":4444:5555:6666:1.2.3.4"],
- [false , ":4444:5555:6666:7777:8888"],
- [false , ":5555:6666:1.2.3.4"],
- [false , ":5555:6666:7777:8888"],
- [false , ":6666:1.2.3.4"],
- [false , ":6666:7777:8888"],
- [false , ":7777:8888"],
- [false , ":8888"],
- [false , "::."],
- [false , "::.."],
- [false , "::..."],
- [false , "::...4"],
- [false , "::..3."],
- [false , "::..3.4"],
- [false , "::.2.."],
- [false , "::.2.3."],
- [false , "::.2.3.4"],
- [false , "::1..."],
- [false , "::1.2.."],
- [false , "::1.2.256.4"],
- [false , "::1.2.3."],
- [false , "::1.2.3.256"],
- [false , "::1.2.3.300"],
- [false , "::1.2.3.900"],
- [false , "::1.2.300.4"],
- [false , "::1.2.900.4"],
- [false , "::1.256.3.4"],
- [false , "::1.300.3.4"],
- [false , "::1.900.3.4"],
- [false , "::1111:2222:3333:4444:5555:6666::"],
- [false , "::2222:3333:4444:5555:6666:7777:1.2.3.4"],
- [false , "::2222:3333:4444:5555:6666:7777:8888:"],
- [false , "::2222:3333:4444:5555:6666:7777:8888:9999"],
- [false , "::2222:3333:4444:5555:7777:8888::"],
- [false , "::2222:3333:4444:5555:7777::8888"],
- [false , "::2222:3333:4444:5555::1.2.3.4"],
- [false , "::2222:3333:4444:5555::7777:8888"],
- [false , "::2222:3333:4444::6666:1.2.3.4"],
- [false , "::2222:3333:4444::6666:7777:8888"],
- [false , "::2222:3333::5555:6666:1.2.3.4"],
- [false , "::2222:3333::5555:6666:7777:8888"],
- [false , "::2222::4444:5555:6666:1.2.3.4"],
- [false , "::2222::4444:5555:6666:7777:8888"],
- [false , "::256.2.3.4"],
- [false , "::260.2.3.4"],
- [false , "::300.2.3.4"],
- [false , "::300.300.300.300"],
- [false , "::3000.30.30.30"],
- [false , "::3333:4444:5555:6666:7777:8888:"],
- [false , "::400.2.3.4"],
- [false , "::4444:5555:6666:7777:8888:"],
- [false , "::5555:"],
- [false , "::5555:6666:7777:8888:"],
- [false , "::6666:7777:8888:"],
- [false , "::7777:8888:"],
- [false , "::8888:"],
- [false , "::900.2.3.4"],
- [false , ":::"],
- [false , ":::1.2.3.4"],
- [false , ":::2222:3333:4444:5555:6666:1.2.3.4"],
- [false , ":::2222:3333:4444:5555:6666:7777:8888"],
- [false , ":::3333:4444:5555:6666:7777:8888"],
- [false , ":::4444:5555:6666:1.2.3.4"],
- [false , ":::4444:5555:6666:7777:8888"],
- [false , ":::5555"],
- [false , ":::5555:6666:1.2.3.4"],
- [false , ":::5555:6666:7777:8888"],
- [false , ":::6666:1.2.3.4"],
- [false , ":::6666:7777:8888"],
- [false , ":::7777:8888"],
- [false , ":::8888"],
- [false , "::ffff:192x168.1.26"],
- [false , "::ffff:2.3.4"],
- [false , "::ffff:257.1.2.3"],
- [false , "FF01::101::2"],
- [false , "FF02:0000:0000:0000:0000:0000:0000:0000:0001"],
- [false , "XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:1.2.3.4"],
- [false , "XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX"],
- [false , "fe80:0000:0000:0000:0204:61ff:254.157.241.086"],
- [false , "fe80::4413:c8ae:2821:5852%10"],
- [false , "ldkfj"],
- [false , "mydomain.com"],
- [false , "test.mydomain.com"],
- [true , "0000:0000:0000:0000:0000:0000:0000:0000"],
- [true , "0000:0000:0000:0000:0000:0000:0000:0001"],
- [true , "0:0:0:0:0:0:0:0"],
- [true , "0:0:0:0:0:0:0:1"],
- [true , "0:0:0:0:0:0:0::"],
- [true , "0:0:0:0:0:0:13.1.68.3"],
- [true , "0:0:0:0:0:0::"],
- [true , "0:0:0:0:0::"],
- [true , "0:0:0:0:0:FFFF:129.144.52.38"],
- [true , "0:0:0:0::"],
- [true , "0:0:0::"],
- [true , "0:0::"],
- [true , "0::"],
- [true , "0:a:b:c:d:e:f::"],
- [true , "1.2.3.4"],
- [true , "1111:2222:3333:4444:5555:6666:123.123.123.123"],
- [true , "1111:2222:3333:4444:5555:6666:7777:8888"],
- [true , "1111:2222:3333:4444:5555:6666:7777::"],
- [true , "1111:2222:3333:4444:5555:6666::"],
- [true , "1111:2222:3333:4444:5555:6666::8888"],
- [true , "1111:2222:3333:4444:5555::"],
- [true , "1111:2222:3333:4444:5555::123.123.123.123"],
- [true , "1111:2222:3333:4444:5555::7777:8888"],
- [true , "1111:2222:3333:4444:5555::8888"],
- [true , "1111:2222:3333:4444::"],
- [true , "1111:2222:3333:4444::123.123.123.123"],
- [true , "1111:2222:3333:4444::6666:123.123.123.123"],
- [true , "1111:2222:3333:4444::6666:7777:8888"],
- [true , "1111:2222:3333:4444::7777:8888"],
- [true , "1111:2222:3333:4444::8888"],
- [true , "1111:2222:3333::"],
- [true , "1111:2222:3333::123.123.123.123"],
- [true , "1111:2222:3333::5555:6666:123.123.123.123"],
- [true , "1111:2222:3333::5555:6666:7777:8888"],
- [true , "1111:2222:3333::6666:123.123.123.123"],
- [true , "1111:2222:3333::6666:7777:8888"],
- [true , "1111:2222:3333::7777:8888"],
- [true , "1111:2222:3333::8888"],
- [true , "1111:2222::"],
- [true , "1111:2222::123.123.123.123"],
- [true , "1111:2222::4444:5555:6666:123.123.123.123"],
- [true , "1111:2222::4444:5555:6666:7777:8888"],
- [true , "1111:2222::5555:6666:123.123.123.123"],
- [true , "1111:2222::5555:6666:7777:8888"],
- [true , "1111:2222::6666:123.123.123.123"],
- [true , "1111:2222::6666:7777:8888"],
- [true , "1111:2222::7777:8888"],
- [true , "1111:2222::8888"],
- [true , "1111::"],
- [true , "1111::123.123.123.123"],
- [true , "1111::3333:4444:5555:6666:123.123.123.123"],
- [true , "1111::3333:4444:5555:6666:7777:8888"],
- [true , "1111::4444:5555:6666:123.123.123.123"],
- [true , "1111::4444:5555:6666:7777:8888"],
- [true , "1111::5555:6666:123.123.123.123"],
- [true , "1111::5555:6666:7777:8888"],
- [true , "1111::6666:123.123.123.123"],
- [true , "1111::6666:7777:8888"],
- [true , "1111::7777:8888"],
- [true , "1111::8888"],
- [true , "123.23.34.2"],
- [true , "172.26.168.134"],
- [true , "192.168.0.0"],
- [true , "192.168.128.255"],
- [true , "1:2:3:4:5:6:1.2.3.4"],
- [true , "1:2:3:4:5:6:7:8"],
- [true , "1:2:3:4:5:6::"],
- [true , "1:2:3:4:5:6::8"],
- [true , "1:2:3:4:5::"],
- [true , "1:2:3:4:5::1.2.3.4"],
- [true , "1:2:3:4:5::7:8"],
- [true , "1:2:3:4:5::8"],
- [true , "1:2:3:4::"],
- [true , "1:2:3:4::1.2.3.4"],
- [true , "1:2:3:4::5:1.2.3.4"],
- [true , "1:2:3:4::7:8"],
- [true , "1:2:3:4::8"],
- [true , "1:2:3::"],
- [true , "1:2:3::1.2.3.4"],
- [true , "1:2:3::5:1.2.3.4"],
- [true , "1:2:3::7:8"],
- [true , "1:2:3::8"],
- [true , "1:2::"],
- [true , "1:2::1.2.3.4"],
- [true , "1:2::5:1.2.3.4"],
- [true , "1:2::7:8"],
- [true , "1:2::8"],
- [true , "1::"],
- [true , "1::1.2.3.4"],
- [true , "1::2:3"],
- [true , "1::2:3:4"],
- [true , "1::2:3:4:5"],
- [true , "1::2:3:4:5:6"],
- [true , "1::2:3:4:5:6:7"],
- [true , "1::5:1.2.3.4"],
- [true , "1::5:11.22.33.44"],
- [true , "1::7:8"],
- [true , "1::8"],
- [true , "2001:0000:1234:0000:0000:C1C0:ABCD:0876"],
- [true , "2001:0:1234::C1C0:ABCD:876"],
- [true , "2001:0db8:0000:0000:0000:0000:1428:57ab"],
- [true , "2001:0db8:0000:0000:0000::1428:57ab"],
- [true , "2001:0db8:0:0:0:0:1428:57ab"],
- [true , "2001:0db8:0:0::1428:57ab"],
- [true , "2001:0db8:1234:0000:0000:0000:0000:0000"],
- [true , "2001:0db8:1234::"],
- [true , "2001:0db8:1234:ffff:ffff:ffff:ffff:ffff"],
- [true , "2001:0db8:85a3:0000:0000:8a2e:0370:7334"],
- [true , "2001:0db8::1428:57ab"],
- [true , "2001:2:3:4:5:6:7:134"],
- [true , "2001:DB8:0:0:8:800:200C:417A"],
- [true , "2001:DB8::8:800:200C:417A"],
- [true , "2001:db8:85a3:0:0:8a2e:370:7334"],
- [true , "2001:db8:85a3::8a2e:370:7334"],
- [true , "2001:db8::"],
- [true , "2001:db8::1428:57ab"],
- [true , "2001:db8:a::123"],
- [true , "2002::"],
- [true , "2::10"],
- [true , "3ffe:0b00:0000:0000:0001:0000:0000:000a"],
- [true , "3ffe:b00::1:0:0:a"],
- [true , "::"],
- [true , "::0"],
- [true , "::0:0"],
- [true , "::0:0:0"],
- [true , "::0:0:0:0"],
- [true , "::0:0:0:0:0"],
- [true , "::0:0:0:0:0:0"],
- [true , "::0:0:0:0:0:0:0"],
- [true , "::0:a:b:c:d:e:f"],
- [true , "::1"],
- [true , "::123.123.123.123"],
- [true , "::13.1.68.3"],
- [true , "::2222:3333:4444:5555:6666:123.123.123.123"],
- [true , "::2222:3333:4444:5555:6666:7777:8888"],
- [true , "::2:3"],
- [true , "::2:3:4"],
- [true , "::2:3:4:5"],
- [true , "::2:3:4:5:6"],
- [true , "::2:3:4:5:6:7"],
- [true , "::2:3:4:5:6:7:8"],
- [true , "::3333:4444:5555:6666:7777:8888"],
- [true , "::4444:5555:6666:123.123.123.123"],
- [true , "::4444:5555:6666:7777:8888"],
- [true , "::5555:6666:123.123.123.123"],
- [true , "::5555:6666:7777:8888"],
- [true , "::6666:123.123.123.123"],
- [true , "::6666:7777:8888"],
- [true , "::7777:8888"],
- [true , "::8"],
- [true , "::8888"],
- [true , "::FFFF:129.144.52.38"],
- [true , "::ffff:0:0"],
- [true , "::ffff:0c22:384e"],
- [true , "::ffff:12.34.56.78"],
- [true , "::ffff:192.0.2.128"],
- [true , "::ffff:192.168.1.1"],
- [true , "::ffff:192.168.1.26"],
- [true , "::ffff:c000:280"],
- [true , "FF01:0:0:0:0:0:0:101"],
- [true , "FF01::101"],
- [true , "FF02:0000:0000:0000:0000:0000:0000:0001"],
- [true , "FF02::1"],
- [true , "a:b:c:d:e:f:0::"],
- [true , "fe80:0000:0000:0000:0204:61ff:fe9d:f156"],
- [true , "fe80:0:0:0:204:61ff:254.157.241.86"],
- [true , "fe80:0:0:0:204:61ff:fe9d:f156"],
- [true , "fe80::"],
- [true , "fe80::1"],
- [true , "fe80::204:61ff:254.157.241.86"],
- [true , "fe80::204:61ff:fe9d:f156"],
- [true , "fe80::217:f2ff:254.7.237.98"],
- [true , "fe80::217:f2ff:fe07:ed62"],
- [true , "ff02::1"]
-];
+ [false, ' 2001:0000:1234:0000:0000:C1C0:ABCD:0876 '],
+ [false, ' 2001:0000:1234:0000:0000:C1C0:ABCD:0876 0'],
+ [false, ' 2001:0000:1234:0000:0000:C1C0:ABCD:0876'],
+ [false, ' 2001:0:1234::C1C0:ABCD:876 '],
+ [false, ' 2001:0:1234::C1C0:ABCD:876'],
+ [false, ''],
+ [false, "':10.0.0.1"],
+ [false, '---'],
+ [false, '02001:0000:1234:0000:0000:C1C0:ABCD:0876'],
+ [false, '1.2.3.4:1111:2222:3333:4444::5555'],
+ [false, '1.2.3.4:1111:2222:3333::5555'],
+ [false, '1.2.3.4:1111:2222::5555'],
+ [false, '1.2.3.4:1111::5555'],
+ [false, '1.2.3.4::'],
+ [false, '1.2.3.4::5555'],
+ [false, '1111'],
+ [false, '11112222:3333:4444:5555:6666:1.2.3.4'],
+ [false, '11112222:3333:4444:5555:6666:7777:8888'],
+ [false, '1111:'],
+ [false, '1111:1.2.3.4'],
+ [false, '1111:2222'],
+ [false, '1111:22223333:4444:5555:6666:1.2.3.4'],
+ [false, '1111:22223333:4444:5555:6666:7777:8888'],
+ [false, '1111:2222:'],
+ [false, '1111:2222:1.2.3.4'],
+ [false, '1111:2222:3333'],
+ [false, '1111:2222:33334444:5555:6666:1.2.3.4'],
+ [false, '1111:2222:33334444:5555:6666:7777:8888'],
+ [false, '1111:2222:3333:'],
+ [false, '1111:2222:3333:1.2.3.4'],
+ [false, '1111:2222:3333:4444'],
+ [false, '1111:2222:3333:44445555:6666:1.2.3.4'],
+ [false, '1111:2222:3333:44445555:6666:7777:8888'],
+ [false, '1111:2222:3333:4444:'],
+ [false, '1111:2222:3333:4444:1.2.3.4'],
+ [false, '1111:2222:3333:4444:5555'],
+ [false, '1111:2222:3333:4444:55556666:1.2.3.4'],
+ [false, '1111:2222:3333:4444:55556666:7777:8888'],
+ [false, '1111:2222:3333:4444:5555:'],
+ [false, '1111:2222:3333:4444:5555:1.2.3.4'],
+ [false, '1111:2222:3333:4444:5555:6666'],
+ [false, '1111:2222:3333:4444:5555:66661.2.3.4'],
+ [false, '1111:2222:3333:4444:5555:66667777:8888'],
+ [false, '1111:2222:3333:4444:5555:6666:'],
+ [false, '1111:2222:3333:4444:5555:6666:00.00.00.00'],
+ [false, '1111:2222:3333:4444:5555:6666:000.000.000.000'],
+ [false, '1111:2222:3333:4444:5555:6666:1.2.3.4.5'],
+ [false, '1111:2222:3333:4444:5555:6666:255.255.255255'],
+ [false, '1111:2222:3333:4444:5555:6666:255.255255.255'],
+ [false, '1111:2222:3333:4444:5555:6666:255255.255.255'],
+ [false, '1111:2222:3333:4444:5555:6666:256.256.256.256'],
+ [false, '1111:2222:3333:4444:5555:6666:7777'],
+ [false, '1111:2222:3333:4444:5555:6666:77778888'],
+ [false, '1111:2222:3333:4444:5555:6666:7777:'],
+ [false, '1111:2222:3333:4444:5555:6666:7777:1.2.3.4'],
+ [false, '1111:2222:3333:4444:5555:6666:7777:8888:'],
+ [false, '1111:2222:3333:4444:5555:6666:7777:8888:1.2.3.4'],
+ [false, '1111:2222:3333:4444:5555:6666:7777:8888:9999'],
+ [false, '1111:2222:3333:4444:5555:6666:7777:8888::'],
+ [false, '1111:2222:3333:4444:5555:6666:7777:::'],
+ [false, '1111:2222:3333:4444:5555:6666::1.2.3.4'],
+ [false, '1111:2222:3333:4444:5555:6666::8888:'],
+ [false, '1111:2222:3333:4444:5555:6666:::'],
+ [false, '1111:2222:3333:4444:5555:6666:::8888'],
+ [false, '1111:2222:3333:4444:5555::7777:8888:'],
+ [false, '1111:2222:3333:4444:5555::7777::'],
+ [false, '1111:2222:3333:4444:5555::8888:'],
+ [false, '1111:2222:3333:4444:5555:::'],
+ [false, '1111:2222:3333:4444:5555:::1.2.3.4'],
+ [false, '1111:2222:3333:4444:5555:::7777:8888'],
+ [false, '1111:2222:3333:4444::5555:'],
+ [false, '1111:2222:3333:4444::6666:7777:8888:'],
+ [false, '1111:2222:3333:4444::6666:7777::'],
+ [false, '1111:2222:3333:4444::6666::8888'],
+ [false, '1111:2222:3333:4444::7777:8888:'],
+ [false, '1111:2222:3333:4444::8888:'],
+ [false, '1111:2222:3333:4444:::'],
+ [false, '1111:2222:3333:4444:::6666:1.2.3.4'],
+ [false, '1111:2222:3333:4444:::6666:7777:8888'],
+ [false, '1111:2222:3333::5555:'],
+ [false, '1111:2222:3333::5555:6666:7777:8888:'],
+ [false, '1111:2222:3333::5555:6666:7777::'],
+ [false, '1111:2222:3333::5555:6666::8888'],
+ [false, '1111:2222:3333::5555::1.2.3.4'],
+ [false, '1111:2222:3333::5555::7777:8888'],
+ [false, '1111:2222:3333::6666:7777:8888:'],
+ [false, '1111:2222:3333::7777:8888:'],
+ [false, '1111:2222:3333::8888:'],
+ [false, '1111:2222:3333:::'],
+ [false, '1111:2222:3333:::5555:6666:1.2.3.4'],
+ [false, '1111:2222:3333:::5555:6666:7777:8888'],
+ [false, '1111:2222::4444:5555:6666:7777:8888:'],
+ [false, '1111:2222::4444:5555:6666:7777::'],
+ [false, '1111:2222::4444:5555:6666::8888'],
+ [false, '1111:2222::4444:5555::1.2.3.4'],
+ [false, '1111:2222::4444:5555::7777:8888'],
+ [false, '1111:2222::4444::6666:1.2.3.4'],
+ [false, '1111:2222::4444::6666:7777:8888'],
+ [false, '1111:2222::5555:'],
+ [false, '1111:2222::5555:6666:7777:8888:'],
+ [false, '1111:2222::6666:7777:8888:'],
+ [false, '1111:2222::7777:8888:'],
+ [false, '1111:2222::8888:'],
+ [false, '1111:2222:::'],
+ [false, '1111:2222:::4444:5555:6666:1.2.3.4'],
+ [false, '1111:2222:::4444:5555:6666:7777:8888'],
+ [false, '1111::3333:4444:5555:6666:7777:8888:'],
+ [false, '1111::3333:4444:5555:6666:7777::'],
+ [false, '1111::3333:4444:5555:6666::8888'],
+ [false, '1111::3333:4444:5555::1.2.3.4'],
+ [false, '1111::3333:4444:5555::7777:8888'],
+ [false, '1111::3333:4444::6666:1.2.3.4'],
+ [false, '1111::3333:4444::6666:7777:8888'],
+ [false, '1111::3333::5555:6666:1.2.3.4'],
+ [false, '1111::3333::5555:6666:7777:8888'],
+ [false, '1111::4444:5555:6666:7777:8888:'],
+ [false, '1111::5555:'],
+ [false, '1111::5555:6666:7777:8888:'],
+ [false, '1111::6666:7777:8888:'],
+ [false, '1111::7777:8888:'],
+ [false, '1111::8888:'],
+ [false, '1111:::'],
+ [false, '1111:::3333:4444:5555:6666:1.2.3.4'],
+ [false, '1111:::3333:4444:5555:6666:7777:8888'],
+ [false, '123'],
+ [false, '12345::6:7:8'],
+ [false, '192.168.0.256'],
+ [false, '192.168.256.0'],
+ [false, '1:2:3:4:5:6:7:8:9'],
+ [false, '1:2:3::4:5:6:7:8:9'],
+ [false, '1:2:3::4:5::7:8'],
+ [false, '1::1.2.256.4'],
+ [false, '1::1.2.3.256'],
+ [false, '1::1.2.3.300'],
+ [false, '1::1.2.3.900'],
+ [false, '1::1.2.300.4'],
+ [false, '1::1.2.900.4'],
+ [false, '1::1.256.3.4'],
+ [false, '1::1.300.3.4'],
+ [false, '1::1.900.3.4'],
+ [false, '1::256.2.3.4'],
+ [false, '1::260.2.3.4'],
+ [false, '1::2::3'],
+ [false, '1::300.2.3.4'],
+ [false, '1::300.300.300.300'],
+ [false, '1::3000.30.30.30'],
+ [false, '1::400.2.3.4'],
+ [false, '1::5:1.2.256.4'],
+ [false, '1::5:1.2.3.256'],
+ [false, '1::5:1.2.3.300'],
+ [false, '1::5:1.2.3.900'],
+ [false, '1::5:1.2.300.4'],
+ [false, '1::5:1.2.900.4'],
+ [false, '1::5:1.256.3.4'],
+ [false, '1::5:1.300.3.4'],
+ [false, '1::5:1.900.3.4'],
+ [false, '1::5:256.2.3.4'],
+ [false, '1::5:260.2.3.4'],
+ [false, '1::5:300.2.3.4'],
+ [false, '1::5:300.300.300.300'],
+ [false, '1::5:3000.30.30.30'],
+ [false, '1::5:400.2.3.4'],
+ [false, '1::5:900.2.3.4'],
+ [false, '1::900.2.3.4'],
+ [false, '1:::3:4:5'],
+ [false, '2001:0000:1234: 0000:0000:C1C0:ABCD:0876'],
+ [false, '2001:0000:1234:0000:00001:C1C0:ABCD:0876'],
+ [false, '2001:0000:1234:0000:0000:C1C0:ABCD:0876 0'],
+ [false, '2001:1:1:1:1:1:255Z255X255Y255'],
+ [false, '2001::FFD3::57ab'],
+ [false, '2001:DB8:0:0:8:800:200C:417A:221'],
+ [false, '2001:db8:85a3::8a2e:37023:7334'],
+ [false, '2001:db8:85a3::8a2e:370k:7334'],
+ [false, '255.256.255.255'],
+ [false, '256.255.255.255'],
+ [false, '3ffe:0b00:0000:0001:0000:0000:000a'],
+ [false, '3ffe:b00::1::a'],
+ [false, ':'],
+ [false, ':1.2.3.4'],
+ [false, ':1111:2222:3333:4444:5555:6666:1.2.3.4'],
+ [false, ':1111:2222:3333:4444:5555:6666:7777:8888'],
+ [false, ':1111:2222:3333:4444:5555:6666:7777::'],
+ [false, ':1111:2222:3333:4444:5555:6666::'],
+ [false, ':1111:2222:3333:4444:5555:6666::8888'],
+ [false, ':1111:2222:3333:4444:5555::'],
+ [false, ':1111:2222:3333:4444:5555::1.2.3.4'],
+ [false, ':1111:2222:3333:4444:5555::7777:8888'],
+ [false, ':1111:2222:3333:4444:5555::8888'],
+ [false, ':1111:2222:3333:4444::'],
+ [false, ':1111:2222:3333:4444::1.2.3.4'],
+ [false, ':1111:2222:3333:4444::5555'],
+ [false, ':1111:2222:3333:4444::6666:1.2.3.4'],
+ [false, ':1111:2222:3333:4444::6666:7777:8888'],
+ [false, ':1111:2222:3333:4444::7777:8888'],
+ [false, ':1111:2222:3333:4444::8888'],
+ [false, ':1111:2222:3333::'],
+ [false, ':1111:2222:3333::1.2.3.4'],
+ [false, ':1111:2222:3333::5555'],
+ [false, ':1111:2222:3333::5555:6666:1.2.3.4'],
+ [false, ':1111:2222:3333::5555:6666:7777:8888'],
+ [false, ':1111:2222:3333::6666:1.2.3.4'],
+ [false, ':1111:2222:3333::6666:7777:8888'],
+ [false, ':1111:2222:3333::7777:8888'],
+ [false, ':1111:2222:3333::8888'],
+ [false, ':1111:2222::'],
+ [false, ':1111:2222::1.2.3.4'],
+ [false, ':1111:2222::4444:5555:6666:1.2.3.4'],
+ [false, ':1111:2222::4444:5555:6666:7777:8888'],
+ [false, ':1111:2222::5555'],
+ [false, ':1111:2222::5555:6666:1.2.3.4'],
+ [false, ':1111:2222::5555:6666:7777:8888'],
+ [false, ':1111:2222::6666:1.2.3.4'],
+ [false, ':1111:2222::6666:7777:8888'],
+ [false, ':1111:2222::7777:8888'],
+ [false, ':1111:2222::8888'],
+ [false, ':1111::'],
+ [false, ':1111::1.2.3.4'],
+ [false, ':1111::3333:4444:5555:6666:1.2.3.4'],
+ [false, ':1111::3333:4444:5555:6666:7777:8888'],
+ [false, ':1111::4444:5555:6666:1.2.3.4'],
+ [false, ':1111::4444:5555:6666:7777:8888'],
+ [false, ':1111::5555'],
+ [false, ':1111::5555:6666:1.2.3.4'],
+ [false, ':1111::5555:6666:7777:8888'],
+ [false, ':1111::6666:1.2.3.4'],
+ [false, ':1111::6666:7777:8888'],
+ [false, ':1111::7777:8888'],
+ [false, ':1111::8888'],
+ [false, ':2222:3333:4444:5555:6666:1.2.3.4'],
+ [false, ':2222:3333:4444:5555:6666:7777:8888'],
+ [false, ':3333:4444:5555:6666:1.2.3.4'],
+ [false, ':3333:4444:5555:6666:7777:8888'],
+ [false, ':4444:5555:6666:1.2.3.4'],
+ [false, ':4444:5555:6666:7777:8888'],
+ [false, ':5555:6666:1.2.3.4'],
+ [false, ':5555:6666:7777:8888'],
+ [false, ':6666:1.2.3.4'],
+ [false, ':6666:7777:8888'],
+ [false, ':7777:8888'],
+ [false, ':8888'],
+ [false, '::.'],
+ [false, '::..'],
+ [false, '::...'],
+ [false, '::...4'],
+ [false, '::..3.'],
+ [false, '::..3.4'],
+ [false, '::.2..'],
+ [false, '::.2.3.'],
+ [false, '::.2.3.4'],
+ [false, '::1...'],
+ [false, '::1.2..'],
+ [false, '::1.2.256.4'],
+ [false, '::1.2.3.'],
+ [false, '::1.2.3.256'],
+ [false, '::1.2.3.300'],
+ [false, '::1.2.3.900'],
+ [false, '::1.2.300.4'],
+ [false, '::1.2.900.4'],
+ [false, '::1.256.3.4'],
+ [false, '::1.300.3.4'],
+ [false, '::1.900.3.4'],
+ [false, '::1111:2222:3333:4444:5555:6666::'],
+ [false, '::2222:3333:4444:5555:6666:7777:1.2.3.4'],
+ [false, '::2222:3333:4444:5555:6666:7777:8888:'],
+ [false, '::2222:3333:4444:5555:6666:7777:8888:9999'],
+ [false, '::2222:3333:4444:5555:7777:8888::'],
+ [false, '::2222:3333:4444:5555:7777::8888'],
+ [false, '::2222:3333:4444:5555::1.2.3.4'],
+ [false, '::2222:3333:4444:5555::7777:8888'],
+ [false, '::2222:3333:4444::6666:1.2.3.4'],
+ [false, '::2222:3333:4444::6666:7777:8888'],
+ [false, '::2222:3333::5555:6666:1.2.3.4'],
+ [false, '::2222:3333::5555:6666:7777:8888'],
+ [false, '::2222::4444:5555:6666:1.2.3.4'],
+ [false, '::2222::4444:5555:6666:7777:8888'],
+ [false, '::256.2.3.4'],
+ [false, '::260.2.3.4'],
+ [false, '::300.2.3.4'],
+ [false, '::300.300.300.300'],
+ [false, '::3000.30.30.30'],
+ [false, '::3333:4444:5555:6666:7777:8888:'],
+ [false, '::400.2.3.4'],
+ [false, '::4444:5555:6666:7777:8888:'],
+ [false, '::5555:'],
+ [false, '::5555:6666:7777:8888:'],
+ [false, '::6666:7777:8888:'],
+ [false, '::7777:8888:'],
+ [false, '::8888:'],
+ [false, '::900.2.3.4'],
+ [false, ':::'],
+ [false, ':::1.2.3.4'],
+ [false, ':::2222:3333:4444:5555:6666:1.2.3.4'],
+ [false, ':::2222:3333:4444:5555:6666:7777:8888'],
+ [false, ':::3333:4444:5555:6666:7777:8888'],
+ [false, ':::4444:5555:6666:1.2.3.4'],
+ [false, ':::4444:5555:6666:7777:8888'],
+ [false, ':::5555'],
+ [false, ':::5555:6666:1.2.3.4'],
+ [false, ':::5555:6666:7777:8888'],
+ [false, ':::6666:1.2.3.4'],
+ [false, ':::6666:7777:8888'],
+ [false, ':::7777:8888'],
+ [false, ':::8888'],
+ [false, '::ffff:192x168.1.26'],
+ [false, '::ffff:2.3.4'],
+ [false, '::ffff:257.1.2.3'],
+ [false, 'FF01::101::2'],
+ [false, 'FF02:0000:0000:0000:0000:0000:0000:0000:0001'],
+ [false, 'XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:1.2.3.4'],
+ [false, 'XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX'],
+ [false, 'fe80:0000:0000:0000:0204:61ff:254.157.241.086'],
+ [false, 'fe80::4413:c8ae:2821:5852%10'],
+ [false, 'ldkfj'],
+ [false, 'mydomain.com'],
+ [false, 'test.mydomain.com'],
+ [true, '0000:0000:0000:0000:0000:0000:0000:0000'],
+ [true, '0000:0000:0000:0000:0000:0000:0000:0001'],
+ [true, '0:0:0:0:0:0:0:0'],
+ [true, '0:0:0:0:0:0:0:1'],
+ [true, '0:0:0:0:0:0:0::'],
+ [true, '0:0:0:0:0:0:13.1.68.3'],
+ [true, '0:0:0:0:0:0::'],
+ [true, '0:0:0:0:0::'],
+ [true, '0:0:0:0:0:FFFF:129.144.52.38'],
+ [true, '0:0:0:0::'],
+ [true, '0:0:0::'],
+ [true, '0:0::'],
+ [true, '0::'],
+ [true, '0:a:b:c:d:e:f::'],
+ [true, '1.2.3.4'],
+ [true, '1111:2222:3333:4444:5555:6666:123.123.123.123'],
+ [true, '1111:2222:3333:4444:5555:6666:7777:8888'],
+ [true, '1111:2222:3333:4444:5555:6666:7777::'],
+ [true, '1111:2222:3333:4444:5555:6666::'],
+ [true, '1111:2222:3333:4444:5555:6666::8888'],
+ [true, '1111:2222:3333:4444:5555::'],
+ [true, '1111:2222:3333:4444:5555::123.123.123.123'],
+ [true, '1111:2222:3333:4444:5555::7777:8888'],
+ [true, '1111:2222:3333:4444:5555::8888'],
+ [true, '1111:2222:3333:4444::'],
+ [true, '1111:2222:3333:4444::123.123.123.123'],
+ [true, '1111:2222:3333:4444::6666:123.123.123.123'],
+ [true, '1111:2222:3333:4444::6666:7777:8888'],
+ [true, '1111:2222:3333:4444::7777:8888'],
+ [true, '1111:2222:3333:4444::8888'],
+ [true, '1111:2222:3333::'],
+ [true, '1111:2222:3333::123.123.123.123'],
+ [true, '1111:2222:3333::5555:6666:123.123.123.123'],
+ [true, '1111:2222:3333::5555:6666:7777:8888'],
+ [true, '1111:2222:3333::6666:123.123.123.123'],
+ [true, '1111:2222:3333::6666:7777:8888'],
+ [true, '1111:2222:3333::7777:8888'],
+ [true, '1111:2222:3333::8888'],
+ [true, '1111:2222::'],
+ [true, '1111:2222::123.123.123.123'],
+ [true, '1111:2222::4444:5555:6666:123.123.123.123'],
+ [true, '1111:2222::4444:5555:6666:7777:8888'],
+ [true, '1111:2222::5555:6666:123.123.123.123'],
+ [true, '1111:2222::5555:6666:7777:8888'],
+ [true, '1111:2222::6666:123.123.123.123'],
+ [true, '1111:2222::6666:7777:8888'],
+ [true, '1111:2222::7777:8888'],
+ [true, '1111:2222::8888'],
+ [true, '1111::'],
+ [true, '1111::123.123.123.123'],
+ [true, '1111::3333:4444:5555:6666:123.123.123.123'],
+ [true, '1111::3333:4444:5555:6666:7777:8888'],
+ [true, '1111::4444:5555:6666:123.123.123.123'],
+ [true, '1111::4444:5555:6666:7777:8888'],
+ [true, '1111::5555:6666:123.123.123.123'],
+ [true, '1111::5555:6666:7777:8888'],
+ [true, '1111::6666:123.123.123.123'],
+ [true, '1111::6666:7777:8888'],
+ [true, '1111::7777:8888'],
+ [true, '1111::8888'],
+ [true, '123.23.34.2'],
+ [true, '172.26.168.134'],
+ [true, '192.168.0.0'],
+ [true, '192.168.128.255'],
+ [true, '1:2:3:4:5:6:1.2.3.4'],
+ [true, '1:2:3:4:5:6:7:8'],
+ [true, '1:2:3:4:5:6::'],
+ [true, '1:2:3:4:5:6::8'],
+ [true, '1:2:3:4:5::'],
+ [true, '1:2:3:4:5::1.2.3.4'],
+ [true, '1:2:3:4:5::7:8'],
+ [true, '1:2:3:4:5::8'],
+ [true, '1:2:3:4::'],
+ [true, '1:2:3:4::1.2.3.4'],
+ [true, '1:2:3:4::5:1.2.3.4'],
+ [true, '1:2:3:4::7:8'],
+ [true, '1:2:3:4::8'],
+ [true, '1:2:3::'],
+ [true, '1:2:3::1.2.3.4'],
+ [true, '1:2:3::5:1.2.3.4'],
+ [true, '1:2:3::7:8'],
+ [true, '1:2:3::8'],
+ [true, '1:2::'],
+ [true, '1:2::1.2.3.4'],
+ [true, '1:2::5:1.2.3.4'],
+ [true, '1:2::7:8'],
+ [true, '1:2::8'],
+ [true, '1::'],
+ [true, '1::1.2.3.4'],
+ [true, '1::2:3'],
+ [true, '1::2:3:4'],
+ [true, '1::2:3:4:5'],
+ [true, '1::2:3:4:5:6'],
+ [true, '1::2:3:4:5:6:7'],
+ [true, '1::5:1.2.3.4'],
+ [true, '1::5:11.22.33.44'],
+ [true, '1::7:8'],
+ [true, '1::8'],
+ [true, '2001:0000:1234:0000:0000:C1C0:ABCD:0876'],
+ [true, '2001:0:1234::C1C0:ABCD:876'],
+ [true, '2001:0db8:0000:0000:0000:0000:1428:57ab'],
+ [true, '2001:0db8:0000:0000:0000::1428:57ab'],
+ [true, '2001:0db8:0:0:0:0:1428:57ab'],
+ [true, '2001:0db8:0:0::1428:57ab'],
+ [true, '2001:0db8:1234:0000:0000:0000:0000:0000'],
+ [true, '2001:0db8:1234::'],
+ [true, '2001:0db8:1234:ffff:ffff:ffff:ffff:ffff'],
+ [true, '2001:0db8:85a3:0000:0000:8a2e:0370:7334'],
+ [true, '2001:0db8::1428:57ab'],
+ [true, '2001:2:3:4:5:6:7:134'],
+ [true, '2001:DB8:0:0:8:800:200C:417A'],
+ [true, '2001:DB8::8:800:200C:417A'],
+ [true, '2001:db8:85a3:0:0:8a2e:370:7334'],
+ [true, '2001:db8:85a3::8a2e:370:7334'],
+ [true, '2001:db8::'],
+ [true, '2001:db8::1428:57ab'],
+ [true, '2001:db8:a::123'],
+ [true, '2002::'],
+ [true, '2::10'],
+ [true, '3ffe:0b00:0000:0000:0001:0000:0000:000a'],
+ [true, '3ffe:b00::1:0:0:a'],
+ [true, '::'],
+ [true, '::0'],
+ [true, '::0:0'],
+ [true, '::0:0:0'],
+ [true, '::0:0:0:0'],
+ [true, '::0:0:0:0:0'],
+ [true, '::0:0:0:0:0:0'],
+ [true, '::0:0:0:0:0:0:0'],
+ [true, '::0:a:b:c:d:e:f'],
+ [true, '::1'],
+ [true, '::123.123.123.123'],
+ [true, '::13.1.68.3'],
+ [true, '::2222:3333:4444:5555:6666:123.123.123.123'],
+ [true, '::2222:3333:4444:5555:6666:7777:8888'],
+ [true, '::2:3'],
+ [true, '::2:3:4'],
+ [true, '::2:3:4:5'],
+ [true, '::2:3:4:5:6'],
+ [true, '::2:3:4:5:6:7'],
+ [true, '::2:3:4:5:6:7:8'],
+ [true, '::3333:4444:5555:6666:7777:8888'],
+ [true, '::4444:5555:6666:123.123.123.123'],
+ [true, '::4444:5555:6666:7777:8888'],
+ [true, '::5555:6666:123.123.123.123'],
+ [true, '::5555:6666:7777:8888'],
+ [true, '::6666:123.123.123.123'],
+ [true, '::6666:7777:8888'],
+ [true, '::7777:8888'],
+ [true, '::8'],
+ [true, '::8888'],
+ [true, '::FFFF:129.144.52.38'],
+ [true, '::ffff:0:0'],
+ [true, '::ffff:0c22:384e'],
+ [true, '::ffff:12.34.56.78'],
+ [true, '::ffff:192.0.2.128'],
+ [true, '::ffff:192.168.1.1'],
+ [true, '::ffff:192.168.1.26'],
+ [true, '::ffff:c000:280'],
+ [true, 'FF01:0:0:0:0:0:0:101'],
+ [true, 'FF01::101'],
+ [true, 'FF02:0000:0000:0000:0000:0000:0000:0001'],
+ [true, 'FF02::1'],
+ [true, 'a:b:c:d:e:f:0::'],
+ [true, 'fe80:0000:0000:0000:0204:61ff:fe9d:f156'],
+ [true, 'fe80:0:0:0:204:61ff:254.157.241.86'],
+ [true, 'fe80:0:0:0:204:61ff:fe9d:f156'],
+ [true, 'fe80::'],
+ [true, 'fe80::1'],
+ [true, 'fe80::204:61ff:254.157.241.86'],
+ [true, 'fe80::204:61ff:fe9d:f156'],
+ [true, 'fe80::217:f2ff:254.7.237.98'],
+ [true, 'fe80::217:f2ff:fe07:ed62'],
+ [true, 'ff02::1'],
+]
describe('get_ipany_re', function () {
it('IPv6, Prefix', function (done) {
// for x-*-ip headers
// it must fail as of not valide
- assert.ok(!net.isIPv6('IPv6:2001:db8:85a3::8a2e:370:7334'));
+ assert.ok(!net.isIPv6('IPv6:2001:db8:85a3::8a2e:370:7334'))
// must okay!
- assert.ok(net.isIPv6('2001:db8:85a3::8a2e:370:7334'));
- done();
+ assert.ok(net.isIPv6('2001:db8:85a3::8a2e:370:7334'))
+ done()
})
it('IP fixtures check', function (done) {
for (const i in ip_fixtures) {
- const match = net_utils.get_ipany_re('^','$').test(ip_fixtures[i][1]);
+ const match = net_utils.get_ipany_re('^', '$').test(ip_fixtures[i][1])
// console.log('IP:', `'${ip_fixtures[i][1]}'` , 'Expected:', ip_fixtures[i][0] , 'Match:' , match);
- assert.ok((match===ip_fixtures[i][0]), `${ip_fixtures[i][1]} - Expected: ${ip_fixtures[i][0]} - Match: ${match}`);
+ assert.ok(
+ match === ip_fixtures[i][0],
+ `${ip_fixtures[i][1]} - Expected: ${ip_fixtures[i][0]} - Match: ${match}`,
+ )
}
- done();
+ done()
})
it('IPv4, bare', function (done) {
// for x-*-ip headers
- const match = net_utils.get_ipany_re().exec('127.0.0.1');
- assert.equal(match[1], '127.0.0.1');
- assert.equal(match.length, 2);
- done();
+ const match = net_utils.get_ipany_re().exec('127.0.0.1')
+ assert.equal(match[1], '127.0.0.1')
+ assert.equal(match.length, 2)
+ done()
})
it('IPv4, Received header, parens', function (done) {
- const received_re = net_utils.get_ipany_re('^Received:.*?[\\[\\(]', '[\\]\\)]');
- const match = received_re.exec('Received: from unknown (HELO mail.theartfarm.com) (127.0.0.30) by mail.theartfarm.com with SMTP; 5 Sep 2015 14:29:00 -0000');
- assert.equal(match[1], '127.0.0.30');
- assert.equal(match.length, 2);
- done();
+ const received_re = net_utils.get_ipany_re(
+ '^Received:.*?[\\[\\(]',
+ '[\\]\\)]',
+ )
+ const match = received_re.exec(
+ 'Received: from unknown (HELO mail.theartfarm.com) (127.0.0.30) by mail.theartfarm.com with SMTP; 5 Sep 2015 14:29:00 -0000',
+ )
+ assert.equal(match[1], '127.0.0.30')
+ assert.equal(match.length, 2)
+ done()
})
it('IPv4, Received header, bracketed, expedia', function (done) {
- const received_header = 'Received: from mta2.expediamail.com (mta2.expediamail.com [66.231.89.19]) by mail.theartfarm.com (Haraka/2.6.2-toaster) with ESMTPS id C669CF18-1C1C-484C-8A5B-A89088B048CB.1 envelope-from (version=TLSv1/SSLv3 cipher=AES256-SHA verify=NO); Sat, 05 Sep 2015 07:28:57 -0700';
- const received_re = net_utils.get_ipany_re('^Received:.*?[\\[\\(]', '[\\]\\)]');
- const match = received_re.exec(received_header);
- assert.equal(match[1], '66.231.89.19');
- assert.equal(match.length, 2);
- done();
+ const received_header =
+ 'Received: from mta2.expediamail.com (mta2.expediamail.com [66.231.89.19]) by mail.theartfarm.com (Haraka/2.6.2-toaster) with ESMTPS id C669CF18-1C1C-484C-8A5B-A89088B048CB.1 envelope-from (version=TLSv1/SSLv3 cipher=AES256-SHA verify=NO); Sat, 05 Sep 2015 07:28:57 -0700'
+ const received_re = net_utils.get_ipany_re(
+ '^Received:.*?[\\[\\(]',
+ '[\\]\\)]',
+ )
+ const match = received_re.exec(received_header)
+ assert.equal(match[1], '66.231.89.19')
+ assert.equal(match.length, 2)
+ done()
})
it('IPv4, Received header, bracketed, github', function (done) {
- const received_re = net_utils.get_ipany_re('^Received:.*?[\\[\\(]', '[\\]\\)]');
- const match = received_re.exec('Received: from github-smtp2a-ext-cp1-prd.iad.github.net (github-smtp2-ext5.iad.github.net [192.30.252.196])');
- assert.equal(match[1], '192.30.252.196');
- assert.equal(match.length, 2);
- done();
+ const received_re = net_utils.get_ipany_re(
+ '^Received:.*?[\\[\\(]',
+ '[\\]\\)]',
+ )
+ const match = received_re.exec(
+ 'Received: from github-smtp2a-ext-cp1-prd.iad.github.net (github-smtp2-ext5.iad.github.net [192.30.252.196])',
+ )
+ assert.equal(match[1], '192.30.252.196')
+ assert.equal(match.length, 2)
+ done()
})
it('IPv6, Received header, bracketed', function (done) {
- const received_header = 'Received: from ?IPv6:2601:184:c001:5cf7:a53f:baf7:aaf3:bce7? ([2601:184:c001:5cf7:a53f:baf7:aaf3:bce7])';
- const received_re = net_utils.get_ipany_re('^Received:.*?[\\[\\(]', '[\\]\\)]');
- const match = received_re.exec(received_header);
- assert.equal(match[1], '2601:184:c001:5cf7:a53f:baf7:aaf3:bce7');
- assert.equal(match.length, 2);
- done();
+ const received_header =
+ 'Received: from ?IPv6:2601:184:c001:5cf7:a53f:baf7:aaf3:bce7? ([2601:184:c001:5cf7:a53f:baf7:aaf3:bce7])'
+ const received_re = net_utils.get_ipany_re(
+ '^Received:.*?[\\[\\(]',
+ '[\\]\\)]',
+ )
+ const match = received_re.exec(received_header)
+ assert.equal(match[1], '2601:184:c001:5cf7:a53f:baf7:aaf3:bce7')
+ assert.equal(match.length, 2)
+ done()
})
it('IPv6, Received header, bracketed, IPv6 prefix', function (done) {
- const received_re = net_utils.get_ipany_re('^Received:.*?[\\[\\(](?:IPv6:)?', '[\\]\\)]');
- const match = received_re.exec('Received: from hub.freebsd.org (hub.freebsd.org [IPv6:2001:1900:2254:206c::16:88])');
- assert.equal(match[1], '2001:1900:2254:206c::16:88');
- assert.equal(match.length, 2);
- done();
+ const received_re = net_utils.get_ipany_re(
+ '^Received:.*?[\\[\\(](?:IPv6:)?',
+ '[\\]\\)]',
+ )
+ const match = received_re.exec(
+ 'Received: from hub.freebsd.org (hub.freebsd.org [IPv6:2001:1900:2254:206c::16:88])',
+ )
+ assert.equal(match[1], '2001:1900:2254:206c::16:88')
+ assert.equal(match.length, 2)
+ done()
})
it('IPv6, folded Received header, bracketed, IPv6 prefix', function (done) {
// note the use of [\s\S], '.' doesn't match newlines in JS regexp
- const received_re = net_utils.get_ipany_re('^Received:[\\s\\S]*?[\\[\\(](?:IPv6:)?', '[\\]\\)]');
- const match = received_re.exec('Received: from freefall.freebsd.org (freefall.freebsd.org\r\n [IPv6:2001:1900:2254:206c::16:87])');
+ const received_re = net_utils.get_ipany_re(
+ '^Received:[\\s\\S]*?[\\[\\(](?:IPv6:)?',
+ '[\\]\\)]',
+ )
+ const match = received_re.exec(
+ 'Received: from freefall.freebsd.org (freefall.freebsd.org\r\n [IPv6:2001:1900:2254:206c::16:87])',
+ )
if (match) {
- assert.equal(match[1], '2001:1900:2254:206c::16:87');
- assert.equal(match.length, 2);
+ assert.equal(match[1], '2001:1900:2254:206c::16:87')
+ assert.equal(match.length, 2)
}
- done();
+ done()
})
it('IPv6, Received header, bracketed, IPv6 prefix, localhost compressed', function (done) {
- const received_re = net_utils.get_ipany_re('^Received:.*?[\\[\\(](?:IPv6:)?', '[\\]\\)]');
- const match = received_re.exec('Received: from ietfa.amsl.com (localhost [IPv6:::1])');
- assert.equal(match[1], '::1');
- assert.equal(match.length, 2);
- done();
+ const received_re = net_utils.get_ipany_re(
+ '^Received:.*?[\\[\\(](?:IPv6:)?',
+ '[\\]\\)]',
+ )
+ const match = received_re.exec(
+ 'Received: from ietfa.amsl.com (localhost [IPv6:::1])',
+ )
+ assert.equal(match[1], '::1')
+ assert.equal(match.length, 2)
+ done()
})
it('IPv6 bogus', function (done) {
- const is_bogus = net_utils.ipv6_bogus('::192.41.13.251'); // From https://github.com/haraka/Haraka/issues/2763
- assert.equal(is_bogus, true);
- done();
+ const is_bogus = net_utils.ipv6_bogus('::192.41.13.251') // From https://github.com/haraka/Haraka/issues/2763
+ assert.equal(is_bogus, true)
+ done()
})
})
@@ -1058,166 +1101,190 @@ describe('get_ips_by_host', function () {
'192.48.85.147',
'192.48.85.148',
'192.48.85.149',
- '2607:f060:b008:feed::2'
+ '2607:f060:b008:feed::2',
],
- 'localhost.simerson.net': [ '127.0.0.1', '::1' ]
+ 'localhost.haraka.tnpi.net': ['127.0.0.1', '::1'],
+ // 'non-exist.haraka.tnpi.net': [],
}
for (const t in tests) {
-
it(`get_ips_by_host, ${t}`, function (done) {
this.timeout(7000)
net_utils.get_ips_by_host(t, function (err, res) {
if (err && err.length) {
- console.error(err);
+ console.error(err)
+ return done()
}
- assert.deepEqual(err, []);
- assert.deepEqual(res.sort(), tests[t].sort());
- done();
- });
+ assert.deepEqual(err, [])
+ assert.deepEqual(res.sort(), tests[t].sort())
+ done()
+ })
})
it(`get_ips_by_host, promise, ${t}`, async function () {
try {
const res = await net_utils.get_ips_by_host(t)
- assert.deepEqual(res.sort(), tests[t].sort());
- }
- catch (e) {
- console.error(e);
+ assert.deepEqual(res.sort(), tests[t].sort())
+ } catch (e) {
+ console.error(e)
}
})
}
})
-function _check_list (done, list, ip, res) {
- assert.equal(net_utils.ip_in_list(list, ip), res); // keys of object
- assert.equal(net_utils.ip_in_list(Object.keys(list), ip), res); // array
- done();
+function _check_list(done, list, ip, res) {
+ assert.equal(net_utils.ip_in_list(list, ip), res) // keys of object
+ assert.equal(net_utils.ip_in_list(Object.keys(list), ip), res) // array
+ done()
}
describe('ip_in_list', function () {
it('domain.com', function (done) {
- _check_list(done, { 'domain.com': undefined }, 'domain.com', true);
+ _check_list(done, { 'domain.com': undefined }, 'domain.com', true)
})
it('foo.com', function (done) {
- _check_list(done, { }, 'foo.com', false);
+ _check_list(done, {}, 'foo.com', false)
})
it('1.2.3.4', function (done) {
- _check_list(done, { '1.2.3.4': undefined }, '1.2.3.4', true);
+ _check_list(done, { '1.2.3.4': undefined }, '1.2.3.4', true)
})
it('1.2.3.4/32', function (done) {
- _check_list(done, { '1.2.3.4/32': undefined }, '1.2.3.4', true);
+ _check_list(done, { '1.2.3.4/32': undefined }, '1.2.3.4', true)
})
it('1.2.0.0/16 <-> 1.2.3.4', function (done) {
- _check_list(done, { '1.2.0.0/16': undefined }, '1.2.3.4', true);
+ _check_list(done, { '1.2.0.0/16': undefined }, '1.2.3.4', true)
})
it('1.2.0.0/16 <-> 5.6.7.8', function (done) {
- _check_list(done, { '1.2.0.0/16': undefined }, '5.6.7.8', false);
+ _check_list(done, { '1.2.0.0/16': undefined }, '5.6.7.8', false)
})
it('0000:0000:0000:0000:0000:0000:0000:0001', function (done) {
- _check_list(done, { '0000:0000:0000:0000:0000:0000:0000:0001': undefined }, '0000:0000:0000:0000:0000:0000:0000:0001', true);
+ _check_list(
+ done,
+ { '0000:0000:0000:0000:0000:0000:0000:0001': undefined },
+ '0000:0000:0000:0000:0000:0000:0000:0001',
+ true,
+ )
})
it('0:0:0:0:0:0:0:1', function (done) {
- _check_list(done, { '0:0:0:0:0:0:0:1': undefined }, '0000:0000:0000:0000:0000:0000:0000:0001', true);
+ _check_list(
+ done,
+ { '0:0:0:0:0:0:0:1': undefined },
+ '0000:0000:0000:0000:0000:0000:0000:0001',
+ true,
+ )
})
it('1.2 (bad config)', function (done) {
- _check_list(done, { '1.2': undefined }, '1.2.3.4', false);
+ _check_list(done, { 1.2: undefined }, '1.2.3.4', false)
})
it('1.2.3.4/ (mask ignored)', function (done) {
- _check_list(done, { '1.2.3.4/': undefined }, '1.2.3.4', true);
+ _check_list(done, { '1.2.3.4/': undefined }, '1.2.3.4', true)
})
it('1.2.3.4/gr (mask ignored)', function (done) {
- _check_list(done, { '1.2.3.4/gr': undefined }, '1.2.3.4', true);
+ _check_list(done, { '1.2.3.4/gr': undefined }, '1.2.3.4', true)
})
it('1.2.3.4/400 (mask read as 400 bits)', function (done) {
- _check_list(done, { '1.2.3.4/400': undefined }, '1.2.3.4', true);
+ _check_list(done, { '1.2.3.4/400': undefined }, '1.2.3.4', true)
})
})
describe('get_primary_host_name', function () {
beforeEach(function (done) {
- this.net_utils = require('../index');
- this.net_utils.config = this.net_utils.config.module_config(path.resolve('test'));
- done();
+ this.net_utils = require('../index')
+ this.net_utils.config = this.net_utils.config.module_config(
+ path.resolve('test'),
+ )
+ done()
})
it('with me config', function (done) {
- assert.equal(this.net_utils.get_primary_host_name(), 'test-hostname');
- done();
+ assert.equal(this.net_utils.get_primary_host_name(), 'test-hostname')
+ done()
})
it('without me config', function (done) {
- this.net_utils.config = this.net_utils.config.module_config(path.resolve('doesnt-exist'));
- assert.equal(this.net_utils.get_primary_host_name(), os.hostname());
- done();
+ this.net_utils.config = this.net_utils.config.module_config(
+ path.resolve('doesnt-exist'),
+ )
+ assert.equal(this.net_utils.get_primary_host_name(), os.hostname())
+ done()
})
})
describe('on_local_interface', function () {
beforeEach(function (done) {
- this.net_utils = require('../index');
- this.net_utils.config = this.net_utils.config.module_config(path.resolve('test'));
- done();
+ this.net_utils = require('../index')
+ this.net_utils.config = this.net_utils.config.module_config(
+ path.resolve('test'),
+ )
+ done()
})
it('localhost 127.0.0.1', function (done) {
- assert.equal(this.net_utils.on_local_interface('127.0.0.1'), true);
- done();
+ assert.equal(this.net_utils.on_local_interface('127.0.0.1'), true)
+ done()
})
it('multicast 1.1.1.1', function (done) {
- assert.equal(this.net_utils.on_local_interface('1.1.1.1'), false);
- done();
+ assert.equal(this.net_utils.on_local_interface('1.1.1.1'), false)
+ done()
})
it('ipv6 localhost ::1', function (done) {
- const r = this.net_utils.on_local_interface('::1');
+ const r = this.net_utils.on_local_interface('::1')
if (r) {
- assert.equal(r, true);
+ assert.equal(r, true)
}
- done();
+ done()
})
})
describe('get_mx', function () {
+ this.timeout(12000)
+
beforeEach(function (done) {
- this.net_utils = require('../index');
- done();
+ this.net_utils = require('../index')
+ done()
})
const validCases = {
- 'tnpi.net' : 'mail.theartfarm.com',
+ 'tnpi.net': 'mail.theartfarm.com',
'matt@tnpi.net': 'mail.theartfarm.com',
'matt.simerson@gmail.com': /google.com/,
- 'example.com' : '',
+ 'example.com': '',
+ 'no-mx.haraka.tnpi.net': '192.0.99.5',
+ 'bad-mx.haraka.tnpi.net': /99/,
+ 'über.haraka.tnpi.net': 'no-mx.haraka.tnpi.net',
}
- function checkValid (c, mxlist) {
- if ('string' === typeof c) {
- assert.equal(mxlist[0].exchange, c);
- }
- else {
- assert.ok(c.test(mxlist[0].exchange))
+ function checkValid(c, mxlist) {
+ try {
+ if ('string' === typeof c) {
+ assert.equal(mxlist[0].exchange, c)
+ } else {
+ assert.ok(c.test(mxlist[0].exchange))
+ }
+ } catch (err) {
+ console.error(err)
}
}
for (const c in validCases) {
it(`gets MX records for ${c}`, function (done) {
- this.timeout(7000)
+ this.timeout(12000)
this.net_utils.get_mx(c, (err, mxlist) => {
if (err) console.error(err)
- assert.ifError(err);
+ assert.ifError(err)
// assert.ok(mxlist.length);
checkValid(validCases[c], mxlist)
done()
@@ -1225,7 +1292,7 @@ describe('get_mx', function () {
})
it(`awaits MX records for ${c}`, async function () {
- this.timeout(7000)
+ this.timeout(12000)
const mxlist = await this.net_utils.get_mx(c)
// assert.ok(mxlist.length);
checkValid(validCases[c], mxlist)
@@ -1234,15 +1301,14 @@ describe('get_mx', function () {
// macOS: ENODATA, win: ENOTOUND, ubuntu: ESERVFAIL
const invalidCases = {
- 'invalid': /queryMx (ENODATA|ENOTFOUND|ESERVFAIL) invalid/,
+ invalid: /queryMx (ENODATA|ENOTFOUND|ESERVFAIL) invalid/,
'gmail.xn--com-0da': /(ENOTFOUND|Cannot convert name to ASCII)/,
}
- function checkInvalid (expected, actual) {
+ function checkInvalid(expected, actual) {
if ('string' === typeof expected) {
assert.strictEqual(actual, expected)
- }
- else {
+ } else {
assert.equal(expected.test(actual), true)
}
}
@@ -1250,7 +1316,6 @@ describe('get_mx', function () {
for (const c in invalidCases) {
it(`cb does not crash on invalid name: ${c}`, function () {
this.net_utils.get_mx(c, (err, mxlist) => {
- // console.error(err)
assert.equal(mxlist.length, 0)
checkInvalid(invalidCases[c], err.message)
})
@@ -1260,11 +1325,67 @@ describe('get_mx', function () {
try {
const mxlist = await this.net_utils.get_mx(c)
assert.equal(mxlist.length, 0)
- }
- catch (err) {
- // console.error(err)
+ } catch (err) {
checkInvalid(invalidCases[c], err.message)
}
})
}
})
+
+describe('resolve_mx_hosts', function () {
+ this.timeout(12000)
+
+ beforeEach((done) => {
+ this.net_utils = require('../index')
+ done()
+ })
+
+ const expectedResolvedMx = [
+ {
+ exchange: '2605:ae00:329::14',
+ priority: 10,
+ from_dns: 'mail.theartfarm.com',
+ },
+ {
+ exchange: '66.128.51.165',
+ priority: 10,
+ from_dns: 'mail.theartfarm.com',
+ },
+ ]
+
+ it('resolves mx hosts to IPs, tnpi.net', async () => {
+ const r = await this.net_utils.resolve_mx_hosts([
+ { exchange: 'mail.theartfarm.com', priority: 10, from_dns: 'tnpi.net' },
+ ])
+ assert.deepEqual(r, expectedResolvedMx)
+ })
+
+ it('resolves mx hosts to IPs, gmail.com', async () => {
+ const mxes = await this.net_utils.get_mx('gmail.com')
+ assert.equal(mxes.length, 5)
+ const r = await this.net_utils.resolve_mx_hosts(mxes)
+ assert.equal(r.length, 10)
+ })
+
+ it('returns IPs as is', async () => {
+ const r = await this.net_utils.resolve_mx_hosts(expectedResolvedMx)
+ assert.deepEqual(r, expectedResolvedMx)
+ })
+
+ it('returns sockets as-is', async () => {
+ const r = await this.net_utils.resolve_mx_hosts([{ path: '/var/run/sock' }])
+ assert.deepEqual(r, [{ path: '/var/run/sock' }])
+ })
+
+ it('resolve_mx_hosts, gmail.com', async () => {
+ const mxes = await this.net_utils.get_mx('gmail.com')
+ const r = await this.net_utils.resolve_mx_hosts(mxes)
+ assert.equal(r.length, 10)
+ })
+
+ it('resolve_mx_hosts, yahoo.com', async () => {
+ const mxes = await this.net_utils.get_mx('yahoo.com')
+ const r = await this.net_utils.resolve_mx_hosts([mxes[0]])
+ assert.equal(r.length, 8)
+ })
+})