Repositorio del curso CCOM4030 el semestre B91 del proyecto Artesanías con el Instituto de Cultura

network.js 56KB

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