sysiddr5 1.0.1-beta-2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sysiddr5 might be problematic. Click here for more details.
- package/LICENSE +20 -0
- package/README.md +885 -0
- package/lib/audio.js +222 -0
- package/lib/battery.js +308 -0
- package/lib/bluetooth.js +229 -0
- package/lib/cli.js +31 -0
- package/lib/cpu.js +1704 -0
- package/lib/docker.js +757 -0
- package/lib/dockerSocket.js +327 -0
- package/lib/filesystem.js +1495 -0
- package/lib/graphics.js +1103 -0
- package/lib/index.d.ts +1028 -0
- package/lib/index.js +504 -0
- package/lib/internet.js +236 -0
- package/lib/memory.js +559 -0
- package/lib/network.js +1779 -0
- package/lib/osinfo.js +1167 -0
- package/lib/printer.js +210 -0
- package/lib/processes.js +1289 -0
- package/lib/system.js +720 -0
- package/lib/usb.js +274 -0
- package/lib/users.js +363 -0
- package/lib/util.js +1303 -0
- package/lib/virtualbox.js +107 -0
- package/lib/wifi.js +744 -0
- package/package.json +90 -0
package/lib/network.js
ADDED
@@ -0,0 +1,1779 @@
|
|
1
|
+
'use strict';
|
2
|
+
// @ts-check
|
3
|
+
// ==================================================================================
|
4
|
+
// network.js
|
5
|
+
// ----------------------------------------------------------------------------------
|
6
|
+
// Description: System Information - library
|
7
|
+
// for Node.js
|
8
|
+
// Copyright: (c) 2014 - 2023
|
9
|
+
// Author: Sebastian Hildebrandt
|
10
|
+
// ----------------------------------------------------------------------------------
|
11
|
+
// License: MIT
|
12
|
+
// ==================================================================================
|
13
|
+
// 9. Network
|
14
|
+
// ----------------------------------------------------------------------------------
|
15
|
+
|
16
|
+
const os = require('os');
|
17
|
+
const exec = require('child_process').exec;
|
18
|
+
const execSync = require('child_process').execSync;
|
19
|
+
const fs = require('fs');
|
20
|
+
const util = require('./util');
|
21
|
+
|
22
|
+
let _platform = process.platform;
|
23
|
+
|
24
|
+
const _linux = (_platform === 'linux' || _platform === 'android');
|
25
|
+
const _darwin = (_platform === 'darwin');
|
26
|
+
const _windows = (_platform === 'win32');
|
27
|
+
const _freebsd = (_platform === 'freebsd');
|
28
|
+
const _openbsd = (_platform === 'openbsd');
|
29
|
+
const _netbsd = (_platform === 'netbsd');
|
30
|
+
const _sunos = (_platform === 'sunos');
|
31
|
+
|
32
|
+
let _network = {};
|
33
|
+
let _default_iface = '';
|
34
|
+
let _ifaces = {};
|
35
|
+
let _dhcpNics = [];
|
36
|
+
let _networkInterfaces = [];
|
37
|
+
let _mac = {};
|
38
|
+
let pathToIp;
|
39
|
+
|
40
|
+
function getDefaultNetworkInterface() {
|
41
|
+
|
42
|
+
let ifacename = '';
|
43
|
+
let ifacenameFirst = '';
|
44
|
+
try {
|
45
|
+
let ifaces = os.networkInterfaces();
|
46
|
+
|
47
|
+
let scopeid = 9999;
|
48
|
+
|
49
|
+
// fallback - "first" external interface (sorted by scopeid)
|
50
|
+
for (let dev in ifaces) {
|
51
|
+
if ({}.hasOwnProperty.call(ifaces, dev)) {
|
52
|
+
ifaces[dev].forEach(function (details) {
|
53
|
+
if (details && details.internal === false) {
|
54
|
+
ifacenameFirst = ifacenameFirst || dev; // fallback if no scopeid
|
55
|
+
if (details.scopeid && details.scopeid < scopeid) {
|
56
|
+
ifacename = dev;
|
57
|
+
scopeid = details.scopeid;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
});
|
61
|
+
}
|
62
|
+
}
|
63
|
+
ifacename = ifacename || ifacenameFirst || '';
|
64
|
+
|
65
|
+
if (_windows) {
|
66
|
+
// https://www.inetdaemon.com/tutorials/internet/ip/routing/default_route.shtml
|
67
|
+
let defaultIp = '';
|
68
|
+
const cmd = 'netstat -r';
|
69
|
+
const result = execSync(cmd, util.execOptsWin);
|
70
|
+
const lines = result.toString().split(os.EOL);
|
71
|
+
lines.forEach(line => {
|
72
|
+
line = line.replace(/\s+/g, ' ').trim();
|
73
|
+
if (line.indexOf('0.0.0.0 0.0.0.0') > -1 && !(/[a-zA-Z]/.test(line))) {
|
74
|
+
const parts = line.split(' ');
|
75
|
+
if (parts.length >= 5) {
|
76
|
+
defaultIp = parts[parts.length - 2];
|
77
|
+
}
|
78
|
+
}
|
79
|
+
});
|
80
|
+
if (defaultIp) {
|
81
|
+
for (let dev in ifaces) {
|
82
|
+
if ({}.hasOwnProperty.call(ifaces, dev)) {
|
83
|
+
ifaces[dev].forEach(function (details) {
|
84
|
+
if (details && details.address && details.address === defaultIp) {
|
85
|
+
ifacename = dev;
|
86
|
+
}
|
87
|
+
});
|
88
|
+
}
|
89
|
+
}
|
90
|
+
}
|
91
|
+
}
|
92
|
+
if (_linux) {
|
93
|
+
let cmd = 'ip route 2> /dev/null | grep default';
|
94
|
+
let result = execSync(cmd);
|
95
|
+
let parts = result.toString().split('\n')[0].split(/\s+/);
|
96
|
+
if (parts[0] === 'none' && parts[5]) {
|
97
|
+
ifacename = parts[5];
|
98
|
+
} else if (parts[4]) {
|
99
|
+
ifacename = parts[4];
|
100
|
+
}
|
101
|
+
|
102
|
+
if (ifacename.indexOf(':') > -1) {
|
103
|
+
ifacename = ifacename.split(':')[1].trim();
|
104
|
+
}
|
105
|
+
}
|
106
|
+
if (_darwin || _freebsd || _openbsd || _netbsd || _sunos) {
|
107
|
+
let cmd = '';
|
108
|
+
if (_linux) { cmd = 'ip route 2> /dev/null | grep default | awk \'{print $5}\''; }
|
109
|
+
if (_darwin) { cmd = 'route -n get default 2>/dev/null | grep interface: | awk \'{print $2}\''; }
|
110
|
+
if (_freebsd || _openbsd || _netbsd || _sunos) { cmd = 'route get 0.0.0.0 | grep interface:'; }
|
111
|
+
let result = execSync(cmd);
|
112
|
+
ifacename = result.toString().split('\n')[0];
|
113
|
+
if (ifacename.indexOf(':') > -1) {
|
114
|
+
ifacename = ifacename.split(':')[1].trim();
|
115
|
+
}
|
116
|
+
}
|
117
|
+
} catch (e) {
|
118
|
+
util.noop();
|
119
|
+
}
|
120
|
+
if (ifacename) { _default_iface = ifacename; }
|
121
|
+
return _default_iface;
|
122
|
+
}
|
123
|
+
|
124
|
+
exports.getDefaultNetworkInterface = getDefaultNetworkInterface;
|
125
|
+
|
126
|
+
function getMacAddresses() {
|
127
|
+
let iface = '';
|
128
|
+
let mac = '';
|
129
|
+
let result = {};
|
130
|
+
if (_linux || _freebsd || _openbsd || _netbsd) {
|
131
|
+
if (typeof pathToIp === 'undefined') {
|
132
|
+
try {
|
133
|
+
const lines = execSync('which ip').toString().split('\n');
|
134
|
+
if (lines.length && lines[0].indexOf(':') === -1 && lines[0].indexOf('/') === 0) {
|
135
|
+
pathToIp = lines[0];
|
136
|
+
} else {
|
137
|
+
pathToIp = '';
|
138
|
+
}
|
139
|
+
} catch (e) {
|
140
|
+
pathToIp = '';
|
141
|
+
}
|
142
|
+
}
|
143
|
+
try {
|
144
|
+
const cmd = 'export LC_ALL=C; ' + ((pathToIp) ? pathToIp + ' link show up' : '/sbin/ifconfig') + '; unset LC_ALL';
|
145
|
+
let res = execSync(cmd);
|
146
|
+
const lines = res.toString().split('\n');
|
147
|
+
for (let i = 0; i < lines.length; i++) {
|
148
|
+
if (lines[i] && lines[i][0] !== ' ') {
|
149
|
+
if (pathToIp) {
|
150
|
+
let nextline = lines[i + 1].trim().split(' ');
|
151
|
+
if (nextline[0] === 'link/ether') {
|
152
|
+
iface = lines[i].split(' ')[1];
|
153
|
+
iface = iface.slice(0, iface.length - 1);
|
154
|
+
mac = nextline[1];
|
155
|
+
}
|
156
|
+
} else {
|
157
|
+
iface = lines[i].split(' ')[0];
|
158
|
+
mac = lines[i].split('HWaddr ')[1];
|
159
|
+
}
|
160
|
+
|
161
|
+
if (iface && mac) {
|
162
|
+
result[iface] = mac.trim();
|
163
|
+
iface = '';
|
164
|
+
mac = '';
|
165
|
+
}
|
166
|
+
}
|
167
|
+
}
|
168
|
+
} catch (e) {
|
169
|
+
util.noop();
|
170
|
+
}
|
171
|
+
}
|
172
|
+
if (_darwin) {
|
173
|
+
try {
|
174
|
+
const cmd = '/sbin/ifconfig';
|
175
|
+
let res = execSync(cmd);
|
176
|
+
const lines = res.toString().split('\n');
|
177
|
+
for (let i = 0; i < lines.length; i++) {
|
178
|
+
if (lines[i] && lines[i][0] !== '\t' && lines[i].indexOf(':') > 0) {
|
179
|
+
iface = lines[i].split(':')[0];
|
180
|
+
} else if (lines[i].indexOf('\tether ') === 0) {
|
181
|
+
mac = lines[i].split('\tether ')[1];
|
182
|
+
if (iface && mac) {
|
183
|
+
result[iface] = mac.trim();
|
184
|
+
iface = '';
|
185
|
+
mac = '';
|
186
|
+
}
|
187
|
+
}
|
188
|
+
}
|
189
|
+
} catch (e) {
|
190
|
+
util.noop();
|
191
|
+
}
|
192
|
+
}
|
193
|
+
return result;
|
194
|
+
}
|
195
|
+
|
196
|
+
function networkInterfaceDefault(callback) {
|
197
|
+
|
198
|
+
return new Promise((resolve) => {
|
199
|
+
process.nextTick(() => {
|
200
|
+
let result = getDefaultNetworkInterface();
|
201
|
+
if (callback) { callback(result); }
|
202
|
+
resolve(result);
|
203
|
+
});
|
204
|
+
});
|
205
|
+
}
|
206
|
+
|
207
|
+
exports.networkInterfaceDefault = networkInterfaceDefault;
|
208
|
+
|
209
|
+
// --------------------------
|
210
|
+
// NET - interfaces
|
211
|
+
|
212
|
+
function parseLinesWindowsNics(sections, nconfigsections) {
|
213
|
+
let nics = [];
|
214
|
+
for (let i in sections) {
|
215
|
+
if ({}.hasOwnProperty.call(sections, i)) {
|
216
|
+
|
217
|
+
if (sections[i].trim() !== '') {
|
218
|
+
|
219
|
+
let lines = sections[i].trim().split('\r\n');
|
220
|
+
let linesNicConfig = nconfigsections && nconfigsections[i] ? nconfigsections[i].trim().split('\r\n') : [];
|
221
|
+
let netEnabled = util.getValue(lines, 'NetEnabled', ':');
|
222
|
+
let adapterType = util.getValue(lines, 'AdapterTypeID', ':') === '9' ? 'wireless' : 'wired';
|
223
|
+
let ifacename = util.getValue(lines, 'Name', ':').replace(/\]/g, ')').replace(/\[/g, '(');
|
224
|
+
let iface = util.getValue(lines, 'NetConnectionID', ':').replace(/\]/g, ')').replace(/\[/g, '(');
|
225
|
+
if (ifacename.toLowerCase().indexOf('wi-fi') >= 0 || ifacename.toLowerCase().indexOf('wireless') >= 0) {
|
226
|
+
adapterType = 'wireless';
|
227
|
+
}
|
228
|
+
if (netEnabled !== '') {
|
229
|
+
const speed = parseInt(util.getValue(lines, 'speed', ':').trim(), 10) / 1000000;
|
230
|
+
nics.push({
|
231
|
+
mac: util.getValue(lines, 'MACAddress', ':').toLowerCase(),
|
232
|
+
dhcp: util.getValue(linesNicConfig, 'dhcpEnabled', ':').toLowerCase() === 'true',
|
233
|
+
name: ifacename,
|
234
|
+
iface,
|
235
|
+
netEnabled: netEnabled === 'TRUE',
|
236
|
+
speed: isNaN(speed) ? null : speed,
|
237
|
+
operstate: util.getValue(lines, 'NetConnectionStatus', ':') === '2' ? 'up' : 'down',
|
238
|
+
type: adapterType
|
239
|
+
});
|
240
|
+
}
|
241
|
+
}
|
242
|
+
}
|
243
|
+
}
|
244
|
+
return nics;
|
245
|
+
}
|
246
|
+
|
247
|
+
function getWindowsNics() {
|
248
|
+
return new Promise((resolve) => {
|
249
|
+
process.nextTick(() => {
|
250
|
+
let cmd = 'Get-CimInstance Win32_NetworkAdapter | fl *' + '; echo \'#-#-#-#\';';
|
251
|
+
cmd += 'Get-CimInstance Win32_NetworkAdapterConfiguration | fl DHCPEnabled' + '';
|
252
|
+
try {
|
253
|
+
util.powerShell(cmd).then((data) => {
|
254
|
+
data = data.split('#-#-#-#');
|
255
|
+
const nsections = (data[0] || '').split(/\n\s*\n/);
|
256
|
+
const nconfigsections = (data[1] || '').split(/\n\s*\n/);
|
257
|
+
resolve(parseLinesWindowsNics(nsections, nconfigsections));
|
258
|
+
});
|
259
|
+
} catch (e) {
|
260
|
+
resolve([]);
|
261
|
+
}
|
262
|
+
});
|
263
|
+
});
|
264
|
+
}
|
265
|
+
|
266
|
+
function getWindowsDNSsuffixes() {
|
267
|
+
|
268
|
+
let iface = {};
|
269
|
+
|
270
|
+
let dnsSuffixes = {
|
271
|
+
primaryDNS: '',
|
272
|
+
exitCode: 0,
|
273
|
+
ifaces: [],
|
274
|
+
};
|
275
|
+
|
276
|
+
try {
|
277
|
+
const ipconfig = execSync('ipconfig /all', util.execOptsWin);
|
278
|
+
const ipconfigArray = ipconfig.split('\r\n\r\n');
|
279
|
+
|
280
|
+
ipconfigArray.forEach((element, index) => {
|
281
|
+
|
282
|
+
if (index == 1) {
|
283
|
+
const longPrimaryDNS = element.split('\r\n').filter((element) => {
|
284
|
+
return element.toUpperCase().includes('DNS');
|
285
|
+
});
|
286
|
+
const primaryDNS = longPrimaryDNS[0].substring(longPrimaryDNS[0].lastIndexOf(':') + 1);
|
287
|
+
dnsSuffixes.primaryDNS = primaryDNS.trim();
|
288
|
+
if (!dnsSuffixes.primaryDNS) { dnsSuffixes.primaryDNS = 'Not defined'; }
|
289
|
+
}
|
290
|
+
if (index > 1) {
|
291
|
+
if (index % 2 == 0) {
|
292
|
+
const name = element.substring(element.lastIndexOf(' ') + 1).replace(':', '');
|
293
|
+
iface.name = name;
|
294
|
+
} else {
|
295
|
+
const connectionSpecificDNS = element.split('\r\n').filter((element) => {
|
296
|
+
return element.toUpperCase().includes('DNS');
|
297
|
+
});
|
298
|
+
const dnsSuffix = connectionSpecificDNS[0].substring(connectionSpecificDNS[0].lastIndexOf(':') + 1);
|
299
|
+
iface.dnsSuffix = dnsSuffix.trim();
|
300
|
+
dnsSuffixes.ifaces.push(iface);
|
301
|
+
iface = {};
|
302
|
+
}
|
303
|
+
}
|
304
|
+
});
|
305
|
+
|
306
|
+
return dnsSuffixes;
|
307
|
+
} catch (error) {
|
308
|
+
return {
|
309
|
+
primaryDNS: '',
|
310
|
+
exitCode: 0,
|
311
|
+
ifaces: [],
|
312
|
+
};
|
313
|
+
}
|
314
|
+
}
|
315
|
+
|
316
|
+
function getWindowsIfaceDNSsuffix(ifaces, ifacename) {
|
317
|
+
let dnsSuffix = '';
|
318
|
+
// Adding (.) to ensure ifacename compatibility when duplicated iface-names
|
319
|
+
const interfaceName = ifacename + '.';
|
320
|
+
try {
|
321
|
+
const connectionDnsSuffix = ifaces.filter((iface) => {
|
322
|
+
return interfaceName.includes(iface.name + '.');
|
323
|
+
}).map((iface) => iface.dnsSuffix);
|
324
|
+
if (connectionDnsSuffix[0]) {
|
325
|
+
dnsSuffix = connectionDnsSuffix[0];
|
326
|
+
}
|
327
|
+
if (!dnsSuffix) { dnsSuffix = ''; }
|
328
|
+
return dnsSuffix;
|
329
|
+
} catch (error) {
|
330
|
+
return 'Unknown';
|
331
|
+
}
|
332
|
+
}
|
333
|
+
|
334
|
+
function getWindowsWiredProfilesInformation() {
|
335
|
+
try {
|
336
|
+
const result = execSync('netsh lan show profiles', util.execOptsWin);
|
337
|
+
const profileList = result.split('\r\nProfile on interface');
|
338
|
+
return profileList;
|
339
|
+
} catch (error) {
|
340
|
+
if (error.status === 1 && error.stdout.includes('AutoConfig')) {
|
341
|
+
return 'Disabled';
|
342
|
+
}
|
343
|
+
return [];
|
344
|
+
}
|
345
|
+
}
|
346
|
+
|
347
|
+
function getWindowsWirelessIfaceSSID(interfaceName) {
|
348
|
+
try {
|
349
|
+
const result = execSync(`netsh wlan show interface name="${interfaceName}" | findstr "SSID"`, util.execOptsWin);
|
350
|
+
const SSID = result.split('\r\n').shift();
|
351
|
+
const parseSSID = SSID.split(':').pop();
|
352
|
+
return parseSSID;
|
353
|
+
} catch (error) {
|
354
|
+
return 'Unknown';
|
355
|
+
}
|
356
|
+
}
|
357
|
+
function getWindowsIEEE8021x(connectionType, iface, ifaces) {
|
358
|
+
let i8021x = {
|
359
|
+
state: 'Unknown',
|
360
|
+
protocol: 'Unknown',
|
361
|
+
};
|
362
|
+
|
363
|
+
if (ifaces === 'Disabled') {
|
364
|
+
i8021x.state = 'Disabled';
|
365
|
+
i8021x.protocol = 'Not defined';
|
366
|
+
return i8021x;
|
367
|
+
}
|
368
|
+
|
369
|
+
if (connectionType == 'wired' && ifaces.length > 0) {
|
370
|
+
try {
|
371
|
+
// Get 802.1x information by interface name
|
372
|
+
const iface8021xInfo = ifaces.find((element) => {
|
373
|
+
return element.includes(iface + '\r\n');
|
374
|
+
});
|
375
|
+
const arrayIface8021xInfo = iface8021xInfo.split('\r\n');
|
376
|
+
const state8021x = arrayIface8021xInfo.find((element) => {
|
377
|
+
return element.includes('802.1x');
|
378
|
+
});
|
379
|
+
|
380
|
+
if (state8021x.includes('Disabled')) {
|
381
|
+
i8021x.state = 'Disabled';
|
382
|
+
i8021x.protocol = 'Not defined';
|
383
|
+
} else if (state8021x.includes('Enabled')) {
|
384
|
+
const protocol8021x = arrayIface8021xInfo.find((element) => {
|
385
|
+
return element.includes('EAP');
|
386
|
+
});
|
387
|
+
i8021x.protocol = protocol8021x.split(':').pop();
|
388
|
+
i8021x.state = 'Enabled';
|
389
|
+
}
|
390
|
+
} catch (error) {
|
391
|
+
return i8021x;
|
392
|
+
}
|
393
|
+
} else if (connectionType == 'wireless') {
|
394
|
+
|
395
|
+
let i8021xState = '';
|
396
|
+
let i8021xProtocol = '';
|
397
|
+
|
398
|
+
|
399
|
+
|
400
|
+
try {
|
401
|
+
const SSID = getWindowsWirelessIfaceSSID(iface);
|
402
|
+
if (SSID !== 'Unknown') {
|
403
|
+
i8021xState = execSync(`netsh wlan show profiles "${SSID}" | findstr "802.1X"`, util.execOptsWin);
|
404
|
+
i8021xProtocol = execSync(`netsh wlan show profiles "${SSID}" | findstr "EAP"`, util.execOptsWin);
|
405
|
+
}
|
406
|
+
|
407
|
+
if (i8021xState.includes(':') && i8021xProtocol.includes(':')) {
|
408
|
+
i8021x.state = i8021xState.split(':').pop();
|
409
|
+
i8021x.protocol = i8021xProtocol.split(':').pop();
|
410
|
+
}
|
411
|
+
} catch (error) {
|
412
|
+
if (error.status === 1 && error.stdout.includes('AutoConfig')) {
|
413
|
+
i8021x.state = 'Disabled';
|
414
|
+
i8021x.protocol = 'Not defined';
|
415
|
+
}
|
416
|
+
return i8021x;
|
417
|
+
}
|
418
|
+
}
|
419
|
+
|
420
|
+
return i8021x;
|
421
|
+
}
|
422
|
+
|
423
|
+
function splitSectionsNics(lines) {
|
424
|
+
const result = [];
|
425
|
+
let section = [];
|
426
|
+
lines.forEach(function (line) {
|
427
|
+
if (!line.startsWith('\t') && !line.startsWith(' ')) {
|
428
|
+
if (section.length) {
|
429
|
+
result.push(section);
|
430
|
+
section = [];
|
431
|
+
}
|
432
|
+
}
|
433
|
+
section.push(line);
|
434
|
+
});
|
435
|
+
if (section.length) {
|
436
|
+
result.push(section);
|
437
|
+
}
|
438
|
+
return result;
|
439
|
+
}
|
440
|
+
|
441
|
+
function parseLinesDarwinNics(sections) {
|
442
|
+
let nics = [];
|
443
|
+
sections.forEach(section => {
|
444
|
+
let nic = {
|
445
|
+
iface: '',
|
446
|
+
mtu: null,
|
447
|
+
mac: '',
|
448
|
+
ip6: '',
|
449
|
+
ip4: '',
|
450
|
+
speed: null,
|
451
|
+
type: '',
|
452
|
+
operstate: '',
|
453
|
+
duplex: '',
|
454
|
+
internal: false
|
455
|
+
};
|
456
|
+
const first = section[0];
|
457
|
+
nic.iface = first.split(':')[0].trim();
|
458
|
+
let parts = first.split('> mtu');
|
459
|
+
nic.mtu = parts.length > 1 ? parseInt(parts[1], 10) : null;
|
460
|
+
if (isNaN(nic.mtu)) {
|
461
|
+
nic.mtu = null;
|
462
|
+
}
|
463
|
+
nic.internal = parts[0].toLowerCase().indexOf('loopback') > -1;
|
464
|
+
section.forEach(line => {
|
465
|
+
if (line.trim().startsWith('ether ')) {
|
466
|
+
nic.mac = line.split('ether ')[1].toLowerCase().trim();
|
467
|
+
}
|
468
|
+
if (line.trim().startsWith('inet6 ') && !nic.ip6) {
|
469
|
+
nic.ip6 = line.split('inet6 ')[1].toLowerCase().split('%')[0].split(' ')[0];
|
470
|
+
}
|
471
|
+
if (line.trim().startsWith('inet ') && !nic.ip4) {
|
472
|
+
nic.ip4 = line.split('inet ')[1].toLowerCase().split(' ')[0];
|
473
|
+
}
|
474
|
+
});
|
475
|
+
let speed = util.getValue(section, 'link rate');
|
476
|
+
nic.speed = speed ? parseFloat(speed) : null;
|
477
|
+
if (nic.speed === null) {
|
478
|
+
speed = util.getValue(section, 'uplink rate');
|
479
|
+
nic.speed = speed ? parseFloat(speed) : null;
|
480
|
+
if (nic.speed !== null && speed.toLowerCase().indexOf('gbps') >= 0) {
|
481
|
+
nic.speed = nic.speed * 1000;
|
482
|
+
}
|
483
|
+
} else {
|
484
|
+
if (speed.toLowerCase().indexOf('gbps') >= 0) {
|
485
|
+
nic.speed = nic.speed * 1000;
|
486
|
+
}
|
487
|
+
}
|
488
|
+
nic.type = util.getValue(section, 'type').toLowerCase().indexOf('wi-fi') > -1 ? 'wireless' : 'wired';
|
489
|
+
const operstate = util.getValue(section, 'status').toLowerCase();
|
490
|
+
nic.operstate = (operstate === 'active' ? 'up' : (operstate === 'inactive' ? 'down' : 'unknown'));
|
491
|
+
nic.duplex = util.getValue(section, 'media').toLowerCase().indexOf('half-duplex') > -1 ? 'half' : 'full';
|
492
|
+
if (nic.ip6 || nic.ip4 || nic.mac) {
|
493
|
+
nics.push(nic);
|
494
|
+
}
|
495
|
+
});
|
496
|
+
return nics;
|
497
|
+
}
|
498
|
+
|
499
|
+
function getDarwinNics() {
|
500
|
+
const cmd = '/sbin/ifconfig -v';
|
501
|
+
try {
|
502
|
+
const lines = execSync(cmd, { maxBuffer: 1024 * 20000 }).toString().split('\n');
|
503
|
+
const nsections = splitSectionsNics(lines);
|
504
|
+
return (parseLinesDarwinNics(nsections));
|
505
|
+
} catch (e) {
|
506
|
+
return [];
|
507
|
+
}
|
508
|
+
}
|
509
|
+
|
510
|
+
function getLinuxIfaceConnectionName(interfaceName) {
|
511
|
+
const cmd = `nmcli device status 2>/dev/null | grep ${interfaceName}`;
|
512
|
+
|
513
|
+
try {
|
514
|
+
const result = execSync(cmd).toString();
|
515
|
+
const resultFormat = result.replace(/\s+/g, ' ').trim();
|
516
|
+
const connectionNameLines = resultFormat.split(' ').slice(3);
|
517
|
+
const connectionName = connectionNameLines.join(' ');
|
518
|
+
return connectionName != '--' ? connectionName : '';
|
519
|
+
} catch (e) {
|
520
|
+
return '';
|
521
|
+
}
|
522
|
+
}
|
523
|
+
|
524
|
+
function checkLinuxDCHPInterfaces(file) {
|
525
|
+
let result = [];
|
526
|
+
try {
|
527
|
+
let cmd = `cat ${file} 2> /dev/null | grep 'iface\\|source'`;
|
528
|
+
const lines = execSync(cmd, { maxBuffer: 1024 * 20000 }).toString().split('\n');
|
529
|
+
|
530
|
+
lines.forEach(line => {
|
531
|
+
const parts = line.replace(/\s+/g, ' ').trim().split(' ');
|
532
|
+
if (parts.length >= 4) {
|
533
|
+
if (line.toLowerCase().indexOf(' inet ') >= 0 && line.toLowerCase().indexOf('dhcp') >= 0) {
|
534
|
+
result.push(parts[1]);
|
535
|
+
}
|
536
|
+
}
|
537
|
+
if (line.toLowerCase().includes('source')) {
|
538
|
+
let file = line.split(' ')[1];
|
539
|
+
result = result.concat(checkLinuxDCHPInterfaces(file));
|
540
|
+
}
|
541
|
+
});
|
542
|
+
} catch (e) {
|
543
|
+
util.noop();
|
544
|
+
}
|
545
|
+
return result;
|
546
|
+
}
|
547
|
+
|
548
|
+
function getLinuxDHCPNics() {
|
549
|
+
// alternate methods getting interfaces using DHCP
|
550
|
+
let cmd = 'ip a 2> /dev/null';
|
551
|
+
let result = [];
|
552
|
+
try {
|
553
|
+
const lines = execSync(cmd, { maxBuffer: 1024 * 20000 }).toString().split('\n');
|
554
|
+
const nsections = splitSectionsNics(lines);
|
555
|
+
result = (parseLinuxDHCPNics(nsections));
|
556
|
+
} catch (e) {
|
557
|
+
util.noop();
|
558
|
+
}
|
559
|
+
try {
|
560
|
+
result = checkLinuxDCHPInterfaces('/etc/network/interfaces');
|
561
|
+
} catch (e) {
|
562
|
+
util.noop();
|
563
|
+
}
|
564
|
+
return result;
|
565
|
+
}
|
566
|
+
|
567
|
+
function parseLinuxDHCPNics(sections) {
|
568
|
+
const result = [];
|
569
|
+
if (sections && sections.length) {
|
570
|
+
sections.forEach(lines => {
|
571
|
+
if (lines && lines.length) {
|
572
|
+
const parts = lines[0].split(':');
|
573
|
+
if (parts.length > 2) {
|
574
|
+
for (let line of lines) {
|
575
|
+
if (line.indexOf(' inet ') >= 0 && line.indexOf(' dynamic ') >= 0) {
|
576
|
+
const parts2 = line.split(' ');
|
577
|
+
const nic = parts2[parts2.length - 1].trim();
|
578
|
+
result.push(nic);
|
579
|
+
break;
|
580
|
+
}
|
581
|
+
}
|
582
|
+
}
|
583
|
+
}
|
584
|
+
});
|
585
|
+
}
|
586
|
+
return result;
|
587
|
+
}
|
588
|
+
|
589
|
+
function getLinuxIfaceDHCPstatus(iface, connectionName, DHCPNics) {
|
590
|
+
let result = false;
|
591
|
+
if (connectionName) {
|
592
|
+
const cmd = `nmcli connection show "${connectionName}" 2>/dev/null | grep ipv4.method;`;
|
593
|
+
try {
|
594
|
+
const lines = execSync(cmd).toString();
|
595
|
+
const resultFormat = lines.replace(/\s+/g, ' ').trim();
|
596
|
+
|
597
|
+
let dhcStatus = resultFormat.split(' ').slice(1).toString();
|
598
|
+
switch (dhcStatus) {
|
599
|
+
case 'auto':
|
600
|
+
result = true;
|
601
|
+
break;
|
602
|
+
|
603
|
+
default:
|
604
|
+
result = false;
|
605
|
+
break;
|
606
|
+
}
|
607
|
+
return result;
|
608
|
+
} catch (e) {
|
609
|
+
return (DHCPNics.indexOf(iface) >= 0);
|
610
|
+
}
|
611
|
+
} else {
|
612
|
+
return (DHCPNics.indexOf(iface) >= 0);
|
613
|
+
}
|
614
|
+
}
|
615
|
+
|
616
|
+
function getDarwinIfaceDHCPstatus(iface) {
|
617
|
+
let result = false;
|
618
|
+
const cmd = `ipconfig getpacket "${iface}" 2>/dev/null | grep lease_time;`;
|
619
|
+
try {
|
620
|
+
const lines = execSync(cmd).toString().split('\n');
|
621
|
+
if (lines.length && lines[0].startsWith('lease_time')) {
|
622
|
+
result = true;
|
623
|
+
}
|
624
|
+
} catch (e) {
|
625
|
+
util.noop();
|
626
|
+
}
|
627
|
+
return result;
|
628
|
+
}
|
629
|
+
|
630
|
+
function getLinuxIfaceDNSsuffix(connectionName) {
|
631
|
+
if (connectionName) {
|
632
|
+
const cmd = `nmcli connection show "${connectionName}" 2>/dev/null | grep ipv4.dns-search;`;
|
633
|
+
try {
|
634
|
+
const result = execSync(cmd).toString();
|
635
|
+
const resultFormat = result.replace(/\s+/g, ' ').trim();
|
636
|
+
const dnsSuffix = resultFormat.split(' ').slice(1).toString();
|
637
|
+
return dnsSuffix == '--' ? 'Not defined' : dnsSuffix;
|
638
|
+
} catch (e) {
|
639
|
+
return 'Unknown';
|
640
|
+
}
|
641
|
+
} else {
|
642
|
+
return 'Unknown';
|
643
|
+
}
|
644
|
+
}
|
645
|
+
|
646
|
+
function getLinuxIfaceIEEE8021xAuth(connectionName) {
|
647
|
+
if (connectionName) {
|
648
|
+
const cmd = `nmcli connection show "${connectionName}" 2>/dev/null | grep 802-1x.eap;`;
|
649
|
+
try {
|
650
|
+
const result = execSync(cmd).toString();
|
651
|
+
const resultFormat = result.replace(/\s+/g, ' ').trim();
|
652
|
+
const authenticationProtocol = resultFormat.split(' ').slice(1).toString();
|
653
|
+
|
654
|
+
|
655
|
+
return authenticationProtocol == '--' ? '' : authenticationProtocol;
|
656
|
+
} catch (e) {
|
657
|
+
return 'Not defined';
|
658
|
+
}
|
659
|
+
} else {
|
660
|
+
return 'Not defined';
|
661
|
+
}
|
662
|
+
}
|
663
|
+
|
664
|
+
function getLinuxIfaceIEEE8021xState(authenticationProtocol) {
|
665
|
+
if (authenticationProtocol) {
|
666
|
+
if (authenticationProtocol == 'Not defined') {
|
667
|
+
return 'Disabled';
|
668
|
+
}
|
669
|
+
return 'Enabled';
|
670
|
+
} else {
|
671
|
+
return 'Unknown';
|
672
|
+
}
|
673
|
+
}
|
674
|
+
|
675
|
+
function testVirtualNic(iface, ifaceName, mac) {
|
676
|
+
const virtualMacs = ['00:00:00:00:00:00', '00:03:FF', '00:05:69', '00:0C:29', '00:0F:4B', '00:13:07', '00:13:BE', '00:15:5d', '00:16:3E', '00:1C:42', '00:21:F6', '00:24:0B', '00:50:56', '00:A0:B1', '00:E0:C8', '08:00:27', '0A:00:27', '18:92:2C', '16:DF:49', '3C:F3:92', '54:52:00', 'FC:15:97'];
|
677
|
+
if (mac) {
|
678
|
+
return virtualMacs.filter(item => { return mac.toUpperCase().toUpperCase().startsWith(item.substring(0, mac.length)); }).length > 0 ||
|
679
|
+
iface.toLowerCase().indexOf(' virtual ') > -1 ||
|
680
|
+
ifaceName.toLowerCase().indexOf(' virtual ') > -1 ||
|
681
|
+
iface.toLowerCase().indexOf('vethernet ') > -1 ||
|
682
|
+
ifaceName.toLowerCase().indexOf('vethernet ') > -1 ||
|
683
|
+
iface.toLowerCase().startsWith('veth') ||
|
684
|
+
ifaceName.toLowerCase().startsWith('veth') ||
|
685
|
+
iface.toLowerCase().startsWith('vboxnet') ||
|
686
|
+
ifaceName.toLowerCase().startsWith('vboxnet');
|
687
|
+
} else { return false; }
|
688
|
+
}
|
689
|
+
|
690
|
+
function networkInterfaces(callback, rescan, defaultString) {
|
691
|
+
|
692
|
+
if (typeof callback === 'string') {
|
693
|
+
defaultString = callback;
|
694
|
+
rescan = true;
|
695
|
+
callback = null;
|
696
|
+
}
|
697
|
+
|
698
|
+
if (typeof callback === 'boolean') {
|
699
|
+
rescan = callback;
|
700
|
+
callback = null;
|
701
|
+
defaultString = '';
|
702
|
+
}
|
703
|
+
if (typeof rescan === 'undefined') {
|
704
|
+
rescan = true;
|
705
|
+
}
|
706
|
+
defaultString = defaultString || '';
|
707
|
+
defaultString = '' + defaultString;
|
708
|
+
|
709
|
+
return new Promise((resolve) => {
|
710
|
+
process.nextTick(() => {
|
711
|
+
|
712
|
+
let ifaces = os.networkInterfaces();
|
713
|
+
|
714
|
+
let result = [];
|
715
|
+
let nics = [];
|
716
|
+
let dnsSuffixes = [];
|
717
|
+
let nics8021xInfo = [];
|
718
|
+
// seperate handling in OSX
|
719
|
+
if (_darwin || _freebsd || _openbsd || _netbsd) {
|
720
|
+
if ((JSON.stringify(ifaces) === JSON.stringify(_ifaces)) && !rescan) {
|
721
|
+
// no changes - just return object
|
722
|
+
result = _networkInterfaces;
|
723
|
+
|
724
|
+
if (callback) { callback(result); }
|
725
|
+
resolve(result);
|
726
|
+
} else {
|
727
|
+
const defaultInterface = getDefaultNetworkInterface();
|
728
|
+
_ifaces = JSON.parse(JSON.stringify(ifaces));
|
729
|
+
|
730
|
+
nics = getDarwinNics();
|
731
|
+
|
732
|
+
|
733
|
+
nics.forEach(nic => {
|
734
|
+
|
735
|
+
if ({}.hasOwnProperty.call(ifaces, nic.iface)) {
|
736
|
+
ifaces[nic.iface].forEach(function (details) {
|
737
|
+
if (details.family === 'IPv4' || details.family === 4) {
|
738
|
+
nic.ip4subnet = details.netmask;
|
739
|
+
}
|
740
|
+
if (details.family === 'IPv6' || details.family === 6) {
|
741
|
+
nic.ip6subnet = details.netmask;
|
742
|
+
}
|
743
|
+
});
|
744
|
+
}
|
745
|
+
|
746
|
+
let ifaceSanitized = '';
|
747
|
+
const s = util.isPrototypePolluted() ? '---' : util.sanitizeShellString(nic.iface);
|
748
|
+
for (let i = 0; i <= util.mathMin(s.length, 2000); i++) {
|
749
|
+
if (s[i] !== undefined) {
|
750
|
+
ifaceSanitized = ifaceSanitized + s[i];
|
751
|
+
}
|
752
|
+
}
|
753
|
+
|
754
|
+
result.push({
|
755
|
+
iface: nic.iface,
|
756
|
+
ifaceName: nic.iface,
|
757
|
+
default: nic.iface === defaultInterface,
|
758
|
+
ip4: nic.ip4,
|
759
|
+
ip4subnet: nic.ip4subnet || '',
|
760
|
+
ip6: nic.ip6,
|
761
|
+
ip6subnet: nic.ip6subnet || '',
|
762
|
+
mac: nic.mac,
|
763
|
+
internal: nic.internal,
|
764
|
+
virtual: nic.internal ? false : testVirtualNic(nic.iface, nic.iface, nic.mac),
|
765
|
+
operstate: nic.operstate,
|
766
|
+
type: nic.type,
|
767
|
+
duplex: nic.duplex,
|
768
|
+
mtu: nic.mtu,
|
769
|
+
speed: nic.speed,
|
770
|
+
dhcp: getDarwinIfaceDHCPstatus(ifaceSanitized),
|
771
|
+
dnsSuffix: '',
|
772
|
+
ieee8021xAuth: '',
|
773
|
+
ieee8021xState: '',
|
774
|
+
carrierChanges: 0
|
775
|
+
});
|
776
|
+
});
|
777
|
+
_networkInterfaces = result;
|
778
|
+
if (defaultString.toLowerCase().indexOf('default') >= 0) {
|
779
|
+
result = result.filter(item => item.default);
|
780
|
+
if (result.length > 0) {
|
781
|
+
result = result[0];
|
782
|
+
} else {
|
783
|
+
result = [];
|
784
|
+
}
|
785
|
+
}
|
786
|
+
if (callback) { callback(result); }
|
787
|
+
resolve(result);
|
788
|
+
}
|
789
|
+
}
|
790
|
+
if (_linux) {
|
791
|
+
if ((JSON.stringify(ifaces) === JSON.stringify(_ifaces)) && !rescan) {
|
792
|
+
// no changes - just return object
|
793
|
+
result = _networkInterfaces;
|
794
|
+
|
795
|
+
if (callback) { callback(result); }
|
796
|
+
resolve(result);
|
797
|
+
} else {
|
798
|
+
_ifaces = JSON.parse(JSON.stringify(ifaces));
|
799
|
+
_dhcpNics = getLinuxDHCPNics();
|
800
|
+
const defaultInterface = getDefaultNetworkInterface();
|
801
|
+
for (let dev in ifaces) {
|
802
|
+
let ip4 = '';
|
803
|
+
let ip4subnet = '';
|
804
|
+
let ip6 = '';
|
805
|
+
let ip6subnet = '';
|
806
|
+
let mac = '';
|
807
|
+
let duplex = '';
|
808
|
+
let mtu = '';
|
809
|
+
let speed = null;
|
810
|
+
let carrierChanges = 0;
|
811
|
+
let dhcp = false;
|
812
|
+
let dnsSuffix = '';
|
813
|
+
let ieee8021xAuth = '';
|
814
|
+
let ieee8021xState = '';
|
815
|
+
let type = '';
|
816
|
+
|
817
|
+
if ({}.hasOwnProperty.call(ifaces, dev)) {
|
818
|
+
let ifaceName = dev;
|
819
|
+
ifaces[dev].forEach(function (details) {
|
820
|
+
if (details.family === 'IPv4' || details.family === 4) {
|
821
|
+
ip4 = details.address;
|
822
|
+
ip4subnet = details.netmask;
|
823
|
+
}
|
824
|
+
if (details.family === 'IPv6' || details.family === 6) {
|
825
|
+
if (!ip6 || ip6.match(/^fe80::/i)) {
|
826
|
+
ip6 = details.address;
|
827
|
+
ip6subnet = details.netmask;
|
828
|
+
}
|
829
|
+
}
|
830
|
+
mac = details.mac;
|
831
|
+
// fallback due to https://github.com/nodejs/node/issues/13581 (node 8.1 - node 8.2)
|
832
|
+
const nodeMainVersion = parseInt(process.versions.node.split('.'), 10);
|
833
|
+
if (mac.indexOf('00:00:0') > -1 && (_linux || _darwin) && (!details.internal) && nodeMainVersion >= 8 && nodeMainVersion <= 11) {
|
834
|
+
if (Object.keys(_mac).length === 0) {
|
835
|
+
_mac = getMacAddresses();
|
836
|
+
}
|
837
|
+
mac = _mac[dev] || '';
|
838
|
+
}
|
839
|
+
});
|
840
|
+
let iface = dev.split(':')[0].trim().toLowerCase();
|
841
|
+
let ifaceSanitized = '';
|
842
|
+
const s = util.isPrototypePolluted() ? '---' : util.sanitizeShellString(iface);
|
843
|
+
for (let i = 0; i <= util.mathMin(s.length, 2000); i++) {
|
844
|
+
if (s[i] !== undefined) {
|
845
|
+
ifaceSanitized = ifaceSanitized + s[i];
|
846
|
+
}
|
847
|
+
}
|
848
|
+
const cmd = `echo -n "addr_assign_type: "; cat /sys/class/net/${ifaceSanitized}/addr_assign_type 2>/dev/null; echo;
|
849
|
+
echo -n "address: "; cat /sys/class/net/${ifaceSanitized}/address 2>/dev/null; echo;
|
850
|
+
echo -n "addr_len: "; cat /sys/class/net/${ifaceSanitized}/addr_len 2>/dev/null; echo;
|
851
|
+
echo -n "broadcast: "; cat /sys/class/net/${ifaceSanitized}/broadcast 2>/dev/null; echo;
|
852
|
+
echo -n "carrier: "; cat /sys/class/net/${ifaceSanitized}/carrier 2>/dev/null; echo;
|
853
|
+
echo -n "carrier_changes: "; cat /sys/class/net/${ifaceSanitized}/carrier_changes 2>/dev/null; echo;
|
854
|
+
echo -n "dev_id: "; cat /sys/class/net/${ifaceSanitized}/dev_id 2>/dev/null; echo;
|
855
|
+
echo -n "dev_port: "; cat /sys/class/net/${ifaceSanitized}/dev_port 2>/dev/null; echo;
|
856
|
+
echo -n "dormant: "; cat /sys/class/net/${ifaceSanitized}/dormant 2>/dev/null; echo;
|
857
|
+
echo -n "duplex: "; cat /sys/class/net/${ifaceSanitized}/duplex 2>/dev/null; echo;
|
858
|
+
echo -n "flags: "; cat /sys/class/net/${ifaceSanitized}/flags 2>/dev/null; echo;
|
859
|
+
echo -n "gro_flush_timeout: "; cat /sys/class/net/${ifaceSanitized}/gro_flush_timeout 2>/dev/null; echo;
|
860
|
+
echo -n "ifalias: "; cat /sys/class/net/${ifaceSanitized}/ifalias 2>/dev/null; echo;
|
861
|
+
echo -n "ifindex: "; cat /sys/class/net/${ifaceSanitized}/ifindex 2>/dev/null; echo;
|
862
|
+
echo -n "iflink: "; cat /sys/class/net/${ifaceSanitized}/iflink 2>/dev/null; echo;
|
863
|
+
echo -n "link_mode: "; cat /sys/class/net/${ifaceSanitized}/link_mode 2>/dev/null; echo;
|
864
|
+
echo -n "mtu: "; cat /sys/class/net/${ifaceSanitized}/mtu 2>/dev/null; echo;
|
865
|
+
echo -n "netdev_group: "; cat /sys/class/net/${ifaceSanitized}/netdev_group 2>/dev/null; echo;
|
866
|
+
echo -n "operstate: "; cat /sys/class/net/${ifaceSanitized}/operstate 2>/dev/null; echo;
|
867
|
+
echo -n "proto_down: "; cat /sys/class/net/${ifaceSanitized}/proto_down 2>/dev/null; echo;
|
868
|
+
echo -n "speed: "; cat /sys/class/net/${ifaceSanitized}/speed 2>/dev/null; echo;
|
869
|
+
echo -n "tx_queue_len: "; cat /sys/class/net/${ifaceSanitized}/tx_queue_len 2>/dev/null; echo;
|
870
|
+
echo -n "type: "; cat /sys/class/net/${ifaceSanitized}/type 2>/dev/null; echo;
|
871
|
+
echo -n "wireless: "; cat /proc/net/wireless 2>/dev/null | grep ${ifaceSanitized}; echo;
|
872
|
+
echo -n "wirelessspeed: "; iw dev ${ifaceSanitized} link 2>&1 | grep bitrate; echo;`;
|
873
|
+
|
874
|
+
let lines = [];
|
875
|
+
try {
|
876
|
+
lines = execSync(cmd).toString().split('\n');
|
877
|
+
const connectionName = getLinuxIfaceConnectionName(ifaceSanitized);
|
878
|
+
dhcp = getLinuxIfaceDHCPstatus(ifaceSanitized, connectionName, _dhcpNics);
|
879
|
+
dnsSuffix = getLinuxIfaceDNSsuffix(connectionName);
|
880
|
+
ieee8021xAuth = getLinuxIfaceIEEE8021xAuth(connectionName);
|
881
|
+
ieee8021xState = getLinuxIfaceIEEE8021xState(ieee8021xAuth);
|
882
|
+
} catch (e) {
|
883
|
+
util.noop();
|
884
|
+
}
|
885
|
+
duplex = util.getValue(lines, 'duplex');
|
886
|
+
duplex = duplex.startsWith('cat') ? '' : duplex;
|
887
|
+
mtu = parseInt(util.getValue(lines, 'mtu'), 10);
|
888
|
+
let myspeed = parseInt(util.getValue(lines, 'speed'), 10);
|
889
|
+
speed = isNaN(myspeed) ? null : myspeed;
|
890
|
+
let wirelessspeed = util.getValue(lines, 'wirelessspeed').split('tx bitrate: ');
|
891
|
+
if (speed === null && wirelessspeed.length === 2) {
|
892
|
+
myspeed = parseFloat(wirelessspeed[1]);
|
893
|
+
speed = isNaN(myspeed) ? null : myspeed;
|
894
|
+
}
|
895
|
+
carrierChanges = parseInt(util.getValue(lines, 'carrier_changes'), 10);
|
896
|
+
const operstate = util.getValue(lines, 'operstate');
|
897
|
+
type = operstate === 'up' ? (util.getValue(lines, 'wireless').trim() ? 'wireless' : 'wired') : 'unknown';
|
898
|
+
if (ifaceSanitized === 'lo' || ifaceSanitized.startsWith('bond')) { type = 'virtual'; }
|
899
|
+
|
900
|
+
let internal = (ifaces[dev] && ifaces[dev][0]) ? ifaces[dev][0].internal : false;
|
901
|
+
if (dev.toLowerCase().indexOf('loopback') > -1 || ifaceName.toLowerCase().indexOf('loopback') > -1) {
|
902
|
+
internal = true;
|
903
|
+
}
|
904
|
+
const virtual = internal ? false : testVirtualNic(dev, ifaceName, mac);
|
905
|
+
result.push({
|
906
|
+
iface: ifaceSanitized,
|
907
|
+
ifaceName,
|
908
|
+
default: iface === defaultInterface,
|
909
|
+
ip4,
|
910
|
+
ip4subnet,
|
911
|
+
ip6,
|
912
|
+
ip6subnet,
|
913
|
+
mac,
|
914
|
+
internal,
|
915
|
+
virtual,
|
916
|
+
operstate,
|
917
|
+
type,
|
918
|
+
duplex,
|
919
|
+
mtu,
|
920
|
+
speed,
|
921
|
+
dhcp,
|
922
|
+
dnsSuffix,
|
923
|
+
ieee8021xAuth,
|
924
|
+
ieee8021xState,
|
925
|
+
carrierChanges,
|
926
|
+
});
|
927
|
+
}
|
928
|
+
}
|
929
|
+
_networkInterfaces = result;
|
930
|
+
if (defaultString.toLowerCase().indexOf('default') >= 0) {
|
931
|
+
result = result.filter(item => item.default);
|
932
|
+
if (result.length > 0) {
|
933
|
+
result = result[0];
|
934
|
+
} else {
|
935
|
+
result = [];
|
936
|
+
}
|
937
|
+
}
|
938
|
+
if (callback) { callback(result); }
|
939
|
+
resolve(result);
|
940
|
+
}
|
941
|
+
}
|
942
|
+
if (_windows) {
|
943
|
+
if ((JSON.stringify(ifaces) === JSON.stringify(_ifaces)) && !rescan) {
|
944
|
+
// no changes - just return object
|
945
|
+
result = _networkInterfaces;
|
946
|
+
|
947
|
+
if (callback) { callback(result); }
|
948
|
+
resolve(result);
|
949
|
+
} else {
|
950
|
+
_ifaces = JSON.parse(JSON.stringify(ifaces));
|
951
|
+
const defaultInterface = getDefaultNetworkInterface();
|
952
|
+
|
953
|
+
getWindowsNics().then(function (nics) {
|
954
|
+
nics.forEach(nic => {
|
955
|
+
let found = false;
|
956
|
+
Object.keys(ifaces).forEach(key => {
|
957
|
+
if (!found) {
|
958
|
+
ifaces[key].forEach(value => {
|
959
|
+
if (Object.keys(value).indexOf('mac') >= 0) {
|
960
|
+
found = value['mac'] === nic.mac;
|
961
|
+
}
|
962
|
+
});
|
963
|
+
}
|
964
|
+
});
|
965
|
+
|
966
|
+
if (!found) {
|
967
|
+
ifaces[nic.name] = [{ mac: nic.mac }];
|
968
|
+
}
|
969
|
+
});
|
970
|
+
nics8021xInfo = getWindowsWiredProfilesInformation();
|
971
|
+
dnsSuffixes = getWindowsDNSsuffixes();
|
972
|
+
for (let dev in ifaces) {
|
973
|
+
|
974
|
+
let ifaceSanitized = '';
|
975
|
+
const s = util.isPrototypePolluted() ? '---' : util.sanitizeShellString(dev);
|
976
|
+
for (let i = 0; i <= util.mathMin(s.length, 2000); i++) {
|
977
|
+
if (s[i] !== undefined) {
|
978
|
+
ifaceSanitized = ifaceSanitized + s[i];
|
979
|
+
}
|
980
|
+
}
|
981
|
+
|
982
|
+
let iface = dev;
|
983
|
+
let ip4 = '';
|
984
|
+
let ip4subnet = '';
|
985
|
+
let ip6 = '';
|
986
|
+
let ip6subnet = '';
|
987
|
+
let mac = '';
|
988
|
+
let duplex = '';
|
989
|
+
let mtu = '';
|
990
|
+
let speed = null;
|
991
|
+
let carrierChanges = 0;
|
992
|
+
let operstate = 'down';
|
993
|
+
let dhcp = false;
|
994
|
+
let dnsSuffix = '';
|
995
|
+
let ieee8021xAuth = '';
|
996
|
+
let ieee8021xState = '';
|
997
|
+
let type = '';
|
998
|
+
|
999
|
+
if ({}.hasOwnProperty.call(ifaces, dev)) {
|
1000
|
+
let ifaceName = dev;
|
1001
|
+
ifaces[dev].forEach(function (details) {
|
1002
|
+
if (details.family === 'IPv4' || details.family === 4) {
|
1003
|
+
ip4 = details.address;
|
1004
|
+
ip4subnet = details.netmask;
|
1005
|
+
}
|
1006
|
+
if (details.family === 'IPv6' || details.family === 6) {
|
1007
|
+
if (!ip6 || ip6.match(/^fe80::/i)) {
|
1008
|
+
ip6 = details.address;
|
1009
|
+
ip6subnet = details.netmask;
|
1010
|
+
}
|
1011
|
+
}
|
1012
|
+
mac = details.mac;
|
1013
|
+
// fallback due to https://github.com/nodejs/node/issues/13581 (node 8.1 - node 8.2)
|
1014
|
+
const nodeMainVersion = parseInt(process.versions.node.split('.'), 10);
|
1015
|
+
if (mac.indexOf('00:00:0') > -1 && (_linux || _darwin) && (!details.internal) && nodeMainVersion >= 8 && nodeMainVersion <= 11) {
|
1016
|
+
if (Object.keys(_mac).length === 0) {
|
1017
|
+
_mac = getMacAddresses();
|
1018
|
+
}
|
1019
|
+
mac = _mac[dev] || '';
|
1020
|
+
}
|
1021
|
+
});
|
1022
|
+
|
1023
|
+
|
1024
|
+
|
1025
|
+
dnsSuffix = getWindowsIfaceDNSsuffix(dnsSuffixes.ifaces, ifaceSanitized);
|
1026
|
+
let foundFirst = false;
|
1027
|
+
nics.forEach(detail => {
|
1028
|
+
if (detail.mac === mac && !foundFirst) {
|
1029
|
+
iface = detail.iface || iface;
|
1030
|
+
ifaceName = detail.name;
|
1031
|
+
dhcp = detail.dhcp;
|
1032
|
+
operstate = detail.operstate;
|
1033
|
+
speed = detail.speed;
|
1034
|
+
type = detail.type;
|
1035
|
+
foundFirst = true;
|
1036
|
+
}
|
1037
|
+
});
|
1038
|
+
|
1039
|
+
if (dev.toLowerCase().indexOf('wlan') >= 0 || ifaceName.toLowerCase().indexOf('wlan') >= 0 || ifaceName.toLowerCase().indexOf('802.11n') >= 0 || ifaceName.toLowerCase().indexOf('wireless') >= 0 || ifaceName.toLowerCase().indexOf('wi-fi') >= 0 || ifaceName.toLowerCase().indexOf('wifi') >= 0) {
|
1040
|
+
type = 'wireless';
|
1041
|
+
}
|
1042
|
+
|
1043
|
+
const IEEE8021x = getWindowsIEEE8021x(type, ifaceSanitized, nics8021xInfo);
|
1044
|
+
ieee8021xAuth = IEEE8021x.protocol;
|
1045
|
+
ieee8021xState = IEEE8021x.state;
|
1046
|
+
let internal = (ifaces[dev] && ifaces[dev][0]) ? ifaces[dev][0].internal : false;
|
1047
|
+
if (dev.toLowerCase().indexOf('loopback') > -1 || ifaceName.toLowerCase().indexOf('loopback') > -1) {
|
1048
|
+
internal = true;
|
1049
|
+
}
|
1050
|
+
const virtual = internal ? false : testVirtualNic(dev, ifaceName, mac);
|
1051
|
+
result.push({
|
1052
|
+
iface,
|
1053
|
+
ifaceName,
|
1054
|
+
default: iface === defaultInterface,
|
1055
|
+
ip4,
|
1056
|
+
ip4subnet,
|
1057
|
+
ip6,
|
1058
|
+
ip6subnet,
|
1059
|
+
mac,
|
1060
|
+
internal,
|
1061
|
+
virtual,
|
1062
|
+
operstate,
|
1063
|
+
type,
|
1064
|
+
duplex,
|
1065
|
+
mtu,
|
1066
|
+
speed,
|
1067
|
+
dhcp,
|
1068
|
+
dnsSuffix,
|
1069
|
+
ieee8021xAuth,
|
1070
|
+
ieee8021xState,
|
1071
|
+
carrierChanges,
|
1072
|
+
});
|
1073
|
+
}
|
1074
|
+
}
|
1075
|
+
_networkInterfaces = result;
|
1076
|
+
if (defaultString.toLowerCase().indexOf('default') >= 0) {
|
1077
|
+
result = result.filter(item => item.default);
|
1078
|
+
if (result.length > 0) {
|
1079
|
+
result = result[0];
|
1080
|
+
} else {
|
1081
|
+
result = [];
|
1082
|
+
}
|
1083
|
+
}
|
1084
|
+
if (callback) { callback(result); }
|
1085
|
+
resolve(result);
|
1086
|
+
});
|
1087
|
+
}
|
1088
|
+
}
|
1089
|
+
});
|
1090
|
+
});
|
1091
|
+
}
|
1092
|
+
|
1093
|
+
exports.networkInterfaces = networkInterfaces;
|
1094
|
+
|
1095
|
+
// --------------------------
|
1096
|
+
// NET - Speed
|
1097
|
+
|
1098
|
+
function calcNetworkSpeed(iface, rx_bytes, tx_bytes, operstate, rx_dropped, rx_errors, tx_dropped, tx_errors) {
|
1099
|
+
let result = {
|
1100
|
+
iface,
|
1101
|
+
operstate,
|
1102
|
+
rx_bytes,
|
1103
|
+
rx_dropped,
|
1104
|
+
rx_errors,
|
1105
|
+
tx_bytes,
|
1106
|
+
tx_dropped,
|
1107
|
+
tx_errors,
|
1108
|
+
rx_sec: null,
|
1109
|
+
tx_sec: null,
|
1110
|
+
ms: 0
|
1111
|
+
};
|
1112
|
+
|
1113
|
+
if (_network[iface] && _network[iface].ms) {
|
1114
|
+
result.ms = Date.now() - _network[iface].ms;
|
1115
|
+
result.rx_sec = (rx_bytes - _network[iface].rx_bytes) >= 0 ? (rx_bytes - _network[iface].rx_bytes) / (result.ms / 1000) : 0;
|
1116
|
+
result.tx_sec = (tx_bytes - _network[iface].tx_bytes) >= 0 ? (tx_bytes - _network[iface].tx_bytes) / (result.ms / 1000) : 0;
|
1117
|
+
_network[iface].rx_bytes = rx_bytes;
|
1118
|
+
_network[iface].tx_bytes = tx_bytes;
|
1119
|
+
_network[iface].rx_sec = result.rx_sec;
|
1120
|
+
_network[iface].tx_sec = result.tx_sec;
|
1121
|
+
_network[iface].ms = Date.now();
|
1122
|
+
_network[iface].last_ms = result.ms;
|
1123
|
+
_network[iface].operstate = operstate;
|
1124
|
+
} else {
|
1125
|
+
if (!_network[iface]) { _network[iface] = {}; }
|
1126
|
+
_network[iface].rx_bytes = rx_bytes;
|
1127
|
+
_network[iface].tx_bytes = tx_bytes;
|
1128
|
+
_network[iface].rx_sec = null;
|
1129
|
+
_network[iface].tx_sec = null;
|
1130
|
+
_network[iface].ms = Date.now();
|
1131
|
+
_network[iface].last_ms = 0;
|
1132
|
+
_network[iface].operstate = operstate;
|
1133
|
+
}
|
1134
|
+
return result;
|
1135
|
+
}
|
1136
|
+
|
1137
|
+
function networkStats(ifaces, callback) {
|
1138
|
+
|
1139
|
+
let ifacesArray = [];
|
1140
|
+
|
1141
|
+
return new Promise((resolve) => {
|
1142
|
+
process.nextTick(() => {
|
1143
|
+
|
1144
|
+
// fallback - if only callback is given
|
1145
|
+
if (util.isFunction(ifaces) && !callback) {
|
1146
|
+
callback = ifaces;
|
1147
|
+
ifacesArray = [getDefaultNetworkInterface()];
|
1148
|
+
} else {
|
1149
|
+
if (typeof ifaces !== 'string' && ifaces !== undefined) {
|
1150
|
+
if (callback) { callback([]); }
|
1151
|
+
return resolve([]);
|
1152
|
+
}
|
1153
|
+
ifaces = ifaces || getDefaultNetworkInterface();
|
1154
|
+
|
1155
|
+
ifaces.__proto__.toLowerCase = util.stringToLower;
|
1156
|
+
ifaces.__proto__.replace = util.stringReplace;
|
1157
|
+
ifaces.__proto__.trim = util.stringTrim;
|
1158
|
+
|
1159
|
+
ifaces = ifaces.trim().toLowerCase().replace(/,+/g, '|');
|
1160
|
+
ifacesArray = ifaces.split('|');
|
1161
|
+
}
|
1162
|
+
|
1163
|
+
const result = [];
|
1164
|
+
|
1165
|
+
const workload = [];
|
1166
|
+
if (ifacesArray.length && ifacesArray[0].trim() === '*') {
|
1167
|
+
ifacesArray = [];
|
1168
|
+
networkInterfaces(false).then(allIFaces => {
|
1169
|
+
for (let iface of allIFaces) {
|
1170
|
+
ifacesArray.push(iface.iface);
|
1171
|
+
}
|
1172
|
+
networkStats(ifacesArray.join(',')).then(result => {
|
1173
|
+
if (callback) { callback(result); }
|
1174
|
+
resolve(result);
|
1175
|
+
});
|
1176
|
+
});
|
1177
|
+
} else {
|
1178
|
+
for (let iface of ifacesArray) {
|
1179
|
+
workload.push(networkStatsSingle(iface.trim()));
|
1180
|
+
}
|
1181
|
+
if (workload.length) {
|
1182
|
+
Promise.all(
|
1183
|
+
workload
|
1184
|
+
).then((data) => {
|
1185
|
+
if (callback) { callback(data); }
|
1186
|
+
resolve(data);
|
1187
|
+
});
|
1188
|
+
} else {
|
1189
|
+
if (callback) { callback(result); }
|
1190
|
+
resolve(result);
|
1191
|
+
}
|
1192
|
+
}
|
1193
|
+
});
|
1194
|
+
});
|
1195
|
+
}
|
1196
|
+
|
1197
|
+
function networkStatsSingle(iface) {
|
1198
|
+
|
1199
|
+
function parseLinesWindowsPerfData(sections) {
|
1200
|
+
let perfData = [];
|
1201
|
+
for (let i in sections) {
|
1202
|
+
if ({}.hasOwnProperty.call(sections, i)) {
|
1203
|
+
if (sections[i].trim() !== '') {
|
1204
|
+
let lines = sections[i].trim().split('\r\n');
|
1205
|
+
perfData.push({
|
1206
|
+
name: util.getValue(lines, 'Name', ':').replace(/[()[\] ]+/g, '').replace(/#|\//g, '_').toLowerCase(),
|
1207
|
+
rx_bytes: parseInt(util.getValue(lines, 'BytesReceivedPersec', ':'), 10),
|
1208
|
+
rx_errors: parseInt(util.getValue(lines, 'PacketsReceivedErrors', ':'), 10),
|
1209
|
+
rx_dropped: parseInt(util.getValue(lines, 'PacketsReceivedDiscarded', ':'), 10),
|
1210
|
+
tx_bytes: parseInt(util.getValue(lines, 'BytesSentPersec', ':'), 10),
|
1211
|
+
tx_errors: parseInt(util.getValue(lines, 'PacketsOutboundErrors', ':'), 10),
|
1212
|
+
tx_dropped: parseInt(util.getValue(lines, 'PacketsOutboundDiscarded', ':'), 10)
|
1213
|
+
});
|
1214
|
+
}
|
1215
|
+
}
|
1216
|
+
}
|
1217
|
+
return perfData;
|
1218
|
+
}
|
1219
|
+
|
1220
|
+
return new Promise((resolve) => {
|
1221
|
+
process.nextTick(() => {
|
1222
|
+
let ifaceSanitized = '';
|
1223
|
+
const s = util.isPrototypePolluted() ? '---' : util.sanitizeShellString(iface);
|
1224
|
+
for (let i = 0; i <= util.mathMin(s.length, 2000); i++) {
|
1225
|
+
if (s[i] !== undefined) {
|
1226
|
+
ifaceSanitized = ifaceSanitized + s[i];
|
1227
|
+
}
|
1228
|
+
}
|
1229
|
+
|
1230
|
+
let result = {
|
1231
|
+
iface: ifaceSanitized,
|
1232
|
+
operstate: 'unknown',
|
1233
|
+
rx_bytes: 0,
|
1234
|
+
rx_dropped: 0,
|
1235
|
+
rx_errors: 0,
|
1236
|
+
tx_bytes: 0,
|
1237
|
+
tx_dropped: 0,
|
1238
|
+
tx_errors: 0,
|
1239
|
+
rx_sec: null,
|
1240
|
+
tx_sec: null,
|
1241
|
+
ms: 0
|
1242
|
+
};
|
1243
|
+
|
1244
|
+
let operstate = 'unknown';
|
1245
|
+
let rx_bytes = 0;
|
1246
|
+
let tx_bytes = 0;
|
1247
|
+
let rx_dropped = 0;
|
1248
|
+
let rx_errors = 0;
|
1249
|
+
let tx_dropped = 0;
|
1250
|
+
let tx_errors = 0;
|
1251
|
+
|
1252
|
+
let cmd, lines, stats;
|
1253
|
+
if (!_network[ifaceSanitized] || (_network[ifaceSanitized] && !_network[ifaceSanitized].ms) || (_network[ifaceSanitized] && _network[ifaceSanitized].ms && Date.now() - _network[ifaceSanitized].ms >= 500)) {
|
1254
|
+
if (_linux) {
|
1255
|
+
if (fs.existsSync('/sys/class/net/' + ifaceSanitized)) {
|
1256
|
+
cmd =
|
1257
|
+
'cat /sys/class/net/' + ifaceSanitized + '/operstate; ' +
|
1258
|
+
'cat /sys/class/net/' + ifaceSanitized + '/statistics/rx_bytes; ' +
|
1259
|
+
'cat /sys/class/net/' + ifaceSanitized + '/statistics/tx_bytes; ' +
|
1260
|
+
'cat /sys/class/net/' + ifaceSanitized + '/statistics/rx_dropped; ' +
|
1261
|
+
'cat /sys/class/net/' + ifaceSanitized + '/statistics/rx_errors; ' +
|
1262
|
+
'cat /sys/class/net/' + ifaceSanitized + '/statistics/tx_dropped; ' +
|
1263
|
+
'cat /sys/class/net/' + ifaceSanitized + '/statistics/tx_errors; ';
|
1264
|
+
exec(cmd, function (error, stdout) {
|
1265
|
+
if (!error) {
|
1266
|
+
lines = stdout.toString().split('\n');
|
1267
|
+
operstate = lines[0].trim();
|
1268
|
+
rx_bytes = parseInt(lines[1], 10);
|
1269
|
+
tx_bytes = parseInt(lines[2], 10);
|
1270
|
+
rx_dropped = parseInt(lines[3], 10);
|
1271
|
+
rx_errors = parseInt(lines[4], 10);
|
1272
|
+
tx_dropped = parseInt(lines[5], 10);
|
1273
|
+
tx_errors = parseInt(lines[6], 10);
|
1274
|
+
|
1275
|
+
result = calcNetworkSpeed(ifaceSanitized, rx_bytes, tx_bytes, operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
|
1276
|
+
|
1277
|
+
}
|
1278
|
+
resolve(result);
|
1279
|
+
});
|
1280
|
+
} else {
|
1281
|
+
resolve(result);
|
1282
|
+
}
|
1283
|
+
}
|
1284
|
+
if (_freebsd || _openbsd || _netbsd) {
|
1285
|
+
cmd = 'netstat -ibndI ' + ifaceSanitized; // lgtm [js/shell-command-constructed-from-input]
|
1286
|
+
exec(cmd, function (error, stdout) {
|
1287
|
+
if (!error) {
|
1288
|
+
lines = stdout.toString().split('\n');
|
1289
|
+
for (let i = 1; i < lines.length; i++) {
|
1290
|
+
const line = lines[i].replace(/ +/g, ' ').split(' ');
|
1291
|
+
if (line && line[0] && line[7] && line[10]) {
|
1292
|
+
rx_bytes = rx_bytes + parseInt(line[7]);
|
1293
|
+
if (line[6].trim() !== '-') { rx_dropped = rx_dropped + parseInt(line[6]); }
|
1294
|
+
if (line[5].trim() !== '-') { rx_errors = rx_errors + parseInt(line[5]); }
|
1295
|
+
tx_bytes = tx_bytes + parseInt(line[10]);
|
1296
|
+
if (line[12].trim() !== '-') { tx_dropped = tx_dropped + parseInt(line[12]); }
|
1297
|
+
if (line[9].trim() !== '-') { tx_errors = tx_errors + parseInt(line[9]); }
|
1298
|
+
operstate = 'up';
|
1299
|
+
}
|
1300
|
+
}
|
1301
|
+
result = calcNetworkSpeed(ifaceSanitized, rx_bytes, tx_bytes, operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
|
1302
|
+
}
|
1303
|
+
resolve(result);
|
1304
|
+
});
|
1305
|
+
}
|
1306
|
+
if (_darwin) {
|
1307
|
+
cmd = 'ifconfig ' + ifaceSanitized + ' | grep "status"'; // lgtm [js/shell-command-constructed-from-input]
|
1308
|
+
exec(cmd, function (error, stdout) {
|
1309
|
+
result.operstate = (stdout.toString().split(':')[1] || '').trim();
|
1310
|
+
result.operstate = (result.operstate || '').toLowerCase();
|
1311
|
+
result.operstate = (result.operstate === 'active' ? 'up' : (result.operstate === 'inactive' ? 'down' : 'unknown'));
|
1312
|
+
cmd = 'netstat -bdI ' + ifaceSanitized; // lgtm [js/shell-command-constructed-from-input]
|
1313
|
+
exec(cmd, function (error, stdout) {
|
1314
|
+
if (!error) {
|
1315
|
+
lines = stdout.toString().split('\n');
|
1316
|
+
// if there is less than 2 lines, no information for this interface was found
|
1317
|
+
if (lines.length > 1 && lines[1].trim() !== '') {
|
1318
|
+
// skip header line
|
1319
|
+
// use the second line because it is tied to the NIC instead of the ipv4 or ipv6 address
|
1320
|
+
stats = lines[1].replace(/ +/g, ' ').split(' ');
|
1321
|
+
const offset = stats.length > 11 ? 1 : 0;
|
1322
|
+
rx_bytes = parseInt(stats[offset + 5]);
|
1323
|
+
rx_dropped = parseInt(stats[offset + 10]);
|
1324
|
+
rx_errors = parseInt(stats[offset + 4]);
|
1325
|
+
tx_bytes = parseInt(stats[offset + 8]);
|
1326
|
+
tx_dropped = parseInt(stats[offset + 10]);
|
1327
|
+
tx_errors = parseInt(stats[offset + 7]);
|
1328
|
+
result = calcNetworkSpeed(ifaceSanitized, rx_bytes, tx_bytes, result.operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
|
1329
|
+
}
|
1330
|
+
}
|
1331
|
+
resolve(result);
|
1332
|
+
});
|
1333
|
+
});
|
1334
|
+
}
|
1335
|
+
if (_windows) {
|
1336
|
+
let perfData = [];
|
1337
|
+
let ifaceName = ifaceSanitized;
|
1338
|
+
|
1339
|
+
// Performance Data
|
1340
|
+
util.powerShell('Get-CimInstance Win32_PerfRawData_Tcpip_NetworkInterface | select Name,BytesReceivedPersec,PacketsReceivedErrors,PacketsReceivedDiscarded,BytesSentPersec,PacketsOutboundErrors,PacketsOutboundDiscarded | fl').then((stdout, error) => {
|
1341
|
+
if (!error) {
|
1342
|
+
const psections = stdout.toString().split(/\n\s*\n/);
|
1343
|
+
perfData = parseLinesWindowsPerfData(psections);
|
1344
|
+
}
|
1345
|
+
|
1346
|
+
// Network Interfaces
|
1347
|
+
networkInterfaces(false).then(interfaces => {
|
1348
|
+
// get bytes sent, received from perfData by name
|
1349
|
+
rx_bytes = 0;
|
1350
|
+
tx_bytes = 0;
|
1351
|
+
perfData.forEach(detail => {
|
1352
|
+
interfaces.forEach(det => {
|
1353
|
+
if ((det.iface.toLowerCase() === ifaceSanitized.toLowerCase() ||
|
1354
|
+
det.mac.toLowerCase() === ifaceSanitized.toLowerCase() ||
|
1355
|
+
det.ip4.toLowerCase() === ifaceSanitized.toLowerCase() ||
|
1356
|
+
det.ip6.toLowerCase() === ifaceSanitized.toLowerCase() ||
|
1357
|
+
det.ifaceName.replace(/[()[\] ]+/g, '').replace(/#|\//g, '_').toLowerCase() === ifaceSanitized.replace(/[()[\] ]+/g, '').replace('#', '_').toLowerCase()) &&
|
1358
|
+
(det.ifaceName.replace(/[()[\] ]+/g, '').replace(/#|\//g, '_').toLowerCase() === detail.name)) {
|
1359
|
+
ifaceName = det.iface;
|
1360
|
+
rx_bytes = detail.rx_bytes;
|
1361
|
+
rx_dropped = detail.rx_dropped;
|
1362
|
+
rx_errors = detail.rx_errors;
|
1363
|
+
tx_bytes = detail.tx_bytes;
|
1364
|
+
tx_dropped = detail.tx_dropped;
|
1365
|
+
tx_errors = detail.tx_errors;
|
1366
|
+
operstate = det.operstate;
|
1367
|
+
}
|
1368
|
+
});
|
1369
|
+
});
|
1370
|
+
if (rx_bytes && tx_bytes) {
|
1371
|
+
result = calcNetworkSpeed(ifaceName, parseInt(rx_bytes), parseInt(tx_bytes), operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
|
1372
|
+
}
|
1373
|
+
resolve(result);
|
1374
|
+
});
|
1375
|
+
});
|
1376
|
+
}
|
1377
|
+
} else {
|
1378
|
+
result.rx_bytes = _network[ifaceSanitized].rx_bytes;
|
1379
|
+
result.tx_bytes = _network[ifaceSanitized].tx_bytes;
|
1380
|
+
result.rx_sec = _network[ifaceSanitized].rx_sec;
|
1381
|
+
result.tx_sec = _network[ifaceSanitized].tx_sec;
|
1382
|
+
result.ms = _network[ifaceSanitized].last_ms;
|
1383
|
+
result.operstate = _network[ifaceSanitized].operstate;
|
1384
|
+
resolve(result);
|
1385
|
+
}
|
1386
|
+
});
|
1387
|
+
});
|
1388
|
+
}
|
1389
|
+
|
1390
|
+
exports.networkStats = networkStats;
|
1391
|
+
|
1392
|
+
// --------------------------
|
1393
|
+
// NET - connections (sockets)
|
1394
|
+
|
1395
|
+
function getProcessName(processes, pid) {
|
1396
|
+
let cmd = '';
|
1397
|
+
processes.forEach(line => {
|
1398
|
+
const parts = line.split(' ');
|
1399
|
+
const id = parseInt(parts[0], 10) || -1;
|
1400
|
+
if (id === pid) {
|
1401
|
+
parts.shift();
|
1402
|
+
cmd = parts.join(' ').split(':')[0];
|
1403
|
+
}
|
1404
|
+
});
|
1405
|
+
cmd = cmd.split(' -')[0];
|
1406
|
+
// return cmd;
|
1407
|
+
const cmdParts = cmd.split('/');
|
1408
|
+
return cmdParts[cmdParts.length - 1];
|
1409
|
+
}
|
1410
|
+
|
1411
|
+
function networkConnections(callback) {
|
1412
|
+
|
1413
|
+
return new Promise((resolve) => {
|
1414
|
+
process.nextTick(() => {
|
1415
|
+
let result = [];
|
1416
|
+
if (_linux || _freebsd || _openbsd || _netbsd) {
|
1417
|
+
let cmd = 'export LC_ALL=C; netstat -tunap | grep "ESTABLISHED\\|SYN_SENT\\|SYN_RECV\\|FIN_WAIT1\\|FIN_WAIT2\\|TIME_WAIT\\|CLOSE\\|CLOSE_WAIT\\|LAST_ACK\\|LISTEN\\|CLOSING\\|UNKNOWN"; unset LC_ALL';
|
1418
|
+
if (_freebsd || _openbsd || _netbsd) { cmd = 'export LC_ALL=C; netstat -na | grep "ESTABLISHED\\|SYN_SENT\\|SYN_RECV\\|FIN_WAIT1\\|FIN_WAIT2\\|TIME_WAIT\\|CLOSE\\|CLOSE_WAIT\\|LAST_ACK\\|LISTEN\\|CLOSING\\|UNKNOWN"; unset LC_ALL'; }
|
1419
|
+
exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
|
1420
|
+
let lines = stdout.toString().split('\n');
|
1421
|
+
if (!error && (lines.length > 1 || lines[0] != '')) {
|
1422
|
+
lines.forEach(function (line) {
|
1423
|
+
line = line.replace(/ +/g, ' ').split(' ');
|
1424
|
+
if (line.length >= 7) {
|
1425
|
+
let localip = line[3];
|
1426
|
+
let localport = '';
|
1427
|
+
let localaddress = line[3].split(':');
|
1428
|
+
if (localaddress.length > 1) {
|
1429
|
+
localport = localaddress[localaddress.length - 1];
|
1430
|
+
localaddress.pop();
|
1431
|
+
localip = localaddress.join(':');
|
1432
|
+
}
|
1433
|
+
let peerip = line[4];
|
1434
|
+
let peerport = '';
|
1435
|
+
let peeraddress = line[4].split(':');
|
1436
|
+
if (peeraddress.length > 1) {
|
1437
|
+
peerport = peeraddress[peeraddress.length - 1];
|
1438
|
+
peeraddress.pop();
|
1439
|
+
peerip = peeraddress.join(':');
|
1440
|
+
}
|
1441
|
+
let connstate = line[5];
|
1442
|
+
let proc = line[6].split('/');
|
1443
|
+
|
1444
|
+
if (connstate) {
|
1445
|
+
result.push({
|
1446
|
+
protocol: line[0],
|
1447
|
+
localAddress: localip,
|
1448
|
+
localPort: localport,
|
1449
|
+
peerAddress: peerip,
|
1450
|
+
peerPort: peerport,
|
1451
|
+
state: connstate,
|
1452
|
+
pid: proc[0] && proc[0] !== '-' ? parseInt(proc[0], 10) : null,
|
1453
|
+
process: proc[1] ? proc[1].split(' ')[0].split(':')[0] : ''
|
1454
|
+
});
|
1455
|
+
}
|
1456
|
+
}
|
1457
|
+
});
|
1458
|
+
if (callback) {
|
1459
|
+
callback(result);
|
1460
|
+
}
|
1461
|
+
resolve(result);
|
1462
|
+
} else {
|
1463
|
+
cmd = 'ss -tunap | grep "ESTAB\\|SYN-SENT\\|SYN-RECV\\|FIN-WAIT1\\|FIN-WAIT2\\|TIME-WAIT\\|CLOSE\\|CLOSE-WAIT\\|LAST-ACK\\|LISTEN\\|CLOSING"';
|
1464
|
+
exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
|
1465
|
+
|
1466
|
+
if (!error) {
|
1467
|
+
let lines = stdout.toString().split('\n');
|
1468
|
+
lines.forEach(function (line) {
|
1469
|
+
line = line.replace(/ +/g, ' ').split(' ');
|
1470
|
+
if (line.length >= 6) {
|
1471
|
+
let localip = line[4];
|
1472
|
+
let localport = '';
|
1473
|
+
let localaddress = line[4].split(':');
|
1474
|
+
if (localaddress.length > 1) {
|
1475
|
+
localport = localaddress[localaddress.length - 1];
|
1476
|
+
localaddress.pop();
|
1477
|
+
localip = localaddress.join(':');
|
1478
|
+
}
|
1479
|
+
let peerip = line[5];
|
1480
|
+
let peerport = '';
|
1481
|
+
let peeraddress = line[5].split(':');
|
1482
|
+
if (peeraddress.length > 1) {
|
1483
|
+
peerport = peeraddress[peeraddress.length - 1];
|
1484
|
+
peeraddress.pop();
|
1485
|
+
peerip = peeraddress.join(':');
|
1486
|
+
}
|
1487
|
+
let connstate = line[1];
|
1488
|
+
if (connstate === 'ESTAB') { connstate = 'ESTABLISHED'; }
|
1489
|
+
if (connstate === 'TIME-WAIT') { connstate = 'TIME_WAIT'; }
|
1490
|
+
let pid = null;
|
1491
|
+
let process = '';
|
1492
|
+
if (line.length >= 7 && line[6].indexOf('users:') > -1) {
|
1493
|
+
let proc = line[6].replace('users:(("', '').replace(/"/g, '').split(',');
|
1494
|
+
if (proc.length > 2) {
|
1495
|
+
process = proc[0].split(' ')[0].split(':')[0];
|
1496
|
+
pid = parseInt(proc[1], 10);
|
1497
|
+
}
|
1498
|
+
}
|
1499
|
+
if (connstate) {
|
1500
|
+
result.push({
|
1501
|
+
protocol: line[0],
|
1502
|
+
localAddress: localip,
|
1503
|
+
localPort: localport,
|
1504
|
+
peerAddress: peerip,
|
1505
|
+
peerPort: peerport,
|
1506
|
+
state: connstate,
|
1507
|
+
pid,
|
1508
|
+
process
|
1509
|
+
});
|
1510
|
+
}
|
1511
|
+
}
|
1512
|
+
});
|
1513
|
+
}
|
1514
|
+
if (callback) {
|
1515
|
+
callback(result);
|
1516
|
+
}
|
1517
|
+
resolve(result);
|
1518
|
+
});
|
1519
|
+
}
|
1520
|
+
});
|
1521
|
+
}
|
1522
|
+
if (_darwin) {
|
1523
|
+
// let cmd = 'netstat -natv | grep "ESTABLISHED\\|SYN_SENT\\|SYN_RECV\\|FIN_WAIT1\\|FIN_WAIT2\\|TIME_WAIT\\|CLOSE\\|CLOSE_WAIT\\|LAST_ACK\\|LISTEN\\|CLOSING\\|UNKNOWN"';
|
1524
|
+
let cmd = 'netstat -natv | grep "tcp4\\|tcp6\\|udp4\\|udp6"';
|
1525
|
+
const states = 'ESTABLISHED|SYN_SENT|SYN_RECV|FIN_WAIT1|FIN_WAIT2|TIME_WAIT|CLOSE|CLOSE_WAIT|LAST_ACK|LISTEN|CLOSING|UNKNOWN';
|
1526
|
+
exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
|
1527
|
+
if (!error) {
|
1528
|
+
exec('ps -axo pid,command', { maxBuffer: 1024 * 20000 }, function (err2, stdout2) {
|
1529
|
+
let processes = stdout2.toString().split('\n');
|
1530
|
+
processes = processes.map((line => { return line.trim().replace(/ +/g, ' '); }));
|
1531
|
+
let lines = stdout.toString().split('\n');
|
1532
|
+
|
1533
|
+
lines.forEach(function (line) {
|
1534
|
+
line = line.replace(/ +/g, ' ').split(' ');
|
1535
|
+
if (line.length >= 8) {
|
1536
|
+
let localip = line[3];
|
1537
|
+
let localport = '';
|
1538
|
+
let localaddress = line[3].split('.');
|
1539
|
+
if (localaddress.length > 1) {
|
1540
|
+
localport = localaddress[localaddress.length - 1];
|
1541
|
+
localaddress.pop();
|
1542
|
+
localip = localaddress.join('.');
|
1543
|
+
}
|
1544
|
+
let peerip = line[4];
|
1545
|
+
let peerport = '';
|
1546
|
+
let peeraddress = line[4].split('.');
|
1547
|
+
if (peeraddress.length > 1) {
|
1548
|
+
peerport = peeraddress[peeraddress.length - 1];
|
1549
|
+
peeraddress.pop();
|
1550
|
+
peerip = peeraddress.join('.');
|
1551
|
+
}
|
1552
|
+
const hasState = states.indexOf(line[5]) >= 0;
|
1553
|
+
let connstate = hasState ? line[5] : 'UNKNOWN';
|
1554
|
+
let pid = parseInt(line[8 + (hasState ? 0 : -1)], 10);
|
1555
|
+
if (connstate) {
|
1556
|
+
result.push({
|
1557
|
+
protocol: line[0],
|
1558
|
+
localAddress: localip,
|
1559
|
+
localPort: localport,
|
1560
|
+
peerAddress: peerip,
|
1561
|
+
peerPort: peerport,
|
1562
|
+
state: connstate,
|
1563
|
+
pid: pid,
|
1564
|
+
process: getProcessName(processes, pid)
|
1565
|
+
});
|
1566
|
+
}
|
1567
|
+
}
|
1568
|
+
});
|
1569
|
+
if (callback) {
|
1570
|
+
callback(result);
|
1571
|
+
}
|
1572
|
+
resolve(result);
|
1573
|
+
});
|
1574
|
+
|
1575
|
+
}
|
1576
|
+
});
|
1577
|
+
}
|
1578
|
+
if (_windows) {
|
1579
|
+
let cmd = 'netstat -nao';
|
1580
|
+
try {
|
1581
|
+
exec(cmd, util.execOptsWin, function (error, stdout) {
|
1582
|
+
if (!error) {
|
1583
|
+
|
1584
|
+
let lines = stdout.toString().split('\r\n');
|
1585
|
+
|
1586
|
+
lines.forEach(function (line) {
|
1587
|
+
line = line.trim().replace(/ +/g, ' ').split(' ');
|
1588
|
+
if (line.length >= 4) {
|
1589
|
+
let localip = line[1];
|
1590
|
+
let localport = '';
|
1591
|
+
let localaddress = line[1].split(':');
|
1592
|
+
if (localaddress.length > 1) {
|
1593
|
+
localport = localaddress[localaddress.length - 1];
|
1594
|
+
localaddress.pop();
|
1595
|
+
localip = localaddress.join(':');
|
1596
|
+
}
|
1597
|
+
localip = localip.replace(/\[/g, '').replace(/\]/g, '');
|
1598
|
+
let peerip = line[2];
|
1599
|
+
let peerport = '';
|
1600
|
+
let peeraddress = line[2].split(':');
|
1601
|
+
if (peeraddress.length > 1) {
|
1602
|
+
peerport = peeraddress[peeraddress.length - 1];
|
1603
|
+
peeraddress.pop();
|
1604
|
+
peerip = peeraddress.join(':');
|
1605
|
+
}
|
1606
|
+
peerip = peerip.replace(/\[/g, '').replace(/\]/g, '');
|
1607
|
+
let pid = util.toInt(line[4]);
|
1608
|
+
let connstate = line[3];
|
1609
|
+
if (connstate === 'HERGESTELLT') { connstate = 'ESTABLISHED'; }
|
1610
|
+
if (connstate.startsWith('ABH')) { connstate = 'LISTEN'; }
|
1611
|
+
if (connstate === 'SCHLIESSEN_WARTEN') { connstate = 'CLOSE_WAIT'; }
|
1612
|
+
if (connstate === 'WARTEND') { connstate = 'TIME_WAIT'; }
|
1613
|
+
if (connstate === 'SYN_GESENDET') { connstate = 'SYN_SENT'; }
|
1614
|
+
|
1615
|
+
if (connstate === 'LISTENING') { connstate = 'LISTEN'; }
|
1616
|
+
if (connstate === 'SYN_RECEIVED') { connstate = 'SYN_RECV'; }
|
1617
|
+
if (connstate === 'FIN_WAIT_1') { connstate = 'FIN_WAIT1'; }
|
1618
|
+
if (connstate === 'FIN_WAIT_2') { connstate = 'FIN_WAIT2'; }
|
1619
|
+
if (line[0].toLowerCase() !== 'udp' && connstate) {
|
1620
|
+
result.push({
|
1621
|
+
protocol: line[0].toLowerCase(),
|
1622
|
+
localAddress: localip,
|
1623
|
+
localPort: localport,
|
1624
|
+
peerAddress: peerip,
|
1625
|
+
peerPort: peerport,
|
1626
|
+
state: connstate,
|
1627
|
+
pid,
|
1628
|
+
process: ''
|
1629
|
+
});
|
1630
|
+
} else if (line[0].toLowerCase() === 'udp') {
|
1631
|
+
result.push({
|
1632
|
+
protocol: line[0].toLowerCase(),
|
1633
|
+
localAddress: localip,
|
1634
|
+
localPort: localport,
|
1635
|
+
peerAddress: peerip,
|
1636
|
+
peerPort: peerport,
|
1637
|
+
state: '',
|
1638
|
+
pid: parseInt(line[3], 10),
|
1639
|
+
process: ''
|
1640
|
+
});
|
1641
|
+
}
|
1642
|
+
}
|
1643
|
+
});
|
1644
|
+
if (callback) {
|
1645
|
+
callback(result);
|
1646
|
+
}
|
1647
|
+
resolve(result);
|
1648
|
+
}
|
1649
|
+
});
|
1650
|
+
} catch (e) {
|
1651
|
+
if (callback) { callback(result); }
|
1652
|
+
resolve(result);
|
1653
|
+
}
|
1654
|
+
}
|
1655
|
+
});
|
1656
|
+
});
|
1657
|
+
}
|
1658
|
+
|
1659
|
+
exports.networkConnections = networkConnections;
|
1660
|
+
|
1661
|
+
function networkGatewayDefault(callback) {
|
1662
|
+
|
1663
|
+
return new Promise((resolve) => {
|
1664
|
+
process.nextTick(() => {
|
1665
|
+
let result = '';
|
1666
|
+
if (_linux || _freebsd || _openbsd || _netbsd) {
|
1667
|
+
let cmd = 'ip route get 1';
|
1668
|
+
try {
|
1669
|
+
exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
|
1670
|
+
if (!error) {
|
1671
|
+
let lines = stdout.toString().split('\n');
|
1672
|
+
const line = lines && lines[0] ? lines[0] : '';
|
1673
|
+
let parts = line.split(' via ');
|
1674
|
+
if (parts && parts[1]) {
|
1675
|
+
parts = parts[1].split(' ');
|
1676
|
+
result = parts[0];
|
1677
|
+
}
|
1678
|
+
if (callback) {
|
1679
|
+
callback(result);
|
1680
|
+
}
|
1681
|
+
resolve(result);
|
1682
|
+
} else {
|
1683
|
+
if (callback) {
|
1684
|
+
callback(result);
|
1685
|
+
}
|
1686
|
+
resolve(result);
|
1687
|
+
}
|
1688
|
+
});
|
1689
|
+
} catch (e) {
|
1690
|
+
if (callback) { callback(result); }
|
1691
|
+
resolve(result);
|
1692
|
+
}
|
1693
|
+
}
|
1694
|
+
if (_darwin) {
|
1695
|
+
let cmd = 'route -n get default';
|
1696
|
+
try {
|
1697
|
+
exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
|
1698
|
+
if (!error) {
|
1699
|
+
const lines = stdout.toString().split('\n').map(line => line.trim());
|
1700
|
+
result = util.getValue(lines, 'gateway');
|
1701
|
+
}
|
1702
|
+
if (!result) {
|
1703
|
+
cmd = 'netstat -rn | awk \'/default/ {print $2}\'';
|
1704
|
+
exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
|
1705
|
+
const lines = stdout.toString().split('\n').map(line => line.trim());
|
1706
|
+
result = lines.find(line => (/^(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]?)$/.test(line)));
|
1707
|
+
if (callback) {
|
1708
|
+
callback(result);
|
1709
|
+
}
|
1710
|
+
resolve(result);
|
1711
|
+
});
|
1712
|
+
} else {
|
1713
|
+
if (callback) {
|
1714
|
+
callback(result);
|
1715
|
+
}
|
1716
|
+
resolve(result);
|
1717
|
+
}
|
1718
|
+
});
|
1719
|
+
} catch (e) {
|
1720
|
+
if (callback) { callback(result); }
|
1721
|
+
resolve(result);
|
1722
|
+
}
|
1723
|
+
}
|
1724
|
+
if (_windows) {
|
1725
|
+
try {
|
1726
|
+
exec('netstat -r', util.execOptsWin, function (error, stdout) {
|
1727
|
+
const lines = stdout.toString().split(os.EOL);
|
1728
|
+
lines.forEach(line => {
|
1729
|
+
line = line.replace(/\s+/g, ' ').trim();
|
1730
|
+
if (line.indexOf('0.0.0.0 0.0.0.0') > -1 && !(/[a-zA-Z]/.test(line))) {
|
1731
|
+
const parts = line.split(' ');
|
1732
|
+
if (parts.length >= 5 && (parts[parts.length - 3]).indexOf('.') > -1) {
|
1733
|
+
result = parts[parts.length - 3];
|
1734
|
+
}
|
1735
|
+
}
|
1736
|
+
});
|
1737
|
+
if (!result) {
|
1738
|
+
util.powerShell('Get-CimInstance -ClassName Win32_IP4RouteTable | Where-Object { $_.Destination -eq \'0.0.0.0\' -and $_.Mask -eq \'0.0.0.0\' }')
|
1739
|
+
.then((data) => {
|
1740
|
+
let lines = data.toString().split('\r\n');
|
1741
|
+
if (lines.length > 1 && !result) {
|
1742
|
+
result = util.getValue(lines, 'NextHop');
|
1743
|
+
if (callback) {
|
1744
|
+
callback(result);
|
1745
|
+
}
|
1746
|
+
resolve(result);
|
1747
|
+
// } else {
|
1748
|
+
// exec('ipconfig', util.execOptsWin, function (error, stdout) {
|
1749
|
+
// let lines = stdout.toString().split('\r\n');
|
1750
|
+
// lines.forEach(function (line) {
|
1751
|
+
// line = line.trim().replace(/\. /g, '');
|
1752
|
+
// line = line.trim().replace(/ +/g, '');
|
1753
|
+
// const parts = line.split(':');
|
1754
|
+
// if ((parts[0].toLowerCase().startsWith('standardgate') || parts[0].toLowerCase().indexOf('gateway') > -1 || parts[0].toLowerCase().indexOf('enlace') > -1) && parts[1]) {
|
1755
|
+
// result = parts[1];
|
1756
|
+
// }
|
1757
|
+
// });
|
1758
|
+
// if (callback) { callback(result); }
|
1759
|
+
// resolve(result);
|
1760
|
+
// });
|
1761
|
+
}
|
1762
|
+
});
|
1763
|
+
} else {
|
1764
|
+
if (callback) {
|
1765
|
+
callback(result);
|
1766
|
+
}
|
1767
|
+
resolve(result);
|
1768
|
+
}
|
1769
|
+
});
|
1770
|
+
} catch (e) {
|
1771
|
+
if (callback) { callback(result); }
|
1772
|
+
resolve(result);
|
1773
|
+
}
|
1774
|
+
}
|
1775
|
+
});
|
1776
|
+
});
|
1777
|
+
}
|
1778
|
+
|
1779
|
+
exports.networkGatewayDefault = networkGatewayDefault;
|