343 lines
9.3 KiB
Perl
343 lines
9.3 KiB
Perl
# SNMP::Info::AMAP
|
|
#
|
|
# Copyright (c) 2013 Eric Miller
|
|
# 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::AMAP;
|
|
|
|
use strict;
|
|
use warnings;
|
|
use Exporter;
|
|
use SNMP::Info;
|
|
|
|
@SNMP::Info::AMAP::ISA = qw/SNMP::Info Exporter/;
|
|
@SNMP::Info::AMAP::EXPORT_OK = qw//;
|
|
|
|
our ($VERSION, %FUNCS, %GLOBALS, %MIBS, %MUNGE);
|
|
|
|
$VERSION = '3.79';
|
|
|
|
%MIBS = (
|
|
'ALCATEL-IND1-INTERSWITCH-PROTOCOL-MIB' => 'aipAMAPRemDeviceType',
|
|
);
|
|
|
|
%GLOBALS = (
|
|
|
|
);
|
|
|
|
%FUNCS = (
|
|
# ALCATEL-IND1-INTERSWITCH-PROTOCOL-MIB::aipAMAPRemHostname
|
|
'amap_rem_sysname' => 'aipAMAPRemHostname',
|
|
);
|
|
|
|
%MUNGE = ( 'amap_rem_sysname' => \&SNMP::Info::munge_null, );
|
|
|
|
sub hasAMAP {
|
|
my $amap = shift;
|
|
|
|
my $amap_ip = $amap->aipAMAPIpAddr() || {};
|
|
|
|
return 1 if ( scalar( keys %$amap_ip ) );
|
|
|
|
return;
|
|
}
|
|
|
|
# Break up the aipAMAPhostsTable INDEX into MAC and IP address.
|
|
sub _hosts_table_index {
|
|
my $idx = shift;
|
|
my @oids = split( /\./, $idx );
|
|
my $mac = join( '.', splice( @oids, 0, 6 ) );
|
|
|
|
return ( $mac, join( '.', @oids ) );
|
|
}
|
|
|
|
# Break up the aipAMAPportConnectionTable INDEX and return MAC
|
|
sub _conn_table_mac {
|
|
my $idx = shift;
|
|
my @oids = split( /\./, $idx );
|
|
my $local_idx = shift @oids;
|
|
my $mac = join( '.', splice( @oids, 0, 6 ) );
|
|
|
|
return ($mac);
|
|
}
|
|
|
|
# Since we need to get IP Addresses from the aipAMAPhostsTable which has
|
|
# a different index (MAC, IP) than the aipAMAPportConnectionTable which holds
|
|
# the remote device details we create a combined index and skip any
|
|
# IPs which have an address of 0.0.0.0. Would like to include only one
|
|
# address since they should all originate from the same device, but we don't
|
|
# know if they would all be reachable from the network management application.
|
|
#
|
|
# We don't implement partials since this is private index function
|
|
sub _amap_index {
|
|
my $amap = shift;
|
|
|
|
my $amap_ip = $amap->aipAMAPIpAddr() || {};
|
|
my $amap_rport = $amap->aipAMAPLocalPort() || {};
|
|
|
|
my %amap_index;
|
|
foreach my $key ( keys %$amap_ip ) {
|
|
my ( $mac, $ip ) = _hosts_table_index($key);
|
|
|
|
next if ( $ip eq '0.0.0.0' );
|
|
next unless $ip;
|
|
|
|
foreach my $idx ( keys %$amap_rport ) {
|
|
my $c_mac = _conn_table_mac($idx);
|
|
|
|
if ( $mac eq $c_mac ) {
|
|
my $index = "$idx.$ip";
|
|
$amap_index{$index} = $index;
|
|
}
|
|
}
|
|
}
|
|
return \%amap_index;
|
|
}
|
|
|
|
# Break up _amap_index INDEX into local index, MAC, remote index, and
|
|
# IP address
|
|
sub _amap_index_parts {
|
|
my $idx = shift;
|
|
my @oids = split( /\./, $idx );
|
|
my $local_idx = shift @oids;
|
|
my $mac = join( '.', splice( @oids, 0, 6 ) );
|
|
my $rem_idx = shift @oids;
|
|
|
|
return ( $local_idx, $mac, $rem_idx, join( '.', @oids ) );
|
|
}
|
|
|
|
sub amap_if {
|
|
my $amap = shift;
|
|
|
|
my $index = $amap->_amap_index() || {};
|
|
my $if_idx = $amap->aipAMAPLocalIfindex() || {};
|
|
|
|
my %amap_if;
|
|
foreach my $key ( keys %$index ) {
|
|
my ( $local_idx, $mac, $rem_idx, $ip ) = _amap_index_parts($key);
|
|
my $if_key = "$local_idx.$mac.$rem_idx";
|
|
|
|
if ( $key =~ /^$if_key/ ) {
|
|
my $if = $if_idx->{$if_key};
|
|
$amap_if{$key} = $if;
|
|
}
|
|
}
|
|
|
|
return \%amap_if;
|
|
}
|
|
|
|
sub amap_ip {
|
|
my $amap = shift;
|
|
|
|
my $index = $amap->_amap_index() || {};
|
|
|
|
my %amap_ip;
|
|
foreach my $key ( keys %$index ) {
|
|
my ( $local_idx, $mac, $rem_idx, $ip ) = _amap_index_parts($key);
|
|
|
|
# MIB says should only be IPv4
|
|
next unless ( $ip =~ /\d+(\.\d+){3}/ );
|
|
$amap_ip{$key} = $ip;
|
|
}
|
|
return \%amap_ip;
|
|
}
|
|
|
|
sub amap_port {
|
|
my $amap = shift;
|
|
|
|
my $index = $amap->_amap_index() || {};
|
|
my $amap_rport = $amap->aipAMAPLocalPort() || {};
|
|
my $amap_rslot = $amap->aipAMAPLocalSlot() || {};
|
|
|
|
my %amap_port;
|
|
foreach my $key ( sort keys %$index ) {
|
|
my ( $local_idx, $mac, $rem_idx, $ip ) = _amap_index_parts($key);
|
|
my $p_key = "$local_idx.$mac.$rem_idx";
|
|
|
|
if ( $key =~ /^$p_key/ ) {
|
|
my $port = $amap_rport->{$p_key};
|
|
my $slot = $amap_rslot->{$p_key} || 0;
|
|
next unless $port;
|
|
$amap_port{$key} = defined $slot ? "$slot\/$port" : $port;
|
|
}
|
|
}
|
|
return \%amap_port;
|
|
}
|
|
|
|
sub amap_id {
|
|
my $amap = shift;
|
|
|
|
my $index = $amap->_amap_index() || {};
|
|
my $amap_name = $amap->amap_rem_sysname() || {};
|
|
|
|
my %amap_name;
|
|
foreach my $key ( sort keys %$index ) {
|
|
my ( $local_idx, $mac, $rem_idx, $ip ) = _amap_index_parts($key);
|
|
my $id_key = "$local_idx.$mac.$rem_idx";
|
|
|
|
if ( $key =~ /^$id_key/ ) {
|
|
my $name = $amap_name->{$id_key} || 0;
|
|
next unless $name;
|
|
$amap_name{$key} = $name;
|
|
}
|
|
}
|
|
return \%amap_name;
|
|
}
|
|
|
|
sub amap_platform {
|
|
my $amap = shift;
|
|
|
|
my $index = $amap->_amap_index() || {};
|
|
my $amap_topo_platform = $amap->aipAMAPRemDeviceType() || {};
|
|
|
|
my %amap_platform;
|
|
foreach my $key ( keys %$index ) {
|
|
my ( $local_idx, $mac, $rem_idx, $ip ) = _amap_index_parts($key);
|
|
my $pf_key = "$local_idx.$mac.$rem_idx";
|
|
|
|
if ( $key =~ /^$pf_key/ ) {
|
|
my $platform = $amap_topo_platform->{$pf_key};
|
|
next unless $platform;
|
|
$amap_platform{$key} = $platform;
|
|
}
|
|
}
|
|
return \%amap_platform;
|
|
}
|
|
|
|
1;
|
|
__END__
|
|
|
|
=head1 NAME
|
|
|
|
SNMP::Info::AMAP - SNMP Interface to Alcatel Mapping Adjacency Protocol (AMAP)
|
|
|
|
=head1 AUTHOR
|
|
|
|
Eric Miller
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
my $amap = new SNMP::Info (
|
|
AutoSpecify => 1,
|
|
Debug => 1,
|
|
DestHost => 'router',
|
|
Community => 'public',
|
|
Version => 2
|
|
);
|
|
|
|
my $class = $amap->class();
|
|
print " Using device sub class : $class\n";
|
|
|
|
$hasamap = $amap->hasAMAP() ? 'yes' : 'no';
|
|
|
|
# Print out a map of device ports with AMAP neighbors:
|
|
my $interfaces = $amap->interfaces();
|
|
my $amap_if = $amap->amap_if();
|
|
my $amap_ip = $amap->amap_ip();
|
|
my $amap_port = $amap->amap_port();
|
|
|
|
foreach my $amap_key (keys %$amap_ip){
|
|
my $iid = $amap_if->{$amap_key};
|
|
my $port = $interfaces->{$iid};
|
|
my $neighbor = $amap_ip->{$amap_key};
|
|
my $neighbor_port = $amap_port->{$amap_key};
|
|
print "Port : $port connected to $neighbor / $neighbor_port\n";
|
|
}
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
SNMP::Info::AMAP is a subclass of SNMP::Info that provides an object oriented
|
|
interface to Alcatel Mapping Adjacency Protocol (AMAP) information through
|
|
SNMP.
|
|
|
|
AMAP is a Layer 2 protocol that allows a network device to advertise its
|
|
identity and capabilities on the local network providing topology information.
|
|
|
|
Create or use a device subclass that inherits this class. Do not use
|
|
directly.
|
|
|
|
=head2 Inherited Classes
|
|
|
|
None.
|
|
|
|
=head2 Required MIBs
|
|
|
|
=over
|
|
|
|
=item F<ALCATEL-IND1-INTERSWITCH-PROTOCOL-MIB>
|
|
|
|
=back
|
|
|
|
=head1 GLOBALS
|
|
|
|
These are methods that return scalar values from SNMP
|
|
|
|
=over
|
|
|
|
=item $amap->hasAMAP()
|
|
|
|
Is AMAP is active in this device?
|
|
|
|
=back
|
|
|
|
=head1 TABLE METHODS
|
|
|
|
These are methods that return tables of information in the form of a reference
|
|
to a hash.
|
|
|
|
=over
|
|
|
|
=item $amap->amap_id()
|
|
|
|
Returns the string value used to identify the remote system.
|
|
|
|
=item $amap->amap_if()
|
|
|
|
Returns the mapping to the SNMP Interface Table.
|
|
|
|
=item $amap->amap_ip()
|
|
|
|
Returns remote IPv4 addresses. Note: AMAP returns all IP addresses associated
|
|
with the remote device. It would be preferable to include only one address
|
|
since they should all originate from the same device, but amap_ip() can not
|
|
determine if all addresses are reachable from the network management
|
|
application therefore all addresses are returned and the calling application
|
|
must determine which address to use and if they are in fact from the same
|
|
device.
|
|
|
|
=item $amap->amap_port()
|
|
|
|
Returns remote port ID
|
|
|
|
=item $amap->amap_platform()
|
|
|
|
Returns remote platform ID
|
|
|
|
=back
|
|
|
|
=cut
|