8000
We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
1 parent 4205648 commit 136eea4Copy full SHA for 136eea4
doc/api/os.md
@@ -253,6 +253,9 @@ The properties available on the assigned network address object include:
253
similar interface that is not remotely accessible; otherwise `false`
254
* `scopeid` {number} The numeric IPv6 scope ID (only specified when `family`
255
is `IPv6`)
256
+* `cidr` {string} The assigned IPv4 or IPv6 address with the routing prefix
257
+ in CIDR notation. If the `netmask` is invalid, this property is set
258
+ to `null`
259
260
<!-- eslint-skip -->
261
```js
@@ -263,14 +266,16 @@ The properties available on the assigned network address object include:
263
266
netmask: '255.0.0.0',
264
267
family: 'IPv4',
265
268
mac: '00:00:00:00:00:00',
- internal: true
269
+ internal: true,
270
+ cidr: '127.0.0.1/8'
271
},
272
{
273
address: '::1',
274
netmask: 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
275
family: 'IPv6',
276
277
278
+ cidr: '::1/128'
279
}
280
],
281
eth0: [
@@ -279,14 +284,16 @@ The properties available on the assigned network address object include:
284
netmask: '255.255.255.0',
285
286
mac: '01:02:03:0a:0b:0c',
282
- internal: false
287
+ internal: false,
288
+ cidr: '192.168.1.108/24'
283
289
290
291
address: 'fe80::a00:27ff:fe4e:66a1',
292
netmask: 'ffff:ffff:ffff:ffff::',
293
294
295
296
+ cidr: 'fe80::a00:27ff:fe4e:66a1/64'
297
298
]
299
lib/internal/os.js
@@ -0,0 +1,41 @@
1
+'use strict';
2
+
3
+function getCIDRSuffix(mask, protocol = 'ipv4') {
4
+ const isV6 = protocol === 'ipv6';
5
+ const bitsString = mask
6
+ .split(isV6 ? ':' : '.')
7
+ .filter((v) => !!v)
8
+ .map((v) => pad(parseInt(v, isV6 ? 16 : 10).toString(2), isV6))
9
+ .join('');
10
11
+ if (isValidMask(bitsString)) {
12
+ return countOnes(bitsString);
13
+ } else {
14
+ return null;
15
+ }
16
+}
17
18
+function pad(binaryString, isV6) {
19
+ const groupLength = isV6 ? 16 : 8;
20
+ const binLen = binaryString.length;
21
22
+ return binLen < groupLength ?
23
+ `${'0'.repeat(groupLength - binLen)}${binaryString}` : binaryString;
24
25
26
+function isValidMask(bitsString) {
27
+ const firstIndexOfZero = bitsString.indexOf(0);
28
+ const lastIndexOfOne = bitsString.lastIndexOf(1);
29
30
+ return firstIndexOfZero < 0 || firstIndexOfZero > lastIndexOfOne;
31
32
33
+function countOnes(bitsString) {
34
+ return bitsString
35
+ .split('')
36
+ .reduce((acc, bit) => acc += parseInt(bit, 10), 0);
37
38
39
+module.exports = {
40
+ getCIDRSuffix
41
+};
lib/os.js
@@ -24,6 +24,7 @@
const pushValToArrayMax = process.binding('util').pushValToArrayMax;
const constants = process.binding('constants').os;
const deprecate = require('internal/util').deprecate;
+const getCIDRSuffix = require('internal/os').getCIDRSuffix;
const isWindows = process.platform === 'win32';
const {
@@ -121,6 +122,21 @@ function endianness() {
121
122
123
endianness[Symbol.toPrimitive] = () => kEndianness;
124
125
+function networkInterfaces() {
126
+ const interfaceAddresses = getInterfaceAddresses();
127
128
+ return Object.entries(interfaceAddresses).reduce((acc, [key, val]) => {
129
+ acc[key] = val.map((v) => {
130
+ const protocol = v.family.toLowerCase();
131
+ const suffix = getCIDRSuffix(v.netmask, protocol);
132
+ const cidr = suffix ? `${v.address}/${suffix}` : null;
133
134
+ return Object.assign({}, v, { cidr });
135
+ });
136
+ return acc;
137
+ }, {});
138
139
140
module.exports = exports = {
141
arch,
142
cpus,
@@ -130,7 +146,7 @@ module.exports = exports = {
146
homedir: getHomeDirectory,
147
hostname: getHostname,
148
loadavg,
- networkInterfaces: getInterfaceAddresses,
149
+ networkInterfaces,
150
platform,
151
release: getOSRelease,
152
tmpdir,
node.gyp
@@ -91,6 +91,7 @@
91
'lib/internal/linkedlist.js',
92
'lib/internal/net.js',
93
'lib/internal/module.js',
94
+ 'lib/internal/os.js',
95
'lib/internal/process/next_tick.js',
96
'lib/internal/process/promises.js',
97
'lib/internal/process/stdio.js',
test/parallel/test-internal-os.js
@@ -0,0 +1,32 @@
+// Flags: --expose-internals
+require('../common');
+const assert = require('assert');
+const specs = [
+ // valid
+ ['128.0.0.0', 'ipv4', 1],
+ ['255.0.0.0', 'ipv4', 8],
+ ['255.255.255.128', 'ipv4', 25],
+ ['255.255.255.255', 'ipv4', 32],
+ ['ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', 'ipv6', 128],
+ ['ffff:ffff:ffff:ffff::', 'ipv6', 64],
+ ['ffff:ffff:ffff:ff80::', 'ipv6', 57],
+ // invalid
+ ['255.0.0.1', 'ipv4', null],
+ ['255.255.9.0', 'ipv4', null],
+ ['255.255.1.0', 'ipv4', null],
+ ['ffff:ffff:43::', 'ipv6', null],
+ ['ffff:ffff:ffff:1::', 'ipv6', null]
+];
+specs.forEach(([mask, protocol, expectedSuffix]) => {
+ const actualSuffix = getCIDRSuffix(mask, protocol);
+ assert.strictEqual(
+ actualSuffix, expectedSuffix,
+ `Mask: ${mask}, expected: ${expectedSuffix}, actual: ${actualSuffix}`
+ );
+});
test/parallel/test-os.js
@@ -24,6 +24,7 @@ const common = require('../common');
const assert = require('assert');
const os = require('os');
const path = require('path');
+const { inspect } = require('util');
const is = {
string: (value) => { assert.strictEqual(typeof value, 'string'); },
@@ -121,7 +122,7 @@ switch (platform) {
const actual = interfaces.lo.filter(filter);
const expected = [{ address: '127.0.0.1', netmask: '255.0.0.0',
mac: '00:00:00:00:00:00', family: 'IPv4',
- internal: true }];
+ internal: true, cidr: '127.0.0.1/8' }];
assert.deepStrictEqual(actual, expected);
break;
@@ -131,11 +132,31 @@ switch (platform) {
const actual = interfaces['Loopback Pseudo-Interface 1'].filter(filter);
+function flatten(arr) {
+ return arr.reduce(
+ (acc, c) => acc.concat(Array.isArray(c) ? flatten(c) : c),
143
+ []
144
145
+const netmaskToCIDRSuffixMap = new Map(Object.entries({
+ '255.0.0.0': 8,
+ '255.255.255.0': 24,
+ 'ffff:ffff:ffff:ffff::': 64,
+ 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff': 128
+}));
+flatten(Object.values(interfaces))
153
+ .map((v) => ({ v, mask: netmaskToCIDRSuffixMap.get(v.netmask) }))
154
+ .forEach(({ v, mask }) => {
155
+ assert.ok('cidr' in v, `"cidr" prop not found in ${inspect(v)}`);
156
+ if (mask) {
157
+ assert.strictEqual(v.cidr, `${v.address}/${mask}`);
158
159
160
161
const EOL = os.EOL;
162
assert.ok(EOL.length > 0);