Advertisement
dckiller

Openwrt Monitoring SSH

Aug 9th, 2021
458
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 17.54 KB | None | 0 0
  1. <?php
  2.  
  3. /* This file is part of Jeedom.
  4. *
  5. * Jeedom is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * Jeedom is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with Jeedom. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18.  
  19. /* * ***************************Includes********************************* */
  20. require_once dirname(__FILE__) . '/../../../../core/php/core.inc.php';
  21.  
  22. class openWrt extends eqLogic
  23. {
  24.   /*     * ************************* Attributs ****************************** */
  25.  
  26.   public static $_connection = false;
  27.  
  28.   /*     * *********************** Methodes statiques *************************** */
  29.  
  30.   /*
  31.    * Fonction exécutée automatiquement toutes les minutes par Jeedom */
  32.   public static function cron()
  33.   {
  34.     if (self::getCron() == 'cron1') {
  35.       self::refreshDevices();
  36.       self::refreshRouters();
  37.     }
  38.   }
  39.   public static function cron5()
  40.   {
  41.     if (self::getCron() == 'cron5') {
  42.       self::refreshDevices();
  43.       self::refreshRouters();
  44.     }
  45.   }
  46.   public static function cron10()
  47.   {
  48.     if (self::getCron() == 'cron10') {
  49.       self::refreshDevices();
  50.       self::refreshRouters();
  51.     }
  52.   }
  53.   public static function cron15()
  54.   {
  55.     if (self::getCron() == 'cron15') {
  56.       self::refreshDevices();
  57.       self::refreshRouters();
  58.     }
  59.   }
  60.   public static function cron30()
  61.   {
  62.     if (self::getCron() == 'cron30') {
  63.       self::refreshDevices();
  64.       self::refreshRouters();
  65.     }
  66.   }
  67.   public static function cronHourly()
  68.   {
  69.     if (self::getCron() == 'cron60') {
  70.       self::refreshDevices();
  71.       self::refreshRouters();
  72.     }
  73.   }
  74.  
  75.   private static function getCron()
  76.   {
  77.     $cron = config::byKey('cron', 'openWrt');
  78.     return array_search('1', $cron);
  79.   }
  80.  
  81.   public static function refreshDevices()
  82.   {
  83.     $equipments = openWrt::getDevices();
  84.  
  85.     foreach (eqLogic::byType("openWrt", true) as $equipment) {
  86.       $equipment->refreshEq($equipments);
  87.     }
  88.   }
  89.  
  90.   public static function refreshRouters()
  91.   {
  92.     $result = openWrt::getRouter();
  93.     $eqlogic = openWrt::byLogicalId('router', 'openWrt');
  94.     if (!is_object($eqlogic)) {
  95.       $eqlogic = new openWrt();
  96.       $eqlogic->setEqType_name('openWrt');
  97.       $eqlogic->setLogicalId('router');
  98.       $eqlogic->setIsEnable(1);
  99.       $eqlogic->setIsVisible(1);
  100.       $eqlogic->setName('Routeur');
  101.       $eqlogic->save();
  102.     }
  103.     $eqlogic->loadCmdFromConf('router');
  104.  
  105.     //Récupération des interfaces wifi
  106.     foreach ($result['wifiIface'] as $logicalid => $wiface) {
  107.       $command = null;
  108.       if (sizeof($wiface->interfaces) > 0) {
  109.         $command["logicalId"] = $logicalid;
  110.         $command["name"] = $wiface->interfaces[0]->ifname . " Statut (" . $wiface->interfaces[0]->config->ssid . ")";
  111.         $command["type"] = "info";
  112.         $command["subtype"] = "binary";
  113.         $command["isVisible"] = 0;
  114.  
  115.         $cmdInfo = $eqlogic->createCmd($command);
  116.         $eqlogic->checkAndUpdateCmd($logicalid, sizeof($wiface->interfaces) > 0);
  117.  
  118.         $command["logicalId"] = $logicalid . "on";
  119.         $command["name"] = $wiface->interfaces[0]->ifname . " On";
  120.         $command["type"] = "action";
  121.         $command["subtype"] = "other";
  122.         $command["value"] = $cmdInfo->getId();
  123.         $command["configuration"] = ['type' => 'ifaceon'];
  124.         $eqlogic->createCmd($command);
  125.  
  126.         $command["logicalId"] = $logicalid . "off";
  127.         $command["name"] = $wiface->interfaces[0]->ifname . " Off";
  128.         $command["configuration"] = ['type' => 'ifaceoff'];
  129.         $eqlogic->createCmd($command);
  130.       } else {
  131.         $eqlogic->checkAndUpdateCmd($logicalid, sizeof($wiface->interfaces) > 0);
  132.       }
  133.     }
  134.  
  135.     //Calculs de la vitesse des échanges en fonction du dernier cron
  136.     $MBpsConvert = substr(self::getCron(), 4) * 60 * 1048576;
  137.     $cmd = cmd::byEqLogicIdAndLogicalId($eqlogic->getId(), 'txtotal');
  138.     $past = $cmd->execCmd();
  139.     $speed = round(($result['txtotal'] - $past) / $MBpsConvert, 2);
  140.     $eqlogic->checkAndUpdateCmd('txspeed', $speed);
  141.     $cmd = cmd::byEqLogicIdAndLogicalId($eqlogic->getId(), 'rxtotal');
  142.     $past = $cmd->execCmd();
  143.     $speed = round(($result['rxtotal'] - $past) / $MBpsConvert, 2);
  144.     $eqlogic->checkAndUpdateCmd('rxspeed', $speed);
  145.  
  146.     // Met à jour les commandes info
  147.     foreach ($result as $logicalid => $value) {
  148.       if ($logicalid != 'wifiIface')
  149.         $eqlogic->checkAndUpdateCmd($logicalid, $value);
  150.     }
  151.   }
  152.  
  153.   public static function getDevices($enforceDisconnect = false)
  154.   {
  155.     $result = array();
  156.  
  157.     // Récupère l'équipement Routeur
  158.     foreach (eqLogic::byType('openWrt') as $openWrt) {
  159.       if ($openWrt->getLogicalId('id') == 'router') {
  160.         continue;
  161.       }
  162.       $result[$openWrt->getConfiguration('mac')]['status'] = 0;
  163.       $result[$openWrt->getConfiguration('mac')]['mac'] = $openWrt->getConfiguration('mac');
  164.     }
  165.  
  166.     // Connexion SSH
  167.     if (!$connection = openWrt::sshConnect()) return 'error connecting';
  168.  
  169.     // Récupération des bauds actifs
  170.     $stream = ssh2_exec($connection, "cat /tmp/dhcp.leases | awk '{print $2\" \"$3\" \"$4}'");
  171.     stream_set_blocking($stream, true);
  172.     while ($line = stream_get_line($stream, 65535, "\n")) {
  173.       $array = explode(" ", $line);
  174.       $mac = trim(strtolower($array[0]));
  175.       if ($mac == '') {
  176.         continue;
  177.       }
  178.       $result[$mac]['mac'] = $mac;
  179.       $result[$mac]['ip'] = $array[1];
  180.       $result[$mac]['hostname'] = $array[2];
  181.       $result[$mac]['rssi'] = 0;
  182.       $result[$mac]['status'] = 0;
  183.       $result[$mac]['connexion'] = 'Ethernet';
  184.     }
  185.     fclose($stream);
  186.  
  187.     //Table ARP
  188.     $stream = ssh2_exec($connection, 'ip neigh');
  189.     stream_set_blocking($stream, true);
  190.     while ($line = stream_get_line($stream, 65535, "\n")) {
  191.  
  192.       if (preg_match('/^(\d+\.\d+\.\d+\.\d+).*(.{2}:.{2}:.{2}:.{2}:.{2}:.{2}).* (.*)/i', $line, $array)) {
  193.         $mac = trim(strtolower($array[2]));
  194.         if (!array_key_exists($mac, $result)) {
  195.           $result[$mac]['mac'] = $mac;
  196.           $result[$mac]['hostname'] = "*";
  197.           $result[$mac]['rssi'] = 0;
  198.           $result[$mac]['connexion'] = 'Ethernet';
  199.           $result[$mac]['ip'] = $array[1];
  200.         }
  201.         $result[$mac]['status'] = ($array[3] == "FAILED" || $array[3] == "DELAY" || $array[3] == "INCOMPLETE" ? 0 : 1);
  202.       }
  203.     }
  204.     fclose($stream);
  205.  
  206.     //Récupération des interfaces Wifi
  207.     $stream = ssh2_exec($connection, 'iwinfo | grep ESSID | cut -f 1 -s -d" "');
  208.     stream_set_blocking($stream, true);
  209.     while ($iface = stream_get_line($stream, 65535, "\n")) {
  210.       log::add('openWrt', 'debug', 'Wifi: interface ' . $iface);
  211.  
  212.       //Récupération des équipements connectés au wifi
  213.       $stream2 = ssh2_exec($connection, 'iwinfo ' . $iface . ' assoclist | grep dBm');
  214.       stream_set_blocking($stream2, true);
  215.       while ($line = fgets($stream2)) {
  216.         if (preg_match('/^(.{2}:.{2}:.{2}:.{2}:.{2}:.{2}).* (.*) dBm/i', $line, $array)) {
  217.           $mac = trim(strtolower($array[1]));
  218.           if (!array_key_exists($mac, $result)) {
  219.             $result[$mac]['mac'] = $mac;
  220.             $result[$mac]['hostname'] = "*";
  221.             $result[$mac]['ip'] = '?';
  222.           }
  223.           $result[$mac]['connexion'] = 'Wifi ' . $iface;
  224.           $result[$mac]['rssi'] = $array[2];
  225.           $result[$mac]['status'] = 1;
  226.         }
  227.       }
  228.       fclose($stream2);
  229.     }
  230.     fclose($stream);
  231.  
  232.     //conserve la connexion pour le scan du routeur
  233.     if ($enforceDisconnect)
  234.       openWrt::sshDisconnect();
  235.  
  236.     log::add('openWrt', 'debug', 'Scan openWrt, result ' . json_encode($result));
  237.     return $result;
  238.   }
  239.  
  240.   public static function getRouter()
  241.   {
  242.     $result = array();
  243.     if (!$connection = openWrt::sshConnect()) return 'error connecting';
  244.  
  245.     $cpu = explode(' ', openWrt::getSshContents($connection, "top -bn1 | head -3 | awk '/CPU/ {print $2,$4,$6,$8,$10,$12,$14}' | sed 's/%//g'"));
  246.     $result['cpu_user'] = $cpu[0];
  247.     $result['cpu_sys'] = $cpu[1];
  248.     $result['cpu_nic'] = $cpu[2];
  249.     $result['cpu_idle'] = $cpu[3];
  250.     $result['cpu_io'] = $cpu[4];
  251.     $result['cpu_irq'] = $cpu[5];
  252.     $result['cpu_sirq'] = $cpu[6];
  253.     $result['cpu_load'] = 100 - $cpu[3];
  254.  
  255.     $result['txtotal'] = openWrt::getSshContents($connection, 'cat /sys/class/net/eth0/statistics/tx_bytes');
  256.  
  257.     $result['rxtotal'] = openWrt::getSshContents($connection, 'cat /sys/class/net/eth0/statistics/rx_bytes');
  258.  
  259.     $result['wifiIface'] = json_decode(openWrt::getSshContents($connection, 'ubus call network.wireless status'));
  260.  
  261.  
  262.     $ping0 = openWrt::getSshContents($connection, "ping -c1 -W1 www.google.com | tail -1");
  263.     log::add('openWrt', 'debug', 'Ping Google ' . $ping0);
  264.     $ping = explode(' = ', $ping0);
  265.     $ping2 = explode('/', $ping[1]);
  266.     $result['ping_google'] = floatval($ping2[0]);
  267.     log::add('openWrt', 'debug', 'Ping Google ' . $result['ping_google']);
  268.  
  269.     $ping = explode(' = ', openWrt::getSshContents($connection, "ping -c1 -W1 8.8.8.8 | tail -1"));
  270.     $ping2 = explode('/', $ping[1]);
  271.     $result['ping_dns'] = floatval($ping2[0]);
  272.  
  273.     $memory = explode(' ', openWrt::getSshContents($connection, "top -bn1 | head -3 | awk '/Mem/ {print $2,$4}' | sed 's/K//g'"));
  274.     $result['mem_used'] = round($memory[0] / 1024, 2);
  275.     $result['mem_free'] = round($memory[1] / 1024, 2);
  276.  
  277.     if (preg_match('/up (.*),.*load/i', openWrt::getSshContents($connection, 'uptime'), $array)) {
  278.       $result['uptime'] = $array[1];
  279.     }
  280.  
  281.     //Récupération de la température
  282.     $element = openWrt::getSshContents($connection, "cat /sys/kernel/debug/ieee80211/phy1/*/temperature | sed -n -e 's/^.*: //p'");
  283.     if (self::is_really_numeric($element)) {
  284.       $result['temperature'] = $element;
  285.     } else {
  286.       $element = openWrt::getSshContents($connection, "echo $((`cat /sys/class/thermal/thermal_zone0/temp`/1000))");
  287.       $result['temperature'] = self::is_really_numeric($element) ? $element : 0;
  288.     }
  289.  
  290.     openWrt::sshDisconnect();
  291.  
  292.     log::add('openWrt', 'debug', 'Speed openWrt, result ' . json_encode($result));
  293.     return $result;
  294.   }
  295.  
  296.   private static function is_really_numeric($string) {
  297.     return preg_match('#^(?!0[1-9])\d*\.?(?!\.)\d+$#', $string);
  298.   }
  299.  
  300.   public static function getSshContents($connection = false, $cmd = '')
  301.   {
  302.     if (!$connection = openWrt::sshConnect()) return 'error connecting';
  303.  
  304.     log::add('openWrt', 'debug', 'GetContent commande : ' . $cmd);
  305.  
  306.     $stream = ssh2_exec($connection, $cmd);
  307.     stream_set_blocking($stream, true);
  308.     $result = stream_get_contents($stream);
  309.     fclose($stream);
  310.  
  311.     log::add('openWrt', 'debug', 'GetContent résultat : ' . $result);
  312.  
  313.     return $result;
  314.   }
  315.  
  316.   public static function sshConnect()
  317.   {
  318.     if (!self::$_connection) {
  319.       log::add('openWrt', 'debug', 'Tentative de connexion SSH...');
  320.       $sshport = config::byKey('sshport', 'openWrt') == '' ? '22' : config::byKey('sshport', 'openWrt');
  321.  
  322.       if (!self::$_connection = ssh2_connect(config::byKey('addr', 'openWrt'), $sshport)) {
  323.         log::add('openWrt', 'error', 'Connexion SSH KO');
  324.         return false;
  325.       }
  326.       if (self::$_connection && !ssh2_auth_password(self::$_connection, config::byKey('user', 'openWrt'), config::byKey('password', 'openWrt'))) {
  327.         log::add('openWrt', 'error', 'Authentification SSH KO');
  328.         return false;
  329.       } else {
  330.         log::add('openWrt', 'debug', 'SSH Connecté !');
  331.       }
  332.     }
  333.     return self::$_connection;
  334.   }
  335.  
  336.   public static function sshDisconnect()
  337.   {
  338.     if (self::$_connection) {
  339.       $closesession = ssh2_exec(self::$_connection, 'exit');
  340.       stream_set_blocking($closesession, true);
  341.       stream_get_contents($closesession);
  342.       self::$_connection = false;
  343.       log::add('openWrt', 'debug', 'Session SSH terminée.');
  344.     }
  345.   }
  346.  
  347.   /*     * ********************* Méthodes d'instance ************************* */
  348.  
  349.   public function loadCmdFromConf($type)
  350.   {
  351.     if (!is_file(dirname(__FILE__) . '/../config/devices/' . $type . '.json')) {
  352.       return;
  353.     }
  354.     $content = file_get_contents(dirname(__FILE__) . '/../config/devices/' . $type . '.json');
  355.     if (!is_json($content)) {
  356.       return;
  357.     }
  358.     $device = json_decode($content, true);
  359.     if (!is_array($device) || !isset($device['commands'])) {
  360.       return true;
  361.     }
  362.     foreach ($device['commands'] as $command) {
  363.       $this->createCmd($command);
  364.     }
  365.   }
  366.  
  367.   private function createCmd($command)
  368.   {
  369.     $cmd = null;
  370.     foreach ($this->getCmd() as $liste_cmd) {
  371.       if ((isset($command['logicalId']) && $liste_cmd->getLogicalId() == $command['logicalId'])
  372.         || (isset($command['name']) && $liste_cmd->getName() == $command['name'])
  373.       ) {
  374.         $cmd = $liste_cmd;
  375.         break;
  376.       }
  377.     }
  378.     if ($cmd == null || !is_object($cmd)) {
  379.       $cmd = new openWrtCmd();
  380.       $cmd->setEqLogic_id($this->getId());
  381.       utils::a2o($cmd, $command);
  382.       $cmd->save();
  383.     }
  384.  
  385.     return $cmd;
  386.   }
  387.  
  388.   public function preInsert()
  389.   {
  390.     //Récupère la liste des équipements
  391.     $equipments = openWrt::getDevices();
  392.     //Récupère l'équipement qui vient d'être créé via son adresse mac
  393.     $equipment = $equipments[$this->name];
  394.  
  395.     //défini le nom et l'adresse mac
  396.     if ($equipment['hostname'] != '') {
  397.       $this->setName($equipment['hostname']);
  398.       $this->setConfiguration('mac', $equipment['mac']);
  399.       $this->setConfiguration('hostname', $equipment['hostname']);
  400.       $this->setIsEnable(1);
  401.       $this->setIsVisible(1);
  402.     }
  403.   }
  404.  
  405.   public function postUpdate()
  406.   {
  407.     if ($this->getLogicalId('id') != 'router') {
  408.       $this->loadCmdFromConf('client');
  409.     }
  410.   }
  411.  
  412.   public function refreshEq($equipments)
  413.   {
  414.     try {
  415.       //passer la valeur en variable depuis le cron (plus performant que de tout lister ici ou faire les deux traitement pour pouvoir utiliser la fonction standard de refresh automatique)
  416.       $macAddress = $this->getConfiguration('mac');
  417.       if ($macAddress == '') {
  418.         return;
  419.       }
  420.       log::add('openWrt', 'debug', 'Refresh equipment ' . $macAddress);
  421.  
  422.       if ($equipments == null) {
  423.         $equipments = openWrt::getDevices();
  424.       }
  425.  
  426.       $equipment = $equipments[$macAddress];
  427.  
  428.       if ($equipment != null) {
  429.         $this->checkAndUpdateCmd('status', $equipment['status']);
  430.         $this->checkAndUpdateCmd('ip', $equipment['ip']);
  431.         $this->checkAndUpdateCmd('mac', $equipment['mac']);
  432.         $this->checkAndUpdateCmd('hostname', $equipment['hostname']);
  433.         $this->checkAndUpdateCmd('connexion', $equipment['connexion']);
  434.         $this->checkAndUpdateCmd('rssi', $equipment['rssi']);
  435.       } else {
  436.         $this->checkAndUpdateCmd('status', 0);
  437.         $this->checkAndUpdateCmd('rssi', 0);
  438.       }
  439.     } catch (Exception $e) {
  440.       log::add('openWrt', 'error', $e->getCode());
  441.     }
  442.   }
  443.  
  444.   public function restartRouter()
  445.   {
  446.     $this->sendCmdRouter('reboot');
  447.   }
  448.  
  449.   public function ifaceOn($iface)
  450.   {
  451.     $this->sendCmdRouter("uci -q set wireless.default_" . $iface . ".disabled=0 && wifi reload " . $iface);
  452.   }
  453.  
  454.   public function ifaceOff($iface)
  455.   {
  456.     $this->sendCmdRouter("uci -q set wireless.default_" . $iface . ".disabled=1 && wifi reload " . $iface);
  457.   }
  458.  
  459.   public function sendCmdRouter($_cmd = '')
  460.   {
  461.     $connection = openWrt::sshConnect();
  462.     if (!$connection) return 'error connecting';
  463.  
  464.     $response = '';
  465.     if (is_array($_cmd)) {
  466.       foreach ($_cmd as $command) {
  467.         $response .= $this->sendCmdToRouter($connection, $command);
  468.       }
  469.     } else {
  470.       $response .= $this->sendCmdToRouter($connection, $_cmd);
  471.     }
  472.  
  473.     openWrt::sshDisconnect();
  474.  
  475.     return $response;
  476.   }
  477.  
  478.   private function sendCmdToRouter($connection, $_cmd = '')
  479.   {
  480.     log::add('openWrt', 'debug', 'Send : ' . $_cmd);
  481.  
  482.     $stream = @ssh2_exec($connection, $_cmd);
  483.     $errorStream = @ssh2_fetch_stream($stream, SSH2_STREAM_STDERR);
  484.  
  485.     /* Enable Blocking */
  486.     @stream_set_blocking($errorStream, true);
  487.     @stream_set_blocking($stream, true);
  488.  
  489.     /* Grab Response */
  490.     $response = stream_get_contents($stream);
  491.     $error = stream_get_contents($errorStream);
  492.  
  493.     if (strlen($error) > 0) {
  494.       log::add('openWrt', 'error', 'Error when sending command ' . $_cmd . ' : ' . $error);
  495.     }
  496.  
  497.     if (is_null($response)) {
  498.       return false;
  499.     }
  500.  
  501.     return $response;
  502.   }
  503. }
  504.  
  505. class openWrtCmd extends cmd
  506. {
  507.   public function execute($_options = null)
  508.   {
  509.     if ($this->getType() != "info") {
  510.       if ($this->getLogicalId() == 'refresh') {
  511.         $this->getEqLogic()->refreshEq();
  512.         return;
  513.       }
  514.       switch ($this->getConfiguration('type')) {
  515.         case 'restart':
  516.           $this->getEqLogic()->restartRouter();
  517.           break;
  518.  
  519.         case 'ifaceon':
  520.           $this->getEqLogic()->ifaceOn(substr($this->getLogicalId(), 0, -2));
  521.           $cmd = cmd::byId($this->getValue())->event(1);
  522.           break;
  523.  
  524.         case 'ifaceoff':
  525.           $this->getEqLogic()->ifaceOff(substr($this->getLogicalId(), 0, -3));
  526.           $cmd = cmd::byId($this->getValue())->event(0);
  527.           break;
  528.  
  529.         default:
  530.           break;
  531.       }
  532.     }
  533.   }
  534. }
  535.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement