wifiInterfaces(), wifiConnections() added

This commit is contained in:
Sebastian Hildebrandt
2021-02-10 16:08:55 +01:00
parent cce9fd5f73
commit ac29803f03
18 changed files with 904 additions and 97 deletions
+1 -1
View File
@@ -552,7 +552,7 @@ function getCpu() {
result.virtualization = flags.indexOf('vmx') > -1 || flags.indexOf('svm') > -1;
if (_windows) {
try {
const systeminfo = execSync('systeminfo').toString();
const systeminfo = execSync('systeminfo', util.execOptsWin).toString();
result.virtualization = result.virtualization || (systeminfo.indexOf('Virtualization Enabled In Firmware: Yes') !== -1) || (systeminfo.indexOf('Virtualisierung in Firmware aktiviert: Ja') !== -1) || (systeminfo.indexOf('Virtualisation activée dans le microprogramme : Qiu') !== -1);
} catch (e) {
util.noop();
+1
View File
@@ -408,6 +408,7 @@ function graphics(callback) {
function nvidiaSmi(options) {
const nvidiaSmiExe = getNvidiaSmi();
options = options || util.execOptsWin;
if (nvidiaSmiExe) {
const nvidiaSmiOpts = '--query-gpu=driver_version,pci.sub_device_id,name,pci.bus_id,fan.speed,memory.total,memory.used,memory.free,utilization.gpu,utilization.memory,temperature.gpu,temperature.memory,power.draw,power.limit,clocks.gr,clocks.mem --format=csv,noheader,nounits';
const cmd = nvidiaSmiExe + ' ' + nvidiaSmiOpts + (_linux ? ' 2>/dev/null' : '');
+21
View File
@@ -487,6 +487,27 @@ export namespace Systeminformation {
rsnFlags: string[];
}
interface WifiInterfaceData {
id: string;
iface: string;
model: string;
vendor: string;
}
interface WifiConnectionData {
id: string;
iface: string;
model: string;
ssid: string;
bssid: string;
channel: number;
type: string;
security: string;
frequency: number;
signalLevel: number;
txRate: number;
}
// 7. Current Load, Processes & Services
interface CurrentLoadData {
+2
View File
@@ -469,6 +469,8 @@ exports.networkStats = network.networkStats;
exports.networkConnections = network.networkConnections;
exports.wifiNetworks = wifi.wifiNetworks;
exports.wifiInterfaces = wifi.wifiInterfaces;
exports.wifiConnections = wifi.wifiConnections;
exports.services = processes.services;
exports.processes = processes.processes;
+2 -1
View File
@@ -805,7 +805,8 @@ function networkInterfaces(callback, rescan = true) {
}
mac = details.mac;
// fallback due to https://github.com/nodejs/node/issues/13581 (node 8.1 - node 8.2)
if (mac.indexOf('00:00:0') > -1 && (_linux || _darwin) && parseInt(process.versions.node.split('.'), 10) === 8) {
const nodeMainVersion = parseInt(process.versions.node.split('.'), 10);
if (mac.indexOf('00:00:0') > -1 && (_linux || _darwin) && (!details.internal) && nodeMainVersion >= 8 && nodeMainVersion <= 11) {
if (Object.keys(_mac).length === 0) {
_mac = getMacAddresses();
}
+63 -8
View File
@@ -178,7 +178,7 @@ function getFQDN() {
}
if (_windows) {
try {
const stdout = execSync('echo %COMPUTERNAME%.%USERDNSDOMAIN%');
const stdout = execSync('echo %COMPUTERNAME%.%USERDNSDOMAIN%', util.execOptsWin);
fqdn = stdout.toString().replace('.%USERDNSDOMAIN%', '').split(os.EOL)[0];
} catch (e) {
util.noop();
@@ -323,7 +323,7 @@ function osInfo(callback) {
try {
const workload = [];
workload.push(util.wmic('os get /value'));
workload.push(execPromise('systeminfo'));
workload.push(execPromise('systeminfo', util.execOptsWin));
util.promiseAll(
workload
).then(data => {
@@ -433,6 +433,10 @@ function versions(apps, callback) {
java: '',
gcc: '',
virtualbox: '',
bash: '',
zsh: '',
fish: '',
powershell: '',
dotnet: ''
};
@@ -440,7 +444,7 @@ function versions(apps, callback) {
if (apps === '*') {
return {
versions: versionObject,
counter: 26
counter: 30
};
}
if (!Array.isArray(apps)) {
@@ -607,7 +611,7 @@ function versions(apps, callback) {
exec('apachectl -v 2>&1', function (error, stdout) {
if (!error) {
const apache = (stdout.toString().split('\n')[0] || '').split(':');
appsObj.versions.apache = (apache.length > 1 ? apache[1].replace('Apache', '').replace('/', '').trim() : '');
appsObj.versions.apache = (apache.length > 1 ? apache[1].replace('Apache', '').replace('/', '').split('(')[0].trim() : '');
}
functionProcessed();
});
@@ -926,15 +930,66 @@ function versions(apps, callback) {
functionProcessed();
});
}
if ({}.hasOwnProperty.call(appsObj.versions, 'dotnet')) {
exec('dotnet --version 2>&1', function (error, stdout) {
if ({}.hasOwnProperty.call(appsObj.versions, 'bash')) {
exec('bash --version', function (error, stdout) {
if (!error) {
const dotnet = stdout.toString().split('\n')[0] || '';
appsObj.versions.dotnet = dotnet.trim();
const line = stdout.toString().split('\n')[0];
const parts = line.split(' version ');
if (parts.length > 1) {
appsObj.versions.bash = parts[1].split(' ')[0].split('(')[0];
}
}
functionProcessed();
});
}
if ({}.hasOwnProperty.call(appsObj.versions, 'zsh')) {
exec('zsh --version', function (error, stdout) {
if (!error) {
const line = stdout.toString().split('\n')[0];
const parts = line.split('zsh ');
if (parts.length > 1) {
appsObj.versions.zsh = parts[1].split(' ')[0];
}
}
functionProcessed();
});
}
if ({}.hasOwnProperty.call(appsObj.versions, 'fish')) {
exec('fish --version', function (error, stdout) {
if (!error) {
const line = stdout.toString().split('\n')[0];
const parts = line.split(' version ');
if (parts.length > 1) {
appsObj.versions.fish = parts[1].split(' ')[0];
}
}
functionProcessed();
});
}
if ({}.hasOwnProperty.call(appsObj.versions, 'powershell')) {
if (_windows) {
util.powerShell('$PSVersionTable').then(stdout => {
const lines = stdout.toString().split('\n').map(line => line.replace(/ +/g, ' ').replace(/ +/g, ':'));
appsObj.versions.powershell = util.getVersion(lines, 'psversion');
functionProcessed();
});
} else {
functionProcessed();
}
}
if ({}.hasOwnProperty.call(appsObj.versions, 'dotnet')) {
util.powerShell('gci "HKLM:\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP" -recurse | gp -name Version,Release -EA 0 | where { $_.PSChildName -match "^(?!S)\\p{L}"} | select PSChildName, Version, Release').then(stdout => {
const lines = stdout.toString().split('\r\n');
let dotnet = '';
lines.forEach(line => {
line = line.replace(/ +/g, ' ');
const parts = line.split(' ');
dotnet = dotnet || ((parts[0].toLowerCase().startsWith('client') && parts.length > 2 ? parts[1].trim() : (parts[0].toLowerCase().startsWith('full') && parts.length > 2 ? parts[1].trim() : '')));
});
appsObj.versions.dotnet = dotnet.trim();
functionProcessed();
});
}
} catch (e) {
if (callback) { callback(appsObj.versions); }
resolve(appsObj.versions);
+2 -2
View File
@@ -301,7 +301,7 @@ function getWmic() {
wmicPath = WINDIR + '\\system32\\wbem\\wmic.exe';
if (!fs.existsSync(wmicPath)) {
try {
const wmicPathArray = execSync('WHERE WMIC').toString().split('\r\n');
const wmicPathArray = execSync('WHERE WMIC', execOptsWin).toString().split('\r\n');
if (wmicPathArray && wmicPathArray.length) {
wmicPath = wmicPathArray[0];
} else {
@@ -392,7 +392,7 @@ function getCodepage() {
if (_windows) {
if (!codepage) {
try {
const stdout = execSync('chcp');
const stdout = execSync('chcp', execOptsWin);
const lines = stdout.toString().split('\r\n');
const parts = lines[0].split(':');
codepage = parts.length > 1 ? parts[1].replace('.', '') : '';
+373 -54
View File
@@ -112,7 +112,116 @@ function wifiFrequencyFromChannel(channel) {
return {}.hasOwnProperty.call(frequencies, channel) ? frequencies[channel] : null;
}
function getWifiNetworkAlt(iface) {
function ifaceListLinux() {
const result = [];
const cmd = 'iw dev';
try {
const all = execSync(cmd).toString().split('\n').map(line => line.trim()).join('\n');
const parts = all.split('\nInterface ');
parts.shift();
parts.foreach(ifaceDetails => {
const lines = ifaceDetails.split('\n');
const iface = lines[0];
const id = util.toInt(util.getValue(lines, 'ifindex', ' '));
const mac = util.getValue(lines, 'addr', ' ');
const channel = util.toInt(util.getValue(lines, 'channel', ' '));
result.push({
id,
iface,
mac,
channel
});
});
return result;
} catch (e) {
return [];
}
}
function nmiDeviceLinux(iface) {
const cmd = 'nmcli -t -f general,wifi-properties,capabilities,ip4,ip6 device show ' + iface;
try {
const lines = execSync(cmd).toString().split('\n');
return {
iface,
type: util.getValue(lines, 'GENERAL.TYPE'),
vendor: util.getValue(lines, 'GENERAL.VENDOR'),
product: util.getValue(lines, 'GENERAL.PRODUCT'),
mac: util.getValue(lines, 'GENERAL.HWADDR').toLowerCase(),
ssid: util.getValue(lines, 'GENERAL.CONNECTION'),
};
} catch (e) {
return {};
}
}
function nmiConnectionLinux(ssid) {
const cmd = 'nmcli -t --show-secrets connection show ' + ssid;
try {
const lines = execSync(cmd).toString().split('\n');
return {
ssid,
uuid: util.getValue(lines, 'connection.uuid'),
type: util.getValue(lines, 'connection.type'),
autoconnect: util.getValue(lines, 'connection.autoconnect') === 'yes',
security: util.getValue(lines, '802-11-wireless-security.key-mgmt'),
bssid: util.getValue(lines, '802-11-wireless.seen-bssids').toLowerCase()
};
} catch (e) {
return {};
}
}
function wpaConnectionLinux(iface) {
const cmd = `wpa_cli -i ${iface} status`;
try {
const lines = execSync(cmd).toString().split('\n');
return {
ssid: util.getValue(lines, 'ssid', '='),
uuid: util.getValue(lines, 'uuid', '='),
security: util.getValue(lines, 'key_mgmt', '='),
freq: util.getValue(lines, 'freq', '='),
bssid: util.getValue(lines, 'bssid', '=').toLowerCase()
};
} catch (e) {
return {};
}
}
function getWifiNetworkListNmi() {
const result = [];
const cmd = 'nmcli -t -m multiline --fields active,ssid,bssid,mode,chan,freq,signal,security,wpa-flags,rsn-flags device wifi list 2>/dev/null';
try {
const stdout = execSync(cmd, { maxBuffer: 1024 * 20000 });
const parts = stdout.toString().split('ACTIVE:');
parts.shift();
parts.forEach(part => {
part = 'ACTIVE:' + part;
const lines = part.split(os.EOL);
const channel = util.getValue(lines, 'CHAN');
const frequency = util.getValue(lines, 'FREQ').toLowerCase().replace('mhz', '').trim();
const security = util.getValue(lines, 'SECURITY').replace('(', '').replace(')', '');
const wpaFlags = util.getValue(lines, 'WPA-FLAGS').replace('(', '').replace(')', '');
const rsnFlags = util.getValue(lines, 'RSN-FLAGS').replace('(', '').replace(')', '');
result.push({
ssid: util.getValue(lines, 'SSID'),
bssid: util.getValue(lines, 'BSSID').toLowerCase(),
mode: util.getValue(lines, 'MODE'),
channel: channel ? parseInt(channel, 10) : null,
frequency: frequency ? parseInt(frequency, 10) : null,
signalLevel: wifiDBFromQuality(util.getValue(lines, 'SIGNAL')),
quality: parseFloat(util.getValue(lines, 'SIGNAL')),
security: security && security !== 'none' ? security.split(' ') : [],
wpaFlags: wpaFlags && wpaFlags !== 'none' ? wpaFlags.split(' ') : [],
rsnFlags: rsnFlags && rsnFlags !== 'none' ? rsnFlags.split(' ') : []
});
});
} catch (e) {
return [];
}
}
function getWifiNetworkListIw(iface) {
const result = [];
try {
let iwlistParts = execSync(`export LC_ALL=C; iwlist ${iface} scan 2>&1; unset LC_ALL`).toString().split(' Cell ');
@@ -196,80 +305,53 @@ function wifiNetworks(callback) {
process.nextTick(() => {
let result = [];
if (_linux) {
let cmd = 'nmcli --terse --fields active,ssid,bssid,mode,chan,freq,signal,security,wpa-flags,rsn-flags device wifi list 2>/dev/null';
exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
const parts = stdout.toString().split('ACTIVE:');
parts.shift();
parts.forEach(part => {
part = 'ACTIVE:' + part;
const lines = part.split(os.EOL);
const channel = util.getValue(lines, 'CHAN');
const frequency = util.getValue(lines, 'FREQ').toLowerCase().replace('mhz', '').trim();
const security = util.getValue(lines, 'SECURITY').replace('(', '').replace(')', '');
const wpaFlags = util.getValue(lines, 'WPA-FLAGS').replace('(', '').replace(')', '');
const rsnFlags = util.getValue(lines, 'RSN-FLAGS').replace('(', '').replace(')', '');
result.push({
ssid: util.getValue(lines, 'SSID'),
bssid: util.getValue(lines, 'BSSID').toLowerCase(),
mode: util.getValue(lines, 'MODE'),
channel: channel ? parseInt(channel, 10) : null,
frequency: frequency ? parseInt(frequency, 10) : null,
signalLevel: wifiDBFromQuality(util.getValue(lines, 'SIGNAL')),
quality: parseFloat(util.getValue(lines, 'SIGNAL')),
security: security && security !== 'none' ? security.split(' ') : [],
wpaFlags: wpaFlags && wpaFlags !== 'none' ? wpaFlags.split(' ') : [],
rsnFlags: rsnFlags && rsnFlags !== 'none' ? rsnFlags.split(' ') : []
});
});
if (result.length === 0) {
try {
const iwconfigParts = execSync('export LC_ALL=C; iwconfig 2>/dev/null; unset LC_ALL').toString().split('\n\n');
let iface = '';
for (let i = 0; i < iwconfigParts.length; i++) {
if (iwconfigParts[i].indexOf('no wireless') === -1) {
iface = iwconfigParts[i].split(' ')[0];
}
result = getWifiNetworkListNmi();
if (result.length === 0) {
try {
const iwconfigParts = execSync('export LC_ALL=C; iwconfig 2>/dev/null; unset LC_ALL').toString().split('\n\n');
let iface = '';
for (let i = 0; i < iwconfigParts.length; i++) {
if (iwconfigParts[i].indexOf('no wireless') === -1) {
iface = iwconfigParts[i].split(' ')[0];
}
if (iface) {
const res = getWifiNetworkAlt(iface);
if (res === -1) {
// try again after 4 secs
setTimeout(function (iface) {
const res = getWifiNetworkAlt(iface);
if (res != -1) { result = res; }
if (callback) {
callback(result);
}
resolve(result);
}, 4000);
} else {
result = res;
}
if (iface) {
const res = getWifiNetworkListIw(iface);
if (res === -1) {
// try again after 4 secs
setTimeout(function (iface) {
const res = getWifiNetworkListIw(iface);
if (res != -1) { result = res; }
if (callback) {
callback(result);
}
resolve(result);
}
}, 4000);
} else {
result = res;
if (callback) {
callback(result);
}
resolve(result);
}
} catch (e) {
} else {
if (callback) {
callback(result);
}
resolve(result);
}
} else {
} catch (e) {
if (callback) {
callback(result);
}
resolve(result);
}
});
} else {
if (callback) {
callback(result);
}
resolve(result);
}
} else if (_darwin) {
let cmd = '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -s';
exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
@@ -361,3 +443,240 @@ function wifiNetworks(callback) {
}
exports.wifiNetworks = wifiNetworks;
function getVendor(model) {
model = model.toLowerCase();
let result = '';
if (model.indexOf('intel') >= 0) { result = 'Intel'; }
else if (model.indexOf('realtek') >= 0) { result = 'Realtek'; }
else if (model.indexOf('qualcom') >= 0) { result = 'Qualcom'; }
else if (model.indexOf('broadcom') >= 0) { result = 'Broadcom'; }
else if (model.indexOf('cavium') >= 0) { result = 'Cavium'; }
else if (model.indexOf('cisco') >= 0) { result = 'Cisco'; }
else if (model.indexOf('marvel') >= 0) { result = 'Marvel'; }
else if (model.indexOf('zyxel') >= 0) { result = 'Zyxel'; }
else if (model.indexOf('melanox') >= 0) { result = 'Melanox'; }
else if (model.indexOf('d-link') >= 0) { result = 'D-Link'; }
else if (model.indexOf('tp-link') >= 0) { result = 'TP-Link'; }
else if (model.indexOf('asus') >= 0) { result = 'Asus'; }
else if (model.indexOf('linksys') >= 0) { result = 'Linksys'; }
return result;
}
function wifiConnections(callback) {
return new Promise((resolve) => {
process.nextTick(() => {
const result = [];
if (_linux) {
const ifaces = ifaceListLinux();
const networkList = getWifiNetworkListNmi();
ifaces.forEach(ifaceDetail => {
const nmiDetails = nmiDeviceLinux(ifaceDetail.iface);
const wpaDetails = wpaConnectionLinux(ifaceDetail.iface);
const ssid = nmiDetails.ssid;
const network = networkList.filter(nw => nw.ssid === ssid);
const nmiConnection = nmiConnectionLinux(ssid);
const channel = network && network.length && network[0].channel ? network[0].channel : null;
result.push({
id: ifaceDetail.id,
iface: ifaceDetail.iface,
model: nmiDetails.product,
ssid,
bssid: network && network.length && network[0].bssid ? network[0].bssid : (wpaDetails && wpaDetails.bssid ? wpaDetails.bssid : null),
channel,
frequency: channel ? wifiFrequencyFromChannel(channel) : null,
type: nmiConnection && nmiConnection.type ? nmiConnection.type : '802.11',
security: nmiConnection && nmiConnection.security ? nmiConnection.security : (wpaDetails && wpaDetails.security ? wpaDetails.security : null),
signalLevel: network && network.length && network[0].signalLevel ? network[0].signalLevel : null,
txRate: null
});
});
if (callback) {
callback(result);
}
resolve(result);
} else if (_darwin) {
let cmd = 'system_profiler SPNetworkDataType';
exec(cmd, function (error, stdout) {
const parts1 = stdout.toString().split('\n\n Wi-Fi:\n\n');
if (parts1.length > 1) {
const lines = parts1[1].split('\n\n')[0].split('\n');
const iface = util.getValue(lines, 'BSD Device Name', ':', true);
const model = util.getValue(lines, 'hardware', ':', true);
cmd = '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I';
exec(cmd, function (error, stdout) {
const lines2 = stdout.toString().split('\n');
if (lines.length > 10) {
const ssid = util.getValue(lines2, 'ssid', ':', true);
const bssid = util.getValue(lines2, 'bssid', ':', true);
const security = util.getValue(lines2, 'link auth', ':', true);
const txRate = util.getValue(lines2, 'lastTxRate', ':', true);
const channel = util.getValue(lines2, 'channel', ':', true).split(',')[0];
const type = '802.11';
const rssi = util.toInt(util.getValue(lines2, 'agrCtlRSSI', ':', true));
const noise = util.toInt(util.getValue(lines2, 'agrCtlNoise', ':', true));
const signalLevel = rssi - noise;
// const signal = wifiQualityFromDB(signalLevel);
if (ssid && bssid) {
result.push({
id: 'Wi-Fi',
iface,
model,
ssid,
bssid,
channel: util.toInt(channel),
frequency: channel ? wifiFrequencyFromChannel(channel) : null,
type,
security,
signalLevel,
txRate
});
}
}
if (callback) {
callback(result);
}
resolve(result);
});
}
});
} else if (_windows) {
let cmd = 'netsh wlan show interfaces';
exec(cmd, util.execOptsWin, function (error, stdout) {
const parts = stdout.toString().split(':\r\n\r\n');
parts.shift();
parts.forEach(part => {
const lines = part.split('\r\n');
if (lines.length >= 5) {
const iface = lines[0].indexOf(':') >= 0 ? lines[0].split(':')[1].trim() : '';
const model = lines[1].indexOf(':') >= 0 ? lines[1].split(':')[1].trim() : '';
const id = lines[2].indexOf(':') >= 0 ? lines[2].split(':')[1].trim() : '';
const ssid = util.getValue(lines, 'SSID', ':', true);
const bssid = util.getValue(lines, 'BSSID', ':', true);
const signalLevel = util.getValue(lines, 'Signal', ':', true);
const type = util.getValue(lines, 'Radio type', ':', true) || util.getValue(lines, 'Type de radio', ':', true) || util.getValue(lines, 'Funktyp', ':', true) || null;
const security = util.getValue(lines, 'authentication', ':', true) || util.getValue(lines, 'Authentification', ':', true) || util.getValue(lines, 'Authentifizierung', ':', true) || null;
const channel = util.getValue(lines, 'Channel', ':', true) || util.getValue(lines, 'Canal', ':', true) || util.getValue(lines, 'Kanal', ':', true) || null;
const txRate = util.getValue(lines, 'Transmit rate (mbps)', ':', true) || util.getValue(lines, 'Transmission (mbit/s)', ':', true) || util.getValue(lines, 'Übertragungsrate (MBit/s)', ':', true) || null;
if (model && id && ssid && bssid) {
result.push({
id,
iface,
model,
ssid,
bssid,
channel: util.toInt(channel),
frequency: channel ? wifiFrequencyFromChannel(channel) : null,
type,
security,
signalLevel,
txRate
});
}
}
});
if (callback) {
callback(result);
}
resolve(result);
});
} else {
if (callback) {
callback(result);
}
resolve(result);
}
});
});
}
exports.wifiConnections = wifiConnections;
function wifiInterfaces(callback) {
return new Promise((resolve) => {
process.nextTick(() => {
const result = [];
if (_linux) {
const ifaces = ifaceListLinux();
ifaces.forEach(ifaceDetail => {
const nmiDetails = nmiDeviceLinux(ifaceDetail.iface);
result.push({
id: ifaceDetail.id,
iface: ifaceDetail.iface,
name: ifaceDetail.name,
model: nmiDetails.product,
vendor: nmiDetails.vendor,
mac: ifaceDetail.mac,
});
});
if (callback) {
callback(result);
}
resolve(result);
} else if (_darwin) {
let cmd = 'system_profiler SPNetworkDataType';
exec(cmd, function (error, stdout) {
const parts1 = stdout.toString().split('\n\n Wi-Fi:\n\n');
if (parts1.length > 1) {
const lines = parts1[1].split('\n\n')[0].split('\n');
const iface = util.getValue(lines, 'BSD Device Name', ':', true);
const mac = util.getValue(lines, 'MAC Address', ':', true);
const model = util.getValue(lines, 'hardware', ':', true);
result.push({
id: 'Wi-Fi',
iface,
model,
vendor: '',
mac
});
}
if (callback) {
callback(result);
}
resolve(result);
});
} else if (_windows) {
let cmd = 'netsh wlan show interfaces';
exec(cmd, util.execOptsWin, function (error, stdout) {
const parts = stdout.toString().split(':\r\n\r\n');
parts.shift();
parts.forEach(part => {
const lines = part.split('\r\n');
if (lines.length >= 5) {
const iface = lines[0].indexOf(':') >= 0 ? lines[0].split(':')[1].trim() : '';
const model = lines[1].indexOf(':') >= 0 ? lines[1].split(':')[1].trim() : '';
const id = lines[2].indexOf(':') >= 0 ? lines[2].split(':')[1].trim() : '';
const mac = lines[3].indexOf(':') >= 0 ? lines[3].split(':')[1].trim() : '';
const vendor = getVendor(model);
if (iface && model && id && mac) {
result.push({
id,
iface,
model,
vendor,
mac,
});
}
}
});
if (callback) {
callback(result);
}
resolve(result);
});
} else {
if (callback) {
callback(result);
}
resolve(result);
}
});
});
}
exports.wifiInterfaces = wifiInterfaces;