diff --git a/includes/defaults.inc.php b/includes/defaults.inc.php index 739cc1127..fa8dda436 100644 --- a/includes/defaults.inc.php +++ b/includes/defaults.inc.php @@ -565,6 +565,7 @@ $config['discovery_modules']['toner'] = 1; $config['discovery_modules']['ucd-diskio'] = 1; $config['discovery_modules']['services'] = 1; $config['discovery_modules']['charge'] = 1; +$config['discovery_modules']['mib'] = 0; $config['modules_compat']['rfc1628']['liebert'] = 1; $config['modules_compat']['rfc1628']['netmanplus'] = 1; diff --git a/includes/discovery/mib.inc.php b/includes/discovery/mib.inc.php new file mode 100644 index 000000000..5d1d608e0 --- /dev/null +++ b/includes/discovery/mib.inc.php @@ -0,0 +1,53 @@ + + * + * This program 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. Please see LICENSE.txt at the top level of + * the source code distribution for details. + */ + +/* + * The overall plan for MIB-based support is: + * + * Discovery: + * 1. SNMP_get sysObjectID; look for a MIB matching this object (set_os_mib). + * 2. Add any extra MIBs that should be there for a given device + * (includes/discovery/os/*.inc.php). + * 3. Walk these MIBs to see if they exist in the device (this file). + * Save the ones that do in the database table device_oids. + * + * Polling: + * 5. For each MIB in the device_oids table, walk the device for that MIB. + * 6. Save each MIB value in its own RRD file. (At present there is no + * deletion of values that disappear.) + * + * Graphing: + * 7. For each MIB in the device_oids table, create a graph from the RRD + * file. All graphs go into the MIB section at present. + */ + +set_os_mib($device); +$mibs = array(); + +// remove any existing device_oids for this device +dbDelete('device_oids', 'device_id = ?', array($device['device_id'])); + +// parse MIBs and check for them on the device +foreach ($device['mibs'] as $name => $module) { + d_echo("MIB discovery: $name, $module"); + $mibs[$name] = snmp_mib_load($name, $module); + $oids = snmpwalk_cache_oid($device, "$module::$name", array(), $module); + + // add the oids for this device + foreach ($oids[0] as $key => $val) { + $data = $mibs[$name][$key]; + $data['device_id'] = $device['device_id']; + $result = dbInsert($data, 'device_oids'); + d_echo("dbInsert for $name $key returned $result"); + } +} diff --git a/includes/discovery/os/ruckuswireless.inc.php b/includes/discovery/os/ruckuswireless.inc.php index edc1c90f9..3e7325eb0 100644 --- a/includes/discovery/os/ruckuswireless.inc.php +++ b/includes/discovery/os/ruckuswireless.inc.php @@ -3,6 +3,7 @@ * LibreNMS Ruckus Wireless OS information module * * Copyright (c) 2015 Søren Friis Rosiak +* Copyright (c) 2015 Gear Consulting Pty Ltd * This program 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 @@ -14,4 +15,11 @@ if (!$os) { $os = "ruckuswireless"; } } + +if ($os == "ruckuswireless") { + $ruckus_mibs = array( + "ruckusZDSystemStats" => "RUCKUS-ZD-SYSTEM-MIB", + ); + set_mibs($ruckus_mibs, $device); +} ?> diff --git a/includes/snmp.inc.php b/includes/snmp.inc.php index 6c8b64a1a..68d119aeb 100644 --- a/includes/snmp.inc.php +++ b/includes/snmp.inc.php @@ -819,15 +819,17 @@ function snmp_gen_auth (&$device) } /* + * Translate the given MIB into a vaguely useful PHP array. Each keyword becomes an array index. + * * Example: * snmptranslate -Td -On -M mibs -m RUCKUS-ZD-SYSTEM-MIB RUCKUS-ZD-SYSTEM-MIB::ruckusZDSystemStatsNumSta * .1.3.6.1.4.1.25053.1.2.1.1.1.15.30 * ruckusZDSystemStatsAllNumSta OBJECT-TYPE - * -- FROM RUCKUS-ZD-SYSTEM-MIB - * SYNTAX Unsigned32 - * MAX-ACCESS read-only - * STATUS current - * DESCRIPTION "Number of All client devices" + * -- FROM RUCKUS-ZD-SYSTEM-MIB + * SYNTAX Unsigned32 + * MAX-ACCESS read-only + * STATUS current + * DESCRIPTION "Number of All client devices" * ::= { iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) ruckusRootMIB(25053) ruckusObjects(1) ruckusZD(2) ruckusZDSystemModule(1) ruckusZDSystemMIB(1) ruckusZDSystemObjects(1) * ruckusZDSystemStats(15) 30 } */ @@ -843,7 +845,7 @@ function snmp_mib_parse($oid, $mib, $module, $mibdir = null) $cmd .= $lastpart; $result = array(); - $lines = preg_split('/\n+/', trim(external_exec($cmd))); + $lines = preg_split('/\n+/', trim(shell_exec($cmd))); foreach ($lines as $l) { $f = preg_split('/\s+/', trim($l)); // first line is all numeric @@ -853,16 +855,16 @@ function snmp_mib_parse($oid, $mib, $module, $mibdir = null) } // then the name of the object type if ($f[1] && $f[1] == "OBJECT-TYPE") { - $result[strtolower($f[1])] = $f[0]; + $result['object_type'] = $f[0]; continue; } // then the other data elements if ($f[0] == "--" && $f[1] == "FROM") { - $result[strtolower($f[1])] = $f[2]; + $result['module'] = $f[2]; continue; } if ($f[0] == "MAX-ACCESS") { - $result[strtolower($f[0])] = $f[1]; + $result['max_access'] = $f[1]; continue; } if ($f[0] == "STATUS") { @@ -895,6 +897,10 @@ function snmp_mib_parse($oid, $mib, $module, $mibdir = null) /* + * Walks through the given MIB module, looking for the given MIB. + * NOTE: different from snmp walk - this doesn't touch the device. + * NOTE: There's probably a better way to do this with snmptranslate. + * * Example: * snmptranslate -Ts -M mibs -m RUCKUS-ZD-SYSTEM-MIB | grep ruckusZDSystemStats * .iso.org.dod.internet.private.enterprises.ruckusRootMIB.ruckusObjects.ruckusZD.ruckusZDSystemModule.ruckusZDSystemMIB.ruckusZDSystemObjects.ruckusZDSystemStats @@ -908,7 +914,7 @@ function snmp_mib_walk($mib, $module, $mibdir = null) $cmd .= mibdir($mibdir); $cmd .= " -m ".$module; $result = array(); - $data = preg_split('/\n+/', external_exec($cmd)); + $data = preg_split('/\n+/', shell_exec($cmd)); foreach ($data as $oid) { // only include oids which are part of this mib if (strstr($oid, $mib)) { @@ -921,4 +927,73 @@ function snmp_mib_walk($mib, $module, $mibdir = null) return $result; } +/* + * @return an array containing all of the mib objects, keyed by object-type; + * returns an empty array if something goes wrong. + */ +function snmp_mib_load($mib, $module, $mibdir = null) +{ + $mibs = array(); + foreach (snmp_mib_walk($mib, $module, $mibdir) as $obj) { + $mibs[$obj['object_type']] = $obj; + } + return $mibs; +} + +/* + * Turn the given oid (name or numeric value) into a MODULE::mib name. + * @return an array consisting of the module and mib names, or null if no matching MIB is found. + */ +function snmp_translate($oid, $module, $mibdir = null) +{ + if ($module !== "all") { + $oid = "$module::$oid"; + } + $cmd = "snmptranslate" . mibdir($mibdir); + $cmd .= " -m $module $oid"; // load all the MIBs looking for our object + $cmd .= " 2>/dev/null"; // ignore invalid MIBs + + $lines = preg_split('/\n+/', shell_exec($cmd)); + if (!$lines) { + d_echo("No results from snmptranslate"); + return null; + } + + $matches = array(); + if (!preg_match('/(.*)::(.*)/', $lines[0], $matches)) { + d_echo("This doesn't look like a MIB: ".$lines[0]); + return null; + } + + d_echo("SNMP translated: $module::$oid -> $matches[1]::$matches[2]"); + return $matches; +} + +/* + * Validate MIBs and set $device['mibs'][$name] = $module based on the results. + * Can be slow due to use of snmptranslate - call only during discovery. + */ +function set_mibs($list, &$device) +{ + foreach ($list as $name => $module) { + $matches = snmp_translate($name, $module); + if ($matches) { + $device['mibs'][$matches[2]] = $matches[1]; + } + } +} + +/* + * Validate the MIB given in sysObjectId against our MIB collection. If none is found, do nothing. + * If one is found, call set_mibs() for the given MIB name & module. + */ +function set_os_mib(&$device) +{ + $sysObjectId = trim(snmp_get($device, "SNMPv2-MIB::sysObjectID.0", "-Ovqn")); + if ($sysObjectId === false || $sysObjectID === "") { + return; + } + set_mibs(array($sysObjectId => "all"), $device); +} + ?>