From efb32ac10d124164a29b6fdc6a92f9b7857d707f Mon Sep 17 00:00:00 2001 From: Alexander Hartmaier Date: Mon, 14 Mar 2022 22:37:27 +0100 Subject: [PATCH] add Cisco BGP MIB support to all Cisco Layer 3 devices (#451) This also adds a munge_inetaddress function which can be used to parse a binary IP address as defined by the SNMP InetAddress type. --- Changes | 4 + lib/SNMP/Info.pm | 28 ++++ lib/SNMP/Info/CiscoBGP.pm | 267 ++++++++++++++++++++++++++++++++++ lib/SNMP/Info/Layer3/Cisco.pm | 21 ++- 4 files changed, 315 insertions(+), 5 deletions(-) create mode 100644 lib/SNMP/Info/CiscoBGP.pm diff --git a/Changes b/Changes index 8ee6e559..82571ac3 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,7 @@ + [NEW FEATURES] + + * add Cisco BGP MIB support to all Cisco Layer 3 devices + Version 3.81 (2021-10-07) [ENHANCEMENTS] diff --git a/lib/SNMP/Info.pm b/lib/SNMP/Info.pm index ab9e1c22..3a8c8d76 100644 --- a/lib/SNMP/Info.pm +++ b/lib/SNMP/Info.pm @@ -278,6 +278,13 @@ SNMP Interface to Cisco Aggregated Links See documentation in L for details. +=item SNMP::Info::CiscoBGP + +F. Cisco BGPv4 support. Inherited by Cisco devices with +Layer3 support. + +See documentation in L for details. + =item SNMP::Info::CiscoConfig F, F, and F. @@ -3822,6 +3829,27 @@ sub munge_ip { return join( '.', unpack( 'C4', $ip ) ); } +=item munge_inetaddress + +Takes a binary IP address as defined by the SNMP InetAddress type and returns +it as human readable string; + +=cut + +sub munge_inetaddress { + my $ip = shift; + # 4 bytes = IPv4 + if (length($ip) == 4) { + return SNMP::Info::munge_ip($ip); + } + # 16 bytes = IPv6 + elsif (length($ip) == 16) { + return sprintf( "%x:%x:%x:%x:%x:%x:%x:%x", + unpack( 'n8', $ip )); + } + return ''; +} + =item munge_mac() Takes an octet stream (HEX-STRING) and returns a colon separated ASCII hex diff --git a/lib/SNMP/Info/CiscoBGP.pm b/lib/SNMP/Info/CiscoBGP.pm new file mode 100644 index 00000000..20e8ac28 --- /dev/null +++ b/lib/SNMP/Info/CiscoBGP.pm @@ -0,0 +1,267 @@ +# SNMP::Info::CiscoBGP +# +# Copyright (c) 2022 Alexander Hartmaier +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Santa Cruz nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +package SNMP::Info::CiscoBGP; + +use strict; +use warnings; +use Exporter; +use SNMP::Info; + +@SNMP::Info::CiscoBGP::ISA = qw( SNMP::Info Exporter ); +@SNMP::Info::CiscoBGP::EXPORT_OK = qw( + parse_cisco_bgp_peer2_peer2entry_index +); + +our ($VERSION, %MIBS, %FUNCS, %GLOBALS, %MUNGE); + +$VERSION = '3.81'; + +%MIBS = ( 'CISCO-BGP4-MIB' => 'cbgpPeer2State', ); + +%GLOBALS = (); + +%FUNCS = ( + # cbgpPeer2Table + 'cisco_bgp_peer2_state' => 'cbgpPeer2State', + 'cisco_bgp_peer2_adminstatus' => 'cbgpPeer2AdminStatus', + 'cisco_bgp_peer2_localaddr' => 'cbgpPeer2LocalAddr', + 'cisco_bgp_peer2_localport' => 'cbgpPeer2LocalPort', + 'cisco_bgp_peer2_localas' => 'cbgpPeer2LocalAs', + 'cisco_bgp_peer2_localidentifier' => 'cbgpPeer2LocalIdentifier', + 'cisco_bgp_peer2_remoteport' => 'cbgpPeer2RemotePort', + 'cisco_bgp_peer2_remoteas' => 'cbgpPeer2RemoteAs', + 'cisco_bgp_peer2_remoteidentifier' => 'cbgpPeer2RemoteIdentifier', + 'cisco_bgp_peer2_inupdates' => 'cbgpPeer2InUpdates', + 'cisco_bgp_peer2_outupdates' => 'cbgpPeer2OutUpdates', + 'cisco_bgp_peer2_intotalmessages' => 'cbgpPeer2InTotalMessages', + 'cisco_bgp_peer2_outtotalmessages' => 'cbgpPeer2OutTotalMessages', + 'cisco_bgp_peer2_lasterror' => 'cbgpPeer2LastError', + 'cisco_bgp_peer2_fsmestablishedtransitions' + => 'cbgpPeer2FsmEstablishedTransitions', + 'cisco_bgp_peer2_fsmestablishedtime' => 'cbgpPeer2FsmEstablishedTime', + 'cisco_bgp_peer2_connectretryinterval'=> 'cbgpPeer2ConnectRetryInterval', + 'cisco_bgp_peer2_holdtime' => 'cbgpPeer2HoldTime', + 'cisco_bgp_peer2_keepalive' => 'cbgpPeer2KeepAlive', + 'cisco_bgp_peer2_holdtimeconfigured' => 'cbgpPeer2HoldTimeConfigured', + 'cisco_bgp_peer2_keepaliveconfigured' => 'cbgpPeer2KeepAliveConfigured', + 'cisco_bgp_peer2_minasoriginationinterval' + => 'cbgpPeer2MinASOriginationInterval', + 'cisco_bgp_peer2_inupdatelapsedtime' => 'cbgpPeer2InUpdateElapsedTime', + 'cisco_bgp_peer2_lasterrortxt' => 'cbgpPeer2LastErrorTxt', + 'cisco_bgp_peer2_prevstate' => 'cbgpPeer2PrevState', + + # cbgpPeer2AddrFamilyPrefixTable + 'cisco_bgp_peer2_acceptedprefixes' => 'cbgpPeer2AcceptedPrefixes', + 'cisco_bgp_peer2_deniedprefixes' => 'cbgpPeer2DeniedPrefixes', + 'cisco_bgp_peer2_prefixadminlimit' => 'cbgpPeer2PrefixAdminLimit', + 'cisco_bgp_peer2_prefixthreshold' => 'cbgpPeer2PrefixThreshold', + 'cisco_bgp_peer2_prefixclearthreshold'=> 'cbgpPeer2PrefixClearThreshold', + 'cisco_bgp_peer2_advertisedprefixes' => 'cbgpPeer2AdvertisedPrefixes', + 'cisco_bgp_peer2_suppressedprefixes' => 'cbgpPeer2SuppressedPrefixes', + 'cisco_bgp_peer2_withdrawnprefixes' => 'cbgpPeer2WithdrawnPrefixes', +); + +%MUNGE = ( + 'cisco_bgp_peer2_localaddr' => \&SNMP::Info::munge_inetaddress, + 'cisco_bgp_peer2_lasterror' => \&SNMP::Info::munge_octet2hex, +); + +sub parse_cisco_bgp_peer2_peer2entry_index { + my ($self, $index) = @_; + my ($type, $addrlength, $ip) = split(/\./, $index, 3); + # decode IPv6 remote address + if ($addrlength == 16) { + # copied from SNMP::Info::IPv6/ipv6_addr + my @parts = split(/\./, $ip); + $ip = sprintf("%x:%x:%x:%x:%x:%x:%x:%x", + unpack('n8', pack('C*', @parts))); + } + return $type, $addrlength, $ip; +} + +1; +__END__ + +=head1 NAME + +SNMP::Info::CiscoBGP - SNMP Interface to Cisco's BGP MIBs + +=head1 AUTHOR + +Alexander Hartmaier + +=head1 SYNOPSIS + +# Let SNMP::Info determine the correct subclass for you. +my $device = SNMP::Info->( + AutoSpecify => 1, + Debug => 1, + DestHost => 'myswitch', + Community => 'public', + Version => 2 +) or die "Can't connect to DestHost.\n"; + +my $remoteas_for_index = $device->cisco_bgp_peer2_remoteas; + +for my $index (keys $remoteas_for_index->%*) { + my ($type, $addrlength, $ip) = + $device->parse_cisco_bgp_peer2_peer2entry_index($index); + printf('remote: %-39s type: %-4s remote AS: %5d', + $ip, $type, $remoteas_for_index->{$index}); +} + +=head1 DESCRIPTION + +SNMP::Info::CiscoBGP is a subclass of SNMP::Info that provides +information about a cisco device's BGP configuration and state. + +Use or create in a subclass of SNMP::Info. Do not use directly. + +=head2 Inherited Classes + +none. + +=head2 Required MIBs + +=over + +=item F + +=back + +=head1 GLOBALS + +=over + +None + +=back + +=head1 TABLE METHODS + +=head2 Cisco BGP Peer 2 Table (cbgpPeer2Table) + +This table contains, one entry per BGP peer, information about the connections +with BGP peers. + +=over + +=item cisco_bgp_peer2_state (cbgpPeer2State) + +=item cisco_bgp_peer2_adminstatus (cbgpPeer2AdminStatus) + +=item cisco_bgp_peer2_localaddr (cbgpPeer2LocalAddr) + +=item cisco_bgp_peer2_localport (cbgpPeer2LocalPort) + +=item cisco_bgp_peer2_localas (cbgpPeer2LocalAs) + +=item cisco_bgp_peer2_localidentifier (cbgpPeer2LocalIdentifier) + +=item cisco_bgp_peer2_remoteport (cbgpPeer2RemotePort) + +=item cisco_bgp_peer2_remoteas (cbgpPeer2RemoteAs) + +=item cisco_bgp_peer2_remoteidentifier (cbgpPeer2RemoteIdentifier) + +=item cisco_bgp_peer2_inupdates (cbgpPeer2InUpdates) + +=item cisco_bgp_peer2_outupdates (cbgpPeer2OutUpdates) + +=item cisco_bgp_peer2_intotalmessages (cbgpPeer2InTotalMessages) + +=item cisco_bgp_peer2_outtotalmessages (cbgpPeer2OutTotalMessages) + +=item cisco_bgp_peer2_lasterror (cbgpPeer2LastError) + +=item cisco_bgp_peer2_fsmestablishedtransitions (cbgpPeer2FsmEstablishedTransitions) + +=item cisco_bgp_peer2_fsmestablishedtime (cbgpPeer2FsmEstablishedTime) + +=item cisco_bgp_peer2_connectretryinterval (cbgpPeer2ConnectRetryInterval) + +=item cisco_bgp_peer2_holdtime (cbgpPeer2HoldTime) + +=item cisco_bgp_peer2_keepalive (cbgpPeer2KeepAlive) + +=item cisco_bgp_peer2_holdtimeconfigured (cbgpPeer2HoldTimeConfigured) + +=item cisco_bgp_peer2_keepaliveconfigured (cbgpPeer2KeepAliveConfigured) + +=item cisco_bgp_peer2_minasoriginationinterval (cbgpPeer2MinASOriginationInterval) + +=item cisco_bgp_peer2_inupdatelapsedtime (cbgpPeer2InUpdateElapsedTime) + +=item cisco_bgp_peer2_lasterrortxt (cbgpPeer2LastErrorTxt) + +=item cisco_bgp_peer2_prevstate (cbgpPeer2PrevState) + +=back + +=head2 Cisco BGP Peer 2 Address Family Prefix Table (cbgpPeer2AddrFamilyPrefixTable) + +This table contains prefix related information related to address families +supported by a peer. + +=over + +=item cisco_bgp_peer2_acceptedprefixes (cbgpPeer2AcceptedPrefixes) + +=item cisco_bgp_peer2_deniedprefixes (cbgpPeer2DeniedPrefixes) + +=item cisco_bgp_peer2_prefixadminlimit (cbgpPeer2PrefixAdminLimit) + +=item cisco_bgp_peer2_prefixthreshold (cbgpPeer2PrefixThreshold) + +=item cisco_bgp_peer2_prefixclearthreshold (cbgpPeer2PrefixClearThreshold) + +=item cisco_bgp_peer2_advertisedprefixes (cbgpPeer2AdvertisedPrefixes) + +=item cisco_bgp_peer2_suppressedprefixes (cbgpPeer2SuppressedPrefixes) + +=item cisco_bgp_peer2_withdrawnprefixes (cbgpPeer2WithdrawnPrefixes) + +=back + +=head2 METHODS + +=over + +=item parse_cisco_bgp_peer2_peer2entry_index + +Takes a cbgpPeer2Entry index as returned by all methods of the Cisco BGP Peer +2 Table methods. + +Returns a list of type (numeric, cbgpPeer2Type), address length (in bytes: +4 for IPv4, 16 for IPv6) and the remote IP address as string. + +=back + +=cut diff --git a/lib/SNMP/Info/Layer3/Cisco.pm b/lib/SNMP/Info/Layer3/Cisco.pm index b9873b5d..e9b02d9b 100644 --- a/lib/SNMP/Info/Layer3/Cisco.pm +++ b/lib/SNMP/Info/Layer3/Cisco.pm @@ -32,6 +32,7 @@ package SNMP::Info::Layer3::Cisco; use strict; use warnings; use Exporter; +use SNMP::Info::CiscoBGP; use SNMP::Info::CiscoVTP; use SNMP::Info::CDP; use SNMP::Info::CiscoStats; @@ -42,7 +43,9 @@ use SNMP::Info::CiscoPower; use SNMP::Info::CiscoStpExtensions; use SNMP::Info::Layer3; -@SNMP::Info::Layer3::Cisco::ISA = qw/SNMP::Info::CiscoVTP +@SNMP::Info::Layer3::Cisco::ISA = qw/ + SNMP::Info::CiscoBGP + SNMP::Info::CiscoVTP SNMP::Info::CDP SNMP::Info::CiscoStats SNMP::Info::CiscoRTT SNMP::Info::CiscoQOS SNMP::Info::CiscoConfig @@ -57,6 +60,7 @@ $VERSION = '3.81'; %MIBS = ( %SNMP::Info::Layer3::MIBS, + %SNMP::Info::CiscoBGP::MIBS, %SNMP::Info::CiscoStpExtensions::MIBS, %SNMP::Info::CiscoPower::MIBS, %SNMP::Info::CiscoConfig::MIBS, @@ -70,6 +74,7 @@ $VERSION = '3.81'; %GLOBALS = ( %SNMP::Info::Layer3::GLOBALS, + %SNMP::Info::CiscoBGP::GLOBALS, %SNMP::Info::CiscoStpExtensions::GLOBALS, %SNMP::Info::CiscoPower::GLOBALS, %SNMP::Info::CiscoConfig::GLOBALS, @@ -83,6 +88,7 @@ $VERSION = '3.81'; %FUNCS = ( %SNMP::Info::Layer3::FUNCS, + %SNMP::Info::CiscoBGP::FUNCS, %SNMP::Info::CiscoStpExtensions::FUNCS, %SNMP::Info::CiscoPower::FUNCS, %SNMP::Info::CiscoConfig::FUNCS, @@ -98,10 +104,15 @@ $VERSION = '3.81'; ); %MUNGE = ( - %SNMP::Info::Layer3::MUNGE, %SNMP::Info::CiscoStpExtensions::MUNGE, - %SNMP::Info::CiscoPower::MUNGE, %SNMP::Info::CiscoConfig::MUNGE, - %SNMP::Info::CiscoQOS::MUNGE, %SNMP::Info::CiscoRTT::MUNGE, - %SNMP::Info::CiscoStats::MUNGE, %SNMP::Info::CDP::MUNGE, + %SNMP::Info::Layer3::MUNGE, + %SNMP::Info::CiscoBGP::MUNGE, + %SNMP::Info::CiscoStpExtensions::MUNGE, + %SNMP::Info::CiscoPower::MUNGE, + %SNMP::Info::CiscoConfig::MUNGE, + %SNMP::Info::CiscoQOS::MUNGE, + %SNMP::Info::CiscoRTT::MUNGE, + %SNMP::Info::CiscoStats::MUNGE, + %SNMP::Info::CDP::MUNGE, %SNMP::Info::CiscoVTP::MUNGE, );