systeminformation 5.9.9 → 5.9.13

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