walk('FOUNDRY-SN-SWITCH-GROUP-MIB::snFdpCacheEntry')->table(2); foreach ($fdp_array as $key => $fdp_if_array) { $interface = get_port_by_ifIndex($device['device_id'], $key); d_echo($fdp_if_array); foreach ($fdp_if_array as $entry_key => $fdp) { $remote_device_id = find_device_id($fdp['snFdpCacheDeviceId']); if (! $remote_device_id && ! can_skip_discovery($fdp['snFdpCacheDeviceId'], $fdp['snFdpCacheVersion']) ) { if (Config::get('autodiscovery.xdp') === true) { $remote_device_id = discover_new_device($fdp['snFdpCacheDeviceId'], $device, 'FDP', $interface); } } $remote_port_id = find_port_id($fdp['snFdpCacheDevicePort'], '', $remote_device_id); discover_link( $interface['port_id'], $fdp['snFdpCacheVendorId'], $remote_port_id, $fdp['snFdpCacheDeviceId'], $fdp['snFdpCacheDevicePort'], $fdp['snFdpCachePlatform'], $fdp['snFdpCacheVersion'], $device['device_id'], $remote_device_id ); } }//end foreach echo PHP_EOL; }//end if if (isset($device['os_group']) && $device['os_group'] == 'cisco') { echo ' CISCO-CDP-MIB: '; $cdp_array = SnmpQuery::hideMib()->walk('CISCO-CDP-MIB::cdpCache')->table(2); foreach ($cdp_array as $key => $cdp_if_array) { $interface = get_port_by_ifIndex($device['device_id'], $key); foreach ($cdp_if_array as $entry_key => $cdp) { d_echo($cdp); $cdp_ip = IP::fromHexString($cdp['cdpCacheAddress'], true); $remote_device_id = find_device_id($cdp['cdpCacheDeviceId'], $cdp_ip); if ( ! $remote_device_id && ! can_skip_discovery($cdp['cdpCacheDeviceId'], $cdp['cdpCacheVersion'], $cdp['cdpCachePlatform']) && Config::get('autodiscovery.xdp') === true ) { $remote_device_id = discover_new_device($cdp['cdpCacheDeviceId'], $device, 'CDP', $interface); if (! $remote_device_id && Config::get('discovery_by_ip', false)) { $remote_device_id = discover_new_device($cdp_ip, $device, 'CDP', $interface); } } if ($interface['port_id'] && $cdp['cdpCacheDeviceId'] && $cdp['cdpCacheDevicePort']) { $remote_port_id = find_port_id($cdp['cdpCacheDevicePort'], '', $remote_device_id); discover_link( $interface['port_id'], 'cdp', $remote_port_id, $cdp['cdpCacheDeviceId'], $cdp['cdpCacheDevicePort'], $cdp['cdpCachePlatform'], $cdp['cdpCacheVersion'], $device['device_id'], $remote_device_id ); } } //end foreach } //end foreach echo PHP_EOL; }//end if if (($device['os'] == 'routeros') && version_compare($device['version'], '7.7', '<')) { echo ' LLDP-MIB: '; $lldp_array = SnmpQuery::hideMib()->walk('LLDP-MIB::lldpRemEntry')->table(3); if (! empty($lldp_array)) { // workaround for routeros returning the incorrect index if (! empty($lldp_array[0][0])) { $lldp_array = $lldp_array[0][0]; } $lldp_ports = SnmpQuery::hideMib()->walk('MIKROTIK-MIB::mtxrInterfaceStatsName')->table(); $lldp_ports_num = SnmpQuery::hideMib()->walk('MIKROTIK-MIB::mtxrNeighborInterfaceID')->table(); foreach ($lldp_array as $key => $lldp) { $local_port_ifName = $lldp_ports[hexdec($lldp_ports_num[$key]['mtxrNeighborInterfaceID'])]['mtxrInterfaceStatsName']; $local_port_id = find_port_id($local_port_ifName, null, $device['device_id']); $interface = get_port_by_id($local_port_id); if ($lldp['lldpRemPortIdSubtype'] == 3) { // 3 = macaddress $remote_port_mac = str_replace([' ', ':', '-'], '', strtolower($lldp['lldpRemPortId'])); } $remote_device_id = find_device_id($lldp['lldpRemSysName'], $lldp['lldpRemManAddr'], $remote_port_mac); if (! $remote_device_id && \LibreNMS\Util\Validate::hostname($lldp['lldpRemSysName']) && ! can_skip_discovery($lldp['lldpRemSysName'], $lldp['lldpRemSysDesc']) && Config::get('autodiscovery.xdp') === true) { $remote_device_id = discover_new_device($lldp['lldpRemSysName'], $device, 'LLDP', $interface); } if ($interface['port_id'] && $lldp['lldpRemSysName'] && $lldp['lldpRemPortId']) { $remote_port_id = find_port_id($lldp['lldpRemPortDesc'], $lldp['lldpRemPortId'], $remote_device_id); discover_link( $interface['port_id'], 'lldp', $remote_port_id, $lldp['lldpRemSysName'], $lldp['lldpRemPortId'], null, $lldp['lldpRemSysDesc'], $device['device_id'], $remote_device_id ); } }//end foreach } echo PHP_EOL; } elseif ($device['os'] == 'pbn' || $device['os'] == 'bdcom' || $device['os'] == 'fs-bdcom') { echo ' NMS-LLDP-MIB: '; $lldp_array = SnmpQuery::hideMib()->walk('NMS-LLDP-MIB::lldpRemoteSystemsData')->table(2); foreach ($lldp_array as $key => $lldp_array_inner) { foreach ($lldp_array_inner as $ifIndex => $lldp) { d_echo($lldp); $interface = get_port_by_ifIndex($device['device_id'], $lldp['lldpRemLocalPortNum']); $remote_device_id = find_device_id($lldp['lldpRemSysName']); if (! $remote_device_id && \LibreNMS\Util\Validate::hostname($lldp['lldpRemSysName']) && ! can_skip_discovery($lldp['lldpRemSysName'], $lldp['lldpRemSysDesc'] && Config::get('autodiscovery.xdp') === true) ) { $remote_device_id = discover_new_device($lldp['lldpRemSysName'], $device, 'LLDP', $interface); } if ($interface['port_id'] && $lldp['lldpRemSysName'] && $lldp['lldpRemPortId']) { $remote_port_id = find_port_id($lldp['lldpRemPortDesc'], $lldp['lldpRemPortId'], $remote_device_id); discover_link( $interface['port_id'], 'lldp', $remote_port_id, $lldp['lldpRemSysName'], $lldp['lldpRemPortId'], null, $lldp['lldpRemSysDesc'], $device['device_id'], $remote_device_id ); } } //end foreach $lldp_array_inner }//end foreach $lldp_array echo PHP_EOL; } elseif ($device['os'] == 'timos') { echo ' TIMETRA-LLDP-MIB: '; $lldp_array = SnmpQuery::hideMib()->walk('TIMETRA-LLDP-MIB::tmnxLldpRemoteSystemsData')->table(4); foreach ($lldp_array as $timeMark => $sub_lldp_1) { foreach ($sub_lldp_1 as $ifIndex => $sub_lldp_2) { foreach ($sub_lldp_2 as $macIndex => $sub_lldp_3) { foreach ($sub_lldp_3 as $remIndex => $lldp) { $interface = get_port_by_ifIndex($device['device_id'], $ifIndex); $remote_device_id = find_device_id($lldp['tmnxLldpRemSysName']); if (! $remote_device_id && \LibreNMS\Util\Validate::hostname($lldp['tmnxLldpRemSysName']) && ! can_skip_discovery($lldp['tmnxLldpRemSysName'], $lldp['tmnxLldpRemSysDesc']) && Config::get('autodiscovery.xdp') === true ) { $remote_device_id = discover_new_device($lldp['tmnxLldpRemSysName'], $device, 'LLDP', $interface); } if ($interface['port_id'] && $lldp['tmnxLldpRemSysName'] && $lldp['tmnxLldpRemPortId']) { $remote_port_id = find_port_id($lldp['tmnxLldpRemPortDesc'], $lldp['tmnxLldpRemPortId'], $remote_device_id); discover_link( $interface['port_id'], 'lldp', $remote_port_id, $lldp['tmnxLldpRemSysName'], $lldp['tmnxLldpRemPortId'], null, $lldp['tmnxLldpRemSysDesc'], $device['device_id'], $remote_device_id ); } } } } }//end foreach echo PHP_EOL; } elseif ($device['os'] == 'jetstream') { echo ' JETSTREAM-LLDP MIB: '; $lldp = SnmpQuery::hideMib()->walk('TPLINK-LLDPINFO-MIB::lldpNeighborInfoEntry')->table(); if (is_array($lldp['lldpNeighborPortIndexId'])) { foreach ($lldp['lldpNeighborPortIndexId'] as $IndexId => $lldp_data) { if (! is_array($lldp_data)) { // code below will fail so no need to finish this loop occurence. continue; } $local_ifName = $lldp['lldpNeighborPortId'][$IndexId][1]; $local_port_id = find_port_id('gigabitEthernet ' . $local_ifName, null, $device['device_id']); $remote_device_id = find_device_id($lldp['lldpNeighborDeviceName'][$IndexId][1]); $remote_device_name = $lldp['lldpNeighborDeviceName'][$IndexId][1]; $remote_device_sysDescr = $lldp['lldpNeighborDeviceDescr'][$IndexId][1]; $remote_device_ip = $lldp['lldpNeighborManageIpAddr'][$IndexId][1]; $remote_port_descr = $lldp['lldpNeighborPortIdDescr'][$IndexId][1]; $remote_port_id = find_port_id($remote_port_descr, null, $remote_device_id); if (! $remote_device_id && \LibreNMS\Util\Validate::hostname($remote_device_name) && ! can_skip_discovery($remote_device_name, $remote_device_ip) && Config::get('autodiscovery.xdp') === true) { $remote_device_id = discover_new_device($remote_device_name, $device, 'LLDP', $local_ifName); } discover_link( $local_port_id, //our port id from database 'lldp', $remote_port_id, //remote port id from database if applicable $remote_device_name, //remote device name from SNMP walk $remote_port_descr, //remote port description from SNMP walk null, $remote_device_sysDescr, //remote device description from SNMP walk $device['device_id'], //our device id $remote_device_id //remote device id if applicable ); } } echo PHP_EOL; } else { echo ' LLDP-MIB: '; $lldp_array = SnmpQuery::hideMib()->walk('LLDP-MIB::lldpRemTable')->table(3); if (! empty($lldp_array)) { $lldp_remAddr_num = SnmpQuery::hideMib()->numeric()->walk('.1.0.8802.1.1.2.1.4.2.1.3'); foreach ($lldp_remAddr_num as $key => $value) { $res = preg_match("/1\.0\.8802\.1\.1\.2\.1\.4\.2\.1\.3\.([^\.]*)\.([^\.]*)\.([^\.]*)\.([^\.]*)\.([^\.]*).(([^\.]*)(\.([^\.]*))+)/", $key, $matches); if ($res) { //collect the Management IP address from the OID if ($matches[5] == 4) { $lldp_array[$matches[1]][$matches[2]][$matches[3]]['lldpRemManAddr'] = $matches[6]; } else { $ipv6 = implode( ':', array_map( function ($v) { return sprintf('%02x', $v); }, explode('.', $matches[6]) ) ); $ipv6 = preg_replace('/([^:]{2}):([^:]{2})/i', '$1$2', $ipv6); $lldp_array[$matches[1]][$matches[2]][$matches[3]]['lldpRemManAddr'] = $ipv6; } } } if ($device['os'] == 'aos7') { $lldp_local = snmpwalk_cache_oid($device, 'lldpLocPortEntry', [], 'LLDP-MIB'); $lldp_ports = snmpwalk_group($device, 'lldpLocPortId', 'LLDP-MIB'); } else { $dot1d_array = snmpwalk_group($device, 'dot1dBasePortIfIndex', 'BRIDGE-MIB'); $lldp_ports = snmpwalk_group($device, 'lldpLocPortId', 'LLDP-MIB'); } } else { echo ' LLDP-V2-MIB: '; $lldpv2_array = SnmpQuery::hideMib()->walk('LLDP-V2-MIB::lldpV2RemTable')->table(4); } $mapV2toV1 = [ 'lldpV2RemChassisIdSubtype' => 'lldpRemChassisIdSubtype', 'lldpV2RemChassisId' => 'lldpRemChassisId', 'lldpV2RemPortIdSubtype' => 'lldpRemPortIdSubtype', 'lldpV2RemPortId' => 'lldpRemPortId', 'lldpV2RemPortDesc' => 'lldpRemPortDesc', 'lldpV2RemSysName' => 'lldpRemSysName', 'lldpV2RemSysDesc' => 'lldpRemSysDesc', 'lldpV2RemSysCapSupported' => 'lldpRemSysCapSupported', 'lldpV2RemSysCapEnabled' => 'lldpRemSysCapEnabled', 'lldpV2RemRemoteChanges' => 'lldpRemRemoteChanges', 'lldpV2RemTooManyNeighbors' => 'lldpRemTooManyNeighbors', 'lldpV2RemManAddrTable' => 'lldpRemManAddrTable', 'lldpV2RemManAddrEntry' => 'lldpRemManAddrEntry', 'lldpV2RemManAddrSubtype' => 'lldpRemManAddrSubtype', 'lldpV2RemManAddr' => 'lldpRemManAddr', 'lldpV2RemManAddrIfSubtype' => 'lldpRemManAddrIfSubtype', 'lldpV2RemManAddrIfId' => 'lldpRemManAddrIfId', 'lldpV2RemManAddrOID' => 'lldpRemManAddrOID', ]; if (! empty($lldpv2_array)) { // map it to lldp_array foreach ($lldpv2_array as $lldpV2RemTimeMark => $value) { foreach ($value as $lldpV2RemLocalIfIndex => $value) { foreach ($value as $lldpV2RemLocalDestMACAddress => $value) { foreach ($value as $lldpV2RemIndex => $lldpv2_array_entries) { foreach ($lldpv2_array_entries as $key => $value) { $newKey = $mapV2toV1[$key] ?? $key; $lldp_array[$lldpV2RemTimeMark][$lldpV2RemLocalIfIndex][$lldpV2RemIndex][$newKey] = $value; } $lldp_array[$lldpV2RemTimeMark][$lldpV2RemLocalIfIndex][$lldpV2RemIndex]['lldpRemLocalDestMACAddress'] = $lldpV2RemLocalDestMACAddress; } } } } } foreach ($lldp_array as $key => $lldp_if_array) { foreach ($lldp_if_array as $entry_key => $lldp_instance) { if ($device['os'] == 'aos7') { $ifName = $lldp_local[$entry_key]['lldpLocPortDesc']; } elseif (is_numeric($dot1d_array[$entry_key]['dot1dBasePortIfIndex'])) { $ifIndex = $dot1d_array[$entry_key]['dot1dBasePortIfIndex']; } else { $ifIndex = $entry_key; } if ($device['os'] == 'aos7') { $local_port_id = find_port_id($ifName, null, $device['device_id']); } else { $local_port_id = find_port_id($lldp_ports[$entry_key]['lldpLocPortId'], $ifIndex, $device['device_id']); } $interface = get_port_by_id($local_port_id); d_echo($lldp_instance); foreach ($lldp_instance as $entry_instance => $lldp) { // If lldpRemPortIdSubtype is 5 and lldpRemPortId is hex, convert it to ASCII. if ($lldp['lldpRemPortIdSubtype'] == 5 && ctype_xdigit(str_replace([' ', ':', '-'], '', strtolower($lldp['lldpRemPortId'])))) { $lldp['lldpRemPortId'] = StringHelpers::hexToAscii($lldp['lldpRemPortId'], ':'); } // normalize MAC address if present $remote_port_mac = ''; $remote_port_name = $lldp['lldpRemPortId']; if ($lldp['lldpRemChassisIdSubtype'] == 4) { // 4 = macaddress $remote_port_mac = str_replace([' ', ':', '-'], '', strtolower($lldp['lldpRemChassisId'])); } if ($lldp['lldpRemPortIdSubtype'] == 3) { // 3 = macaddress $remote_port_mac = str_replace([' ', ':', '-'], '', strtolower($lldp['lldpRemPortId'])); } if ($lldp['lldpRemChassisIdSubtype'] == 6 || $lldp['lldpRemChassisIdSubtype'] == 2) { // 6=ifName 2=ifAlias $remote_port_name = $lldp['lldpRemChassisId']; } // Linksys / Cisco SRW2016/24/48 all have lldpRemSysDesc Ethernet Interface, which makes all lldp mappings go to port g1. // ex: // 'lldpRemSysDesc' => '16-Port 10/100/1000 Gigabit Switch w/WebView', if (str_ends_with($lldp['lldpRemSysDesc'], 'Gigabit Switch w/WebView')) { $lldp['lldpRemPortDesc'] = ''; } $remote_device_id = find_device_id($lldp['lldpRemSysName'], $lldp['lldpRemManAddr'], $remote_port_mac); // add device if configured to do so if (! $remote_device_id && ! can_skip_discovery($lldp['lldpRemSysName'], $lldp['lldpRemSysDesc']) && Config::get('autodiscovery.xdp') === true) { $remote_device_id = discover_new_device($lldp['lldpRemSysName'], $device, 'LLDP', $interface); if (! $remote_device_id && Config::get('discovery_by_ip', false)) { $ptopo_array = snmpwalk_cache_multi_oid($device, 'ptopoConnEntry', [], 'PTOPO-MIB'); d_echo($ptopo_array); foreach ($ptopo_array as $ptopo) { if (strcmp(trim($ptopo['ptopoConnRemoteChassis']), trim($lldp['lldpRemChassisId'])) == 0) { $ip = IP::fromHexString($ptopo['ptopoConnAgentNetAddr'], true); $remote_device_id = discover_new_device($ip, $device, 'LLDP', $interface); break; } } if (! $remote_device_id && isset($lldp['lldpRemManAddr'])) { $remote_device_id = discover_new_device($lldp['lldpRemManAddr'], $device, 'LLDP', $interface); } unset($ptopo_array); } } $remote_device = device_by_id_cache($remote_device_id); if ($remote_device['os'] == 'calix') { $remote_port_name = 'EthPort ' . $lldp['lldpRemPortId']; } if ($remote_device['os'] == 'xos') { $slot_port = explode(':', $remote_port_name); if (sizeof($slot_port) == 2) { $n_slot = (int) $slot_port[0]; $n_port = (int) $slot_port[1]; } else { $n_slot = 1; $n_port = (int) $slot_port[0]; } $remote_port_name = (string) ($n_slot * 1000 + $n_port); } if ($remote_device['os'] == 'netgear' && $remote_device['sysDescr'] == 'GS108T' && $lldp['lldpRemSysDesc'] == 'Smart Switch') { // Some netgear switches, as Netgear GS108Tv1 presents it's port name over snmp as // "Port 1 Gigabit Ethernet" but as 'lldpRemPortId' => 'g1' and // 'lldpRemPortDesc' => 'Port #1' over lldp. // So remap g1 to 1 so it matches ifIndex if (preg_match("/^g(\d+)$/", $lldp['lldpRemPortId'], $matches)) { $remote_port_name = $matches[1]; } } $remote_port_id = find_port_id( $lldp['lldpRemPortDesc'], $remote_port_name, $remote_device_id, $remote_port_mac ); if ($remote_port_id == 0) { //We did not find it $remote_port_name = $remote_port_name . ' (' . $remote_port_mac . ')'; } if (empty($lldp['lldpRemSysName'])) { $lldp['lldpRemSysName'] = $remote_device['sysName'] ?: $remote_device['hostname']; } if (empty($lldp['lldpRemSysName'])) { $lldp['lldpRemSysName'] = $lldp['lldpRemSysDesc']; } if ($interface['port_id'] && $lldp['lldpRemSysName'] && $remote_port_name) { discover_link( $interface['port_id'], 'lldp', $remote_port_id, $lldp['lldpRemSysName'], $remote_port_name, null, $lldp['lldpRemSysDesc'], $device['device_id'], $remote_device_id ); } }//end foreach }//end foreach }//end foreach unset( $dot1d_array ); echo PHP_EOL; }//end elseif if (Config::get('autodiscovery.ospf') === true) { echo ' OSPF Discovery: '; $sql = 'SELECT DISTINCT(`ospfNbrIpAddr`),`device_id` FROM `ospf_nbrs` WHERE `device_id`=?'; foreach (dbFetchRows($sql, [$device['device_id']]) as $nbr) { try { $ip = IP::parse($nbr['ospfNbrIpAddr']); if ($ip->inNetworks(Config::get('autodiscovery.nets-exclude'))) { echo 'x'; continue; } if (! $ip->inNetworks(Config::get('nets'))) { echo 'i'; continue; } $name = gethostbyaddr($ip); $remote_device_id = discover_new_device($name, $device, 'OSPF'); } catch (\LibreNMS\Exceptions\InvalidIpException $e) { // } } echo PHP_EOL; } d_echo($link_exists); $sql = 'SELECT * FROM `links` AS L, `ports` AS I WHERE L.local_port_id = I.port_id AND I.device_id = ?'; foreach (dbFetchRows($sql, [$device['device_id']]) as $test) { $local_port_id = $test['local_port_id']; $remote_hostname = $test['remote_hostname']; $remote_port = $test['remote_port']; d_echo("$local_port_id -> $remote_hostname -> $remote_port \n"); if (! $link_exists[$local_port_id][$remote_hostname][$remote_port]) { echo '-'; $rows = dbDelete('links', '`id` = ?', [$test['id']]); d_echo("$rows deleted "); } } // remove orphaned links $deleted = (int) dbDeleteOrphans('links', ['devices.device_id.local_device_id']); echo str_repeat('-', $deleted); d_echo(" $deleted orphaned links deleted\n"); unset( $link_exists, $sql, $fdp_array, $cdp_array, $lldp_array, $deleted );