@depup/systeminformation 5.31.4-depup.0

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