244 lines
9.6 KiB
PHP

<?php
/**
* Observium
*
* This file is part of Observium.
*
* @package observium
* @subpackage discovery
* @copyright (C) Adam Armstrong
*
*/
// IPv4 addresses
$ip_version = 'ipv4';
// NOTE. By default used old tables IP-MIB, because some weird vendors use "random" data in new tables:
//ipAddressIfIndex.ipv4."94.142.242.194" = 2
//ipAddressIfIndex.ipv4."127.0.0.1" = 1
//ipAddressPrefix.ipv4."94.142.242.194" = ipAddressPrefixOrigin.2.ipv4."88.0.0.0".5
//ipAddressPrefix.ipv4."127.0.0.1" = ipAddressPrefixOrigin.1.ipv4."51.101.48.0".0
// Get IP addresses from IP-MIB (old table)
// Normal:
//IP-MIB::ipAdEntIfIndex.10.0.0.130 = 193
//IP-MIB::ipAdEntNetMask.10.0.0.130 = 255.255.255.252
// Cisco Nexus (seems as first number is interface index):
//IP-MIB::ipAdEntIfIndex.4.10.44.44.110 = 151192525
//IP-MIB::ipAdEntNetMask.4.10.44.44.110 = 255.255.255.0
// Bintec Elmeg (seems as last number is counter number 1,2,3,etc)
//IP-MIB::ipAdEntIfIndex.192.168.1.254.0 = 1000
//IP-MIB::ipAdEntNetMask.192.168.1.254.0 = 255.255.255.0
$oid_data = snmpwalk_cache_oid($device, 'ipAdEntIfIndex', [], 'IP-MIB');
if (snmp_status()) {
$oid_data = snmpwalk_cache_oid($device, 'ipAdEntNetMask', $oid_data, 'IP-MIB');
if (is_numeric(array_key_first($oid_data))) {
// Some devices report just numbers instead ip address:
// IP-MIB::ipAdEntAddr.0 = IpAddress: 0.0.0.0
// IP-MIB::ipAdEntAddr.2130706433 = IpAddress: 127.0.0.1
// IP-MIB::ipAdEntIfIndex.0 = INTEGER: 6620672
// IP-MIB::ipAdEntIfIndex.2130706433 = INTEGER: 6625280
// IP-MIB::ipAdEntNetMask.0 = IpAddress: 255.255.255.0
// IP-MIB::ipAdEntNetMask.2130706433 = IpAddress: 255.255.255.255
// IP-MIB::ipAdEntBcastAddr.0 = INTEGER: 1
// IP-MIB::ipAdEntBcastAddr.2130706433 = INTEGER: 0
$oid_data = snmpwalk_cache_oid($device, 'ipAdEntAddr', $oid_data, 'IP-MIB');
}
print_debug_vars($oid_data);
}
// Rewrite IP-MIB array
foreach ($oid_data as $ip_address => $entry) {
$ifIndex = $entry['ipAdEntIfIndex'];
$ip_address_fix = explode('.', $ip_address);
switch (count($ip_address_fix)) {
case 4:
break; // Just normal IPv4 address
case 5:
if (in_array($device['os_group'], ['bintec', 'fortinet'])) {
// Bintec Elmeg, see: http://jira.observium.org/browse/OBSERVIUM-1958
// Same trouble on Fortinet devices
// ipAdEntNetMask.10.3.250.111.1 = 255.255.255.255
// ipAdEntNetMask.10.111.6.1.1 = 255.255.255.0
unset($ip_address_fix[4]);
} else {
// Cisco Nexus, see: http://jira.observium.org/browse/OBSERVIUM-728
unset($ip_address_fix[0]);
}
$ip_address = implode('.', $ip_address_fix);
break;
default:
if (isset($entry['ipAdEntAddr']) && get_ip_version($entry['ipAdEntAddr'])) {
$ip_address = $entry['ipAdEntAddr'];
} else {
print_debug("Detected unknown IPv4 address: $ip_address");
continue 2;
}
}
$ip_mask_fix = explode('.', $entry['ipAdEntNetMask']);
if ($ip_mask_fix[0] < 255 && $ip_mask_fix[1] <= '255' && $ip_mask_fix[2] <= '255' && $ip_mask_fix[3] == '255') {
// On some D-Link used wrong masks: 252.255.255.255, 0.255.255.255
$entry['ipAdEntNetMask'] = $ip_mask_fix[3] . '.' . $ip_mask_fix[2] . '.' . $ip_mask_fix[1] . '.' . $ip_mask_fix[0];
}
if (empty($entry['ipAdEntNetMask']) || safe_count($ip_mask_fix) != 4) {
$entry['ipAdEntNetMask'] = '255.255.255.255';
}
$data = [
'ifIndex' => $ifIndex,
'ip' => $ip_address,
'mask' => $entry['ipAdEntNetMask']
];
discover_add_ip_address($device, $mib, $data);
}
// Get IP addresses from IP-MIB (new table, both IPv4/IPv6)
$flags = OBS_SNMP_ALL ^ OBS_QUOTES_STRIP;
$oid_data = snmpwalk_cache_twopart_oid($device, 'ipAddressIfIndex', [], 'IP-MIB', NULL, $flags);
if (snmp_status()) {
foreach (['ipAddressType', 'ipAddressPrefix', 'ipAddressOrigin'] as $oid) {
$oid_data = snmpwalk_cache_twopart_oid($device, $oid, $oid_data, 'IP-MIB', NULL, $flags);
}
print_debug_vars($oid_data);
}
// IPv4 addresses
if (safe_empty($ip_data[$ip_version])) {
//IP-MIB::ipAddressIfIndex.ipv4."198.237.180.2" = 8
//IP-MIB::ipAddressPrefix.ipv4."198.237.180.2" = ipAddressPrefixOrigin.8.ipv4."198.237.180.2".32
//IP-MIB::ipAddressOrigin.ipv4."198.237.180.2" = manual
//Origins: 1:other, 2:manual, 4:dhcp, 5:linklayer, 6:random
// Fortigate example:
// IP-MIB::ipAddressIfIndex.ipv4."10.200.100.184".1 = INTEGER: 1
// IP-MIB::ipAddressType.ipv4."10.200.100.184".1 = INTEGER: unicast(1)
// IP-MIB::ipAddressPrefix.ipv4."10.200.100.184".1 = OID: SNMPv2-SMI::zeroDotZero.0
// IP-MIB::ipAddressOrigin.ipv4."10.200.100.184".1 = INTEGER: manual(2)
// IP-MIB::ipAddressStatus.ipv4."10.200.100.184".1 = INTEGER: preferred(1)
// IPv4z (not sure, never seen)
if (isset($oid_data[$ip_version . 'z'])) {
$oid_data[$ip_version] = array_merge((array)$oid_data[$ip_version], $oid_data[$ip_version . 'z']);
}
// Rewrite IP-MIB array
foreach ($oid_data[$ip_version] as $ip_address => $entry) {
//$ip_address = str_replace($ip_version.'.', '', $key);
$ifIndex = $entry['ipAddressIfIndex'];
// ipAddressOrigin.ipv4.169.254.1.1.23 = manual
$ip_address_fix = explode('.', $ip_address);
$index_prefix = NULL;
switch (safe_count($ip_address_fix)) {
case 5:
// get last number as prefix
$index_prefix = array_pop($ip_address_fix);
if ($ifIndex == $index_prefix) {
// Fortigate report ifIndex as last index part
// See: https://jira.observium.org/browse/OBS-4341
$index_prefix = NULL;
}
$ip_address = implode('.', $ip_address_fix);
break;
case 4:
// Common, no need for changes
break;
default:
print_debug("Unknown IP index: $ip_address");
continue 2;
}
if (!str_contains($entry['ipAddressPrefix'], 'zeroDotZero')) {
$tmp_prefix = explode('.', $entry['ipAddressPrefix']);
$entry['ipAddressPrefix'] = end($tmp_prefix);
unset($tmp_prefix);
}
if (!is_intnum($entry['ipAddressPrefix']) && is_intnum($index_prefix)) {
$entry['ipAddressPrefix'] = $index_prefix;
}
$data = [
'ifIndex' => $ifIndex,
'ip' => $ip_address,
'prefix' => $entry['ipAddressPrefix'],
'type' => $entry['ipAddressType'],
'origin' => $entry['ipAddressOrigin']
];
discover_add_ip_address($device, $mib, $data);
}
}
// IPv6 addresses
$ip_version = 'ipv6';
//ipAddressIfIndex.ipv6."00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01" = 1
//ipAddressPrefix.ipv6."00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01" = ipAddressPrefixOrigin.1.ipv6."00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01".128
//ipAddressOrigin.ipv6."00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01" = manual
//Origins: 1:other, 2:manual, 4:dhcp, 5:linklayer, 6:random
// IPv6z
if (isset($oid_data[$ip_version . 'z'])) {
$oid_data[$ip_version] = array_merge((array)$oid_data[$ip_version], $oid_data[$ip_version . 'z']);
}
// Rewrite IP-MIB array
$check_ipv6_mib = FALSE; // Flag for additionally check IPv6-MIB
foreach ($oid_data[$ip_version] as $ip_snmp => $entry) {
$ifIndex = $entry['ipAddressIfIndex'];
if (str_contains($ip_snmp, '.')) {
// incorrect indexes with prefix
// ipAddressOrigin.ipv6.65152.0.0.0.521.4095.65033.51218.27 = manual
$ip_address_fix = explode('.', $ip_snmp);
$index_prefix = NULL;
switch (count($ip_address_fix)) {
case 9:
// get last number as prefix
$index_prefix = array_pop($ip_address_fix);
if ($ifIndex == $index_prefix) {
// Fortigate report ifIndex as last index part
// See: https://jira.observium.org/browse/OBS-4341
$index_prefix = NULL;
}
//break; // Do not break here!
case 8:
$ip_address_fix = array_map('dechex', $ip_address_fix);
$ip_address = ip_uncompress(implode(':', $ip_address_fix));
break;
default:
print_debug("Unknown IP index: $ip_snmp");
continue 2;
}
} else {
// Common address index
$ip_address = hex2ip($ip_snmp);
}
if (str_contains($entry['ipAddressPrefix'], 'zeroDotZero')) {
// Additionally walk IPV6-MIB, especially in JunOS because they spit at world standards
// See: http://jira.observium.org/browse/OBSERVIUM-1271
$check_ipv6_mib = TRUE;
} else {
$tmp_prefix = explode('.', $entry['ipAddressPrefix']);
$entry['ipAddressPrefix'] = end($tmp_prefix);
}
if (!is_intnum($entry['ipAddressPrefix']) && is_intnum($index_prefix)) {
$entry['ipAddressPrefix'] = $index_prefix;
$check_ipv6_mib = FALSE;
}
$data = [
'ifIndex' => $ifIndex,
'ip' => $ip_address,
'prefix' => $entry['ipAddressPrefix'],
'type' => $entry['ipAddressType'],
'origin' => $entry['ipAddressOrigin']
];
discover_add_ip_address($device, $mib, $data);
}
unset($ifIndex, $ip_address, $tmp_prefix, $oid_data);
// EOF