UNPKG

56.5 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].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 getWindowsNics().forEach(nic => {
749 let found = false;
750 Object.keys(ifaces).forEach(key => {
751 if (!found) {
752 ifaces[key].forEach(value => {
753 if (Object.keys(value).indexOf('mac') >= 0) {
754 found = value['mac'] === nic.mac;
755 }
756 });
757 }
758 });
759
760 if (!found) {
761 ifaces[nic.name] = [{ mac: nic.mac }];
762 }
763 });
764
765 nics8021xInfo = getWindowsWiredProfilesInformation();
766 nics = getWindowsNics();
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 : null;
888 const virtual = internal ? false : testVirtualNic(dev, ifaceName, mac);
889 result.push({
890 iface: dev,
891 ifaceName,
892 ip4,
893 ip4subnet,
894 ip6,
895 ip6subnet,
896 mac,
897 internal,
898 virtual,
899 operstate,
900 type,
901 duplex,
902 mtu,
903 speed,
904 dhcp,
905 dnsSuffix,
906 ieee8021xAuth,
907 ieee8021xState,
908 carrierChanges,
909 });
910 }
911 }
912 _networkInterfaces = result;
913 if (callback) { callback(result); }
914 resolve(result);
915 }
916 }
917 });
918 });
919}
920
921exports.networkInterfaces = networkInterfaces;
922
923// --------------------------
924// NET - Speed
925
926function calcNetworkSpeed(iface, rx_bytes, tx_bytes, operstate, rx_dropped, rx_errors, tx_dropped, tx_errors) {
927 let result = {
928 iface,
929 operstate,
930 rx_bytes,
931 rx_dropped,
932 rx_errors,
933 tx_bytes,
934 tx_dropped,
935 tx_errors,
936 rx_sec: -1,
937 tx_sec: -1,
938 ms: 0
939 };
940
941 if (_network[iface] && _network[iface].ms) {
942 result.ms = Date.now() - _network[iface].ms;
943 result.rx_sec = (rx_bytes - _network[iface].rx_bytes) >= 0 ? (rx_bytes - _network[iface].rx_bytes) / (result.ms / 1000) : 0;
944 result.tx_sec = (tx_bytes - _network[iface].tx_bytes) >= 0 ? (tx_bytes - _network[iface].tx_bytes) / (result.ms / 1000) : 0;
945 _network[iface].rx_bytes = rx_bytes;
946 _network[iface].tx_bytes = tx_bytes;
947 _network[iface].rx_sec = result.rx_sec;
948 _network[iface].tx_sec = result.tx_sec;
949 _network[iface].ms = Date.now();
950 _network[iface].last_ms = result.ms;
951 _network[iface].operstate = operstate;
952 } else {
953 if (!_network[iface]) _network[iface] = {};
954 _network[iface].rx_bytes = rx_bytes;
955 _network[iface].tx_bytes = tx_bytes;
956 _network[iface].rx_sec = -1;
957 _network[iface].tx_sec = -1;
958 _network[iface].ms = Date.now();
959 _network[iface].last_ms = 0;
960 _network[iface].operstate = operstate;
961 }
962 return result;
963}
964
965function networkStats(ifaces, callback) {
966
967 let ifacesArray = [];
968 // fallback - if only callback is given
969 if (util.isFunction(ifaces) && !callback) {
970 callback = ifaces;
971 ifacesArray = [getDefaultNetworkInterface()];
972 } else {
973 ifaces = ifaces || getDefaultNetworkInterface();
974 ifaces = ifaces.trim().toLowerCase().replace(/,+/g, '|');
975 ifacesArray = ifaces.split('|');
976 }
977
978 return new Promise((resolve) => {
979 process.nextTick(() => {
980
981 const result = [];
982
983 const workload = [];
984 if (ifacesArray.length && ifacesArray[0].trim() === '*') {
985 ifacesArray = [];
986 networkInterfaces(false).then(allIFaces => {
987 for (let iface of allIFaces) {
988 ifacesArray.push(iface.iface);
989 }
990 networkStats(ifacesArray.join(',')).then(result => {
991 if (callback) { callback(result); }
992 resolve(result);
993 });
994 });
995 } else {
996 for (let iface of ifacesArray) {
997 workload.push(networkStatsSingle(iface.trim()));
998 }
999 if (workload.length) {
1000 Promise.all(
1001 workload
1002 ).then(data => {
1003 if (callback) { callback(data); }
1004 resolve(data);
1005 });
1006 } else {
1007 if (callback) { callback(result); }
1008 resolve(result);
1009 }
1010 }
1011 });
1012 });
1013}
1014
1015function networkStatsSingle(iface) {
1016
1017 function parseLinesWindowsPerfData(sections) {
1018 let perfData = [];
1019 for (let i in sections) {
1020 if ({}.hasOwnProperty.call(sections, i)) {
1021 if (sections[i].trim() !== '') {
1022 let lines = sections[i].trim().split('\r\n');
1023 perfData.push({
1024 name: util.getValue(lines, 'Name', '=').replace(/[()\[\] ]+/g, '').replace('#', '_').toLowerCase(),
1025 rx_bytes: parseInt(util.getValue(lines, 'BytesReceivedPersec', '='), 10),
1026 rx_errors: parseInt(util.getValue(lines, 'PacketsReceivedErrors', '='), 10),
1027 rx_dropped: parseInt(util.getValue(lines, 'PacketsReceivedDiscarded', '='), 10),
1028 tx_bytes: parseInt(util.getValue(lines, 'BytesSentPersec', '='), 10),
1029 tx_errors: parseInt(util.getValue(lines, 'PacketsOutboundErrors', '='), 10),
1030 tx_dropped: parseInt(util.getValue(lines, 'PacketsOutboundDiscarded', '='), 10)
1031 });
1032 }
1033 }
1034 }
1035 return perfData;
1036 }
1037
1038 return new Promise((resolve) => {
1039 process.nextTick(() => {
1040
1041 const ifaceSanitized = util.sanitizeShellString(iface);
1042
1043 let result = {
1044 iface: ifaceSanitized,
1045 operstate: 'unknown',
1046 rx_bytes: 0,
1047 rx_dropped: 0,
1048 rx_errors: 0,
1049 tx_bytes: 0,
1050 tx_dropped: 0,
1051 tx_errors: 0,
1052 rx_sec: -1,
1053 tx_sec: -1,
1054 ms: 0
1055 };
1056
1057 let operstate = 'unknown';
1058 let rx_bytes = 0;
1059 let tx_bytes = 0;
1060 let rx_dropped = 0;
1061 let rx_errors = 0;
1062 let tx_dropped = 0;
1063 let tx_errors = 0;
1064
1065 let cmd, lines, stats;
1066 if (!_network[ifaceSanitized] || (_network[ifaceSanitized] && !_network[ifaceSanitized].ms) || (_network[ifaceSanitized] && _network[ifaceSanitized].ms && Date.now() - _network[ifaceSanitized].ms >= 500)) {
1067 if (_linux) {
1068 if (fs.existsSync('/sys/class/net/' + ifaceSanitized)) {
1069 cmd =
1070 'cat /sys/class/net/' + ifaceSanitized + '/operstate; ' +
1071 'cat /sys/class/net/' + ifaceSanitized + '/statistics/rx_bytes; ' +
1072 'cat /sys/class/net/' + ifaceSanitized + '/statistics/tx_bytes; ' +
1073 'cat /sys/class/net/' + ifaceSanitized + '/statistics/rx_dropped; ' +
1074 'cat /sys/class/net/' + ifaceSanitized + '/statistics/rx_errors; ' +
1075 'cat /sys/class/net/' + ifaceSanitized + '/statistics/tx_dropped; ' +
1076 'cat /sys/class/net/' + ifaceSanitized + '/statistics/tx_errors; ';
1077 exec(cmd, function (error, stdout) {
1078 if (!error) {
1079 lines = stdout.toString().split('\n');
1080 operstate = lines[0].trim();
1081 rx_bytes = parseInt(lines[1], 10);
1082 tx_bytes = parseInt(lines[2], 10);
1083 rx_dropped = parseInt(lines[3], 10);
1084 rx_errors = parseInt(lines[4], 10);
1085 tx_dropped = parseInt(lines[5], 10);
1086 tx_errors = parseInt(lines[6], 10);
1087
1088 result = calcNetworkSpeed(ifaceSanitized, rx_bytes, tx_bytes, operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
1089
1090 }
1091 resolve(result);
1092 });
1093 } else {
1094 resolve(result);
1095 }
1096 }
1097 if (_freebsd || _openbsd || _netbsd) {
1098 cmd = 'netstat -ibndI ' + ifaceSanitized;
1099 exec(cmd, function (error, stdout) {
1100 if (!error) {
1101 lines = stdout.toString().split('\n');
1102 for (let i = 1; i < lines.length; i++) {
1103 const line = lines[i].replace(/ +/g, ' ').split(' ');
1104 if (line && line[0] && line[7] && line[10]) {
1105 rx_bytes = rx_bytes + parseInt(line[7]);
1106 if (line[6].trim() !== '-') { rx_dropped = rx_dropped + parseInt(line[6]); }
1107 if (line[5].trim() !== '-') { rx_errors = rx_errors + parseInt(line[5]); }
1108 tx_bytes = tx_bytes + parseInt(line[10]);
1109 if (line[12].trim() !== '-') { tx_dropped = tx_dropped + parseInt(line[12]); }
1110 if (line[9].trim() !== '-') { tx_errors = tx_errors + parseInt(line[9]); }
1111 operstate = 'up';
1112 }
1113 }
1114 result = calcNetworkSpeed(ifaceSanitized, rx_bytes, tx_bytes, operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
1115 }
1116 resolve(result);
1117 });
1118 }
1119 if (_darwin) {
1120 cmd = 'ifconfig ' + ifaceSanitized + ' | grep "status"';
1121 exec(cmd, function (error, stdout) {
1122 result.operstate = (stdout.toString().split(':')[1] || '').trim();
1123 result.operstate = (result.operstate || '').toLowerCase();
1124 result.operstate = (result.operstate === 'active' ? 'up' : (result.operstate === 'inactive' ? 'down' : 'unknown'));
1125 cmd = 'netstat -bdI ' + ifaceSanitized;
1126 exec(cmd, function (error, stdout) {
1127 if (!error) {
1128 lines = stdout.toString().split('\n');
1129 // if there is less than 2 lines, no information for this interface was found
1130 if (lines.length > 1 && lines[1].trim() !== '') {
1131 // skip header line
1132 // use the second line because it is tied to the NIC instead of the ipv4 or ipv6 address
1133 stats = lines[1].replace(/ +/g, ' ').split(' ');
1134 rx_bytes = parseInt(stats[6]);
1135 rx_dropped = parseInt(stats[11]);
1136 rx_errors = parseInt(stats[5]);
1137 tx_bytes = parseInt(stats[9]);
1138 tx_dropped = parseInt(stats[11]);
1139 tx_errors = parseInt(stats[8]);
1140
1141 result = calcNetworkSpeed(ifaceSanitized, rx_bytes, tx_bytes, result.operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
1142 }
1143 }
1144 resolve(result);
1145 });
1146 });
1147 }
1148 if (_windows) {
1149 let perfData = [];
1150 let ifaceName = ifaceSanitized;
1151
1152 // Performance Data
1153 util.wmic('path Win32_PerfRawData_Tcpip_NetworkInterface Get name,BytesReceivedPersec,BytesSentPersec,BytesTotalPersec,PacketsOutboundDiscarded,PacketsOutboundErrors,PacketsReceivedDiscarded,PacketsReceivedErrors /value').then((stdout, error) => {
1154 if (!error) {
1155 const psections = stdout.toString().split(/\n\s*\n/);
1156 perfData = parseLinesWindowsPerfData(psections);
1157 }
1158
1159 // Network Interfaces
1160 networkInterfaces(false).then(interfaces => {
1161 // get bytes sent, received from perfData by name
1162 rx_bytes = 0;
1163 tx_bytes = 0;
1164 perfData.forEach(detail => {
1165 interfaces.forEach(det => {
1166 if ((det.iface.toLowerCase() === ifaceSanitized.toLowerCase() ||
1167 det.mac.toLowerCase() === ifaceSanitized.toLowerCase() ||
1168 det.ip4.toLowerCase() === ifaceSanitized.toLowerCase() ||
1169 det.ip6.toLowerCase() === ifaceSanitized.toLowerCase() ||
1170 det.ifaceName.replace(/[()\[\] ]+/g, '').replace('#', '_').toLowerCase() === ifaceSanitized.replace(/[()\[\] ]+/g, '').replace('#', '_').toLowerCase()) &&
1171 (det.ifaceName.replace(/[()\[\] ]+/g, '').replace('#', '_').toLowerCase() === detail.name)) {
1172 ifaceName = det.iface;
1173 rx_bytes = detail.rx_bytes;
1174 rx_dropped = detail.rx_dropped;
1175 rx_errors = detail.rx_errors;
1176 tx_bytes = detail.tx_bytes;
1177 tx_dropped = detail.tx_dropped;
1178 tx_errors = detail.tx_errors;
1179 operstate = det.operstate;
1180 }
1181 });
1182 });
1183 if (rx_bytes && tx_bytes) {
1184 result = calcNetworkSpeed(ifaceName, parseInt(rx_bytes), parseInt(tx_bytes), operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
1185 }
1186 resolve(result);
1187 });
1188 });
1189 }
1190 } else {
1191 result.rx_bytes = _network[ifaceSanitized].rx_bytes;
1192 result.tx_bytes = _network[ifaceSanitized].tx_bytes;
1193 result.rx_sec = _network[ifaceSanitized].rx_sec;
1194 result.tx_sec = _network[ifaceSanitized].tx_sec;
1195 result.ms = _network[ifaceSanitized].last_ms;
1196 result.operstate = _network[ifaceSanitized].operstate;
1197 resolve(result);
1198 }
1199 });
1200 });
1201}
1202
1203exports.networkStats = networkStats;
1204
1205// --------------------------
1206// NET - connections (sockets)
1207
1208function networkConnections(callback) {
1209
1210 return new Promise((resolve) => {
1211 process.nextTick(() => {
1212 let result = [];
1213 if (_linux || _freebsd || _openbsd || _netbsd) {
1214 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';
1215 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';
1216 exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
1217 let lines = stdout.toString().split('\n');
1218 if (!error && (lines.length > 1 || lines[0] != '')) {
1219 lines.forEach(function (line) {
1220 line = line.replace(/ +/g, ' ').split(' ');
1221 if (line.length >= 7) {
1222 let localip = line[3];
1223 let localport = '';
1224 let localaddress = line[3].split(':');
1225 if (localaddress.length > 1) {
1226 localport = localaddress[localaddress.length - 1];
1227 localaddress.pop();
1228 localip = localaddress.join(':');
1229 }
1230 let peerip = line[4];
1231 let peerport = '';
1232 let peeraddress = line[4].split(':');
1233 if (peeraddress.length > 1) {
1234 peerport = peeraddress[peeraddress.length - 1];
1235 peeraddress.pop();
1236 peerip = peeraddress.join(':');
1237 }
1238 let connstate = line[5];
1239 // if (connstate === 'VERBUNDEN') connstate = 'ESTABLISHED';
1240 let proc = line[6].split('/');
1241
1242 if (connstate) {
1243 result.push({
1244 protocol: line[0],
1245 localaddress: localip,
1246 localport: localport,
1247 peeraddress: peerip,
1248 peerport: peerport,
1249 state: connstate,
1250 pid: proc[0] && proc[0] !== '-' ? parseInt(proc[0], 10) : -1,
1251 process: proc[1] ? proc[1].split(' ')[0] : ''
1252 });
1253 }
1254 }
1255 });
1256 if (callback) {
1257 callback(result);
1258 }
1259 resolve(result);
1260 } else {
1261 cmd = 'ss -tunap | grep "ESTAB\\|SYN-SENT\\|SYN-RECV\\|FIN-WAIT1\\|FIN-WAIT2\\|TIME-WAIT\\|CLOSE\\|CLOSE-WAIT\\|LAST-ACK\\|LISTEN\\|CLOSING"';
1262 exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
1263
1264 if (!error) {
1265 let lines = stdout.toString().split('\n');
1266 lines.forEach(function (line) {
1267 line = line.replace(/ +/g, ' ').split(' ');
1268 if (line.length >= 6) {
1269 let localip = line[4];
1270 let localport = '';
1271 let localaddress = line[4].split(':');
1272 if (localaddress.length > 1) {
1273 localport = localaddress[localaddress.length - 1];
1274 localaddress.pop();
1275 localip = localaddress.join(':');
1276 }
1277 let peerip = line[5];
1278 let peerport = '';
1279 let peeraddress = line[5].split(':');
1280 if (peeraddress.length > 1) {
1281 peerport = peeraddress[peeraddress.length - 1];
1282 peeraddress.pop();
1283 peerip = peeraddress.join(':');
1284 }
1285 let connstate = line[1];
1286 if (connstate === 'ESTAB') connstate = 'ESTABLISHED';
1287 if (connstate === 'TIME-WAIT') connstate = 'TIME_WAIT';
1288 let pid = -1;
1289 let process = '';
1290 if (line.length >= 7 && line[6].indexOf('users:') > -1) {
1291 let proc = line[6].replace('users:(("', '').replace(/"/g, '').split(',');
1292 if (proc.length > 2) {
1293 process = proc[0].split(' ')[0];
1294 pid = parseInt(proc[1], 10);
1295 }
1296 }
1297 if (connstate) {
1298 result.push({
1299 protocol: line[0],
1300 localaddress: localip,
1301 localport: localport,
1302 peeraddress: peerip,
1303 peerport: peerport,
1304 state: connstate,
1305 pid,
1306 process
1307 });
1308 }
1309 }
1310 });
1311 }
1312 if (callback) {
1313 callback(result);
1314 }
1315 resolve(result);
1316 });
1317 }
1318 });
1319 }
1320 if (_darwin) {
1321 let cmd = 'netstat -natv | grep "ESTABLISHED\\|SYN_SENT\\|SYN_RECV\\|FIN_WAIT1\\|FIN_WAIT2\\|TIME_WAIT\\|CLOSE\\|CLOSE_WAIT\\|LAST_ACK\\|LISTEN\\|CLOSING\\|UNKNOWN"';
1322 exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
1323 if (!error) {
1324
1325 let lines = stdout.toString().split('\n');
1326
1327 lines.forEach(function (line) {
1328 line = line.replace(/ +/g, ' ').split(' ');
1329 if (line.length >= 8) {
1330 let localip = line[3];
1331 let localport = '';
1332 let localaddress = line[3].split('.');
1333 if (localaddress.length > 1) {
1334 localport = localaddress[localaddress.length - 1];
1335 localaddress.pop();
1336 localip = localaddress.join('.');
1337 }
1338 let peerip = line[4];
1339 let peerport = '';
1340 let peeraddress = line[4].split('.');
1341 if (peeraddress.length > 1) {
1342 peerport = peeraddress[peeraddress.length - 1];
1343 peeraddress.pop();
1344 peerip = peeraddress.join('.');
1345 }
1346 let connstate = line[5];
1347 let pid = parseInt(line[8], 10);
1348 if (connstate) {
1349 result.push({
1350 protocol: line[0],
1351 localaddress: localip,
1352 localport: localport,
1353 peeraddress: peerip,
1354 peerport: peerport,
1355 state: connstate,
1356 pid: pid,
1357 process: ''
1358 });
1359 }
1360 }
1361 });
1362 if (callback) {
1363 callback(result);
1364 }
1365 resolve(result);
1366 }
1367 });
1368 }
1369 if (_windows) {
1370 let cmd = 'netstat -nao';
1371 try {
1372 exec(cmd, util.execOptsWin, function (error, stdout) {
1373 if (!error) {
1374
1375 let lines = stdout.toString().split('\r\n');
1376
1377 lines.forEach(function (line) {
1378 line = line.trim().replace(/ +/g, ' ').split(' ');
1379 if (line.length >= 4) {
1380 let localip = line[1];
1381 let localport = '';
1382 let localaddress = line[1].split(':');
1383 if (localaddress.length > 1) {
1384 localport = localaddress[localaddress.length - 1];
1385 localaddress.pop();
1386 localip = localaddress.join(':');
1387 }
1388 let peerip = line[2];
1389 let peerport = '';
1390 let peeraddress = line[2].split(':');
1391 if (peeraddress.length > 1) {
1392 peerport = peeraddress[peeraddress.length - 1];
1393 peeraddress.pop();
1394 peerip = peeraddress.join(':');
1395 }
1396 let pid = line[4];
1397 let connstate = line[3];
1398 if (connstate === 'HERGESTELLT') connstate = 'ESTABLISHED';
1399 if (connstate.startsWith('ABH')) connstate = 'LISTEN';
1400 if (connstate === 'SCHLIESSEN_WARTEN') connstate = 'CLOSE_WAIT';
1401 if (connstate === 'WARTEND') connstate = 'TIME_WAIT';
1402 if (connstate === 'SYN_GESENDET') connstate = 'SYN_SENT';
1403
1404 if (connstate === 'LISTENING') connstate = 'LISTEN';
1405 if (connstate === 'SYN_RECEIVED') connstate = 'SYN_RECV';
1406 if (connstate === 'FIN_WAIT_1') connstate = 'FIN_WAIT1';
1407 if (connstate === 'FIN_WAIT_2') connstate = 'FIN_WAIT2';
1408 if (connstate) {
1409 result.push({
1410 protocol: line[0].toLowerCase(),
1411 localaddress: localip,
1412 localport: localport,
1413 peeraddress: peerip,
1414 peerport: peerport,
1415 state: connstate,
1416 pid,
1417 process: ''
1418 });
1419 }
1420 }
1421 });
1422 if (callback) {
1423 callback(result);
1424 }
1425 resolve(result);
1426 }
1427 });
1428 } catch (e) {
1429 if (callback) { callback(result); }
1430 resolve(result);
1431 }
1432 }
1433 });
1434 });
1435}
1436
1437exports.networkConnections = networkConnections;
1438
1439function networkGatewayDefault(callback) {
1440
1441 return new Promise((resolve) => {
1442 process.nextTick(() => {
1443 let result = '';
1444 if (_linux || _freebsd || _openbsd || _netbsd) {
1445 let cmd = 'ip route get 1';
1446 try {
1447 exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
1448 if (!error) {
1449 let lines = stdout.toString().split('\n');
1450 const line = lines && lines[0] ? lines[0] : '';
1451 let parts = line.split(' via ');
1452 if (parts && parts[1]) {
1453 parts = parts[1].split(' ');
1454 result = parts[0];
1455 }
1456 if (callback) {
1457 callback(result);
1458 }
1459 resolve(result);
1460 } else {
1461 if (callback) {
1462 callback(result);
1463 }
1464 resolve(result);
1465 }
1466 });
1467 } catch (e) {
1468 if (callback) { callback(result); }
1469 resolve(result);
1470 }
1471 }
1472 if (_darwin) {
1473 let cmd = 'route -n get default';
1474 try {
1475 exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
1476 if (!error) {
1477 let lines = stdout.toString().split('\n').map(line => line.trim());
1478 result = util.getValue(lines, 'gateway');
1479 if (callback) {
1480 callback(result);
1481 }
1482 resolve(result);
1483 } else {
1484 if (callback) {
1485 callback(result);
1486 }
1487 resolve(result);
1488 }
1489 });
1490 } catch (e) {
1491 if (callback) { callback(result); }
1492 resolve(result);
1493 }
1494 }
1495 if (_windows) {
1496 try {
1497 exec('netstat -r', util.execOptsWin, function (error, stdout) {
1498 const lines = stdout.toString().split(os.EOL);
1499 lines.forEach(line => {
1500 line = line.replace(/\s+/g, ' ').trim();
1501 if (line.indexOf('0.0.0.0 0.0.0.0') > -1 && !(/[a-zA-Z]/.test(line))) {
1502 const parts = line.split(' ');
1503 if (parts.length >= 5 && (parts[parts.length - 3]).indexOf('.') > -1) {
1504 result = parts[parts.length - 3];
1505 }
1506 }
1507 });
1508 if (!result) {
1509 util.powerShell('Get-CimInstance -ClassName Win32_IP4RouteTable | Where-Object { $_.Destination -eq \'0.0.0.0\' -and $_.Mask -eq \'0.0.0.0\' }')
1510 .then(data => {
1511 let lines = data.toString().split('\r\n');
1512 if (lines.length > 1 && !result) {
1513 result = util.getValue(lines, 'NextHop');
1514 if (callback) {
1515 callback(result);
1516 }
1517 resolve(result);
1518 // } else {
1519 // exec('ipconfig', util.execOptsWin, function (error, stdout) {
1520 // let lines = stdout.toString().split('\r\n');
1521 // lines.forEach(function (line) {
1522 // line = line.trim().replace(/\. /g, '');
1523 // line = line.trim().replace(/ +/g, '');
1524 // const parts = line.split(':');
1525 // if ((parts[0].toLowerCase().startsWith('standardgate') || parts[0].toLowerCase().indexOf('gateway') > -1 || parts[0].toLowerCase().indexOf('enlace') > -1) && parts[1]) {
1526 // result = parts[1];
1527 // }
1528 // });
1529 // if (callback) { callback(result); }
1530 // resolve(result);
1531 // });
1532 }
1533 });
1534 } else {
1535 if (callback) {
1536 callback(result);
1537 }
1538 resolve(result);
1539 }
1540 });
1541 } catch (e) {
1542 if (callback) { callback(result); }
1543 resolve(result);
1544 }
1545 }
1546 });
1547 });
1548}
1549
1550exports.networkGatewayDefault = networkGatewayDefault;