domotz-remote-pawn
Version:
Domotz Agent
961 lines (887 loc) • 36.4 kB
JavaScript
/** This file is part of Domotz Agent.
* Copyright (C) 2016 Domotz Ltd
*
* Domotz Agent is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Domotz Agent is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Domotz Agent. If not, see <http://www.gnu.org/licenses/>.
**/
/**
* Created by Tommaso Latini <tommaso@domotz.com> on 25/07/15.
*
* This module recover host information on a UNIX-like operating system (like
* Debian, DSM, Qnap OS).
*
* These information are fundamental for the application, so we recover it
* synchronously at boot and we exit in case of failure.
* The periodical refresh is asynchronous for not blocking nodejs mainloop.
*/
const MODULE_NAME = 'HOST_INTERFACES - ';
const MAC_VALIDATOR = /^(?!(?:ff:ff:ff:ff:ff:ff|00:00:00:00:00:00))(?:[\da-f]{2}:){5}[\da-f]{2}$/i;
const DEFAULT_IP_BLACKLIST = ['10.177.0.1', '192.168.112.112'];
const RECOVER_HOST_INFO_RETRY = 1000;
function checkMac(mac) {
if (!mac || !MAC_VALIDATOR.test(mac.toLowerCase())) {
throw new Error(MODULE_NAME + ' - Invalid MAC address [' + mac + ']. ' + 'Invalid interface');
}
}
var factory = function (networkInterfaces, customInterfaces, resourceLocator) {
var proc = resourceLocator.utils.proc;
var childProcess = resourceLocator.utils.childProcess;
var fileManager = resourceLocator.utils.file;
var platform = resourceLocator.utils.platform;
var ipUtils = resourceLocator.ip;
var nmapXml2Js = resourceLocator.xml2Js;
var lodash = resourceLocator.lodash;
var q = resourceLocator.q;
var dns = resourceLocator.networkTools.dns;
var netmask = resourceLocator.networkTools.netmask;
var myConsole = resourceLocator.log.decorateLogs();
function checkIp(address) {
var ipAddress = new ipUtils.Address4(address);
if (!ipAddress.valid || !ipAddress.v4) {
throw new Error(MODULE_NAME + ' - Invalid IP address. [' + address + '] ' + 'Maybe the interface is not connected.');
}
}
function logInterface(name, mac, ip, netmask) {
myConsole.info('(%s): MAC address: [%s] - IP address: [%s] - Netmask: [%s].', name, mac, ip, netmask);
}
/**
* [**interfacesList] should be an hash of couple:
* <interface_name>: { mac: <mac_address> }
* At least mac address MUST be into interfaces list because
* it is used by licence api for binding domotz agent.
*
* [**defaultInterface] is the name of the interface of the default gateway
*/
var iteration = 0;
var Netmask = netmask.Netmask;
const nonAscii = /[^\x00-\x7F]/g;
function sanitiseNonAscii(str) {
return str.replace(nonAscii, '');
}
function renameNonASCIIKeys(obj) {
Object.keys(obj).forEach(function (key) {
if (nonAscii.test(key)) {
const newKey = sanitiseNonAscii(key);
obj[newKey] = obj[key];
delete obj[key];
}
});
}
function setIteration(i) {
iteration = i;
}
var interfacesList = {};
var defaultGateway = null;
var defaultGatewayMAC = null;
var defaultInterface = null;
var unicastInterfaces = null;
var multicastInterfaces = null;
var fullIpList = [];
function mergeCustomInterfaces(tmp) {
var previousCustomInterfaces = lodash.omitBy(interfacesList, function (value) {
return value.custom !== true;
});
interfacesList = lodash.extend(tmp, previousCustomInterfaces);
}
function recoverHostInfoV1() {
myConsole.info('recoverHostInfoV1 ...');
return proc
.spawn('ip', ['route'])
.then(function (data) {
var lines = data.toString().split(/\r?\n/);
lines.every(function (item) {
var fields = item.split(/ +/);
myConsole.info('route line = > %s', item, {});
if (fields[0] === 'default' && fields[1] === 'via') {
myConsole.debug('Fields = %j', fields, {});
defaultGateway = fields[2];
myConsole.info('Detected gateway => %s', defaultGateway, {});
return false;
}
return true;
});
})
.then(networkInterfaces.getDefaultGatewayAsync)
.then(function (descr) {
defaultInterface = descr.interface;
})
.then(networkInterfaces.getInterfacesAsync)
.then(function (list) {
if (!list || !list.length) {
throw new Error(MODULE_NAME + ': No valid interfaces in the final list');
}
var tmp = {};
list.forEach(function (nic) {
var name = nic.name;
logInterface(name, nic.mac, nic.ip, nic.netmask, defaultInterface);
delete nic.name;
tmp[name] = nic;
});
mergeCustomInterfaces(tmp);
})
.then(getGatewayMac);
}
function recoverHostInfoWinV1() {
myConsole.info('recoverHostInfoWinV1');
return proc
.spawn('route', ['print', '-4'])
.then(function (output) {
if (!output) {
return q.reject();
}
myConsole.debug('Parsing: %s', output);
var rows = output.split('\n');
var counter = 0;
var row;
for (var i = 0; i < rows.length; i++) {
if (rows[i].indexOf('====') === 0) {
counter++;
if (counter === 3) {
row = rows[i + 3];
break;
}
}
}
var fields = row.split(/\s+/);
myConsole.debug('Fields = %j', fields);
defaultGateway = fields[3];
myConsole.info('Detected gateway => %s', defaultGateway);
})
.then(networkInterfaces.getDefaultGatewayAsyncWin)
.then(function (descr) {
defaultInterface = descr.interface;
})
.then(networkInterfaces.getInterfacesAsyncWin)
.then(function (list) {
if (!list || !list.length) {
throw new Error(MODULE_NAME + ': No valid interfaces in the final list');
}
var tmp = {};
list.forEach(function (nic) {
var name = nic.name;
logInterface(name, nic.mac, nic.ip, nic.netmask, defaultInterface);
delete nic.name;
tmp[name] = nic;
});
mergeCustomInterfaces(tmp);
})
.then(getGatewayMac);
}
function recoverHostInfoV2() {
myConsole.info('recoverHostInfoV2');
var path = require('path');
return proc
.spawn(path.join(process.env.DOMOTZ_BIN_DIR, 'domotz_network_utils'))
.then(function (output) {
myConsole.debug('raw output ' + output);
var rows = output.split('\n');
var tmp = {};
var interfaceFound = false;
for (var i = 0; i < rows.length && rows[i].length; i++) {
if (rows[i] === '---') {
// ---
// Default Gateway: 192.168.77.1 (or empty)
// Interface: eth1
// IPv4: 192.168.77.5
// MAC: 08:00:27:53:3a:53
// CIDR: 24
var defaultGatewayFound = false;
if (!defaultGateway) {
defaultGateway = rows[++i].slice(17);
defaultGatewayFound = true;
} else {
i++;
}
var name = rows[++i].slice(11);
var ip = rows[++i].slice(6);
var mac = rows[++i].slice(5).toUpperCase();
var netmask = parseInt(rows[++i].slice(6));
try {
checkIp(ip);
checkMac(mac);
if (defaultGateway && defaultGatewayFound) {
defaultInterface = name;
myConsole.info('(%s): Default Gateway on %s', name, defaultGateway);
}
logInterface(name, mac, ip, netmask);
tmp[name] = {
ip: ip,
mac: mac,
netmask: netmask,
};
interfaceFound = true;
} catch (err) {
myConsole.warn(err.message);
}
}
}
if (!interfaceFound) {
throw new Error('Unable to find a configured network interface');
}
mergeCustomInterfaces(tmp);
})
.then(function () {
overrideDefaultInterface();
})
.then(fixDefaultGateway)
.then(getGatewayMac);
}
function isInterfaceValid(iface) {
if (iface.family !== 'IPv4') {
return false;
}
if (iface.mac === '00:00:00:00:00:00') {
return false;
}
if (DEFAULT_IP_BLACKLIST.indexOf(iface.address) !== -1) {
myConsole.debug('Skip blacklisted interface with IP: %s', iface.address);
return false;
}
return true;
}
function getWindowsGatewayPowershell() {
function powershellExec(cmd) {
cmd = 'powershell.exe "' + cmd.replace(/"/gi, '\\"') + '"';
var rawOutput = childProcess.execSync(cmd).toString();
return JSON.parse(rawOutput);
}
var defaultGatewayInfo = powershellExec(
'Get-CimInstance Win32_NetworkAdapterConfiguration -filter "IPEnabled=true" ' + ' | Select-Object DefaultIPGateway,Index | ConvertTo-JSON'
);
if (defaultGatewayInfo.length) {
defaultGatewayInfo = lodash.filter(defaultGatewayInfo, function (value) {
return value.DefaultIPGateway !== null;
});
defaultGatewayInfo = defaultGatewayInfo[0];
}
var gatewayIP = defaultGatewayInfo.DefaultIPGateway[0];
var gatewayIfIndex = defaultGatewayInfo.Index;
var getInterfaceName =
'Get-CimInstance Win32_NetworkAdapter -filter "Index=' + gatewayIfIndex + '" | Select-Object NetConnectionID,MacAddress | ConvertTo-JSON';
var ifNameOutput = powershellExec(getInterfaceName).NetConnectionID;
return {
gateway: gatewayIP,
interface: ifNameOutput,
};
}
function overrideDefaultInterface() {
if (platform.isNetgearRouter()) {
var netgearInterface = platform.netgearRouterDefaultInterface();
if (getIP(netgearInterface)) {
myConsole.info('Netgear Router platform: default interface is on %s', netgearInterface);
defaultInterface = netgearInterface;
} else {
myConsole.error('%s not found, cannot override default interface', netgearInterface);
}
}
}
function recoverHostInfoNative() {
myConsole.info('recoverHostInfoNative');
var gw;
if (platform.isWindows()) {
try {
gw = getWindowsGatewayPowershell();
} catch (e) {
myConsole.warn('Unable to parse powershell output %s', e.toString());
try {
gw = require('default-gateway').v4.sync();
} catch (e) {
myConsole.error('Unable to obtain default gateway');
return q.reject();
}
}
} else {
try {
gw = require('default-gateway').v4.sync();
} catch (e) {
myConsole.error('Unable to obtain default gateway');
return q.reject();
}
}
if (!gw) {
myConsole.error('Unable to obtain default gateway');
gw = {};
}
if (Object.keys(gw).length > 0) {
defaultGateway = gw.gateway;
defaultInterface = sanitiseNonAscii(gw.interface);
myConsole.info('(%s): Default Gateway on %s', defaultInterface, defaultGateway);
}
// exploring network interfaces
var interfaces = require('os').networkInterfaces();
renameNonASCIIKeys(interfaces);
var tmp = {};
var interfaceFound = false;
Object.keys(interfaces).forEach(function (interfaceName) {
interfaces[interfaceName].forEach(function (element) {
if (isInterfaceValid(element)) {
var name = interfaceName;
var ip = element.address;
var mac = element.mac;
var addr = new Netmask(element.address + '/' + element.netmask);
try {
checkIp(ip);
checkMac(mac);
logInterface(name, mac, ip, addr.bitmask);
tmp[name] = {
ip: ip,
mac: mac,
netmask: addr.bitmask,
};
interfaceFound = true;
} catch (err) {
myConsole.warn(err.message);
}
}
});
});
if (!interfaceFound) {
throw new Error('Unable to find a valid interface');
}
mergeCustomInterfaces(tmp);
overrideDefaultInterface();
fixDefaultGatewayWin()
.then(getGatewayMac)
.catch(function (e) {
myConsole.error('Error recovering gateway information %s', JSON.stringify(e));
});
return q.resolve();
}
function fixDefaultGateway() {
if (defaultGateway && defaultGateway === '255.255.255.127' && fileManager.getFileStats('/sbin/route')) {
myConsole.info('retrieving default gateway using route');
return proc
.spawn('/sbin/route', ['-n'])
.then(function (output) {
if (!output) {
return;
}
myConsole.debug('Parsing: %s', output);
var row = output.split('\n')[2].replace(/\s\s+/g, ' ');
defaultGateway = row.split(' ')[1];
myConsole.info('Replaced default gateway with %s using route', defaultGateway);
})
.catch(function (e) {
myConsole.error('Error getting default gateway using route %s', JSON.stringify(e));
});
}
}
function fixDefaultGatewayWin() {
if (!platform.isWindows()) {
return q.resolve();
}
myConsole.info('retrieving default gateway using route');
return proc.spawn('route', ['print', '-4']).then(function (output) {
if (!output) {
return q.reject();
}
myConsole.debug('Parsing: %s', output);
var rows = output.split('\n');
var counter = 0;
var row;
for (var i = 0; i < rows.length; i++) {
if (rows[i].indexOf('====') === 0) {
counter++;
if (counter === 3) {
row = rows[i + 3];
break;
}
}
}
defaultGateway = row.split(/(\s+)/).filter(function (e) {
return e.trim().length > 0;
})[2];
myConsole.info('Replaced default gateway with %s using route', defaultGateway);
});
}
function getGatewayMac() {
'use strict';
myConsole.info('Searching for Gateway MAC address');
if (!defaultGateway) {
myConsole.info('No Default Gateway MAC');
return q.reject();
}
return proc
.spawn('domotz_nmap', ['-sP', '-oX', '-', defaultGateway])
.then(function (output) {
myConsole.debug('Parsing: %s', output);
nmapXml2Js
.toJSON(output)
.then(function (xml) {
myConsole.debug('%s', JSON.stringify(xml));
xml.nmaprun.host[0].address.every(function (addr) {
if (addr.$.addrtype === 'mac') {
defaultGatewayMAC = addr.$.addr;
myConsole.info('Gateway MAC address: %s', defaultGatewayMAC);
return false;
}
return true;
});
})
.catch(function () {
myConsole.warn('Cannot parse arp output to get default gateway MAC, using onw MAC: %s', output);
defaultGatewayMAC = interfacesList[0].mac;
});
})
.catch(function (e) {
myConsole.error('Error getting default gateway %s', JSON.stringify(e));
});
}
function refreshCustomInterfaces(customSubnets) {
var networkInterfaces = lodash.omitBy(interfacesList, function (element) {
return element.custom === true;
});
var subnets;
if (!customSubnets || Object.keys(customSubnets).length === 0) {
//try to load legacy file-based interfaces. Returns empty object as a fallback
subnets = customInterfaces.get();
} else {
subnets = customSubnets;
}
interfacesList = lodash.extend(subnets, networkInterfaces);
}
function fallbackLinuxHostInfo() {
if (networkInterfaces) {
return recoverHostInfoV1().catch(function () {
return recoverHostInfoV2();
});
} else {
return recoverHostInfoV2();
}
}
function recoverHostInfo() {
if (process.env.USE_RECOVER_HOST_INFO_V2) {
myConsole.info('forcing recoverHostInfoV2 for testing purposes');
return recoverHostInfoV2();
}
if (platform.isNetgearRouter()) {
myConsole.info('forcing recoverHostInfoV2 for Netgear routers');
return recoverHostInfoV2();
}
if (platform.isWindows()) {
return recoverHostInfoNative().catch(function () {
myConsole.warn('Windows native host info retrieval failed, falling back to recoverHostInfoWinV1');
return recoverHostInfoWinV1();
});
} else if (platform.isUbuntuCore() || (!platform.isNodeVersionZero() && fileManager.isExecutableAvailableInPATH('ip'))) {
return recoverHostInfoNative().catch(function () {
return fallbackLinuxHostInfo();
});
} else {
myConsole.info('Using fallback methods on legacy platforms');
return fallbackLinuxHostInfo();
}
}
function recoverHostInfoWithRetry(deferred) {
var hostInfoDeferred = deferred || q.defer();
recoverHostInfo()
.then(function () {
refreshCustomInterfaces();
hostInfoDeferred.resolve();
})
.catch(function () {
setTimeout(function () {
myConsole.warn('Failed retrieving network info, scheduling retry in %s ms', RECOVER_HOST_INFO_RETRY);
recoverHostInfoWithRetry(hostInfoDeferred);
}, RECOVER_HOST_INFO_RETRY);
});
return hostInfoDeferred.promise;
}
var getCustomInterfaces = function () {
return lodash.omitBy(interfacesList, function (el) {
return el.custom !== true;
});
};
function commonChecks(device) {
var customInterfaces = getCustomInterfaces();
if (!customInterfaces) {
return false;
}
if (Object.keys(customInterfaces).length === 0) {
return false;
}
return device.length;
}
var deviceBelongsToExternalSubnet = function (device) {
if (!commonChecks(device)) {
return false;
}
for (var k = 0; k < device.length; k++) {
if (isInCustomSubnet(device[k].ip)) {
return true;
}
}
return false;
};
var deviceBelongsToExternalHosts = function (device) {
if (!commonChecks(device)) {
return false;
}
for (var k = 0; k < device.length; k++) {
if (getExternalHostMac(device[k].ip)) {
return true;
}
}
return false;
};
function getExternalHostMac(ipAddr) {
var customInterfaces = getCustomInterfaces();
for (var customId in customInterfaces) {
var custom = customInterfaces[customId];
if (custom.discovery_hw_address && custom.ip == ipAddr) {
return custom.discovery_hw_address;
}
}
return false;
}
function isAddressInInterfaceSubnet(ipAddr, interface_) {
if (!interface_.ip) {
return false;
}
var netAddress = new ipUtils.Address4(interface_.ip + '/' + interface_.netmask);
if (!netAddress.valid) {
return false;
}
if (interface_.netmask == 32 && ipAddr === interface_.ip) {
return true;
}
var addr = new ipUtils.Address4(ipAddr);
return addr.isInSubnet(netAddress);
}
function isInCustomSubnet(ipAddr) {
var customInterfaces = getCustomInterfaces();
for (var customId in customInterfaces) {
if (isAddressInInterfaceSubnet(ipAddr, customInterfaces[customId])) {
return true;
}
}
return false;
}
function resolveExternalHosts() {
myConsole.info('(%d): Resolving external hosts ...', iteration);
myConsole.debug('(%d): %s', iteration, JSON.stringify(interfacesList));
var promises = [];
for (var name in interfacesList) {
var i = interfacesList[name];
if (i.custom && i.hostname) {
promises.push(
(function (obj) {
var p = q.defer();
myConsole.info('(%d): Resolving ', iteration, JSON.stringify(obj.hostname));
myConsole.debug('(%d): DNS lookup START ...', iteration);
var addressFamily = 4;
dns.lookup(obj.hostname, addressFamily, function (err, ip) {
if (err) {
myConsole.warn('(%d): Error resolving hostname %s: %s', iteration, obj.hostname, JSON.stringify(err));
p.resolve();
return;
}
myConsole.info('(%d): Successfully resolved hostname %s: %s', iteration, obj.hostname, JSON.stringify(ip));
if (typeof ip === 'string') {
obj.ip = ip;
} else {
obj.ip = ip[0];
}
p.resolve();
});
return p.promise;
})(i)
);
}
}
return q.all(promises);
}
function setFullIpList(l) {
fullIpList = lodash.uniq(l);
}
function getInterfacesList() {
lodash.forOwn(interfacesList, function (value, key) {
interfacesList[key].ipList = [];
});
lodash.forEach(fullIpList, function (rawIp) {
var ip = new ipUtils.Address4(rawIp);
if (!ip.valid) {
return;
}
lodash.forOwn(interfacesList, function (nic) {
if (nic.ip) {
var nicIp = new ipUtils.Address4(nic.ip + '/' + nic.netmask);
nic.broadcastAddress = nicIp.endAddress().address;
if (ip.isInSubnet(nicIp)) {
nic.ipList.push(rawIp);
}
}
});
});
return interfacesList;
}
function getAllowedInterfacesList() {
var interfaces = getInterfacesList();
if (!resourceLocator.settingsManager) {
myConsole.warn('Agent Settings not initialized yet, returning deny all interfaces list');
return {};
}
var policies = resourceLocator.settingsManager.getNetworkInterfacesPolicies();
var allowedInterfaces = lodash.pickBy(interfaces, function (value, key) {
if (isExternalHostInterface(key)) {
return false;
}
if (value.custom) {
return true;
}
var match = false;
policies.rules.forEach(function (rule) {
var processedRule = rule.replace(/\./g, '\\.').replace(/\*/g, '.*');
processedRule = '^' + processedRule + '$';
var regexp = new RegExp(processedRule, 'i');
if (regexp.test(key)) {
myConsole.info('Interface %s matched with filtering rule %s', key, processedRule);
match = true;
} else {
myConsole.debug('Interface %s did not match with filtering rule %s', key, processedRule);
}
});
return policies.policy === 'deny' ? !match : match;
});
var externalHostsInterfaces = lodash.pickBy(interfaces, function (value, key) {
return !!isExternalHostInterface(key);
});
allowedInterfaces = _extendInterfacesWithExternalHosts(allowedInterfaces, externalHostsInterfaces);
return extendInterfacesWithForcedIps(allowedInterfaces);
}
function getUnicastInterfacesList() {
if (unicastInterfaces === null && interfacesList) {
return lodash.omitBy(interfacesList, function (el) {
return el.custom !== true;
});
} else {
return unicastInterfaces;
}
}
function getMulticastInterfacesList() {
if (multicastInterfaces === null && interfacesList) {
return lodash.omitBy(interfacesList, function (el) {
return el.custom === true;
});
} else {
return multicastInterfaces;
}
}
function addIpToFullList(ip) {
if (fullIpList.indexOf(ip) < 0) {
fullIpList.push(ip);
}
}
function _extendInterfacesWithExternalHosts(allowedInterfaces, externalHostsInterfaces) {
myConsole.debug('Extending %s with %s', JSON.stringify(allowedInterfaces), JSON.stringify(externalHostsInterfaces));
var name;
var index = 0;
var ifName = 'external_hosts_' + index;
var ifChunk = {};
var current_external_hosts = 0;
var max_external_hosts = resourceLocator.settingsManager.getExternalHostsChunkSize();
var length = Object.keys(externalHostsInterfaces).length;
if (length > 0) {
allowedInterfaces = lodash.clone(allowedInterfaces);
} else {
return allowedInterfaces;
}
ifChunk[ifName] = {
custom: true,
ip: null,
netmask: null,
mac: null,
discovery_hw_address: null,
ipList: [],
forced_ip_list: true,
};
for (name in externalHostsInterfaces) {
if (externalHostsInterfaces.hasOwnProperty(name)) {
current_external_hosts++;
if (current_external_hosts > max_external_hosts) {
index++;
ifName = 'external_hosts_' + index;
ifChunk[ifName] = {
custom: true,
ip: null,
netmask: null,
mac: null,
discovery_hw_address: null,
ipList: [],
forced_ip_list: true,
};
current_external_hosts = 1;
}
var iface = externalHostsInterfaces[name];
ifChunk[ifName].ipList.push(iface.ip);
ifChunk[ifName].ip = iface.ip;
ifChunk[ifName].discovery_hw_address = iface.discovery_hw_address;
}
}
lodash.extend(allowedInterfaces, ifChunk);
myConsole.debug('Allowed interfaces extended with virtual external hosts interfaces: %s', JSON.stringify(allowedInterfaces));
return allowedInterfaces;
}
var _extendInterfacesWithForcedIpList = function (allowedInterfaces) {
var ipPolicy = resourceLocator.settingsManager.getIpPolicy();
if (ipPolicy.forced_ip_addresses.length > 0) {
var allowedIpAddresses = ipPolicy.forced_ip_addresses;
allowedInterfaces = lodash.clone(allowedInterfaces);
var chunks = lodash.chunk(allowedIpAddresses, ipPolicy.max_ip_per_nmap);
lodash.forEach(chunks, function (ipChunk, index) {
var ifChunk = {};
var ifName = 'forced_' + index;
ifChunk[ifName] = {
forced_ip_list: true,
ipList: ipChunk || [],
};
lodash.extend(allowedInterfaces, ifChunk);
});
}
return allowedInterfaces;
};
var _extendInterfacesWithForcedIpRanges = function (allowedInterfaces) {
var ipPolicy = resourceLocator.settingsManager.getIpPolicy();
if (ipPolicy.forced_ip_ranges.length > 0) {
var allowedIpAddressRanges = ipPolicy.forced_ip_ranges;
allowedInterfaces = lodash.clone(allowedInterfaces);
var ipRanges = {};
var name = 'forced_range';
ipRanges[name] = {
ipRange: allowedIpAddressRanges || [],
forced_ip_range: true,
};
lodash.extend(allowedInterfaces, ipRanges);
}
return allowedInterfaces;
};
var extendInterfacesWithForcedIps = function (allowedInterfaces) {
allowedInterfaces = _extendInterfacesWithForcedIpList(allowedInterfaces);
allowedInterfaces = _extendInterfacesWithForcedIpRanges(allowedInterfaces);
return allowedInterfaces;
};
var isCustomInterface = function (nic) {
var iface = interfacesList[nic];
return iface.custom && iface.custom === true;
};
var isExternalHostInterface = function (nic) {
var iface = interfacesList[nic];
return !!(iface.custom && iface.custom === true && iface.discovery_hw_address);
};
var getInternalInterface = function () {
return lodash.omitBy(interfacesList, function (el) {
return !el.mac;
});
};
var getIP = function getIP(nic) {
var selectedInterface = interfacesList[nic || defaultInterface];
if (!selectedInterface) {
return;
}
return selectedInterface.ip;
};
function isDeviceMacInL3DiscoveryDenyList(mac) {
if (!mac) {
return false;
}
if (!resourceLocator.settingsManager) {
return false;
}
var l3DiscoveryDenyList = resourceLocator.settingsManager.getL3DiscoveryDenyList();
return (l3DiscoveryDenyList.indexOf(mac) !== -1);
}
function isDeviceIPInL3DiscoveryDenyList(ip) {
if (!ip) {
return false;
}
if (!resourceLocator.interfacesBindingStorage){
return false;
}
var mac = resourceLocator.interfacesBindingStorage.getMacFromIp(ip);
return isDeviceMacInL3DiscoveryDenyList(mac);
}
function isMacInExternalHostsInterfaces (mac) {
const customInterfaces = getCustomInterfaces();
for (var customId in customInterfaces) {
var custom = customInterfaces[customId];
if (custom && custom.discovery_hw_address === mac) {
return true;
}
}
return false;
}
return {
recoverHostInfo: recoverHostInfo,
recoverHostInfoWithRetry: recoverHostInfoWithRetry,
getIP: getIP,
getMAC: function (nic) {
try {
return interfacesList[nic || defaultInterface].mac;
} catch (e) {
myConsole.warn('Unable to get interface Mac address');
}
},
getNetmask: function (nic) {
return interfacesList[nic || defaultInterface].netmask;
},
getDefaultInterface: function () {
return interfacesList[defaultInterface];
},
getDefaultGateway: function () {
return defaultGateway;
},
getDefaultGatewayMAC: function () {
return defaultGatewayMAC;
},
getInterfacesList: getInterfacesList,
getUnicastInterfacesList: getUnicastInterfacesList,
getMulticastInterfacesList: getMulticastInterfacesList,
getAllowedInterfacesList: getAllowedInterfacesList,
isCustomInterface: isCustomInterface,
isExternalHostInterface: isExternalHostInterface,
isDeviceMacInL3DiscoveryDenyList: isDeviceMacInL3DiscoveryDenyList,
isDeviceIPInL3DiscoveryDenyList: isDeviceIPInL3DiscoveryDenyList,
getInterface: function () {
return defaultInterface;
},
getInterfaceType: function (ip) {
for (var iface in interfacesList) {
if (interfacesList.hasOwnProperty(iface)) {
var nic = interfacesList[iface];
var nicIp = new ipUtils.Address4(nic.ip + '/' + nic.netmask);
var secondIp = new ipUtils.Address4(ip);
if (secondIp.isInSubnet(nicIp)) {
return nic.custom || false;
}
}
}
return false;
},
loadCustomInterfaces: refreshCustomInterfaces,
getCustomInterfaces: getCustomInterfaces,
deviceBelongsToExternalSubnet: deviceBelongsToExternalSubnet,
deviceBelongsToExternalHosts: deviceBelongsToExternalHosts,
getExternalHostMac: getExternalHostMac,
resolveExternalHosts: resolveExternalHosts,
IPisInCustomSubnet: isInCustomSubnet,
setFullIpList: setFullIpList,
fixDefaultGateway: fixDefaultGateway,
setIteration: setIteration,
_recoverHostInfoNative: recoverHostInfoNative,
addIpToFullList: addIpToFullList,
_getWindowsGatewayFallback: getWindowsGatewayPowershell,
getInternalInterfaces: getInternalInterface,
isMacInExternalHostsInterfaces: isMacInExternalHostsInterfaces,
};
};
module.exports.factory = factory;