416 lines
16 KiB
PHP
416 lines
16 KiB
PHP
<?php
|
|
/**
|
|
* Observium
|
|
*
|
|
* This file is part of Observium.
|
|
*
|
|
* @package observium
|
|
* @subpackage discovery
|
|
* @copyright (C) Adam Armstrong
|
|
*
|
|
*/
|
|
|
|
// Init vars
|
|
$identities = [];
|
|
$identities_found = [];
|
|
$mibs_found = []; // 'MIB' => 'where founded' (sysorid, sysordescr, discovery)
|
|
$mibs_disable = []; // List mibs for disable
|
|
$mibs_rename = [
|
|
'ETHERLIKE-MIB' => 'EtherLike-MIB', // Fix camel-case mib name
|
|
'Printer-MIB' => 'SKIP-Printer-MIB', // do not discover it by AGENT-CAPABILITIES, that incorrect
|
|
'Job-Monitoring-MIB' => 'SKIP-Job-Monitoring-MIB', // do not discover it by AGENT-CAPABILITIES, that incorrect
|
|
];
|
|
// Agent capabilities for the CISCO-SIP-UA-MIB. LAST-UPDATED 200506220000Z ciscoSipUaCapabilityV12R0402T AGENT-CAPABILITIES SUPPORTS CISCO-SIP-UA-MIB File name: sys
|
|
$sysordescr_patterns[] = '/AGENT-CAPABILITIES\s+SUPPORTS\s+(?<mib>\S+)/';
|
|
//LLDP-V2-MIB, REVISION 200906080000Z
|
|
//ENTITY-MIB, RFC 4133
|
|
$sysordescr_patterns[] = '/^(?<mib>\S+), (REVISION \d{12}[A-Z]|RFC \d+)$/i';
|
|
|
|
$device_sysORID = snmpwalk_oid_num($device, 'sysORID', [], 'SNMPv2-MIB');
|
|
$device_sysORID = snmpwalk_cache_oid($device, 'sysORDescr', $device_sysORID, 'SNMPv2-MIB', NULL, OBS_SNMP_ALL_MULTILINE);
|
|
print_debug_vars($device_sysORID);
|
|
|
|
foreach ($device_sysORID as $entry) {
|
|
// Collect founded identities
|
|
if (strlen($entry['sysORID'])) {
|
|
$identities[] = $entry['sysORID'];
|
|
}
|
|
|
|
// Collect founded MIBs by sysORDescr
|
|
foreach ($sysordescr_patterns as $pattern) {
|
|
if (preg_match($pattern, $entry['sysORDescr'], $matches)) {
|
|
$mib = array_str_replace($mibs_rename, $matches['mib']);
|
|
if (!isset($mibs_found[$mib])) {
|
|
$mibs_found[$mib] = ['source' => 'sysORDescr'];
|
|
// If identity found, append
|
|
if (strlen($entry['sysORID'])) {
|
|
$mibs_found[$mib]['identity'] = $entry['sysORID'];
|
|
}
|
|
} else {
|
|
print_debug("MIB [$mib] already found");
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// OS defined sysORID
|
|
$os_identities = [];
|
|
if (isset($config['os'][$device['os']]['sysorid'])) {
|
|
// Ekinops example
|
|
// EKINOPS-MGNT2-MIB::mgnt2RootOIDInventory.1 = OID: EKINOPS-Pm200frs02-MIB::pm200frs02ri
|
|
// EKINOPS-MGNT2-MIB::mgnt2RootOIDInventory.2 = OID: EKINOPS-PmPassive-MIB::pmpassiveri
|
|
|
|
$device_sysORID = snmpwalk_oid_num($device, $config['os'][$device['os']]['sysorid'], []);
|
|
print_debug_vars($device_sysORID);
|
|
|
|
foreach ($device_sysORID as $entry) {
|
|
// Collect founded identities
|
|
$oid_num = array_shift($entry);
|
|
|
|
if (preg_match(OBS_PATTERN_SNMP_OID_NUM, $oid_num)) {
|
|
$os_identities[] = $oid_num;
|
|
}
|
|
}
|
|
print_debug_vars($os_identities);
|
|
}
|
|
if (isset($config['os'][$device['os']]['sysordescr'])) {
|
|
// NetApp example
|
|
// NETAPP-SWITCHING-MIB::agentSupportedMibName.43 = STRING: "RFC 3635 - Etherlike-MIB"
|
|
// NETAPP-SWITCHING-MIB::agentSupportedMibName.44 = STRING: "NETAPP-SWITCHING-MIB"
|
|
|
|
$device_sysORDescr = snmpwalk_values($device, $config['os'][$device['os']]['sysordescr'], []);
|
|
print_debug_vars($device_sysORDescr);
|
|
|
|
foreach ($device_sysORDescr as $entry) {
|
|
// Collect founded identities
|
|
if (str_contains($entry, ' - ')) {
|
|
$entry = explode(' - ', $entry)[1];
|
|
}
|
|
if (!isset($mibs_found[$entry]) && is_alpha($entry)) {
|
|
$mibs_found[$entry] = [ 'source' => 'OSsysORDescr' ];
|
|
}
|
|
}
|
|
}
|
|
unset($device_sysORID, $device_sysORDescr);
|
|
|
|
$device_mibs = get_device_mibs($device, FALSE); // MIBs defined by os/model
|
|
$device_mibs_bl = get_device_mibs_blacklist($device); // MIBs blacklisted for os/model
|
|
|
|
// Loop all known MIBs, discovery by snmp requests and validate founded MIB
|
|
$GLOBALS['table_rows'] = [];
|
|
foreach ($config['mibs'] as $mib => $mib_def) {
|
|
if (in_array($mib, $device_mibs_bl)) {
|
|
continue;
|
|
} // Skip blacklisted MIB
|
|
|
|
// Detect MIB by identities
|
|
if (!empty($mib_def['identity_num']) && !isset($mibs_found[$mib])) {
|
|
foreach ((array)$mib_def['identity_num'] as $identity_num) {
|
|
if (in_array($identity_num, $identities)) {
|
|
$mibs_found[$mib] = ['source' => 'sysORID', 'identity' => $identity_num];
|
|
break;
|
|
}
|
|
}
|
|
if (!isset($mibs_found[$mib]) && count($os_identities)) {
|
|
foreach ($os_identities as $identity_num) {
|
|
if (match_oid_num($identity_num, $mib_def['identity_num'])) {
|
|
|
|
$mibs_found[$mib] = ['source' => 'OSsysORID', 'identity' => $identity_num];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Discovery MIB by additional snmp walks
|
|
if (isset($mib_def['discovery']) && !isset($mibs_found[$mib])) {
|
|
$mib_defined = in_array($mib, $device_mibs); // MIB already defined for os/model
|
|
|
|
foreach ($mib_def['discovery'] as $def) {
|
|
// When MIB defined in os/model, match discovery without filter os/group
|
|
// if ($mib_defined)
|
|
// {
|
|
// unset($def['os'], $def['os_group']);
|
|
// }
|
|
|
|
if (match_discovery_oids($device, $def)) {
|
|
$mibs_found[$mib] = ['source' => 'Discovery'];
|
|
// If identity found, append
|
|
if (!safe_empty($mib_def['identity_num'])) {
|
|
$mibs_found[$mib]['identity'] = is_array($mib_def['identity_num']) ? array_shift($mib_def['identity_num']) : $mib_def['identity_num'];
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If mib discovery not found, but os/model have mib defined, opposite disable it
|
|
// See FS.COM FS-SWITCH-MIB
|
|
// HP
|
|
if (!isset($mibs_found[$mib]) && $mib_defined) {
|
|
$mibs_disable[$mib] = ['source' => 'Discovery'];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Just show model-specific MIBs
|
|
$model = get_model_array($device);
|
|
if (isset($model['mibs'])) {
|
|
//print_vars($model);
|
|
foreach ($model['mibs'] as $mib) {
|
|
$mibs_found[$mib] = ['source' => 'Model'];
|
|
// If identity found, append
|
|
$mib_def = $config['mibs'][$mib];
|
|
if (!empty($mib_def['identity_num'])) {
|
|
$mibs_found[$mib]['identity'] = is_array($mib_def['identity_num']) ? array_shift($mib_def['identity_num']) : $mib_def['identity_num'];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Show matched discovery mibs
|
|
if (safe_count($GLOBALS['table_rows'])) {
|
|
//$table_opts = array('max-table-width' => 200);
|
|
$table_headers = ['%WOID%n', '%WMatched definition%n', '%WValue%n'];
|
|
print_cli_table($GLOBALS['table_rows'], $table_headers);
|
|
}
|
|
unset($GLOBALS['table_rows']);
|
|
|
|
/* Detect a correct (new) version of FASTPATH mibs */
|
|
$old_fastpath_mibs = [
|
|
'BROADCOM-POWER-ETHERNET-MIB',
|
|
'FASTPATH-BOXSERVICES-PRIVATE-MIB',
|
|
'FASTPATH-SWITCHING-MIB',
|
|
'FASTPATH-ISDP-MIB'
|
|
];
|
|
if (safe_count($mibs_found) && !empty(array_intersect(array_keys($mibs_found), $old_fastpath_mibs))) {
|
|
$use_fastpath_new = FALSE;
|
|
|
|
// OID tree: .1.3.6.1.4.1.4413.1.1
|
|
// FASTPATH is old reference BROADCOM mibs
|
|
|
|
// First detect by CPU by 'EdgeSwitch-SWITCHING-MIB'
|
|
//FASTPATH-SWITCHING-MIB::agentSwitchCpuProcessGroup.9.0 = STRING: " 5 Secs ( 99.9999%) 60 Secs ( 99.6646%) 300 Secs ( 99.2548%)"
|
|
//EdgeSwitch-SWITCHING-MIB::agentSwitchCpuProcessTotalUtilization.0 = STRING: " 5 Secs ( 99.9999%) 60 Secs ( 99.9224%) 300 Secs ( 99.4892%)"
|
|
$data = snmp_get_oid($device, 'agentSwitchCpuProcessTotalUtilization.0', 'EdgeSwitch-SWITCHING-MIB');
|
|
$use_fastpath_new = preg_match('/300 Secs \(\s*(?<proc>[\d\.]+)%\)/', $data);
|
|
|
|
// Second detect by Temperature indexes by 'EdgeSwitch-BOXSERVICES-PRIVATE-MIB'
|
|
if (empty($data)) {
|
|
$oids = snmpwalk_cache_oid($device, 'boxServicesTempSensorsTable', [], 'EdgeSwitch-BOXSERVICES-PRIVATE-MIB');
|
|
// By first detect if device used old FAST-BOXSERVICES-PRIVATE-MIB, it use single key in boxServicesTempSensorsTable
|
|
$first_key = current(array_keys($oids));
|
|
$use_fastpath_new = count(explode('.', $first_key)) > 1;
|
|
}
|
|
|
|
// Rewrite all founded FASTPATH MIBs
|
|
if ($use_fastpath_new) {
|
|
foreach ($old_fastpath_mibs as $mib) {
|
|
if (isset($mibs_found[$mib])) {
|
|
$new_mib = str_replace(['BROADCOM', 'FASTPATH'], 'EdgeSwitch', $mib);
|
|
$mibs_found[$new_mib] = $mibs_found[$mib];
|
|
$mibs_found[$new_mib]['source'] .= ' (FASTPATH)';
|
|
unset($mibs_found[$mib]);
|
|
print_debug("FASTPATH detect hack, mib renamed: $mib -> $new_mib");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
unset($new_mib, $use_fastpath_new, $data, $first_key);
|
|
/* End of FASTPATH hack */
|
|
|
|
// Now filter known MIBs and pretty print
|
|
print_cli_data_field('MIBs discovered');
|
|
$table_rows = [];
|
|
foreach ($mibs_found as $mib => $entry) {
|
|
$identity_num = $entry['identity'];
|
|
$identities_found[] = $identity_num;
|
|
|
|
if (in_array($mib, $device_mibs_bl)) {
|
|
// MIB is in our blacklist, bail out
|
|
$table_rows[] = [$identity_num, $mib, $entry['source'], '%mMIB blacklisted%n'];
|
|
|
|
unset($mibs_found[$mib]);
|
|
continue;
|
|
}
|
|
if (!isset($config['mibs'][$mib])) {
|
|
// MIB is currently unsupported by Observium
|
|
$table_rows[] = [$identity_num, $mib, $entry['source'], 'MIB not used'];
|
|
|
|
unset($mibs_found[$mib]);
|
|
continue;
|
|
}
|
|
if (isset($config['mibs'][$mib]['enable']) && !$config['mibs'][$mib]['enable']) {
|
|
// MIB is currently unsupported by Observium
|
|
$table_rows[] = [$identity_num, $mib, $entry['source'], '%rMIB disabled globally%n'];
|
|
|
|
unset($mibs_found[$mib]);
|
|
continue;
|
|
}
|
|
if (in_array($mib, $device_mibs)) {
|
|
// Already mapped
|
|
$table_rows[] = [$identity_num, "%y$mib%n", $entry['source'], '%yMIB already defined%n'];
|
|
|
|
unset($mibs_found[$mib]);
|
|
continue;
|
|
}
|
|
|
|
// Checks ended, this MIB will add
|
|
echo("$mib ");
|
|
$table_rows[] = [$identity_num, "%g$mib%n", $entry['source'], '%gMIB added%n'];
|
|
}
|
|
|
|
foreach ($mibs_disable as $mib => $entry) {
|
|
// MIB defined for os/model, but not discovered by snmp check
|
|
$table_rows[] = ['', "%r$mib%n", $entry['source'], '%rMIB defined for os but not found%n'];
|
|
// Not correctly for cases when discovery limited with os/group
|
|
// Currently only inform
|
|
//set_device_mib_disable($device, $mib);
|
|
}
|
|
// Clean cached device mibs
|
|
if (safe_count($mibs_disable) && isset($cache['devices']['mibs_disabled'][$device['device_id']])) {
|
|
//$cache['devices']['mibs'][$device['device_id']] = array_diff($cache['devices']['mibs'][$device['device_id']], array_keys($mibs_disable));
|
|
unset($cache['devices']['mibs_disabled'][$device['device_id']]);
|
|
}
|
|
|
|
// Additionally, filter found identities, just for show that exist but unknown
|
|
$identities = array_diff((array)$identities, (array)$identities_found);
|
|
foreach ($identities as $identity_num) {
|
|
$table_rows[] = [$identity_num, '-', 'sysORID', '%cUnknown Identity%n'];
|
|
}
|
|
|
|
// Set device attribute if we found any new MIBs, else delete the attribute
|
|
if (count($mibs_found)) {
|
|
$sysORID_db = safe_json_decode(get_entity_attrib('device', $device, 'sysORID'));
|
|
$sysORID_mibs = array_keys($mibs_found);
|
|
$update_array = array_diff($sysORID_mibs, (array)$sysORID_db);
|
|
$delete_array = array_diff((array)$sysORID_db, $sysORID_mibs);
|
|
//print_vars($sysORID_db);
|
|
//print_vars($sysORID_mibs);
|
|
//print_vars($update_array);
|
|
//print_vars($delete_array);
|
|
|
|
if (count($update_array)) {
|
|
set_entity_attrib('device', $device, 'sysORID', safe_json_encode($sysORID_mibs));
|
|
log_event("MIBs discovered: '" . implode("', '", $update_array) . "'", $device, 'device', $device['device_id']);
|
|
|
|
// reset cache
|
|
if (isset($GLOBALS['cache']['devices']['mibs'][$device['device_id']])) {
|
|
unset($GLOBALS['cache']['devices']['mibs'][$device['device_id']],
|
|
$GLOBALS['cache']['entity_attribs']['device'][$device['device_id']]['sysORID']);
|
|
}
|
|
} elseif (count($delete_array)) {
|
|
set_entity_attrib('device', $device, 'sysORID', safe_json_encode($sysORID_mibs));
|
|
log_event("MIBs removed: '" . implode("', '", $delete_array) . "'", $device, 'device', $device['device_id']);
|
|
|
|
// reset cache
|
|
if (isset($GLOBALS['cache']['devices']['mibs'][$device['device_id']])) {
|
|
unset($GLOBALS['cache']['devices']['mibs'][$device['device_id']],
|
|
$GLOBALS['cache']['entity_attribs']['device'][$device['device_id']]['sysORID']);
|
|
}
|
|
}
|
|
} else {
|
|
echo('<empty>');
|
|
del_entity_attrib('device', $device, 'sysORID');
|
|
|
|
// reset cache
|
|
if (isset($GLOBALS['cache']['devices']['mibs'][$device['device_id']])) {
|
|
unset($GLOBALS['cache']['devices']['mibs'][$device['device_id']],
|
|
$GLOBALS['cache']['entity_attribs']['device'][$device['device_id']]['sysORID']);
|
|
}
|
|
}
|
|
|
|
if (count($table_rows)) {
|
|
echo(PHP_EOL);
|
|
$table_headers = ['%WIdentity%n', '%WMIB%n', '%WSource%n', '%WStatus%n'];
|
|
print_cli_table($table_rows, $table_headers);
|
|
}
|
|
|
|
// Need to check if module disabled?
|
|
if (FALSE) {
|
|
// sysORID table disabled, delete the attribute
|
|
del_entity_attrib('device', $device, 'sysORID');
|
|
}
|
|
|
|
print_debug_vars(get_device_mibs_permitted($device), 1);
|
|
|
|
///FIXME. This is not exactly related to mibs, but this need check before all other discovery modules
|
|
// Detect (if possible) exist snmp contexts on device (currently only on Cisco IOS, IOS-XE and NX-OS
|
|
/* DISABLED, while not know what TODO with this,
|
|
* currently same functionality only for Cisco Nexis in VRF module
|
|
if (isset($config['os'][$device['os']]['snmp']['virtual_oid']))
|
|
{
|
|
$contexts = [];
|
|
foreach (snmpwalk_values($device, $config['os'][$device['os']]['snmp']['virtual_oid'], []) as $context)
|
|
{
|
|
if ($context !== '')
|
|
{
|
|
$contexts[] = $context;
|
|
}
|
|
}
|
|
$contexts = array_unique($contexts);
|
|
print_debug_vars($contexts);
|
|
|
|
// Add non VLAN contexts to device array, for use in discovery modules
|
|
foreach ($contexts as $context)
|
|
{
|
|
// Detect Vlan specific contexts
|
|
if (preg_match('/^(vlan\-)?(?<vlan>\d{1,4})$/', $context, $matches) &&
|
|
$matches['vlan'] > 0 && $matches['vlan'] < 4096)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
$device['snmp_contexts'][] = $context;
|
|
}
|
|
|
|
$contexts_db = safe_json_decode(get_entity_attrib('device', $device, 'snmp_contexts'));
|
|
print_debug_vars($contexts_db);
|
|
|
|
$update_array = array_diff($contexts, (array)$contexts_db);
|
|
print_debug_vars($update_array);
|
|
$delete_array = array_diff((array)$contexts_db, $contexts);
|
|
print_debug_vars($delete_array);
|
|
|
|
if (count($contexts_db) && empty($contexts))
|
|
{
|
|
del_entity_attrib('device', $device, 'snmp_contexts');
|
|
log_event("SNMP contexts removed.", $device, 'device', $device['device_id']);
|
|
}
|
|
elseif (count($update_array))
|
|
{
|
|
set_entity_attrib('device', $device, 'snmp_contexts', safe_json_encode($contexts));
|
|
|
|
$update_vlans = [];
|
|
foreach ($update_array as $k => $context)
|
|
{
|
|
// Detect Vlan specific contexts
|
|
if (preg_match('/^(vlan\-)?(?<vlan>\d{1,4})$/', $context, $matches) &&
|
|
$matches['vlan'] > 0 && $matches['vlan'] < 4096)
|
|
{
|
|
$update_vlans[] = $matches['vlan'];
|
|
unset($update_array[$k]);
|
|
}
|
|
}
|
|
print_debug_vars($update_vlans);
|
|
$log_msg = 'SNMP contexts found: ';
|
|
if ($update_array)
|
|
{
|
|
log_event("SNMP contexts found: '" . implode("', '", $update_array) . "'", $device, 'device', $device['device_id']);
|
|
}
|
|
if ($update_vlans)
|
|
{
|
|
log_event("SNMP contexts found: VLANs " . range_to_list(array_unique($update_vlans), ', '), $device, 'device', $device['device_id']);
|
|
}
|
|
}
|
|
elseif (count($delete_array))
|
|
{
|
|
set_entity_attrib('device', $device, 'snmp_contexts', safe_json_encode($contexts));
|
|
log_event("SNMP contexts removed: '" . implode("', '", $delete_array) . "'", $device, 'device', $device['device_id']);
|
|
}
|
|
}
|
|
*/
|
|
|
|
// EOF
|