UNPKG

domotz-remote-pawn

Version:

Domotz Agent

184 lines (171 loc) 7.28 kB
/** 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 IP_OCTET = "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"; const IP_VALIDATOR = new RegExp("^(" + IP_OCTET + "\.){3}" + IP_OCTET + "$"); const LINK_LOCAL = new RegExp("^169\.254\." + IP_OCTET + "\." + IP_OCTET + "$"); const MAC_VALIDATOR = /^(?!(?:ff:ff:ff:ff:ff:ff|00:00:00:00:00:00))(?:[\da-f]{2}:){5}[\da-f]{2}$/i; function logInterface(name, mac, ip, netmask) { console.info('%s - (%s): MAC address: [%s] - ' + 'IP address: [%s] - Netmask: [%s].', MODULE_NAME, name, mac, ip, netmask); } function checkIp(addr) { if (!IP_VALIDATOR.test(addr) || LINK_LOCAL.test(addr)) { throw new Error(MODULE_NAME + " - Invalid IP address. [" + addr + "] " + "Maybe the interface is not connected."); } } function checkMac(mac) { if (!mac || !MAC_VALIDATOR.test(mac.toLowerCase())) { throw new Error(MODULE_NAME + " - Invalid MAC address [" + mac + "]. " + "Maybe not a valid interface!"); } } var factory = function (proc, ipUtils, networkInterfaces, customInterfaces) { /** * [**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 interfacesList = {}, defaultGateway = null, defaultInterface = null; var recoverHostInfo = networkInterfaces ? recoverHostInfoV1 : recoverHostInfoV2; function recoverHostInfoV1() { return proc.spawn('ip', ['route']) .then(function (data) { var lines = data.toString().split(/\r?\n/); lines.every(function (item) { var fields = item.split(/ +/); console.debug(MODULE_NAME + ': route line = > %s', item, {}); if (fields[0] === "default" && fields[1] === "via") { console.debug(MODULE_NAME + ': Fields = %j', fields, {}); defaultGateway = fields[2]; console.info(MODULE_NAME + ': 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 = customInterfaces.get(); list.forEach(function (nic) { var name = nic.name; logInterface(name, nic.mac, nic.ip, nic.netmask, defaultInterface); delete nic.name; tmp[name] = nic; }); interfacesList = tmp; }); } function recoverHostInfoV2() { return proc.spawn('domotz_network_utils') .then(function(output) { var rows = output.split('\n'); var tmp = customInterfaces.get(); 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 defaultGateway = rows[++i].slice(17); 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) { defaultInterface = name; console.info('%s - (%s): Default Gateway on %s', MODULE_NAME, name, defaultGateway); } logInterface(name, mac, ip, netmask); tmp[name] = { ip: ip, mac: mac, netmask: netmask }; } catch (err) { console.warn(err.message); } } } interfacesList = tmp; }); } recoverHostInfo(); return { recoverHostInfo: recoverHostInfo, getIP: function getIP(nic) { return interfacesList[nic || defaultInterface].ip; }, getMAC: function (nic) { return interfacesList[nic || defaultInterface].mac; }, getNetmask: function (nic) { return interfacesList[nic || defaultInterface].netmask; }, getDefaultGateway: function () { return defaultGateway; }, getInterfacesList: function () { return interfacesList; }, getInterface: function () { return defaultInterface; }, getInterfaceType: function(ip) { for (var iface in interfacesList) { if (interfacesList.hasOwnProperty(iface)) { var nic = interfacesList[iface]; if (ipUtils.cidrSubnet(nic.ip + '/' + nic.netmask).contains(ip)) { return nic.custom || false; } } } return false; } }; }; module.exports.factory = factory;