PageRenderTime 2134ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 1ms

/node_modules/systeminformation/lib/network.js

https://gitlab.com/varunsonavne/node-hello
JavaScript | 1376 lines | 1226 code | 108 blank | 42 comment | 305 complexity | c848df3715485eda05fa947b9fc90bea MD5 | raw file
  1. 'use strict';
  2. // @ts-check
  3. // ==================================================================================
  4. // network.js
  5. // ----------------------------------------------------------------------------------
  6. // Description: System Information - library
  7. // for Node.js
  8. // Copyright: (c) 2014 - 2022
  9. // Author: Sebastian Hildebrandt
  10. // ----------------------------------------------------------------------------------
  11. // License: MIT
  12. // ==================================================================================
  13. // 9. Network
  14. // ----------------------------------------------------------------------------------
  15. const os = require('os');
  16. const exec = require('child_process').exec;
  17. const execSync = require('child_process').execSync;
  18. const fs = require('fs');
  19. const util = require('./util');
  20. let _platform = process.platform;
  21. const _linux = (_platform === 'linux' || _platform === 'android');
  22. const _darwin = (_platform === 'darwin');
  23. const _windows = (_platform === 'win32');
  24. const _freebsd = (_platform === 'freebsd');
  25. const _openbsd = (_platform === 'openbsd');
  26. const _netbsd = (_platform === 'netbsd');
  27. const _sunos = (_platform === 'sunos');
  28. let _network = {};
  29. let _default_iface = '';
  30. let _ifaces = {};
  31. let _dhcpNics = [];
  32. let _networkInterfaces = [];
  33. let _mac = {};
  34. let pathToIp;
  35. function getDefaultNetworkInterface() {
  36. let ifacename = '';
  37. let ifacenameFirst = '';
  38. try {
  39. let ifaces = os.networkInterfaces();
  40. let scopeid = 9999;
  41. // fallback - "first" external interface (sorted by scopeid)
  42. for (let dev in ifaces) {
  43. if ({}.hasOwnProperty.call(ifaces, dev)) {
  44. ifaces[dev].forEach(function (details) {
  45. if (details && details.internal === false) {
  46. ifacenameFirst = ifacenameFirst || dev; // fallback if no scopeid
  47. if (details.scopeid && details.scopeid < scopeid) {
  48. ifacename = dev;
  49. scopeid = details.scopeid;
  50. }
  51. }
  52. });
  53. }
  54. }
  55. ifacename = ifacename || ifacenameFirst || '';
  56. if (_windows) {
  57. // https://www.inetdaemon.com/tutorials/internet/ip/routing/default_route.shtml
  58. let defaultIp = '';
  59. const cmd = 'netstat -r';
  60. const result = execSync(cmd, util.execOptsWin);
  61. const lines = result.toString().split(os.EOL);
  62. lines.forEach(line => {
  63. line = line.replace(/\s+/g, ' ').trim();
  64. if (line.indexOf('0.0.0.0 0.0.0.0') > -1 && !(/[a-zA-Z]/.test(line))) {
  65. const parts = line.split(' ');
  66. if (parts.length >= 5) {
  67. defaultIp = parts[parts.length - 2];
  68. }
  69. }
  70. });
  71. if (defaultIp) {
  72. for (let dev in ifaces) {
  73. if ({}.hasOwnProperty.call(ifaces, dev)) {
  74. ifaces[dev].forEach(function (details) {
  75. if (details && details.address && details.address === defaultIp) {
  76. ifacename = dev;
  77. }
  78. });
  79. }
  80. }
  81. }
  82. }
  83. if (_linux) {
  84. let cmd = 'ip route 2> /dev/null | grep default';
  85. let result = execSync(cmd);
  86. let parts = result.toString().split('\n')[0].split(/\s+/);
  87. if (parts[0] === 'none' && parts[5]) {
  88. ifacename = parts[5];
  89. } else if (parts[4]) {
  90. ifacename = parts[4];
  91. }
  92. if (ifacename.indexOf(':') > -1) {
  93. ifacename = ifacename.split(':')[1].trim();
  94. }
  95. }
  96. if (_darwin || _freebsd || _openbsd || _netbsd || _sunos) {
  97. let cmd = '';
  98. if (_linux) { cmd = 'ip route 2> /dev/null | grep default | awk \'{print $5}\''; }
  99. if (_darwin) { cmd = 'route -n get default 2>/dev/null | grep interface: | awk \'{print $2}\''; }
  100. if (_freebsd || _openbsd || _netbsd || _sunos) { cmd = 'route get 0.0.0.0 | grep interface:'; }
  101. let result = execSync(cmd);
  102. ifacename = result.toString().split('\n')[0];
  103. if (ifacename.indexOf(':') > -1) {
  104. ifacename = ifacename.split(':')[1].trim();
  105. }
  106. }
  107. } catch (e) {
  108. util.noop();
  109. }
  110. if (ifacename) { _default_iface = ifacename; }
  111. return _default_iface;
  112. }
  113. exports.getDefaultNetworkInterface = getDefaultNetworkInterface;
  114. function getMacAddresses() {
  115. let iface = '';
  116. let mac = '';
  117. let result = {};
  118. if (_linux || _freebsd || _openbsd || _netbsd) {
  119. if (typeof pathToIp === 'undefined') {
  120. try {
  121. const lines = execSync('which ip').toString().split('\n');
  122. if (lines.length && lines[0].indexOf(':') === -1 && lines[0].indexOf('/') === 0) {
  123. pathToIp = lines[0];
  124. } else {
  125. pathToIp = '';
  126. }
  127. } catch (e) {
  128. pathToIp = '';
  129. }
  130. }
  131. try {
  132. const cmd = 'export LC_ALL=C; ' + ((pathToIp) ? pathToIp + ' link show up' : '/sbin/ifconfig') + '; unset LC_ALL';
  133. let res = execSync(cmd);
  134. const lines = res.toString().split('\n');
  135. for (let i = 0; i < lines.length; i++) {
  136. if (lines[i] && lines[i][0] !== ' ') {
  137. if (pathToIp) {
  138. let nextline = lines[i + 1].trim().split(' ');
  139. if (nextline[0] === 'link/ether') {
  140. iface = lines[i].split(' ')[1];
  141. iface = iface.slice(0, iface.length - 1);
  142. mac = nextline[1];
  143. }
  144. } else {
  145. iface = lines[i].split(' ')[0];
  146. mac = lines[i].split('HWaddr ')[1];
  147. }
  148. if (iface && mac) {
  149. result[iface] = mac.trim();
  150. iface = '';
  151. mac = '';
  152. }
  153. }
  154. }
  155. } catch (e) {
  156. util.noop();
  157. }
  158. }
  159. if (_darwin) {
  160. try {
  161. const cmd = '/sbin/ifconfig';
  162. let res = execSync(cmd);
  163. const lines = res.toString().split('\n');
  164. for (let i = 0; i < lines.length; i++) {
  165. if (lines[i] && lines[i][0] !== '\t' && lines[i].indexOf(':') > 0) {
  166. iface = lines[i].split(':')[0];
  167. } else if (lines[i].indexOf('\tether ') === 0) {
  168. mac = lines[i].split('\tether ')[1];
  169. if (iface && mac) {
  170. result[iface] = mac.trim();
  171. iface = '';
  172. mac = '';
  173. }
  174. }
  175. }
  176. } catch (e) {
  177. util.noop();
  178. }
  179. }
  180. return result;
  181. }
  182. function networkInterfaceDefault(callback) {
  183. return new Promise((resolve) => {
  184. process.nextTick(() => {
  185. let result = getDefaultNetworkInterface();
  186. if (callback) { callback(result); }
  187. resolve(result);
  188. });
  189. });
  190. }
  191. exports.networkInterfaceDefault = networkInterfaceDefault;
  192. // --------------------------
  193. // NET - interfaces
  194. function parseLinesWindowsNics(sections, nconfigsections) {
  195. let nics = [];
  196. for (let i in sections) {
  197. if ({}.hasOwnProperty.call(sections, i)) {
  198. if (sections[i].trim() !== '') {
  199. let lines = sections[i].trim().split('\r\n');
  200. let linesNicConfig = nconfigsections[i].trim().split('\r\n');
  201. let netEnabled = util.getValue(lines, 'NetEnabled', ':');
  202. let adapterType = util.getValue(lines, 'AdapterTypeID', ':') === '9' ? 'wireless' : 'wired';
  203. let ifacename = util.getValue(lines, 'Name', ':').replace(/\]/g, ')').replace(/\[/g, '(');
  204. let iface = util.getValue(lines, 'NetConnectionID', ':').replace(/\]/g, ')').replace(/\[/g, '(');
  205. if (ifacename.toLowerCase().indexOf('wi-fi') >= 0 || ifacename.toLowerCase().indexOf('wireless') >= 0) {
  206. adapterType = 'wireless';
  207. }
  208. if (netEnabled !== '') {
  209. const speed = parseInt(util.getValue(lines, 'speed', ':').trim(), 10) / 1000000;
  210. nics.push({
  211. mac: util.getValue(lines, 'MACAddress', ':').toLowerCase(),
  212. dhcp: util.getValue(linesNicConfig, 'dhcpEnabled', ':').toLowerCase() === 'true',
  213. name: ifacename,
  214. iface,
  215. netEnabled: netEnabled === 'TRUE',
  216. speed: isNaN(speed) ? null : speed,
  217. operstate: util.getValue(lines, 'NetConnectionStatus', ':') === '2' ? 'up' : 'down',
  218. type: adapterType
  219. });
  220. }
  221. }
  222. }
  223. }
  224. return nics;
  225. }
  226. function getWindowsNics() {
  227. // const cmd = util.getWmic() + ' nic get /value';
  228. // const cmdnicconfig = util.getWmic() + ' nicconfig get dhcpEnabled /value';
  229. return new Promise((resolve) => {
  230. process.nextTick(() => {
  231. let cmd = 'Get-WmiObject Win32_NetworkAdapter | fl *' + '; echo \'#-#-#-#\';';
  232. cmd += 'Get-WmiObject Win32_NetworkAdapterConfiguration | fl DHCPEnabled' + '';
  233. try {
  234. util.powerShell(cmd).then(data => {
  235. data = data.split('#-#-#-#');
  236. const nsections = (data[0] || '').split(/\n\s*\n/);
  237. const nconfigsections = (data[1] || '').split(/\n\s*\n/);
  238. resolve(parseLinesWindowsNics(nsections, nconfigsections));
  239. });
  240. } catch (e) {
  241. resolve([]);
  242. }
  243. });
  244. });
  245. }
  246. function getWindowsDNSsuffixes() {
  247. let iface = {};
  248. let dnsSuffixes = {
  249. primaryDNS: '',
  250. exitCode: 0,
  251. ifaces: [],
  252. };
  253. try {
  254. const ipconfig = execSync('ipconfig /all', util.execOptsWin);
  255. const ipconfigArray = ipconfig.split('\r\n\r\n');
  256. ipconfigArray.forEach((element, index) => {
  257. if (index == 1) {
  258. const longPrimaryDNS = element.split('\r\n').filter((element) => {
  259. return element.toUpperCase().includes('DNS');
  260. });
  261. const primaryDNS = longPrimaryDNS[0].substring(longPrimaryDNS[0].lastIndexOf(':') + 1);
  262. dnsSuffixes.primaryDNS = primaryDNS.trim();
  263. if (!dnsSuffixes.primaryDNS) { dnsSuffixes.primaryDNS = 'Not defined'; }
  264. }
  265. if (index > 1) {
  266. if (index % 2 == 0) {
  267. const name = element.substring(element.lastIndexOf(' ') + 1).replace(':', '');
  268. iface.name = name;
  269. } else {
  270. const connectionSpecificDNS = element.split('\r\n').filter((element) => {
  271. return element.toUpperCase().includes('DNS');
  272. });
  273. const dnsSuffix = connectionSpecificDNS[0].substring(connectionSpecificDNS[0].lastIndexOf(':') + 1);
  274. iface.dnsSuffix = dnsSuffix.trim();
  275. dnsSuffixes.ifaces.push(iface);
  276. iface = {};
  277. }
  278. }
  279. });
  280. return dnsSuffixes;
  281. } catch (error) {
  282. // console.log('An error occurred trying to bring the Connection-specific DNS suffix', error.message);
  283. return {
  284. primaryDNS: '',
  285. exitCode: 0,
  286. ifaces: [],
  287. };
  288. }
  289. }
  290. function getWindowsIfaceDNSsuffix(ifaces, ifacename) {
  291. let dnsSuffix = '';
  292. // Adding (.) to ensure ifacename compatibility when duplicated iface-names
  293. const interfaceName = ifacename + '.';
  294. try {
  295. const connectionDnsSuffix = ifaces.filter((iface) => {
  296. return interfaceName.includes(iface.name + '.');
  297. }).map((iface) => iface.dnsSuffix);
  298. if (connectionDnsSuffix[0]) {
  299. dnsSuffix = connectionDnsSuffix[0];
  300. }
  301. if (!dnsSuffix) { dnsSuffix = ''; }
  302. return dnsSuffix;
  303. } catch (error) {
  304. // console.log('Error getting Connection-specific DNS suffix: ', error.message);
  305. return 'Unknown';
  306. }
  307. }
  308. function getWindowsWiredProfilesInformation() {
  309. try {
  310. const result = execSync('netsh lan show profiles', util.execOptsWin);
  311. const profileList = result.split('\r\nProfile on interface');
  312. return profileList;
  313. } catch (error) {
  314. if (error.status === 1 && error.stdout.includes('AutoConfig')) {
  315. return 'Disabled';
  316. }
  317. return [];
  318. }
  319. }
  320. function getWindowsWirelessIfaceSSID(interfaceName) {
  321. try {
  322. const result = execSync(`netsh wlan show interface name="${interfaceName}" | findstr "SSID"`, util.execOptsWin);
  323. const SSID = result.split('\r\n').shift();
  324. const parseSSID = SSID.split(':').pop();
  325. return parseSSID;
  326. } catch (error) {
  327. return 'Unknown';
  328. }
  329. }
  330. function getWindowsIEEE8021x(connectionType, iface, ifaces) {
  331. let i8021x = {
  332. state: 'Unknown',
  333. protocol: 'Unknown',
  334. };
  335. if (ifaces === 'Disabled') {
  336. i8021x.state = 'Disabled';
  337. i8021x.protocol = 'Not defined';
  338. return i8021x;
  339. }
  340. if (connectionType == 'wired' && ifaces.length > 0) {
  341. try {
  342. // Get 802.1x information by interface name
  343. const iface8021xInfo = ifaces.find((element) => {
  344. return element.includes(iface + '\r\n');
  345. });
  346. const arrayIface8021xInfo = iface8021xInfo.split('\r\n');
  347. const state8021x = arrayIface8021xInfo.find((element) => {
  348. return element.includes('802.1x');
  349. });
  350. if (state8021x.includes('Disabled')) {
  351. i8021x.state = 'Disabled';
  352. i8021x.protocol = 'Not defined';
  353. } else if (state8021x.includes('Enabled')) {
  354. const protocol8021x = arrayIface8021xInfo.find((element) => {
  355. return element.includes('EAP');
  356. });
  357. i8021x.protocol = protocol8021x.split(':').pop();
  358. i8021x.state = 'Enabled';
  359. }
  360. } catch (error) {
  361. // console.log('Error getting wired information:', error);
  362. return i8021x;
  363. }
  364. } else if (connectionType == 'wireless') {
  365. let i8021xState = '';
  366. let i8021xProtocol = '';
  367. try {
  368. const SSID = getWindowsWirelessIfaceSSID(iface);
  369. if (SSID !== 'Unknown') {
  370. i8021xState = execSync(`netsh wlan show profiles "${SSID}" | findstr "802.1X"`, util.execOptsWin);
  371. i8021xProtocol = execSync(`netsh wlan show profiles "${SSID}" | findstr "EAP"`, util.execOptsWin);
  372. }
  373. if (i8021xState.includes(':') && i8021xProtocol.includes(':')) {
  374. i8021x.state = i8021xState.split(':').pop();
  375. i8021x.protocol = i8021xProtocol.split(':').pop();
  376. }
  377. } catch (error) {
  378. // console.log('Error getting wireless information:', error);
  379. if (error.status === 1 && error.stdout.includes('AutoConfig')) {
  380. i8021x.state = 'Disabled';
  381. i8021x.protocol = 'Not defined';
  382. }
  383. return i8021x;
  384. }
  385. }
  386. return i8021x;
  387. }
  388. function splitSectionsNics(lines) {
  389. const result = [];
  390. let section = [];
  391. lines.forEach(function (line) {
  392. if (!line.startsWith('\t') && !line.startsWith(' ')) {
  393. if (section.length) {
  394. result.push(section);
  395. section = [];
  396. }
  397. }
  398. section.push(line);
  399. });
  400. if (section.length) {
  401. result.push(section);
  402. }
  403. return result;
  404. }
  405. function parseLinesDarwinNics(sections) {
  406. let nics = [];
  407. sections.forEach(section => {
  408. let nic = {
  409. iface: '',
  410. mtu: null,
  411. mac: '',
  412. ip6: '',
  413. ip4: '',
  414. speed: null,
  415. type: '',
  416. operstate: '',
  417. duplex: '',
  418. internal: false
  419. };
  420. const first = section[0];
  421. nic.iface = first.split(':')[0].trim();
  422. let parts = first.split('> mtu');
  423. nic.mtu = parts.length > 1 ? parseInt(parts[1], 10) : null;
  424. if (isNaN(nic.mtu)) {
  425. nic.mtu = null;
  426. }
  427. nic.internal = parts[0].toLowerCase().indexOf('loopback') > -1;
  428. section.forEach(line => {
  429. if (line.trim().startsWith('ether ')) {
  430. nic.mac = line.split('ether ')[1].toLowerCase().trim();
  431. }
  432. if (line.trim().startsWith('inet6 ') && !nic.ip6) {
  433. nic.ip6 = line.split('inet6 ')[1].toLowerCase().split('%')[0].split(' ')[0];
  434. }
  435. if (line.trim().startsWith('inet ') && !nic.ip4) {
  436. nic.ip4 = line.split('inet ')[1].toLowerCase().split(' ')[0];
  437. }
  438. });
  439. let speed = util.getValue(section, 'link rate');
  440. nic.speed = speed ? parseFloat(speed) : null;
  441. if (nic.speed === null) {
  442. speed = util.getValue(section, 'uplink rate');
  443. nic.speed = speed ? parseFloat(speed) : null;
  444. if (nic.speed !== null && speed.toLowerCase().indexOf('gbps') >= 0) {
  445. nic.speed = nic.speed * 1000;
  446. }
  447. } else {
  448. if (speed.toLowerCase().indexOf('gbps') >= 0) {
  449. nic.speed = nic.speed * 1000;
  450. }
  451. }
  452. nic.type = util.getValue(section, 'type').toLowerCase().indexOf('wi-fi') > -1 ? 'wireless' : 'wired';
  453. nic.operstate = util.getValue(section, 'status').toLowerCase().indexOf('active') > -1 ? 'up' : 'down';
  454. nic.duplex = util.getValue(section, 'media').toLowerCase().indexOf('half-duplex') > -1 ? 'half' : 'full';
  455. if (nic.ip6 || nic.ip4 || nic.mac) {
  456. nics.push(nic);
  457. }
  458. });
  459. return nics;
  460. }
  461. function getDarwinNics() {
  462. const cmd = '/sbin/ifconfig -v';
  463. try {
  464. const lines = execSync(cmd, { maxBuffer: 1024 * 20000 }).toString().split('\n');
  465. const nsections = splitSectionsNics(lines);
  466. return (parseLinesDarwinNics(nsections));
  467. } catch (e) {
  468. return [];
  469. }
  470. }
  471. function getLinuxIfaceConnectionName(interfaceName) {
  472. const cmd = `nmcli device status 2>/dev/null | grep ${interfaceName}`;
  473. try {
  474. const result = execSync(cmd).toString();
  475. const resultFormat = result.replace(/\s+/g, ' ').trim();
  476. const connectionNameLines = resultFormat.split(' ').slice(3);
  477. const connectionName = connectionNameLines.join(' ');
  478. return connectionName != '--' ? connectionName : '';
  479. } catch (e) {
  480. return '';
  481. }
  482. }
  483. function checkLinuxDCHPInterfaces(file) {
  484. let result = [];
  485. try {
  486. let cmd = `cat ${file} 2> /dev/null | grep 'iface\\|source'`;
  487. const lines = execSync(cmd, { maxBuffer: 1024 * 20000 }).toString().split('\n');
  488. lines.forEach(line => {
  489. const parts = line.replace(/\s+/g, ' ').trim().split(' ');
  490. if (parts.length >= 4) {
  491. if (line.toLowerCase().indexOf(' inet ') >= 0 && line.toLowerCase().indexOf('dhcp') >= 0) {
  492. result.push(parts[1]);
  493. }
  494. }
  495. if (line.toLowerCase().includes('source')) {
  496. let file = line.split(' ')[1];
  497. result = result.concat(checkLinuxDCHPInterfaces(file));
  498. }
  499. });
  500. } catch (e) {
  501. util.noop();
  502. }
  503. return result;
  504. }
  505. function getLinuxDHCPNics() {
  506. // alternate methods getting interfaces using DHCP
  507. let cmd = 'ip a 2> /dev/null';
  508. let result = [];
  509. try {
  510. const lines = execSync(cmd, { maxBuffer: 1024 * 20000 }).toString().split('\n');
  511. const nsections = splitSectionsNics(lines);
  512. result = (parseLinuxDHCPNics(nsections));
  513. } catch (e) {
  514. util.noop();
  515. }
  516. try {
  517. result = checkLinuxDCHPInterfaces('/etc/network/interfaces');
  518. } catch (e) {
  519. util.noop();
  520. }
  521. return result;
  522. }
  523. function parseLinuxDHCPNics(sections) {
  524. const result = [];
  525. if (sections && sections.length) {
  526. sections.forEach(lines => {
  527. if (lines && lines.length) {
  528. const parts = lines[0].split(':');
  529. if (parts.length > 2) {
  530. for (let line of lines) {
  531. if (line.indexOf(' inet ') >= 0 && line.indexOf(' dynamic ') >= 0) {
  532. const parts2 = line.split(' ');
  533. const nic = parts2[parts2.length - 1].trim();
  534. result.push(nic);
  535. break;
  536. }
  537. }
  538. }
  539. }
  540. });
  541. }
  542. return result;
  543. }
  544. function getLinuxIfaceDHCPstatus(iface, connectionName, DHCPNics) {
  545. let result = false;
  546. if (connectionName) {
  547. const cmd = `nmcli connection show "${connectionName}" 2>/dev/null | grep ipv4.method;`;
  548. try {
  549. const lines = execSync(cmd).toString();
  550. const resultFormat = lines.replace(/\s+/g, ' ').trim();
  551. let dhcStatus = resultFormat.split(' ').slice(1).toString();
  552. switch (dhcStatus) {
  553. case 'auto':
  554. result = true;
  555. break;
  556. default:
  557. result = false;
  558. break;
  559. }
  560. return result;
  561. } catch (e) {
  562. return (DHCPNics.indexOf(iface) >= 0);
  563. }
  564. } else {
  565. return (DHCPNics.indexOf(iface) >= 0);
  566. }
  567. }
  568. function getDarwinIfaceDHCPstatus(iface) {
  569. let result = false;
  570. const cmd = `ipconfig getpacket "${iface}" 2>/dev/null | grep lease_time;`;
  571. try {
  572. const lines = execSync(cmd).toString().split('\n');
  573. if (lines.length && lines[0].startsWith('lease_time')) {
  574. result = true;
  575. }
  576. } catch (e) {
  577. util.noop();
  578. }
  579. return result;
  580. }
  581. function getLinuxIfaceDNSsuffix(connectionName) {
  582. if (connectionName) {
  583. const cmd = `nmcli connection show "${connectionName}" 2>/dev/null | grep ipv4.dns-search;`;
  584. try {
  585. const result = execSync(cmd).toString();
  586. const resultFormat = result.replace(/\s+/g, ' ').trim();
  587. const dnsSuffix = resultFormat.split(' ').slice(1).toString();
  588. return dnsSuffix == '--' ? 'Not defined' : dnsSuffix;
  589. } catch (e) {
  590. return 'Unknown';
  591. }
  592. } else {
  593. return 'Unknown';
  594. }
  595. }
  596. function getLinuxIfaceIEEE8021xAuth(connectionName) {
  597. if (connectionName) {
  598. const cmd = `nmcli connection show "${connectionName}" 2>/dev/null | grep 802-1x.eap;`;
  599. try {
  600. const result = execSync(cmd).toString();
  601. const resultFormat = result.replace(/\s+/g, ' ').trim();
  602. const authenticationProtocol = resultFormat.split(' ').slice(1).toString();
  603. return authenticationProtocol == '--' ? '' : authenticationProtocol;
  604. } catch (e) {
  605. return 'Not defined';
  606. }
  607. } else {
  608. return 'Not defined';
  609. }
  610. }
  611. function getLinuxIfaceIEEE8021xState(authenticationProtocol) {
  612. if (authenticationProtocol) {
  613. if (authenticationProtocol == 'Not defined') {
  614. return 'Disabled';
  615. }
  616. return 'Enabled';
  617. } else {
  618. return 'Unknown';
  619. }
  620. }
  621. function testVirtualNic(iface, ifaceName, mac) {
  622. 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'];
  623. if (mac) {
  624. return virtualMacs.filter(item => { return mac.toUpperCase().toUpperCase().startsWith(item.substr(0, mac.length)); }).length > 0 ||
  625. iface.toLowerCase().indexOf(' virtual ') > -1 ||
  626. ifaceName.toLowerCase().indexOf(' virtual ') > -1 ||
  627. iface.toLowerCase().indexOf('vethernet ') > -1 ||
  628. ifaceName.toLowerCase().indexOf('vethernet ') > -1 ||
  629. iface.toLowerCase().startsWith('veth') ||
  630. ifaceName.toLowerCase().startsWith('veth') ||
  631. iface.toLowerCase().startsWith('vboxnet') ||
  632. ifaceName.toLowerCase().startsWith('vboxnet');
  633. } else { return false; }
  634. }
  635. function networkInterfaces(callback, rescan, defaultString) {
  636. if (typeof callback === 'string') {
  637. defaultString = callback;
  638. rescan = true;
  639. callback = null;
  640. }
  641. if (typeof callback === 'boolean') {
  642. rescan = callback;
  643. callback = null;
  644. defaultString = '';
  645. }
  646. if (typeof rescan === 'undefined') {
  647. rescan = true;
  648. }
  649. defaultString = defaultString || '';
  650. defaultString = '' + defaultString;
  651. return new Promise((resolve) => {
  652. process.nextTick(() => {
  653. const defaultInterface = getDefaultNetworkInterface();
  654. let ifaces = os.networkInterfaces();
  655. let result = [];
  656. let nics = [];
  657. let dnsSuffixes = [];
  658. let nics8021xInfo = [];
  659. // seperate handling in OSX
  660. if (_darwin || _freebsd || _openbsd || _netbsd) {
  661. nics = getDarwinNics();
  662. nics.forEach(nic => {
  663. if ({}.hasOwnProperty.call(ifaces, nic.iface)) {
  664. ifaces[nic.iface].forEach(function (details) {
  665. if (details.family === 'IPv4') {
  666. nic.ip4subnet = details.netmask;
  667. }
  668. if (details.family === 'IPv6') {
  669. nic.ip6subnet = details.netmask;
  670. }
  671. });
  672. }
  673. result.push({
  674. iface: nic.iface,
  675. ifaceName: nic.iface,
  676. default: nic.iface === defaultInterface,
  677. ip4: nic.ip4,
  678. ip4subnet: nic.ip4subnet || '',
  679. ip6: nic.ip6,
  680. ip6subnet: nic.ip6subnet || '',
  681. mac: nic.mac,
  682. internal: nic.internal,
  683. virtual: nic.internal ? false : testVirtualNic(nic.iface, nic.iface, nic.mac),
  684. operstate: nic.operstate,
  685. type: nic.type,
  686. duplex: nic.duplex,
  687. mtu: nic.mtu,
  688. speed: nic.speed,
  689. dhcp: getDarwinIfaceDHCPstatus(nic.iface),
  690. dnsSuffix: '',
  691. ieee8021xAuth: '',
  692. ieee8021xState: '',
  693. carrierChanges: 0
  694. });
  695. });
  696. _networkInterfaces = result;
  697. if (defaultString.toLowerCase().indexOf('default') >= 0) {
  698. result = result.filter(item => item.default);
  699. if (result.length > 0) {
  700. result = result[0];
  701. } else {
  702. result = [];
  703. }
  704. }
  705. if (callback) { callback(result); }
  706. resolve(result);
  707. }
  708. if (_linux) {
  709. if ((JSON.stringify(ifaces) === JSON.stringify(_ifaces)) && !rescan) {
  710. // no changes - just return object
  711. result = _networkInterfaces;
  712. if (callback) { callback(result); }
  713. resolve(result);
  714. } else {
  715. _ifaces = JSON.parse(JSON.stringify(ifaces));
  716. _dhcpNics = getLinuxDHCPNics();
  717. for (let dev in ifaces) {
  718. let ip4 = '';
  719. let ip4subnet = '';
  720. let ip6 = '';
  721. let ip6subnet = '';
  722. let mac = '';
  723. let duplex = '';
  724. let mtu = '';
  725. let speed = null;
  726. let carrierChanges = 0;
  727. let dhcp = false;
  728. let dnsSuffix = '';
  729. let ieee8021xAuth = '';
  730. let ieee8021xState = '';
  731. let type = '';
  732. if ({}.hasOwnProperty.call(ifaces, dev)) {
  733. let ifaceName = dev;
  734. ifaces[dev].forEach(function (details) {
  735. if (details.family === 'IPv4') {
  736. ip4 = details.address;
  737. ip4subnet = details.netmask;
  738. }
  739. if (details.family === 'IPv6') {
  740. if (!ip6 || ip6.match(/^fe80::/i)) {
  741. ip6 = details.address;
  742. ip6subnet = details.netmask;
  743. }
  744. }
  745. mac = details.mac;
  746. // fallback due to https://github.com/nodejs/node/issues/13581 (node 8.1 - node 8.2)
  747. const nodeMainVersion = parseInt(process.versions.node.split('.'), 10);
  748. if (mac.indexOf('00:00:0') > -1 && (_linux || _darwin) && (!details.internal) && nodeMainVersion >= 8 && nodeMainVersion <= 11) {
  749. if (Object.keys(_mac).length === 0) {
  750. _mac = getMacAddresses();
  751. }
  752. mac = _mac[dev] || '';
  753. }
  754. });
  755. let iface = dev.split(':')[0].trim().toLowerCase();
  756. const cmd = `echo -n "addr_assign_type: "; cat /sys/class/net/${iface}/addr_assign_type 2>/dev/null; echo;
  757. echo -n "address: "; cat /sys/class/net/${iface}/address 2>/dev/null; echo;
  758. echo -n "addr_len: "; cat /sys/class/net/${iface}/addr_len 2>/dev/null; echo;
  759. echo -n "broadcast: "; cat /sys/class/net/${iface}/broadcast 2>/dev/null; echo;
  760. echo -n "carrier: "; cat /sys/class/net/${iface}/carrier 2>/dev/null; echo;
  761. echo -n "carrier_changes: "; cat /sys/class/net/${iface}/carrier_changes 2>/dev/null; echo;
  762. echo -n "dev_id: "; cat /sys/class/net/${iface}/dev_id 2>/dev/null; echo;
  763. echo -n "dev_port: "; cat /sys/class/net/${iface}/dev_port 2>/dev/null; echo;
  764. echo -n "dormant: "; cat /sys/class/net/${iface}/dormant 2>/dev/null; echo;
  765. echo -n "duplex: "; cat /sys/class/net/${iface}/duplex 2>/dev/null; echo;
  766. echo -n "flags: "; cat /sys/class/net/${iface}/flags 2>/dev/null; echo;
  767. echo -n "gro_flush_timeout: "; cat /sys/class/net/${iface}/gro_flush_timeout 2>/dev/null; echo;
  768. echo -n "ifalias: "; cat /sys/class/net/${iface}/ifalias 2>/dev/null; echo;
  769. echo -n "ifindex: "; cat /sys/class/net/${iface}/ifindex 2>/dev/null; echo;
  770. echo -n "iflink: "; cat /sys/class/net/${iface}/iflink 2>/dev/null; echo;
  771. echo -n "link_mode: "; cat /sys/class/net/${iface}/link_mode 2>/dev/null; echo;
  772. echo -n "mtu: "; cat /sys/class/net/${iface}/mtu 2>/dev/null; echo;
  773. echo -n "netdev_group: "; cat /sys/class/net/${iface}/netdev_group 2>/dev/null; echo;
  774. echo -n "operstate: "; cat /sys/class/net/${iface}/operstate 2>/dev/null; echo;
  775. echo -n "proto_down: "; cat /sys/class/net/${iface}/proto_down 2>/dev/null; echo;
  776. echo -n "speed: "; cat /sys/class/net/${iface}/speed 2>/dev/null; echo;
  777. echo -n "tx_queue_len: "; cat /sys/class/net/${iface}/tx_queue_len 2>/dev/null; echo;
  778. echo -n "type: "; cat /sys/class/net/${iface}/type 2>/dev/null; echo;
  779. echo -n "wireless: "; cat /proc/net/wireless 2>/dev/null | grep ${iface}; echo;
  780. echo -n "wirelessspeed: "; iw dev ${iface} link 2>&1 | grep bitrate; echo;`;
  781. let lines = [];
  782. try {
  783. lines = execSync(cmd).toString().split('\n');
  784. const connectionName = getLinuxIfaceConnectionName(iface);
  785. dhcp = getLinuxIfaceDHCPstatus(iface, connectionName, _dhcpNics);
  786. dnsSuffix = getLinuxIfaceDNSsuffix(connectionName);
  787. ieee8021xAuth = getLinuxIfaceIEEE8021xAuth(connectionName);
  788. ieee8021xState = getLinuxIfaceIEEE8021xState(ieee8021xAuth);
  789. } catch (e) {
  790. util.noop();
  791. }
  792. duplex = util.getValue(lines, 'duplex');
  793. duplex = duplex.startsWith('cat') ? '' : duplex;
  794. mtu = parseInt(util.getValue(lines, 'mtu'), 10);
  795. let myspeed = parseInt(util.getValue(lines, 'speed'), 10);
  796. speed = isNaN(myspeed) ? null : myspeed;
  797. let wirelessspeed = util.getValue(lines, 'wirelessspeed').split('tx bitrate: ');
  798. if (speed === null && wirelessspeed.length === 2) {
  799. myspeed = parseFloat(wirelessspeed[1]);
  800. speed = isNaN(myspeed) ? null : myspeed;
  801. }
  802. carrierChanges = parseInt(util.getValue(lines, 'carrier_changes'), 10);
  803. const operstate = util.getValue(lines, 'operstate');
  804. type = operstate === 'up' ? (util.getValue(lines, 'wireless').trim() ? 'wireless' : 'wired') : 'unknown';
  805. if (iface === 'lo' || iface.startsWith('bond')) { type = 'virtual'; }
  806. let internal = (ifaces[dev] && ifaces[dev][0]) ? ifaces[dev][0].internal : false;
  807. if (dev.toLowerCase().indexOf('loopback') > -1 || ifaceName.toLowerCase().indexOf('loopback') > -1) {
  808. internal = true;
  809. }
  810. const virtual = internal ? false : testVirtualNic(dev, ifaceName, mac);
  811. result.push({
  812. iface,
  813. ifaceName,
  814. default: iface === defaultInterface,
  815. ip4,
  816. ip4subnet,
  817. ip6,
  818. ip6subnet,
  819. mac,
  820. internal,
  821. virtual,
  822. operstate,
  823. type,
  824. duplex,
  825. mtu,
  826. speed,
  827. dhcp,
  828. dnsSuffix,
  829. ieee8021xAuth,
  830. ieee8021xState,
  831. carrierChanges,
  832. });
  833. }
  834. }
  835. _networkInterfaces = result;
  836. if (defaultString.toLowerCase().indexOf('default') >= 0) {
  837. result = result.filter(item => item.default);
  838. if (result.length > 0) {
  839. result = result[0];
  840. } else {
  841. result = [];
  842. }
  843. }
  844. if (callback) { callback(result); }
  845. resolve(result);
  846. }
  847. }
  848. if (_windows) {
  849. if ((JSON.stringify(ifaces) === JSON.stringify(_ifaces)) && !rescan) {
  850. // no changes - just return object
  851. result = _networkInterfaces;
  852. if (callback) { callback(result); }
  853. resolve(result);
  854. } else {
  855. _ifaces = JSON.parse(JSON.stringify(ifaces));
  856. getWindowsNics().then(function (nics) {
  857. nics.forEach(nic => {
  858. let found = false;
  859. Object.keys(ifaces).forEach(key => {
  860. if (!found) {
  861. ifaces[key].forEach(value => {
  862. if (Object.keys(value).indexOf('mac') >= 0) {
  863. found = value['mac'] === nic.mac;
  864. }
  865. });
  866. }
  867. });
  868. if (!found) {
  869. ifaces[nic.name] = [{ mac: nic.mac }];
  870. }
  871. });
  872. nics8021xInfo = getWindowsWiredProfilesInformation();
  873. dnsSuffixes = getWindowsDNSsuffixes();
  874. for (let dev in ifaces) {
  875. let iface = dev;
  876. let ip4 = '';
  877. let ip4subnet = '';
  878. let ip6 = '';
  879. let ip6subnet = '';
  880. let mac = '';
  881. let duplex = '';
  882. let mtu = '';
  883. let speed = null;
  884. let carrierChanges = 0;
  885. let operstate = 'down';
  886. let dhcp = false;
  887. let dnsSuffix = '';
  888. let ieee8021xAuth = '';
  889. let ieee8021xState = '';
  890. let type = '';
  891. if ({}.hasOwnProperty.call(ifaces, dev)) {
  892. let ifaceName = dev;
  893. ifaces[dev].forEach(function (details) {
  894. if (details.family === 'IPv4') {
  895. ip4 = details.address;
  896. ip4subnet = details.netmask;
  897. }
  898. if (details.family === 'IPv6') {
  899. if (!ip6 || ip6.match(/^fe80::/i)) {
  900. ip6 = details.address;
  901. ip6subnet = details.netmask;
  902. }
  903. }
  904. mac = details.mac;
  905. // fallback due to https://github.com/nodejs/node/issues/13581 (node 8.1 - node 8.2)
  906. const nodeMainVersion = parseInt(process.versions.node.split('.'), 10);
  907. if (mac.indexOf('00:00:0') > -1 && (_linux || _darwin) && (!details.internal) && nodeMainVersion >= 8 && nodeMainVersion <= 11) {
  908. if (Object.keys(_mac).length === 0) {
  909. _mac = getMacAddresses();
  910. }
  911. mac = _mac[dev] || '';
  912. }
  913. });
  914. dnsSuffix = getWindowsIfaceDNSsuffix(dnsSuffixes.ifaces, dev);
  915. let foundFirst = false;
  916. nics.forEach(detail => {
  917. if (detail.mac === mac && !foundFirst) {
  918. iface = detail.iface || iface;
  919. ifaceName = detail.name;
  920. dhcp = detail.dhcp;
  921. operstate = detail.operstate;
  922. speed = detail.speed;
  923. type = detail.type;
  924. foundFirst = true;
  925. }
  926. });
  927. 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) {
  928. type = 'wireless';
  929. }
  930. const IEEE8021x = getWindowsIEEE8021x(type, dev, nics8021xInfo);
  931. ieee8021xAuth = IEEE8021x.protocol;
  932. ieee8021xState = IEEE8021x.state;
  933. let internal = (ifaces[dev] && ifaces[dev][0]) ? ifaces[dev][0].internal : false;
  934. if (dev.toLowerCase().indexOf('loopback') > -1 || ifaceName.toLowerCase().indexOf('loopback') > -1) {
  935. internal = true;
  936. }
  937. const virtual = internal ? false : testVirtualNic(dev, ifaceName, mac);
  938. result.push({
  939. iface,
  940. ifaceName,
  941. default: iface === defaultInterface,
  942. ip4,
  943. ip4subnet,
  944. ip6,
  945. ip6subnet,
  946. mac,
  947. internal,
  948. virtual,
  949. operstate,
  950. type,
  951. duplex,
  952. mtu,
  953. speed,
  954. dhcp,
  955. dnsSuffix,
  956. ieee8021xAuth,
  957. ieee8021xState,
  958. carrierChanges,
  959. });
  960. }
  961. }
  962. _networkInterfaces = result;
  963. if (defaultString.toLowerCase().indexOf('default') >= 0) {
  964. result = result.filter(item => item.default);
  965. if (result.length > 0) {
  966. result = result[0];
  967. } else {
  968. result = [];
  969. }
  970. }
  971. if (callback) { callback(result); }
  972. resolve(result);
  973. });
  974. }
  975. }
  976. });
  977. });
  978. }
  979. exports.networkInterfaces = networkInterfaces;
  980. // --------------------------
  981. // NET - Speed
  982. function calcNetworkSpeed(iface, rx_bytes, tx_bytes, operstate, rx_dropped, rx_errors, tx_dropped, tx_errors) {
  983. let result = {
  984. iface,
  985. operstate,
  986. rx_bytes,
  987. rx_dropped,
  988. rx_errors,
  989. tx_bytes,
  990. tx_dropped,
  991. tx_errors,
  992. rx_sec: null,
  993. tx_sec: null,
  994. ms: 0
  995. };
  996. if (_network[iface] && _network[iface].ms) {
  997. result.ms = Date.now() - _network[iface].ms;
  998. result.rx_sec = (rx_bytes - _network[iface].rx_bytes) >= 0 ? (rx_bytes - _network[iface].rx_bytes) / (result.ms / 1000) : 0;
  999. result.tx_sec = (tx_bytes - _network[iface].tx_bytes) >= 0 ? (tx_bytes - _network[iface].tx_bytes) / (result.ms / 1000) : 0;
  1000. _network[iface].rx_bytes = rx_bytes;
  1001. _network[iface].tx_bytes = tx_bytes;
  1002. _network[iface].rx_sec = result.rx_sec;
  1003. _network[iface].tx_sec = result.tx_sec;
  1004. _network[iface].ms = Date.now();
  1005. _network[iface].last_ms = result.ms;
  1006. _network[iface].operstate = operstate;
  1007. } else {
  1008. if (!_network[iface]) { _network[iface] = {}; }
  1009. _network[iface].rx_bytes = rx_bytes;
  1010. _network[iface].tx_bytes = tx_bytes;
  1011. _network[iface].rx_sec = null;
  1012. _network[iface].tx_sec = null;
  1013. _network[iface].ms = Date.now();
  1014. _network[iface].last_ms = 0;
  1015. _network[iface].operstate = operstate;
  1016. }
  1017. return result;
  1018. }
  1019. function networkStats(ifaces, callback) {
  1020. let ifacesArray = [];
  1021. return new Promise((resolve) => {
  1022. process.nextTick(() => {
  1023. // fallback - if only callback is given
  1024. if (util.isFunction(ifaces) && !callback) {
  1025. callback = ifaces;
  1026. ifacesArray = [getDefaultNetworkInterface()];
  1027. } else {
  1028. if (typeof ifaces !== 'string' && ifaces !== undefined) {
  1029. if (callback) { callback([]); }
  1030. return resolve([]);
  1031. }
  1032. ifaces = ifaces || getDefaultNetworkInterface();
  1033. ifaces.__proto__.toLowerCase = util.stringToLower;
  1034. ifaces.__proto__.replace = util.stringReplace;
  1035. ifaces.__proto__.trim = util.stringTrim;
  1036. ifaces = ifaces.trim().toLowerCase().replace(/,+/g, '|');
  1037. ifacesArray = ifaces.split('|');
  1038. }
  1039. const result = [];
  1040. const workload = [];
  1041. if (ifacesArray.length && ifacesArray[0].trim() === '*') {
  1042. ifacesArray = [];
  1043. networkInterfaces(false).then(allIFaces => {
  1044. for (let iface of allIFaces) {
  1045. ifacesArray.push(iface.iface);
  1046. }
  1047. networkStats(ifacesArray.join(',')).then(result => {
  1048. if (callback) { callback(result); }
  1049. resolve(result);
  1050. });
  1051. });
  1052. } else {
  1053. for (let iface of ifacesArray) {
  1054. workload.push(networkStatsSingle(iface.trim()));
  1055. }
  1056. if (workload.length) {
  1057. Promise.all(
  1058. workload
  1059. ).then(data => {
  1060. if (callback) { callback(data); }
  1061. resolve(data);
  1062. });
  1063. } else {
  1064. if (callback) { callback(result); }
  1065. resolve(result);
  1066. }
  1067. }
  1068. });
  1069. });
  1070. }
  1071. function networkStatsSingle(iface) {
  1072. function parseLinesWindowsPerfData(sections) {
  1073. let perfData = [];
  1074. for (let i in sections) {
  1075. if ({}.hasOwnProperty.call(sections, i)) {
  1076. if (sections[i].trim() !== '') {
  1077. let lines = sections[i].trim().split('\r\n');
  1078. perfData.push({
  1079. name: util.getValue(lines, 'Name', ':').replace(/[()[\] ]+/g, '').replace('#', '_').toLowerCase(),
  1080. rx_bytes: parseInt(util.getValue(lines, 'BytesReceivedPersec', ':'), 10),
  1081. rx_errors: parseInt(util.getValue(lines, 'PacketsReceivedErrors', ':'), 10),
  1082. rx_dropped: parseInt(util.getValue(lines, 'PacketsReceivedDiscarded', ':'), 10),
  1083. tx_bytes: parseInt(util.getValue(lines, 'BytesSentPersec', ':'), 10),
  1084. tx_errors: parseInt(util.getValue(lines, 'PacketsOutboundErrors', ':'), 10),
  1085. tx_dropped: parseInt(util.getValue(lines, 'PacketsOutboundDiscarded', ':'), 10)
  1086. });
  1087. }
  1088. }
  1089. }
  1090. return perfData;
  1091. }
  1092. return new Promise((resolve) => {
  1093. process.nextTick(() => {
  1094. let ifaceSanitized = '';
  1095. const s = util.isPrototypePolluted() ? '---' : util.sanitizeShellString(iface);
  1096. for (let i = 0; i <= util.mathMin(s.length, 2000); i++) {
  1097. if (!(s[i] === undefined)) {
  1098. ifaceSanitized = ifaceSanitized + s[i];
  1099. }
  1100. }
  1101. let result = {
  1102. iface: ifaceSanitized,
  1103. operstate: 'unknown',
  1104. rx_bytes: 0,
  1105. rx_dropped: 0,
  1106. rx_errors: 0,
  1107. tx_bytes: 0,
  1108. tx_dropped: 0,
  1109. tx_errors: 0,
  1110. rx_sec: null,
  1111. tx_sec: null,
  1112. ms: 0
  1113. };
  1114. let operstate = 'unknown';
  1115. let rx_bytes = 0;
  1116. let tx_bytes = 0;
  1117. let rx_dropped = 0;
  1118. let rx_errors = 0;
  1119. let tx_dropped = 0;
  1120. let tx_errors = 0;
  1121. let cmd, lines, stats;
  1122. if (!_network[ifaceSanitized] || (_network[ifaceSanitized] && !_network[ifaceSanitized].ms) || (_network[ifaceSanitized] && _network[ifaceSanitized].ms && Date.now() - _network[ifaceSanitized].ms >= 500)) {
  1123. if (_linux) {
  1124. if (fs.existsSync('/sys/class/net/' + ifaceSanitized)) {
  1125. cmd =
  1126. 'cat /sys/class/net/' + ifaceSanitized + '/operstate; ' +
  1127. 'cat /sys/class/net/' + ifaceSanitized + '/statistics/rx_bytes; ' +
  1128. 'cat /sys/class/net/' + ifaceSanitized + '/statistics/tx_bytes; ' +
  1129. 'cat /sys/class/net/' + ifaceSanitized + '/statistics/rx_dropped; ' +
  1130. 'cat /sys/class/net/' + ifaceSanitized + '/statistics/rx_errors; ' +
  1131. 'cat /sys/class/net/' + ifaceSanitized + '/statistics/tx_dropped; ' +
  1132. 'cat /sys/class/net/' + ifaceSanitized + '/statistics/tx_errors; ';
  1133. exec(cmd, function (error, stdout) {
  1134. if (!error) {
  1135. lines = stdout.toString().split('\n');
  1136. operstate = lines[0].trim();
  1137. rx_bytes = parseInt(lines[1], 10);
  1138. tx_bytes = parseInt(lines[2], 10);
  1139. rx_dropped = parseInt(lines[3], 10);
  1140. rx_errors = parseInt(lines[4], 10);
  1141. tx_dropped = parseInt(lines[5], 10);
  1142. tx_errors = parseInt(lines[6], 10);
  1143. result = calcNetworkSpeed(ifaceSanitized, rx_bytes, tx_bytes, operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
  1144. }
  1145. resolve(result);
  1146. });
  1147. } else {
  1148. resolve(result);
  1149. }
  1150. }
  1151. if (_freebsd || _openbsd || _netbsd) {
  1152. cmd = 'netstat -ibndI ' + ifaceSanitized; // lgtm [js/shell-command-constructed-from-input]
  1153. exec(cmd, function (error, stdout) {
  1154. if (!error) {
  1155. lines = stdout.toString().split('\n');
  1156. for (let i = 1; i < lines.length; i++) {
  1157. const line = lines[i].replace(/ +/g, ' ').split(' ');
  1158. if (line && line[0] && line[7] && line[10]) {
  1159. rx_bytes = rx_bytes + parseInt(line[7]);
  1160. if (line[6].trim() !== '-') { rx_dropped = rx_dropped + parseInt(line[6]); }
  1161. if (line[5].trim() !== '-') { rx_errors = rx_errors + parseInt(line[5]); }
  1162. tx_bytes = tx_bytes + parseInt(line[10]);
  1163. if (line[12].trim() !== '-') { tx_dropped = tx_dropped + parseInt(line[12]); }
  1164. if (line[9].trim() !== '-') { tx_errors = tx_errors + parseInt(line[9]); }
  1165. operstate = 'up';
  1166. }
  1167. }
  1168. result = calcNetworkSpeed(ifaceSanitized, rx_bytes, tx_bytes, operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
  1169. }
  1170. resolve(result);
  1171. });
  1172. }
  1173. if (_darwin) {
  1174. cmd = 'ifconfig ' + ifaceSanitized + ' | grep "status"'; // lgtm [js/shell-command-constructed-from-input]
  1175. exec(cmd, function (error, stdout) {
  1176. result.operstate = (stdout.toString().split(':')[1] || '').trim();
  1177. result.operstate = (result.operstate || '').toLowerCase();
  1178. result.operstate = (result.operstate === 'active' ? 'up' : (result.operstate === 'inactive' ? 'down' : 'unknown'));
  1179. cmd = 'netstat -bdI ' + ifaceSanitized; // lgtm [js/shell-command-constructed-from-input]
  1180. exec(cmd, function (error, stdout) {
  1181. if (!error) {
  1182. lines = stdout.toString().split('\n');
  1183. // if there is less than 2 lines, no information for this interface was found
  1184. if (lines.length > 1 && lines[1].trim() !== '') {
  1185. // skip header line
  1186. // use the second line because it is tied to the NIC instead of the ipv4 or ipv6 address
  1187. stats = lines[1].replace(/ +/g, ' ').split(' ');
  1188. const offset = stats.length > 11 ? 1 : 0;
  1189. rx_bytes = parseInt(stats[offset + 5]);
  1190. rx_dropped = parseInt(stats[offset + 10]);
  1191. rx_errors = parseInt(stats[offset + 4]);
  1192. tx_bytes = parseInt(stats[offset + 8]);
  1193. tx_dropped = parseInt(stats[offset + 10]);
  1194. tx_errors = parseInt(stats[offset + 7]);
  1195. result = calcNetworkSpeed(ifaceSanitized, rx_bytes, tx_bytes, result.operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
  1196. }
  1197. }
  1198. resolve(result);
  1199. });
  1200. });
  1201. }
  1202. if (_windows) {
  1203. let perfData = [];
  1204. let ifaceName = ifaceSanitized;
  1205. // Performance Data
  1206. util.powerShell('Get-WmiObject Win32_PerfRawData_Tcpip_NetworkInterface | select Name,BytesReceivedPersec,PacketsReceivedErrors,PacketsReceivedDiscarded,BytesSentPersec,PacketsOutboundErrors,PacketsOutboundDiscarded | fl').then((stdout, error) => {
  1207. if (!error) {
  1208. const psections = stdout.toString().split(/\n\s*\n/);
  1209. perfData = parseLinesWindowsPerfData(psections);
  1210. }
  1211. // Network Interfaces
  1212. networkInterfaces(false).then(interfaces => {
  1213. // get bytes sent, received from perfData by name
  1214. rx_bytes = 0;
  1215. tx_bytes = 0;
  1216. perfData.forEach(detail => {
  1217. interfaces.forEach(det => {
  1218. if ((det.iface.toLowerCase() === ifaceSanitized.toLowerCase() ||
  1219. det.mac.toLowerCase() === ifaceSanitized.toLowerCase() ||
  1220. det.ip4.toLowerCase() === ifaceSanitized.toLowerCase() ||
  1221. det.ip6.toLowerCase() === ifaceSanitized.toLowerCase() ||
  1222. det.ifaceName.replace(/[()[\] ]+/g, '').replace('#', '_').toLowerCase() === ifaceSanitized.replace(/[()[\] ]+/g, '').replace('#', '_').toLowerCase()) &&
  1223. (det.ifaceName.replace(/[()[\] ]+/g, '').replace('#', '_').toLowerCase() === detail.name)) {
  1224. ifaceName = det.iface;
  1225. rx_bytes = detail.rx_bytes;
  1226. rx_dropped = detail.rx_dropped;
  1227. rx_errors = detail.rx_errors;
  1228. tx_bytes = detail.tx_bytes;
  1229. tx_dropped = detail.tx_dropped;
  1230. tx_errors = detail.tx_errors;
  1231. operstate = det.operstate;
  1232. }
  1233. });
  1234. });
  1235. if (rx_bytes && tx_bytes) {
  1236. result = calcNetworkSpeed(ifaceName, parseInt(rx_bytes), parseInt(tx_bytes), operstate, rx_dropped, rx_errors, tx_dropped, tx_errors);
  1237. }
  1238. resolve(result);
  1239. });
  1240. });
  1241. }
  1242. } else {
  1243. result.rx_bytes = _network[ifaceSanitized].rx_bytes;
  1244. result.tx_bytes = _network[ifaceSanitized].tx_bytes;
  1245. result.rx_sec = _network[ifaceSanitized].rx_sec;
  1246. result.tx_sec = _network[ifaceSanitized].tx_sec;
  1247. result.ms = _network[ifaceSanitized].last_ms;
  1248. result.operstate = _network[ifaceSanitized].operstate;
  1249. resolve(result);
  1250. }
  1251. });
  1252. });
  1253. }
  1254. exports.networkStats = networkStats;
  1255. // --------------------------
  1256. // NET - connections (sockets)
  1257. function networkConnections(callback) {
  1258. return new Promise((resolve) => {
  1259. process.nextTick(() => {
  1260. let result = [];
  1261. if (_linux || _freebsd || _openbsd || _netbsd) {
  1262. 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';
  1263. 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'; }
  1264. exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
  1265. let lines = stdout.toString().split('\n');
  1266. if (!error && (lines.length > 1 || lines[0] != '')) {
  1267. lines.forEach(function (line) {
  1268. l