UNPKG

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