mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
Refactor MAC utilities into a single class (#15379)
* Refactor MAC utils to a new utility class * Apply fixes from StyleCI * Inline functions Add tests Handle bridgeid format * Apply fixes from StyleCI * Dedicated code path for stp bridge parsing, and improve STP output a bit * Correctly parse dot1dBaseBridgeAddress and don't store int in bool field * trim any unexpected character from bridge addresses, add extra test data. * better comment * barsBridge can handle dot1dBaseBridgeAddress correctly now * parseBridge, check for properly formatted mac first. * update test data, empty data = empty mac * Fix new usage after rebase * import --------- Co-authored-by: StyleCI Bot <[email protected]>
This commit is contained in:
co-authored by
GitHub
StyleCI Bot
parent
908aef6596
commit
d8c372bbf4
@@ -55,13 +55,13 @@ class Stp implements Module
|
||||
{
|
||||
$device = $os->getDevice();
|
||||
|
||||
echo 'Instances: ';
|
||||
$instances = $os->discoverStpInstances();
|
||||
echo 'Instances: ';
|
||||
ModuleModelObserver::observe(\App\Models\Stp::class);
|
||||
$this->syncModels($device, 'stpInstances', $instances);
|
||||
|
||||
echo "\nPorts: ";
|
||||
$ports = $os->discoverStpPorts($instances);
|
||||
echo "\nPorts: ";
|
||||
ModuleModelObserver::observe(PortStp::class);
|
||||
$this->syncModels($device, 'stpPorts', $ports);
|
||||
|
||||
@@ -109,27 +109,4 @@ class Stp implements Module
|
||||
->get()->map->makeHidden(['port_stp_id', 'device_id', 'port_id']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* designated root is stored in format 2 octet bridge priority + MAC address, so we need to normalize it
|
||||
*/
|
||||
public function rootToMac(string $root): string
|
||||
{
|
||||
$dr = str_replace(['.', ' ', ':', '-'], '', strtolower($root));
|
||||
|
||||
return substr($dr, -12); //remove first two octets
|
||||
}
|
||||
|
||||
public function designatedPort(string $dp): int
|
||||
{
|
||||
if (preg_match('/-(\d+)/', $dp, $matches)) {
|
||||
// Syntax with "priority" dash "portID" like so : 32768-54, both in decimal
|
||||
return (int) $matches[1];
|
||||
}
|
||||
|
||||
// Port saved in format priority+port (ieee 802.1d-1998: clause 8.5.5.1)
|
||||
$dp = substr($dp, -2); //discard the first octet (priority part)
|
||||
|
||||
return (int) hexdec($dp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,8 @@ use LibreNMS\Interfaces\Polling\Sensors\WirelessApCountPolling;
|
||||
use LibreNMS\Interfaces\Polling\Sensors\WirelessClientsPolling;
|
||||
use LibreNMS\Interfaces\Polling\Sensors\WirelessFrequencyPolling;
|
||||
use LibreNMS\OS;
|
||||
use LibreNMS\Util\Mac;
|
||||
use LibreNMS\Util\Number;
|
||||
use LibreNMS\Util\Rewrite;
|
||||
|
||||
class ArubaInstant extends OS implements
|
||||
OSDiscovery,
|
||||
@@ -77,10 +77,11 @@ class ArubaInstant extends OS implements
|
||||
|
||||
foreach ($ai_ap_data as $ai_ap => $ai_ap_oid) {
|
||||
$value = $ai_ap_oid['aiAPCPUUtilization'];
|
||||
$combined_oid = sprintf('%s::%s.%s', $ai_mib, 'aiAPCPUUtilization', Rewrite::oidMac($ai_ap));
|
||||
$mac = Mac::parse($ai_ap);
|
||||
$combined_oid = sprintf('%s::%s.%s', $ai_mib, 'aiAPCPUUtilization', $mac->oid());
|
||||
$oid = snmp_translate($combined_oid, 'ALL', 'arubaos', '-On');
|
||||
$description = $ai_ap_data[$ai_ap]['aiAPSerialNum'];
|
||||
$processors[] = Processor::discover('aruba-instant', $this->getDeviceId(), $oid, Rewrite::macToHex($ai_ap), $description, 1, $value);
|
||||
$processors[] = Processor::discover('aruba-instant', $this->getDeviceId(), $oid, $mac->hex(), $description, 1, $value);
|
||||
} // end foreach
|
||||
|
||||
return $processors;
|
||||
@@ -126,10 +127,10 @@ class ArubaInstant extends OS implements
|
||||
// Clients Per Radio
|
||||
foreach ($ap_data as $index => $entry) {
|
||||
foreach ($entry['aiRadioClientNum'] as $radio => $value) {
|
||||
$combined_oid = sprintf('%s::%s.%s.%s', $ai_mib, 'aiRadioClientNum', Rewrite::oidMac($index), $radio);
|
||||
$combined_oid = sprintf('%s::%s.%s.%s', $ai_mib, 'aiRadioClientNum', Mac::parse($index)->oid(), $radio);
|
||||
$oid = snmp_translate($combined_oid, 'ALL', 'arubaos', '-On');
|
||||
$description = sprintf('%s Radio %s', $entry['aiAPSerialNum'], $radio);
|
||||
$sensor_index = sprintf('%s.%s', Rewrite::macToHex($index), $radio);
|
||||
$sensor_index = sprintf('%s.%s', Mac::parse($index)->hex(), $radio);
|
||||
$sensors[] = new WirelessSensor('clients', $this->getDeviceId(), $oid, 'aruba-instant', $sensor_index, $description, $value);
|
||||
}
|
||||
}
|
||||
@@ -250,10 +251,10 @@ class ArubaInstant extends OS implements
|
||||
$value = $value * $multiplier;
|
||||
}
|
||||
|
||||
$combined_oid = sprintf('%s::%s.%s.%s', $ai_mib, $mib, Rewrite::oidMac($ai_ap), $ai_ap_radio);
|
||||
$combined_oid = sprintf('%s::%s.%s.%s', $ai_mib, $mib, Mac::parse($ai_ap)->oid(), $ai_ap_radio);
|
||||
$oid = snmp_translate($combined_oid, 'ALL', 'arubaos', '-On');
|
||||
$description = sprintf($desc, $ai_sg_data[$ai_ap]['aiAPSerialNum'], $ai_ap_radio);
|
||||
$index = sprintf('%s.%s', Rewrite::macToHex($ai_ap), $ai_ap_radio);
|
||||
$index = sprintf('%s.%s', Mac::parse($ai_ap)->hex(), $ai_ap_radio);
|
||||
|
||||
$sensors[] = new WirelessSensor($type, $this->getDeviceId(), $oid, 'aruba-instant', $index, $description, $value, $multiplier);
|
||||
} // end foreach
|
||||
|
||||
@@ -35,7 +35,7 @@ use LibreNMS\Interfaces\Discovery\Sensors\WirelessRateDiscovery;
|
||||
use LibreNMS\Interfaces\Discovery\Sensors\WirelessRssiDiscovery;
|
||||
use LibreNMS\Interfaces\Polling\Sensors\WirelessFrequencyPolling;
|
||||
use LibreNMS\OS;
|
||||
use LibreNMS\Util\Rewrite;
|
||||
use LibreNMS\Util\Mac;
|
||||
|
||||
class Lcos extends OS implements
|
||||
WirelessFrequencyDiscovery,
|
||||
@@ -222,7 +222,7 @@ class Lcos extends OS implements
|
||||
$sensors[$bssid] = new WirelessSensor(
|
||||
'ccq',
|
||||
$this->getDeviceId(),
|
||||
'.1.3.6.1.4.1.2356.11.1.3.44.1.10.' . Rewrite::oidMac($bssid) . '.0',
|
||||
'.1.3.6.1.4.1.2356.11.1.3.44.1.10.' . Mac::parse($bssid)->oid() . '.0',
|
||||
'lcos',
|
||||
$bssid,
|
||||
'CCQ ' . $entry['lcsStatusWlanCompetingNetworksEntryInterpointPeerName'] . " $bssid",
|
||||
@@ -255,7 +255,7 @@ class Lcos extends OS implements
|
||||
$sensors[$bssid] = new WirelessSensor(
|
||||
'rate',
|
||||
$this->getDeviceId(),
|
||||
'.1.3.6.1.4.1.2356.11.1.3.44.1.35.' . Rewrite::oidMac($bssid) . '.0',
|
||||
'.1.3.6.1.4.1.2356.11.1.3.44.1.35.' . Mac::parse($bssid)->oid() . '.0',
|
||||
'lcos-tx',
|
||||
$bssid,
|
||||
'TX Rate ' . $entry['lcsStatusWlanCompetingNetworksEntryInterpointPeerName'] . " $bssid",
|
||||
@@ -290,7 +290,7 @@ class Lcos extends OS implements
|
||||
$sensors[$bssid] = new WirelessSensor(
|
||||
'rssi',
|
||||
$this->getDeviceId(),
|
||||
'.1.3.6.1.4.1.2356.11.1.3.44.1.26.' . Rewrite::oidMac($bssid) . '.0',
|
||||
'.1.3.6.1.4.1.2356.11.1.3.44.1.26.' . Mac::parse($bssid)->oid() . '.0',
|
||||
'lcos',
|
||||
$bssid,
|
||||
'RSSI ' . $entry['lcsStatusWlanCompetingNetworksEntryInterpointPeerName'] . " $bssid",
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace LibreNMS\OS\Traits;
|
||||
use App\Models\PortStp;
|
||||
use App\Models\Stp;
|
||||
use Illuminate\Support\Collection;
|
||||
use LibreNMS\Util\Rewrite;
|
||||
use LibreNMS\Util\Mac;
|
||||
use SnmpQuery;
|
||||
|
||||
trait BridgeMib
|
||||
@@ -67,19 +67,20 @@ trait BridgeMib
|
||||
return new Collection;
|
||||
}
|
||||
|
||||
$bridge = Rewrite::macToHex($stp['BRIDGE-MIB::dot1dBaseBridgeAddress.0'] ?? '');
|
||||
$drBridge = Rewrite::macToHex($stp['BRIDGE-MIB::dot1dStpDesignatedRoot.0'] ?? '');
|
||||
\Log::debug('VLAN: ' . ($vlan ?: 1) . " Bridge: {$bridge} DR: {$drBridge}");
|
||||
$bridge = Mac::parseBridge($stp['BRIDGE-MIB::dot1dBaseBridgeAddress.0'] ?? '');
|
||||
$bridgeMac = $bridge->hex();
|
||||
$drBridge = Mac::parseBridge($stp['BRIDGE-MIB::dot1dStpDesignatedRoot.0'] ?? '');
|
||||
\Log::info(sprintf('VLAN: %s Bridge: %s DR: %s', $vlan ?: 1, $bridge->readable(), $drBridge->readable()));
|
||||
|
||||
$instance = new \App\Models\Stp([
|
||||
'vlan' => $vlan,
|
||||
'rootBridge' => $bridge == $drBridge ? 1 : 0,
|
||||
'bridgeAddress' => $bridge,
|
||||
'rootBridge' => $bridgeMac == $drBridge->hex() ? 1 : 0,
|
||||
'bridgeAddress' => $bridgeMac,
|
||||
'protocolSpecification' => $stp['BRIDGE-MIB::dot1dStpProtocolSpecification.0'] ?? 'unknown',
|
||||
'priority' => $stp['BRIDGE-MIB::dot1dStpPriority.0'] ?? 0,
|
||||
'timeSinceTopologyChange' => substr($stp['BRIDGE-MIB::dot1dStpTimeSinceTopologyChange.0'] ?? '', 0, -2) ?: 0,
|
||||
'topChanges' => $stp['BRIDGE-MIB::dot1dStpTopChanges.0'] ?? 0,
|
||||
'designatedRoot' => $drBridge,
|
||||
'designatedRoot' => $drBridge->hex(),
|
||||
'rootCost' => $stp['BRIDGE-MIB::dot1dStpRootCost.0'] ?? 0,
|
||||
'rootPort' => $stp['BRIDGE-MIB::dot1dStpRootPort.0'] ?? 0,
|
||||
'maxAge' => ($stp['BRIDGE-MIB::dot1dStpMaxAge.0'] ?? 0) * $timeFactor,
|
||||
@@ -109,9 +110,9 @@ trait BridgeMib
|
||||
'state' => $data['BRIDGE-MIB::dot1dStpPortState'] ?? 'unknown',
|
||||
'enable' => $data['BRIDGE-MIB::dot1dStpPortEnable'] ?? 'unknown',
|
||||
'pathCost' => $data['BRIDGE-MIB::dot1dStpPortPathCost32'] ?? $data['BRIDGE-MIB::dot1dStpPortPathCost'] ?? 0,
|
||||
'designatedRoot' => Rewrite::macToHex($data['BRIDGE-MIB::dot1dStpPortDesignatedRoot'] ?? ''),
|
||||
'designatedRoot' => Mac::parseBridge($data['BRIDGE-MIB::dot1dStpPortDesignatedRoot'] ?? '')->hex(),
|
||||
'designatedCost' => $data['BRIDGE-MIB::dot1dStpPortDesignatedCost'] ?? 0,
|
||||
'designatedBridge' => Rewrite::macToHex($data['BRIDGE-MIB::dot1dStpPortDesignatedBridge'] ?? ''),
|
||||
'designatedBridge' => Mac::parseBridge($data['BRIDGE-MIB::dot1dStpPortDesignatedBridge'] ?? '')->hex(),
|
||||
'designatedPort' => $this->designatedPort($data['BRIDGE-MIB::dot1dStpPortDesignatedPort'] ?? ''),
|
||||
'forwardTransitions' => $data['BRIDGE-MIB::dot1dStpPortForwardTransitions'] ?? 0,
|
||||
]);
|
||||
@@ -156,7 +157,8 @@ trait BridgeMib
|
||||
|
||||
$instance->timeSinceTopologyChange = substr($data['BRIDGE-MIB::dot1dStpTimeSinceTopologyChange.0'] ?? '', 0, -2) ?: 0;
|
||||
$instance->topChanges = $data['BRIDGE-MIB::dot1dStpTopChanges.0'] ?? 0;
|
||||
$instance->designatedRoot = Rewrite::macToHex($data['BRIDGE-MIB::dot1dStpDesignatedRoot.0'] ?? '');
|
||||
$instance->designatedRoot = Mac::parseBridge($data['BRIDGE-MIB::dot1dStpDesignatedRoot.0'] ?? '')->hex();
|
||||
$instance->rootBridge = $instance->bridgeAddress == $instance->designatedRoot; // dr might have changed
|
||||
});
|
||||
}
|
||||
|
||||
@@ -179,8 +181,8 @@ trait BridgeMib
|
||||
$port->vlan = $vlan;
|
||||
$port->state = $data['BRIDGE-MIB::dot1dStpPortState'] ?? 'unknown';
|
||||
$port->enable = $data['BRIDGE-MIB::dot1dStpPortEnable'] ?? 'unknown';
|
||||
$port->designatedRoot = Rewrite::macToHex($data['BRIDGE-MIB::dot1dStpPortDesignatedRoot'] ?? '');
|
||||
$port->designatedBridge = Rewrite::macToHex($data['BRIDGE-MIB::dot1dStpPortDesignatedBridge'] ?? '');
|
||||
$port->designatedRoot = Mac::parseBridge($data['BRIDGE-MIB::dot1dStpPortDesignatedRoot'] ?? '')->hex();
|
||||
$port->designatedBridge = Mac::parseBridge($data['BRIDGE-MIB::dot1dStpPortDesignatedBridge'] ?? '')->hex();
|
||||
|
||||
return $port;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
/**
|
||||
* Mac.php
|
||||
*
|
||||
* -Description-
|
||||
*
|
||||
* 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
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @link https://www.librenms.org
|
||||
*
|
||||
* @copyright 2023 Tony Murray
|
||||
* @author Tony Murray <[email protected]>
|
||||
*/
|
||||
|
||||
namespace LibreNMS\Util;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class Mac
|
||||
{
|
||||
private array $mac = [];
|
||||
|
||||
public function __construct(string $mac)
|
||||
{
|
||||
$mac = strtolower(trim($mac));
|
||||
|
||||
if (preg_match('/^([0-9a-f]{1,2})[-:.]?([0-9a-f]{1,2})[-:.]?([0-9a-f]{1,2})[-:.]?([0-9a-f]{1,2})[-:.]?([0-9a-f]{1,2})[-:.]?([0-9a-f]{1,2})$/', $mac, $matches)) {
|
||||
// strings without delimiters must have 12 characters
|
||||
if (! preg_match('/^[0-9a-f]{0,11}$/', $mac)) {
|
||||
$this->mac = [
|
||||
str_pad($matches[1], 2, '0', STR_PAD_LEFT),
|
||||
str_pad($matches[2], 2, '0', STR_PAD_LEFT),
|
||||
str_pad($matches[3], 2, '0', STR_PAD_LEFT),
|
||||
str_pad($matches[4], 2, '0', STR_PAD_LEFT),
|
||||
str_pad($matches[5], 2, '0', STR_PAD_LEFT),
|
||||
str_pad($matches[6], 2, '0', STR_PAD_LEFT),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a MAC address from a well-formed MAC string and in a common format.
|
||||
* 00:12:34:ab:cd:ef
|
||||
* 00:12:34:AB:CD:EF
|
||||
* 0:12:34:AB:CD:EF
|
||||
* 00-12-34-AB-CD-EF
|
||||
* 001234-ABCDEF
|
||||
* 0012.34AB.CDEF
|
||||
* 00:02:04:0B:0D:0F
|
||||
* 0:2:4:B:D:F
|
||||
*/
|
||||
public static function parse(?string $mac): static
|
||||
{
|
||||
return new static($mac ?? '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove prefix from STP bridge addresses to parse MAC
|
||||
* Examples: 80 00 3C 2C 99 7A 5D 80
|
||||
* 0-1C.2C.99.7A.5D.80
|
||||
*/
|
||||
public static function parseBridge(string $bridge): static
|
||||
{
|
||||
$plainMac = new static($bridge);
|
||||
if ($plainMac->isValid()) {
|
||||
return $plainMac;
|
||||
}
|
||||
|
||||
return new static(substr(preg_replace('/[^0-9a-f]/', '', strtolower($bridge)), -12));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the parsed string was a valid MAC address
|
||||
*/
|
||||
public function isValid(): bool
|
||||
{
|
||||
return ! empty($this->mac);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reformat the MAC to 12 digit hex string 000a1fa3cc14
|
||||
*/
|
||||
public function hex(): string
|
||||
{
|
||||
return implode($this->mac);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reformat the MAC to a nice readable format 00:0a:1f:a3:cc:14
|
||||
*/
|
||||
public function readable()
|
||||
{
|
||||
return implode(':', $this->mac);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the OUI and return the vendor's name
|
||||
*/
|
||||
public function vendor(): string
|
||||
{
|
||||
$oui = implode(array_slice($this->mac, 0, 3));
|
||||
|
||||
$results = Cache::remember($oui, 21600, function () use ($oui) {
|
||||
return DB::table('vendor_ouis')
|
||||
->where('oui', 'like', "$oui%") // possible matches
|
||||
->orderBy('oui', 'desc') // so we can check longer ones first if we have them
|
||||
->pluck('vendor', 'oui');
|
||||
});
|
||||
|
||||
if (count($results) == 1) {
|
||||
return Arr::first($results);
|
||||
}
|
||||
|
||||
// Then we may have a shorter prefix, so let's try them one after the other
|
||||
$mac = $this->hex();
|
||||
foreach ($results as $oui => $vendor) {
|
||||
if (str_starts_with($mac, $oui)) {
|
||||
return $vendor;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Reformat hex MAC as oid MAC (dotted-decimal)
|
||||
*
|
||||
* 00:12:34:AB:CD:EF becomes 0.18.52.171.205.239
|
||||
* 0:12:34:AB:CD:EF becomes 0.18.52.171.205.239
|
||||
* 00:02:04:0B:0D:0F becomes 0.2.4.11.13.239
|
||||
* 0:2:4:B:D:F becomes 0.2.4.11.13.15
|
||||
*/
|
||||
public function oid(): string
|
||||
{
|
||||
return implode('.', array_map('hexdec', $this->mac));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of the MAC address bytes
|
||||
*/
|
||||
public function array(): array
|
||||
{
|
||||
return $this->mac;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->readable();
|
||||
}
|
||||
}
|
||||
@@ -26,9 +26,6 @@
|
||||
namespace LibreNMS\Util;
|
||||
|
||||
use App\Models\Device;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use LibreNMS\Config;
|
||||
|
||||
class Rewrite
|
||||
@@ -138,91 +135,6 @@ class Rewrite
|
||||
return str_ireplace(array_keys($rewrite_shortif), array_values($rewrite_shortif), $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reformat a mac stored in the DB (only hex) to a nice readable format
|
||||
*
|
||||
* @param string $mac
|
||||
* @return string
|
||||
*/
|
||||
public static function readableMac($mac)
|
||||
{
|
||||
return rtrim(chunk_split($mac, 2, ':'), ':');
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the OUI and match it against database values
|
||||
*
|
||||
* @param string $mac
|
||||
* @return string
|
||||
*/
|
||||
public static function readableOUI($mac): string
|
||||
{
|
||||
$oui = substr($mac, 0, 6);
|
||||
|
||||
$results = Cache::remember($oui, 21600, function () use ($oui) {
|
||||
return DB::table('vendor_ouis')
|
||||
->where('oui', 'like', "$oui%") // possible matches
|
||||
->orderBy('oui', 'desc') // so we can check longer ones first if we have them
|
||||
->pluck('vendor', 'oui');
|
||||
});
|
||||
|
||||
if (count($results) == 1) {
|
||||
return Arr::first($results);
|
||||
}
|
||||
|
||||
// Then we may have a shorter prefix, so let's try them one after the other
|
||||
foreach ($results as $oui => $vendor) {
|
||||
if (str_starts_with($mac, $oui)) {
|
||||
return $vendor;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Reformat hex MAC as oid MAC (dotted-decimal)
|
||||
*
|
||||
* 00:12:34:AB:CD:EF becomes 0.18.52.171.205.239
|
||||
* 0:12:34:AB:CD:EF becomes 0.18.52.171.205.239
|
||||
* 00:02:04:0B:0D:0F becomes 0.2.4.11.13.239
|
||||
* 0:2:4:B:D:F becomes 0.2.4.11.13.15
|
||||
*
|
||||
* @param string $mac
|
||||
* @return string oid representation of a MAC address
|
||||
*/
|
||||
public static function oidMac($mac)
|
||||
{
|
||||
return implode('.', array_map('hexdec', explode(':', $mac)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reformat Hex MAC with delimiters to Hex String without delimiters
|
||||
*
|
||||
* Assumes the MAC address is well-formed and in a common format.
|
||||
* 00:12:34:ab:cd:ef becomes 001234abcdef
|
||||
* 00:12:34:AB:CD:EF becomes 001234abcdef
|
||||
* 0:12:34:AB:CD:EF becomes 001234abcdef
|
||||
* 00-12-34-AB-CD-EF becomes 001234abcdef
|
||||
* 001234-ABCDEF becomes 001234abcdef
|
||||
* 0012.34AB.CDEF becomes 001234abcdef
|
||||
* 00:02:04:0B:0D:0F becomes 0002040b0d0f
|
||||
* 0:2:4:B:D:F becomes 0002040b0d0f
|
||||
*
|
||||
* @param string $mac hexadecimal MAC address with or without common delimiters
|
||||
* @return string undelimited hexadecimal MAC address
|
||||
*/
|
||||
public static function macToHex(string $mac): string
|
||||
{
|
||||
// split it apart
|
||||
$mac_array = explode(':', str_replace(['-', '.', ' '], ':', strtolower(trim($mac))));
|
||||
$len = count($mac_array);
|
||||
$mac_padding = array_fill(0, $len, ceil(12 / $len));
|
||||
|
||||
// pad the parts to prefix 0s and only take the last 12 digits
|
||||
return substr(implode(array_map('zeropad', $mac_array, $mac_padding)), -12);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make Cisco hardware human readable
|
||||
*
|
||||
|
||||
@@ -34,7 +34,7 @@ use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use LibreNMS\Util\IP;
|
||||
use LibreNMS\Util\Rewrite;
|
||||
use LibreNMS\Util\Mac;
|
||||
use LibreNMS\Util\Url;
|
||||
|
||||
class FdbTablesController extends TableController
|
||||
@@ -159,10 +159,11 @@ class FdbTablesController extends TableController
|
||||
*/
|
||||
public function formatItem($fdb_entry)
|
||||
{
|
||||
$mac = Mac::parse($fdb_entry->mac_address);
|
||||
$item = [
|
||||
'device' => $fdb_entry->device ? Url::deviceLink($fdb_entry->device) : '',
|
||||
'mac_address' => Rewrite::readableMac($fdb_entry->mac_address),
|
||||
'mac_oui' => Rewrite::readableOUI($fdb_entry->mac_address),
|
||||
'mac_address' => $mac->readable(),
|
||||
'mac_oui' => $mac->vendor(),
|
||||
'ipv4_address' => $fdb_entry->ipv4Addresses->implode(', '),
|
||||
'interface' => '',
|
||||
'vlan' => $fdb_entry->vlan ? $fdb_entry->vlan->vlan_vlan : '',
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
namespace App\Http\Controllers\Table;
|
||||
|
||||
use App\Models\PortsNac;
|
||||
use LibreNMS\Util\Rewrite;
|
||||
use LibreNMS\Util\Mac;
|
||||
use LibreNMS\Util\Url;
|
||||
|
||||
class PortNacController extends TableController
|
||||
@@ -86,9 +86,10 @@ class PortNacController extends TableController
|
||||
public function formatItem($nac)
|
||||
{
|
||||
$item = $nac->toArray();
|
||||
$mac = Mac::parse($item['mac_address']);
|
||||
$item['port_id'] = Url::portLink($nac->port, $nac->port->getShortLabel());
|
||||
$item['mac_oui'] = Rewrite::readableOUI($item['mac_address']);
|
||||
$item['mac_address'] = Rewrite::readableMac($item['mac_address']);
|
||||
$item['mac_oui'] = $mac->vendor();
|
||||
$item['mac_address'] = $mac->readable();
|
||||
$item['port'] = null; //free some unused data to be sent to the browser
|
||||
$item['device_id'] = Url::deviceLink($nac->device);
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace App\Http\Controllers\Table;
|
||||
use App\Facades\DeviceCache;
|
||||
use App\Models\PortStp;
|
||||
use App\Models\Stp;
|
||||
use LibreNMS\Util\Rewrite;
|
||||
use LibreNMS\Util\Mac;
|
||||
use LibreNMS\Util\Url;
|
||||
|
||||
class PortStpController extends TableController
|
||||
@@ -85,6 +85,9 @@ class PortStpController extends TableController
|
||||
*/
|
||||
public function formatItem($stpPort)
|
||||
{
|
||||
$drMac = Mac::parse($stpPort->designatedRoot);
|
||||
$dbMac = Mac::parse($stpPort->designatedBridge);
|
||||
|
||||
return [
|
||||
'port_id' => Url::portLink($stpPort->port, $stpPort->port->getShortLabel()) . '<br />' . $stpPort->port->getDescription(),
|
||||
'vlan' => $stpPort->vlan ?: 1,
|
||||
@@ -92,12 +95,12 @@ class PortStpController extends TableController
|
||||
'state' => $stpPort->state,
|
||||
'enable' => $stpPort->enable,
|
||||
'pathCost' => $stpPort->pathCost,
|
||||
'designatedRoot' => Rewrite::readableMac($stpPort->designatedRoot),
|
||||
'designatedRoot_vendor' => Rewrite::readableOUI($stpPort->designatedRoot),
|
||||
'designatedRoot' => $drMac->readable(),
|
||||
'designatedRoot_vendor' => $drMac->vendor(),
|
||||
'designatedRoot_device' => Url::deviceLink(DeviceCache::get(Stp::where('bridgeAddress', $stpPort->designatedRoot)->value('device_id'))),
|
||||
'designatedCost' => $stpPort->designatedCost,
|
||||
'designatedBridge' => Rewrite::readableMac($stpPort->designatedBridge),
|
||||
'designatedBridge_vendor' => Rewrite::readableOUI($stpPort->designatedBridge),
|
||||
'designatedBridge' => $dbMac->readable(),
|
||||
'designatedBridge_vendor' => $dbMac->vendor(),
|
||||
'designatedBridge_device' => Url::deviceLink(DeviceCache::get(Stp::where('bridgeAddress', $stpPort->designatedBridge)->value('device_id'))),
|
||||
'designatedPort' => $stpPort->designatedPort,
|
||||
'forwardTransitions' => $stpPort->forwardTransitions,
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Util\Mac;
|
||||
|
||||
foreach (DeviceCache::getPrimary()->getVrfContexts() as $context_name) {
|
||||
if (file_exists(Config::get('install_dir') . "/includes/discovery/arp-table/{$device['os']}.inc.php")) {
|
||||
@@ -69,7 +70,7 @@ foreach (DeviceCache::getPrimary()->getVrfContexts() as $context_name) {
|
||||
$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");
|
||||
log_event("MAC change: $ip : " . \LibreNMS\Util\Rewrite::readableMac($old_mac) . ' -> ' . \LibreNMS\Util\Rewrite::readableMac($mac), $device, 'interface', 4, $port_id);
|
||||
log_event("MAC change: $ip : " . Mac::parse($old_mac)->readable() . ' -> ' . Mac::parse($mac)->readable(), $device, 'interface', 4, $port_id);
|
||||
dbUpdate(['mac_address' => $mac], 'ipv4_mac', 'port_id=? AND ipv4_address=? AND context_name=?', [$port_id, $ip, $context_name]);
|
||||
}
|
||||
d_echo("$raw_mac => $ip\n", '.');
|
||||
|
||||
@@ -42,8 +42,8 @@ use LibreNMS\Exceptions\InvalidTableColumnException;
|
||||
use LibreNMS\Util\Graph;
|
||||
use LibreNMS\Util\IP;
|
||||
use LibreNMS\Util\IPv4;
|
||||
use LibreNMS\Util\Mac;
|
||||
use LibreNMS\Util\Number;
|
||||
use LibreNMS\Util\Rewrite;
|
||||
|
||||
function api_success($result, $result_name, $message = null, $code = 200, $count = null, $extra = null): JsonResponse
|
||||
{
|
||||
@@ -2460,30 +2460,23 @@ function list_fdb(Illuminate\Http\Request $request)
|
||||
|
||||
function list_fdb_detail(Illuminate\Http\Request $request)
|
||||
{
|
||||
$macAddress = Rewrite::macToHex((string) $request->route('mac'));
|
||||
$macAddress = Mac::parse($request->route('mac'));
|
||||
|
||||
$rules = [
|
||||
'macAddress' => 'required|string|regex:/^[0-9a-fA-F]{12}$/',
|
||||
];
|
||||
|
||||
$validate = Validator::make(['macAddress' => $macAddress], $rules);
|
||||
if ($validate->fails()) {
|
||||
return api_error(422, $validate->messages());
|
||||
if (! $macAddress->isValid()) {
|
||||
return api_error(422, 'Invalid MAC address');
|
||||
}
|
||||
|
||||
$extras = ['mac' => Rewrite::readableMac($macAddress), 'mac_oui' => Rewrite::readableOUI($macAddress)];
|
||||
$extras = ['mac' => $macAddress->readable(), 'mac_oui' => $macAddress->vendor()];
|
||||
|
||||
$fdb = PortsFdb::hasAccess(Auth::user())
|
||||
->when(! empty($macAddress), function (Builder $query) use ($macAddress) {
|
||||
return $query->leftJoin('ports', 'ports_fdb.port_id', 'ports.port_id')
|
||||
->leftJoin('devices', 'ports_fdb.device_id', 'devices.device_id')
|
||||
->where('mac_address', $macAddress)
|
||||
->orderBy('ports_fdb.updated_at', 'desc')
|
||||
->select('devices.hostname', 'ports.ifName', 'ports_fdb.updated_at');
|
||||
})
|
||||
->limit(1000)->get();
|
||||
->leftJoin('ports', 'ports_fdb.port_id', 'ports.port_id')
|
||||
->leftJoin('devices', 'ports_fdb.device_id', 'devices.device_id')
|
||||
->where('mac_address', $macAddress->hex())
|
||||
->orderBy('ports_fdb.updated_at', 'desc')
|
||||
->select('devices.hostname', 'ports.ifName', 'ports_fdb.updated_at')
|
||||
->limit(1000)->get();
|
||||
|
||||
if (count($fdb) == 0) {
|
||||
if ($fdb->isEmpty()) {
|
||||
return api_error(404, 'Fdb entry does not exist');
|
||||
}
|
||||
|
||||
@@ -2558,7 +2551,7 @@ function list_arp(Illuminate\Http\Request $request)
|
||||
return api_error(400, 'Invalid Network Address');
|
||||
}
|
||||
} elseif (filter_var($query, FILTER_VALIDATE_MAC)) {
|
||||
$mac = \LibreNMS\Util\Rewrite::macToHex($query);
|
||||
$mac = Mac::parse($query)->hex();
|
||||
$arp = dbFetchRows('SELECT * FROM `ipv4_mac` WHERE `mac_address`=?', [$mac]);
|
||||
} else {
|
||||
$arp = dbFetchRows('SELECT * FROM `ipv4_mac` WHERE `ipv4_address`=?', [$query]);
|
||||
@@ -2967,7 +2960,7 @@ function del_service_from_host(Illuminate\Http\Request $request)
|
||||
|
||||
function search_by_mac(Illuminate\Http\Request $request)
|
||||
{
|
||||
$macAddress = Rewrite::macToHex((string) $request->route('search'));
|
||||
$macAddress = Mac::parse((string) $request->route('search'))->hex();
|
||||
|
||||
$rules = [
|
||||
'macAddress' => 'required|string|regex:/^[0-9a-fA-F]{12}$/',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Exceptions\RrdGraphException;
|
||||
use LibreNMS\Util\Mac;
|
||||
|
||||
if (is_numeric($vars['id'])) {
|
||||
$acc = dbFetchRow('SELECT * FROM `mac_accounting` AS M, `ports` AS I, `devices` AS D WHERE M.ma_id = ? AND I.port_id = M.port_id AND I.device_id = D.device_id', [$vars['id']]);
|
||||
@@ -24,7 +25,7 @@ if (is_numeric($vars['id'])) {
|
||||
$device = device_by_id_cache($port['device_id']);
|
||||
$title = generate_device_link($device);
|
||||
$title .= ' :: Port ' . generate_port_link($port);
|
||||
$title .= ' :: ' . \LibreNMS\Util\Rewrite::readableMac($acc['mac']);
|
||||
$title .= ' :: ' . Mac::parse($acc['mac'])->readable();
|
||||
$auth = true;
|
||||
} else {
|
||||
throw new RrdGraphException('file not found');
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Util\Mac;
|
||||
|
||||
$port = $vars['id'];
|
||||
$stat = $vars['stat'] ?: 'bits';
|
||||
$sort = in_array($vars['sort'], ['in', 'out', 'both']) ? $vars['sort'] : 'in';
|
||||
@@ -49,7 +51,7 @@ $rrd_options .= " COMMENT:' In\: Current
|
||||
foreach ($accs as $acc) {
|
||||
$this_rrd = Rrd::name($acc['hostname'], ['cip', $acc['ifIndex'], $acc['mac']]);
|
||||
if (Rrd::checkRrdExists($this_rrd)) {
|
||||
$mac = \LibreNMS\Util\Rewrite::readableMac($acc['mac']);
|
||||
$mac = Mac::parse($acc['mac'])->readable();
|
||||
$name = $mac;
|
||||
|
||||
$addy = dbFetchRow('SELECT * FROM ipv4_mac where mac_address = ? AND port_id = ?', [$acc['mac'], $acc['port_id']]);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Util\Mac;
|
||||
|
||||
// FIXME - REWRITE!
|
||||
$hostname = $device['hostname'];
|
||||
@@ -186,7 +187,7 @@ if ($vars['subview'] == 'top10') {
|
||||
echo '
|
||||
<table>
|
||||
<tr>
|
||||
<td class=list-large width=200>' . \LibreNMS\Util\Rewrite::readableMac($acc['mac']) . '</td>
|
||||
<td class=list-large width=200>' . Mac::parse($acc['mac'])->readable() . '</td>
|
||||
<td class=list-large width=200>' . $addy['ipv4_address'] . '</td>
|
||||
<td class=list-large width=500>' . $name . ' ' . $arp_name . '</td>
|
||||
<td class=list-large width=100>' . \LibreNMS\Util\Number::formatSi($acc['cipMacHCSwitchedBytes_input_rate'] / 8, 2, 3, 'bps') . '</td>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Util\IP;
|
||||
use LibreNMS\Util\Mac;
|
||||
|
||||
$param = [];
|
||||
|
||||
@@ -87,8 +88,9 @@ foreach (dbFetchRows($sql, $param) as $interface) {
|
||||
if ($vars['search_type'] == 'ipv6') {
|
||||
$address = (string) IP::parse($interface['ipv6_address'], true) . '/' . $interface['ipv6_prefixlen'];
|
||||
} elseif ($vars['search_type'] == 'mac') {
|
||||
$address = \LibreNMS\Util\Rewrite::readableMac($interface['ifPhysAddress']);
|
||||
$mac_oui = \LibreNMS\Util\Rewrite::readableOUI($interface['ifPhysAddress']);
|
||||
$mac = Mac::parse($interface['ifPhysAddress']);
|
||||
$address = $mac->readable();
|
||||
$mac_oui = $mac->vendor();
|
||||
} else {
|
||||
$address = (string) IP::parse($interface['ipv4_address'], true) . '/' . $interface['ipv4_prefixlen'];
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\Util\Mac;
|
||||
|
||||
$param = [];
|
||||
|
||||
$sql = ' FROM `ipv4_mac` AS M, `ports` AS P, `devices` AS D ';
|
||||
@@ -95,9 +97,10 @@ foreach (dbFetchRows($sql, $param) as $entry) {
|
||||
$arp_if = 'Local port';
|
||||
}
|
||||
|
||||
$mac = Mac::parse($entry['mac_address']);
|
||||
$response[] = [
|
||||
'mac_address' => \LibreNMS\Util\Rewrite::readableMac($entry['mac_address']),
|
||||
'mac_oui' => \LibreNMS\Util\Rewrite::readableOUI($entry['mac_address']),
|
||||
'mac_address' => $mac->readable(),
|
||||
'mac_oui' => $mac->vendor(),
|
||||
'ipv4_address' => $entry['ipv4_address'],
|
||||
'hostname' => generate_device_link($entry),
|
||||
'interface' => generate_port_link($entry, makeshortif($entry['label'])) . ' ' . $error_img,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use LibreNMS\RRD\RrdDefinition;
|
||||
use LibreNMS\Util\Mac;
|
||||
|
||||
if ($device['os_group'] == 'cisco') {
|
||||
$acc_rows = dbFetchRows('SELECT *, A.poll_time AS poll_time FROM `mac_accounting` as A, `ports` AS I where A.port_id = I.port_id AND I.device_id = ?', [$device['device_id']]);
|
||||
@@ -27,7 +28,7 @@ if ($device['os_group'] == 'cisco') {
|
||||
foreach ($cip_response->table(3) as $ifIndex => $port_data) {
|
||||
foreach ($port_data as $direction => $dir_data) {
|
||||
foreach ($dir_data as $mac => $mac_data) {
|
||||
$mac = \LibreNMS\Util\Rewrite::macToHex($mac);
|
||||
$mac = Mac::parse($mac)->hex();
|
||||
$cip_array[$ifIndex][$mac]['cipMacHCSwitchedBytes'][$direction] = $mac_data['CISCO-IP-STAT-MIB::cipMacHCSwitchedBytes'] ?? $mac_data['CISCO-IP-STAT-MIB::cipMacSwitchedBytes'] ?? null;
|
||||
$cip_array[$ifIndex][$mac]['cipMacHCSwitchedPkts'][$direction] = $mac_data['CISCO-IP-STAT-MIB::cipMacHCSwitchedPkts'] ?? $mac_data['CISCO-IP-STAT-MIB::cipMacSwitchedPkts'] ?? null;
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
<tr>
|
||||
<td>{{ trans('stp.bridge_address') }}</td>
|
||||
<td>
|
||||
{{ \LibreNMS\Util\Rewrite::readableMac($instance['bridgeAddress']) }}
|
||||
{{ \LibreNMS\Util\Mac::parse($instance['bridgeAddress'])->readable() }}
|
||||
@if($url = \LibreNMS\Util\Url::deviceLink(\App\Facades\DeviceCache::get(\App\Models\Stp::where('bridgeAddress', $instance['bridgeAddress'])->value('device_id'))))
|
||||
({!! $url !!})
|
||||
@elseif($brVendor = \LibreNMS\Util\Rewrite::readableOUI($instance['bridgeAddress']))
|
||||
({!! $url !!})
|
||||
@elseif($brVendor = \LibreNMS\Util\Mac::parse($instance['bridgeAddress'])->vendor())
|
||||
({{ $brVendor }})
|
||||
@endif
|
||||
</td>
|
||||
@@ -41,10 +41,10 @@
|
||||
<tr>
|
||||
<td>{{ trans('stp.designated_root') }}</td>
|
||||
<td>
|
||||
{{ \LibreNMS\Util\Rewrite::readableMac($instance['designatedRoot']) }}
|
||||
{{ Mac::parse($instance['designatedRoot'])->readable() }}
|
||||
@if($url = \LibreNMS\Util\Url::deviceLink(\App\Facades\DeviceCache::get(\App\Models\Stp::where('bridgeAddress', $instance['designatedRoot'])->value('device_id'))))
|
||||
({!! $url !!})
|
||||
@elseif($drVendor = \LibreNMS\Util\Rewrite::readableOUI($instance['designatedRoot']))
|
||||
({!! $url !!})
|
||||
@elseif($drVendor = \LibreNMS\Util\Mac::parse($instance['designatedRoot'])->vendor())
|
||||
({{ $drVendor }})
|
||||
@endif
|
||||
</td>
|
||||
@@ -117,7 +117,7 @@
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
var grid = $("#stp-ports").bootgrid( {
|
||||
var grid = $("#stp-ports").bootgrid({
|
||||
ajax: true,
|
||||
templates: {search: ""},
|
||||
formatters: {
|
||||
@@ -130,8 +130,7 @@
|
||||
return html;
|
||||
}
|
||||
},
|
||||
post: function ()
|
||||
{
|
||||
post: function () {
|
||||
return {
|
||||
device_id: '{{ $data['device_id'] }}',
|
||||
vlan: '{{ $data['vlan'] }}',
|
||||
|
||||
@@ -27,16 +27,10 @@ namespace LibreNMS\Tests;
|
||||
|
||||
use LibreNMS\Device\YamlDiscovery;
|
||||
use LibreNMS\Util\Number;
|
||||
use LibreNMS\Util\Rewrite;
|
||||
use LibreNMS\Util\Time;
|
||||
|
||||
class FunctionsTest extends TestCase
|
||||
{
|
||||
public function testMacCleanToReadable(): void
|
||||
{
|
||||
$this->assertEquals('de:ad:be:ef:a0:c3', Rewrite::readableMac('deadbeefa0c3'));
|
||||
}
|
||||
|
||||
public function testHex2Str(): void
|
||||
{
|
||||
$this->assertEquals('Big 10 UP', hex2str('426967203130205550'));
|
||||
|
||||
@@ -33,6 +33,7 @@ use Illuminate\Support\Str;
|
||||
use LibreNMS\Data\Source\NetSnmpQuery;
|
||||
use LibreNMS\Data\Source\SnmpQueryInterface;
|
||||
use LibreNMS\Data\Source\SnmpResponse;
|
||||
use LibreNMS\Util\Mac;
|
||||
use LibreNMS\Util\Oid;
|
||||
use Log;
|
||||
|
||||
@@ -243,7 +244,7 @@ class SnmpQueryMock implements SnmpQueryInterface
|
||||
'1.3.6.1.2.1.17.1.1.0', // BRIDGE-MIB::dot1dBaseBridgeAddress.0
|
||||
'1.3.6.1.4.1.890.1.5.13.13.8.1.1.20', // IES5206-MIB::slotModuleMacAddress
|
||||
])) {
|
||||
$data = \LibreNMS\Util\Rewrite::readableMac($data);
|
||||
$data = Mac::parse($data)->readable();
|
||||
} else {
|
||||
$data = hex2str($data);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace LibreNMS\Tests\Unit\Util;
|
||||
|
||||
use LibreNMS\Tests\TestCase;
|
||||
use LibreNMS\Util\Mac;
|
||||
|
||||
class MacUtilTest extends TestCase
|
||||
{
|
||||
public function testMacOutput(): void
|
||||
{
|
||||
$mac = Mac::parse('DeadBeefa0c3');
|
||||
$this->assertTrue($mac->isValid());
|
||||
$this->assertEquals('de:ad:be:ef:a0:c3', $mac->readable());
|
||||
$this->assertEquals('deadbeefa0c3', $mac->hex());
|
||||
$this->assertEquals('222.173.190.239.160.195', $mac->oid());
|
||||
$this->assertEquals(['de', 'ad', 'be', 'ef', 'a0', 'c3'], $mac->array());
|
||||
}
|
||||
|
||||
public function testBridgeParsing(): void
|
||||
{
|
||||
$this->assertEquals('0c85255ce500', Mac::parseBridge('80 62 0c 85 25 5c e5 00')->hex());
|
||||
$this->assertEquals('000000000001', Mac::parseBridge('00 00 00 00 00 00 00 01 ')->hex());
|
||||
$this->assertEquals('000000000002', Mac::parseBridge('0-00.00.00.00.00.02')->hex());
|
||||
$this->assertEquals('00186e6449a0', Mac::parseBridge('0:18:6e:64:49:a0')->hex());
|
||||
$this->assertEquals('0c85255ce500', Mac::parseBridge('80620c85255ce500')->hex());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @dataProvider validMacProvider
|
||||
*/
|
||||
public function testMacToHex(string $from, string $to): void
|
||||
{
|
||||
$this->assertEquals($to, Mac::parse($from)->hex());
|
||||
}
|
||||
|
||||
public function validMacProvider(): array
|
||||
{
|
||||
return [
|
||||
['00:00:00:00:00:01', '000000000001'],
|
||||
['00-00-00-00-00-01', '000000000001'],
|
||||
['000000.000001', '000000000001'],
|
||||
['000000000001', '000000000001'],
|
||||
['00:12:34:ab:cd:ef', '001234abcdef'],
|
||||
['00:12:34:AB:CD:EF', '001234abcdef'],
|
||||
['0:12:34:AB:CD:EF', '001234abcdef'],
|
||||
['00-12-34-AB-CD-EF', '001234abcdef'],
|
||||
['001234-ABCDEF', '001234abcdef'],
|
||||
['0012.34AB.CDEF', '001234abcdef'],
|
||||
['00:02:04:0B:0D:0F', '0002040b0d0f'],
|
||||
['0:2:4:B:D:F', '0002040b0d0f'],
|
||||
['0:2:4:B:D:F', '0002040b0d0f'],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace LibreNMS\Tests\Unit\Util;
|
||||
|
||||
use LibreNMS\Tests\TestCase;
|
||||
use LibreNMS\Util\Rewrite;
|
||||
|
||||
class RewriteTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @dataProvider validMacProvider
|
||||
*/
|
||||
public function testMacToHex(string $from, string $to): void
|
||||
{
|
||||
$this->assertEquals($to, Rewrite::macToHex($from));
|
||||
}
|
||||
|
||||
public function validMacProvider(): array
|
||||
{
|
||||
return [
|
||||
['00:00:00:00:00:01', '000000000001'],
|
||||
['00-00-00-00-00-01', '000000000001'],
|
||||
['000000.000001', '000000000001'],
|
||||
['000000000001', '000000000001'],
|
||||
['00:12:34:ab:cd:ef', '001234abcdef'],
|
||||
['00:12:34:AB:CD:EF', '001234abcdef'],
|
||||
['0:12:34:AB:CD:EF', '001234abcdef'],
|
||||
['00-12-34-AB-CD-EF', '001234abcdef'],
|
||||
['001234-ABCDEF', '001234abcdef'],
|
||||
['0012.34AB.CDEF', '001234abcdef'],
|
||||
['00:02:04:0B:0D:0F', '0002040b0d0f'],
|
||||
['0:2:4:B:D:F', '0002040b0d0f'],
|
||||
['0:2:4:B:D:F', '0002040b0d0f'],
|
||||
['80 62 0c 85 25 5c e5 00', '0c85255ce500'], // BridgeId format
|
||||
['80620c85255ce500', '0c85255ce500'],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -4855,8 +4855,8 @@
|
||||
"stp": [
|
||||
{
|
||||
"vlan": null,
|
||||
"rootBridge": 1,
|
||||
"bridgeAddress": "000000000000",
|
||||
"rootBridge": 0,
|
||||
"bridgeAddress": "",
|
||||
"protocolSpecification": "ieee8021d",
|
||||
"priority": 0,
|
||||
"timeSinceTopologyChange": "0",
|
||||
|
||||
@@ -19945,8 +19945,8 @@
|
||||
"stp": [
|
||||
{
|
||||
"vlan": null,
|
||||
"rootBridge": 1,
|
||||
"bridgeAddress": "000000000000",
|
||||
"rootBridge": 0,
|
||||
"bridgeAddress": "",
|
||||
"protocolSpecification": "ieee8021d",
|
||||
"priority": 32768,
|
||||
"timeSinceTopologyChange": "0",
|
||||
|
||||
@@ -20045,8 +20045,8 @@
|
||||
"stp": [
|
||||
{
|
||||
"vlan": null,
|
||||
"rootBridge": 1,
|
||||
"bridgeAddress": "000000000000",
|
||||
"rootBridge": 0,
|
||||
"bridgeAddress": "",
|
||||
"protocolSpecification": "ieee8021d",
|
||||
"priority": 32768,
|
||||
"timeSinceTopologyChange": "0",
|
||||
|
||||
@@ -3746,7 +3746,7 @@
|
||||
"priority": 0,
|
||||
"timeSinceTopologyChange": "21474836",
|
||||
"topChanges": 0,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedRoot": "",
|
||||
"rootCost": 0,
|
||||
"rootPort": 0,
|
||||
"maxAge": 0,
|
||||
|
||||
@@ -6412,7 +6412,7 @@
|
||||
"priority": 65535,
|
||||
"timeSinceTopologyChange": "0",
|
||||
"topChanges": 0,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedRoot": "",
|
||||
"rootCost": 0,
|
||||
"rootPort": 0,
|
||||
"maxAge": 0,
|
||||
|
||||
@@ -3597,13 +3597,13 @@
|
||||
"stp": [
|
||||
{
|
||||
"vlan": null,
|
||||
"rootBridge": 1,
|
||||
"rootBridge": 0,
|
||||
"bridgeAddress": "000000000000",
|
||||
"protocolSpecification": "ieee8021d",
|
||||
"priority": 32768,
|
||||
"timeSinceTopologyChange": "0",
|
||||
"topChanges": 0,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedRoot": "",
|
||||
"rootCost": 0,
|
||||
"rootPort": 0,
|
||||
"maxAge": 0,
|
||||
|
||||
@@ -5773,7 +5773,7 @@
|
||||
"priority": 28672,
|
||||
"timeSinceTopologyChange": "0",
|
||||
"topChanges": 0,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedRoot": "",
|
||||
"rootCost": 0,
|
||||
"rootPort": 0,
|
||||
"maxAge": 0,
|
||||
|
||||
@@ -1355,7 +1355,7 @@
|
||||
"priority": 32768,
|
||||
"timeSinceTopologyChange": "0",
|
||||
"topChanges": 0,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedRoot": "",
|
||||
"rootCost": 0,
|
||||
"rootPort": 0,
|
||||
"maxAge": 0,
|
||||
@@ -1377,7 +1377,7 @@
|
||||
"pathCost": 10,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedCost": 0,
|
||||
"designatedBridge": "000000000000",
|
||||
"designatedBridge": "",
|
||||
"designatedPort": 0,
|
||||
"forwardTransitions": 0,
|
||||
"ifIndex": 1
|
||||
@@ -1391,7 +1391,7 @@
|
||||
"pathCost": 10,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedCost": 0,
|
||||
"designatedBridge": "000000000000",
|
||||
"designatedBridge": "",
|
||||
"designatedPort": 0,
|
||||
"forwardTransitions": 0,
|
||||
"ifIndex": 2
|
||||
@@ -1405,7 +1405,7 @@
|
||||
"pathCost": 10,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedCost": 0,
|
||||
"designatedBridge": "000000000000",
|
||||
"designatedBridge": "",
|
||||
"designatedPort": 0,
|
||||
"forwardTransitions": 0,
|
||||
"ifIndex": 3
|
||||
@@ -1419,7 +1419,7 @@
|
||||
"pathCost": 10,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedCost": 0,
|
||||
"designatedBridge": "000000000000",
|
||||
"designatedBridge": "",
|
||||
"designatedPort": 0,
|
||||
"forwardTransitions": 0,
|
||||
"ifIndex": 4
|
||||
@@ -1433,7 +1433,7 @@
|
||||
"pathCost": 10,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedCost": 0,
|
||||
"designatedBridge": "000000000000",
|
||||
"designatedBridge": "",
|
||||
"designatedPort": 0,
|
||||
"forwardTransitions": 0,
|
||||
"ifIndex": 5
|
||||
|
||||
@@ -2761,7 +2761,7 @@
|
||||
"priority": 32768,
|
||||
"timeSinceTopologyChange": "0",
|
||||
"topChanges": 0,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedRoot": "",
|
||||
"rootCost": 0,
|
||||
"rootPort": 0,
|
||||
"maxAge": 0,
|
||||
@@ -2783,7 +2783,7 @@
|
||||
"pathCost": 10,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedCost": 0,
|
||||
"designatedBridge": "000000000000",
|
||||
"designatedBridge": "",
|
||||
"designatedPort": 0,
|
||||
"forwardTransitions": 0,
|
||||
"ifIndex": 1
|
||||
@@ -2797,7 +2797,7 @@
|
||||
"pathCost": 10,
|
||||
"designatedRoot": "c006c3a13f46",
|
||||
"designatedCost": 20000,
|
||||
"designatedBridge": "000000000000",
|
||||
"designatedBridge": "",
|
||||
"designatedPort": 9,
|
||||
"forwardTransitions": 0,
|
||||
"ifIndex": 6
|
||||
@@ -2811,7 +2811,7 @@
|
||||
"pathCost": 10,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedCost": 0,
|
||||
"designatedBridge": "000000000000",
|
||||
"designatedBridge": "",
|
||||
"designatedPort": 0,
|
||||
"forwardTransitions": 0,
|
||||
"ifIndex": 5
|
||||
@@ -2825,7 +2825,7 @@
|
||||
"pathCost": 10,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedCost": 0,
|
||||
"designatedBridge": "000000000000",
|
||||
"designatedBridge": "",
|
||||
"designatedPort": 0,
|
||||
"forwardTransitions": 0,
|
||||
"ifIndex": 4
|
||||
|
||||
@@ -659,12 +659,12 @@
|
||||
{
|
||||
"vlan": null,
|
||||
"rootBridge": 1,
|
||||
"bridgeAddress": "000000000000",
|
||||
"bridgeAddress": "",
|
||||
"protocolSpecification": "ieee8021d",
|
||||
"priority": 0,
|
||||
"timeSinceTopologyChange": "0",
|
||||
"topChanges": 0,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedRoot": "",
|
||||
"rootCost": 0,
|
||||
"rootPort": 0,
|
||||
"maxAge": 0,
|
||||
|
||||
@@ -1056,7 +1056,7 @@
|
||||
"priority": 32768,
|
||||
"timeSinceTopologyChange": "0",
|
||||
"topChanges": 0,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedRoot": "",
|
||||
"rootCost": 0,
|
||||
"rootPort": 0,
|
||||
"maxAge": 0,
|
||||
@@ -1078,7 +1078,7 @@
|
||||
"pathCost": 10,
|
||||
"designatedRoot": "788a20fa53cb",
|
||||
"designatedCost": 0,
|
||||
"designatedBridge": "000000000000",
|
||||
"designatedBridge": "",
|
||||
"designatedPort": 10,
|
||||
"forwardTransitions": 0,
|
||||
"ifIndex": 2
|
||||
@@ -1092,7 +1092,7 @@
|
||||
"pathCost": 10,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedCost": 0,
|
||||
"designatedBridge": "000000000000",
|
||||
"designatedBridge": "",
|
||||
"designatedPort": 0,
|
||||
"forwardTransitions": 0,
|
||||
"ifIndex": 4
|
||||
|
||||
+1
-1
@@ -11967,7 +11967,7 @@
|
||||
"priority": 65535,
|
||||
"timeSinceTopologyChange": "0",
|
||||
"topChanges": 0,
|
||||
"designatedRoot": "000000000000",
|
||||
"designatedRoot": "",
|
||||
"rootCost": 0,
|
||||
"rootPort": 0,
|
||||
"maxAge": 0,
|
||||
|
||||
@@ -2733,7 +2733,7 @@
|
||||
{
|
||||
"vlan": null,
|
||||
"rootBridge": 0,
|
||||
"bridgeAddress": "000000000000",
|
||||
"bridgeAddress": "",
|
||||
"protocolSpecification": "ieee8021d",
|
||||
"priority": 24576,
|
||||
"timeSinceTopologyChange": "0",
|
||||
|
||||
@@ -51667,8 +51667,8 @@
|
||||
"stp": [
|
||||
{
|
||||
"vlan": null,
|
||||
"rootBridge": 1,
|
||||
"bridgeAddress": "000000000000",
|
||||
"rootBridge": 0,
|
||||
"bridgeAddress": "",
|
||||
"protocolSpecification": "ieee8021d",
|
||||
"priority": 32768,
|
||||
"timeSinceTopologyChange": "0",
|
||||
|
||||
Reference in New Issue
Block a user