2010-01-13 23:40:07 +00:00
|
|
|
<?php
|
2016-11-25 15:14:35 -06:00
|
|
|
/**
|
|
|
|
* arp-table.php
|
|
|
|
*
|
|
|
|
* Collect arp table entries from devices and update the database
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2021-02-09 00:29:04 +01:00
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2016-11-25 15:14:35 -06:00
|
|
|
*
|
2021-02-09 00:29:04 +01:00
|
|
|
* @link https://www.librenms.org
|
2021-09-10 20:09:53 +02:00
|
|
|
*
|
2016-11-25 15:14:35 -06:00
|
|
|
* @copyright 2016 Tony Murray
|
|
|
|
* @author Tony Murray <murraytony@gmail.com>
|
|
|
|
*/
|
2010-01-13 23:40:07 +00:00
|
|
|
|
2017-09-11 15:26:41 -05:00
|
|
|
use LibreNMS\Config;
|
|
|
|
|
2021-08-23 01:22:28 -05:00
|
|
|
foreach (DeviceCache::getPrimary()->getVrfContexts() as $context_name) {
|
|
|
|
$device['context_name'] = $context_name;
|
2016-04-12 16:00:52 +02:00
|
|
|
|
2017-09-11 15:26:41 -05:00
|
|
|
if (file_exists(Config::get('install_dir') . "/includes/discovery/arp-table/{$device['os']}.inc.php")) {
|
|
|
|
include Config::get('install_dir') . "/includes/discovery/arp-table/{$device['os']}.inc.php";
|
2017-08-22 20:55:39 +01:00
|
|
|
} else {
|
|
|
|
$arp_data = snmpwalk_group($device, 'ipNetToPhysicalPhysAddress', 'IP-MIB');
|
|
|
|
$arp_data = snmpwalk_group($device, 'ipNetToMediaPhysAddress', 'IP-MIB', 1, $arp_data);
|
|
|
|
}
|
2011-03-15 11:24:35 +00:00
|
|
|
|
2020-09-21 15:59:34 +02:00
|
|
|
$sql = 'SELECT * from `ipv4_mac` WHERE `device_id`=? AND `context_name`=?';
|
2021-08-23 01:22:28 -05:00
|
|
|
$existing_data = dbFetchRows($sql, [$device['device_id'], $context_name]);
|
2018-01-24 14:51:00 -06:00
|
|
|
|
2017-07-04 16:27:43 -05:00
|
|
|
$ipv4_addresses = array_map(function ($data) {
|
|
|
|
return $data['ipv4_address'];
|
|
|
|
}, $existing_data);
|
2020-09-21 15:40:17 +02:00
|
|
|
$arp_table = [];
|
|
|
|
$insert_data = [];
|
2017-07-04 16:27:43 -05:00
|
|
|
foreach ($arp_data as $ifIndex => $data) {
|
|
|
|
$interface = get_port_by_index_cache($device['device_id'], $ifIndex);
|
2016-11-25 15:14:35 -06:00
|
|
|
$port_id = $interface['port_id'];
|
2012-02-06 17:46:09 +00:00
|
|
|
|
2017-07-04 16:27:43 -05:00
|
|
|
$port_arp = array_merge(
|
2020-09-21 15:40:17 +02:00
|
|
|
(array) $data['ipNetToMediaPhysAddress'],
|
2021-03-12 18:10:14 -06:00
|
|
|
is_array($data['ipNetToPhysicalPhysAddress']) ? (array) $data['ipNetToPhysicalPhysAddress']['ipv4'] : []
|
2017-07-04 16:27:43 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
echo "{$interface['ifName']}: \n";
|
|
|
|
foreach ($port_arp as $ip => $raw_mac) {
|
|
|
|
if (empty($ip) || empty($raw_mac) || $raw_mac == '0:0:0:0:0:0' || isset($arp_table[$port_id][$ip])) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-11-25 15:14:35 -06:00
|
|
|
$mac = implode(array_map('zeropad', explode(':', $raw_mac)));
|
|
|
|
$arp_table[$port_id][$ip] = $mac;
|
2012-02-06 17:46:09 +00:00
|
|
|
|
2016-11-30 17:13:19 -06:00
|
|
|
$index = array_search($ip, $ipv4_addresses);
|
2016-11-25 15:14:35 -06:00
|
|
|
if ($index !== false) {
|
|
|
|
$old_mac = $existing_data[$index]['mac_address'];
|
|
|
|
if ($mac != $old_mac && $mac != '') {
|
|
|
|
d_echo("Changed mac address for $ip from $old_mac to $mac\n");
|
2021-03-28 17:25:30 -05:00
|
|
|
log_event("MAC change: $ip : " . \LibreNMS\Util\Rewrite::readableMac($old_mac) . ' -> ' . \LibreNMS\Util\Rewrite::readableMac($mac), $device, 'interface', 4, $port_id);
|
2021-08-23 01:22:28 -05:00
|
|
|
dbUpdate(['mac_address' => $mac], 'ipv4_mac', 'port_id=? AND ipv4_address=? AND context_name=?', [$port_id, $ip, $context_name]);
|
2016-08-28 12:32:58 -05:00
|
|
|
}
|
2017-07-04 16:27:43 -05:00
|
|
|
d_echo("$raw_mac => $ip\n", '.');
|
2016-08-28 12:32:58 -05:00
|
|
|
} elseif (isset($interface['port_id'])) {
|
2017-07-04 16:27:43 -05:00
|
|
|
d_echo("$raw_mac => $ip\n", '+');
|
2020-09-21 15:40:17 +02:00
|
|
|
$insert_data[] = [
|
2016-11-25 15:14:35 -06:00
|
|
|
'port_id' => $port_id,
|
2017-07-04 16:27:43 -05:00
|
|
|
'device_id' => $device['device_id'],
|
2016-11-25 15:14:35 -06:00
|
|
|
'mac_address' => $mac,
|
|
|
|
'ipv4_address' => $ip,
|
2021-08-23 01:22:28 -05:00
|
|
|
'context_name' => (string) $context_name,
|
2020-09-21 15:40:17 +02:00
|
|
|
];
|
2016-11-25 15:14:35 -06:00
|
|
|
}
|
|
|
|
}
|
2017-07-04 16:27:43 -05:00
|
|
|
echo PHP_EOL;
|
2016-11-25 15:14:35 -06:00
|
|
|
}
|
|
|
|
|
2017-02-08 04:54:30 +00:00
|
|
|
unset(
|
2017-07-04 16:27:43 -05:00
|
|
|
$interface,
|
2017-02-08 04:54:30 +00:00
|
|
|
$arp_data,
|
|
|
|
$ipv4_addresses,
|
|
|
|
$data
|
|
|
|
);
|
|
|
|
|
2016-11-25 15:14:35 -06:00
|
|
|
// add new entries
|
2020-09-21 15:40:17 +02:00
|
|
|
if (! empty($insert_data)) {
|
2016-11-25 15:14:35 -06:00
|
|
|
dbBulkInsert($insert_data, 'ipv4_mac');
|
|
|
|
}
|
2011-03-15 11:24:35 +00:00
|
|
|
|
2016-11-25 15:14:35 -06:00
|
|
|
// remove stale entries
|
|
|
|
foreach ($existing_data as $entry) {
|
2016-08-28 12:32:58 -05:00
|
|
|
$entry_mac = $entry['mac_address'];
|
2020-09-21 15:40:17 +02:00
|
|
|
$entry_if = $entry['port_id'];
|
|
|
|
$entry_ip = $entry['ipv4_address'];
|
2016-11-25 15:14:35 -06:00
|
|
|
if ($arp_table[$entry_if][$entry_ip] != $entry_mac) {
|
2021-08-23 01:22:28 -05:00
|
|
|
dbDelete('ipv4_mac', '`port_id` = ? AND `mac_address`=? AND `ipv4_address`=? AND `context_name`=?', [$entry_if, $entry_mac, $entry_ip, $context_name]);
|
2016-11-25 15:14:35 -06:00
|
|
|
d_echo(null, '-');
|
2016-08-28 12:32:58 -05:00
|
|
|
}
|
2015-07-13 20:10:26 +02:00
|
|
|
}
|
2017-04-25 21:28:25 +01:00
|
|
|
|
|
|
|
// remove entries that no longer have an owner
|
2020-09-21 15:40:17 +02:00
|
|
|
dbDeleteOrphans('ipv4_mac', ['ports.port_id', 'devices.device_id']);
|
2017-04-25 21:28:25 +01:00
|
|
|
|
2016-11-25 15:14:35 -06:00
|
|
|
echo PHP_EOL;
|
2017-02-08 04:54:30 +00:00
|
|
|
unset(
|
|
|
|
$existing_data,
|
|
|
|
$arp_table,
|
|
|
|
$insert_data,
|
|
|
|
$sql,
|
|
|
|
$params,
|
|
|
|
$entry,
|
|
|
|
$device['context_name']
|
|
|
|
);
|
2016-04-12 16:00:52 +02:00
|
|
|
}
|