4630 lines
		
	
	
		
			124 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			4630 lines
		
	
	
		
			124 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
# SNMP::Info
 | 
						|
#
 | 
						|
# Copyright (c) 2003-2012 Max Baker and SNMP::Info Developers
 | 
						|
# All rights reserved.
 | 
						|
#
 | 
						|
# Portions Copyright (c) 2002-2003, Regents of the University of California
 | 
						|
# All rights reserved.
 | 
						|
#
 | 
						|
# See COPYRIGHT at bottom
 | 
						|
 | 
						|
package SNMP::Info;
 | 
						|
 | 
						|
use warnings;
 | 
						|
use strict;
 | 
						|
use Exporter;
 | 
						|
use SNMP;
 | 
						|
use Carp;
 | 
						|
use Math::BigInt;
 | 
						|
 | 
						|
@SNMP::Info::ISA       = qw/Exporter/;
 | 
						|
@SNMP::Info::EXPORT_OK = qw//;
 | 
						|
 | 
						|
use vars
 | 
						|
    qw/$VERSION %FUNCS %GLOBALS %MIBS %MUNGE $AUTOLOAD $INIT $DEBUG %SPEED_MAP
 | 
						|
    $NOSUCH $BIGINT $REPEATERS/;
 | 
						|
 | 
						|
$VERSION = '3.14';
 | 
						|
 | 
						|
=head1 NAME
 | 
						|
 | 
						|
SNMP::Info - OO Interface to Network devices and MIBs through SNMP
 | 
						|
 | 
						|
=head1 VERSION
 | 
						|
 | 
						|
SNMP::Info - Version 3.14
 | 
						|
 | 
						|
=head1 AUTHOR
 | 
						|
 | 
						|
SNMP::Info is maintained by team of Open Source authors headed by Eric Miller,
 | 
						|
Bill Fenner, Max Baker, Jeroen van Ingen and Oliver Gorwits.
 | 
						|
 | 
						|
Please visit L<http://sourceforge.net/projects/snmp-info/> for most up-to-date
 | 
						|
list of developers.
 | 
						|
 | 
						|
SNMP::Info was originally created at UCSC for the Netdisco project L<http://netdisco.org>
 | 
						|
by Max Baker.
 | 
						|
 | 
						|
=head1 DEVICES SUPPORTED
 | 
						|
 | 
						|
See L<http://netdisco.org/doc/DeviceMatrix.html> or L<DeviceMatrix.txt> for more details.
 | 
						|
 | 
						|
=head1 SYNOPSIS
 | 
						|
 | 
						|
 use SNMP::Info;
 | 
						|
 | 
						|
 my $info = new SNMP::Info( 
 | 
						|
                            # Auto Discover more specific Device Class
 | 
						|
                            AutoSpecify => 1,
 | 
						|
                            Debug       => 1,
 | 
						|
                            # The rest is passed to SNMP::Session
 | 
						|
                            DestHost    => 'router',
 | 
						|
                            Community   => 'public',
 | 
						|
                            Version     => 2 
 | 
						|
                          ) or die "Can't connect to device.\n";
 | 
						|
 | 
						|
 my $err = $info->error();
 | 
						|
 die "SNMP Community or Version probably wrong connecting to device. $err\n" if defined $err;
 | 
						|
 | 
						|
 $name  = $info->name();
 | 
						|
 $class = $info->class();
 | 
						|
 print "SNMP::Info is using this device class : $class\n";
 | 
						|
 | 
						|
 # Find out the Duplex status for the ports
 | 
						|
 my $interfaces = $info->interfaces();
 | 
						|
 my $i_duplex   = $info->i_duplex();
 | 
						|
 | 
						|
 # Get CDP Neighbor info
 | 
						|
 my $c_if       = $info->c_if();
 | 
						|
 my $c_ip       = $info->c_ip();
 | 
						|
 my $c_port     = $info->c_port();
 | 
						|
 | 
						|
 # Print out data per port
 | 
						|
 foreach my $iid (keys %$interfaces){
 | 
						|
    my $duplex = $i_duplex->{$iid};
 | 
						|
    # Print out physical port name, not snmp iid
 | 
						|
    my $port  = $interfaces->{$iid};
 | 
						|
 | 
						|
    print "$port: ";
 | 
						|
    print "$duplex duplex" if defined $duplex;
 | 
						|
 | 
						|
    # The CDP Table has table entries different than the interface tables.
 | 
						|
    # So we use c_if to get the map from cdp table to interface table.
 | 
						|
 | 
						|
    my %c_map = reverse %$c_if; 
 | 
						|
    my $c_key = $c_map{$iid};
 | 
						|
    unless (defined $c_key) {
 | 
						|
         print "\n\n";
 | 
						|
         next;
 | 
						|
     }
 | 
						|
    my $neighbor_ip   = $c_ip->{$c_key};
 | 
						|
    my $neighbor_port = $c_port->{$c_key};
 | 
						|
 | 
						|
    print " connected to $neighbor_ip / $neighbor_port\n" if defined $neighbor_ip;
 | 
						|
    print "\n";
 | 
						|
 | 
						|
 }
 | 
						|
 | 
						|
=head1 SUPPORT
 | 
						|
 | 
						|
Please direct all support, help, and bug requests to the snmp-info-users
 | 
						|
Mailing List at L<http://lists.sourceforge.net/lists/listinfo/snmp-info-users>.
 | 
						|
 | 
						|
=head1 DESCRIPTION 
 | 
						|
 | 
						|
SNMP::Info gives an object oriented interface to information obtained through
 | 
						|
SNMP.
 | 
						|
 | 
						|
This module is geared towards network devices.  Subclasses exist for a number
 | 
						|
of network devices and common MIBs. 
 | 
						|
 | 
						|
The idea behind this module is to give a common interface to data from network
 | 
						|
devices, leaving the device-specific hacks behind the scenes in subclasses.
 | 
						|
 | 
						|
In the SYNOPSIS example we fetch the name of all the ports on the device and
 | 
						|
the duplex setting for that port with two methods -- interfaces() and
 | 
						|
i_duplex().
 | 
						|
 | 
						|
The information may be coming from any number of MIB files and is very vendor
 | 
						|
specific.  SNMP::Info provides you a common method for all supported devices.
 | 
						|
 | 
						|
Adding support for your own device is easy, and takes little SNMP knowledge.
 | 
						|
 | 
						|
The module is not limited to network devices. Any MIB or device can be given
 | 
						|
an objected oriented front-end by making a module that consists of a couple
 | 
						|
hashes.  See EXTENDING SNMP::INFO.
 | 
						|
 | 
						|
=head1 REQUIREMENTS
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item 1. Net-SNMP
 | 
						|
 | 
						|
To use this module, you must have Net-SNMP installed on your system.
 | 
						|
More specifically you need the Perl modules that come with it.
 | 
						|
 | 
						|
DO NOT INSTALL SNMP:: or Net::SNMP from CPAN!
 | 
						|
 | 
						|
The SNMP module is matched to an install of net-snmp, and must be installed
 | 
						|
from the net-snmp source tree.
 | 
						|
 | 
						|
The Perl module C<SNMP> is found inside the net-snmp distribution.  Go to the
 | 
						|
F<perl/> directory of the distribution to install it, or run
 | 
						|
C<./configure --with-perl-modules> from the top directory of the net-snmp
 | 
						|
distribution.
 | 
						|
 | 
						|
Net-SNMP can be found at http://net-snmp.sourceforge.net
 | 
						|
 | 
						|
Version 5.3.2 or greater is recommended.
 | 
						|
 | 
						|
Versions 5.0.1, 5.0301 and 5.0203 have issues with bulkwalk and are not supported.
 | 
						|
 | 
						|
B<Redhat Users>: Some versions that come with certain versions of
 | 
						|
Redhat/Fedora don't have the Perl library installed.  Uninstall the RPM and
 | 
						|
install by hand.
 | 
						|
 | 
						|
=item 2. MIBS
 | 
						|
 | 
						|
SNMP::Info operates on textual descriptors found in MIBs.
 | 
						|
 | 
						|
If you are using SNMP::Info separate from Netdisco, 
 | 
						|
download the Netdisco MIB package at L<http://sourceforge.net/project/showfiles.php?group_id=80033&package_id=135517>
 | 
						|
 | 
						|
Make sure that your snmp.conf is updated to point to your MIB directory
 | 
						|
and that the MIBs are world-readable.
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head1 DESIGN GOALS
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item 1. Use of textual MIB leaf identifier and enumerated values 
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item * All values are retrieved via MIB Leaf node names
 | 
						|
 | 
						|
For example SNMP::Info has an entry in its %GLOBALS hash for ``sysName''
 | 
						|
instead of 1.3.6.1.2.1.1.5.
 | 
						|
 | 
						|
=item * Data returned is in the enumerated value form.
 | 
						|
 | 
						|
For Example instead of looking up 1.3.6.1.2.1.2.2.1.3 and getting back C<23>
 | 
						|
 | 
						|
SNMP::Info will ask for C<RFC1213-MIB::ifType> and will get back C<ppp>. 
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=item 2. SNMP::Info is easily extended to new devices
 | 
						|
 | 
						|
You can create a new subclass for a device by providing four hashes :
 | 
						|
%GLOBALS, %MIBS, %FUNCS, and %MUNGE.  
 | 
						|
 | 
						|
Or you can override any existing methods from a parent class by making a short
 | 
						|
subroutine. 
 | 
						|
 | 
						|
See the section EXTENDING SNMP::INFO for more details.
 | 
						|
 | 
						|
When you make a new subclass for a device, please be sure to send it back to
 | 
						|
the developers (via Source Forge or the mailing list) for inclusion in the
 | 
						|
next version.
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head1 SUBCLASSES
 | 
						|
 | 
						|
These are the subclasses that implement MIBs and support devices:
 | 
						|
 | 
						|
Required MIBs not included in the install instructions above are noted here.
 | 
						|
 | 
						|
=head2 MIB Subclasses
 | 
						|
 | 
						|
These subclasses implement method to access one or more MIBs.  These are not 
 | 
						|
used directly, but rather inherited from device subclasses.
 | 
						|
 | 
						|
For more info run C<perldoc> on any of the following module names.
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item SNMP::Info::AdslLine
 | 
						|
 | 
						|
SNMP Interface to the ADSL-LINE-MIB for ADSL interfaces.
 | 
						|
 | 
						|
Requires the F<ADSL-LINE-MIB>, down loadable from Cisco.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::AdslLine> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Aggregate
 | 
						|
 | 
						|
SNMP Interface to F<IF-MIB> C<ifStackTable> Aggregated Links
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Aggregate> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Airespace
 | 
						|
 | 
						|
F<AIRESPACE-WIRELESS-MIB> and F<AIRESPACE-SWITCHING-MIB>.  Inherited by
 | 
						|
devices based on the Airespace wireless platform.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Airespace> for details.
 | 
						|
 | 
						|
=item SNMP::Info::AMAP
 | 
						|
 | 
						|
F<ALCATEL-IND1-INTERSWITCH-PROTOCOL-MIB>.  Alcatel Mapping Adjacency
 | 
						|
Protocol (AMAP) Support.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::AMAP> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Bridge
 | 
						|
 | 
						|
F<BRIDGE-MIB> (RFC1286).  F<QBRIDGE-MIB>. Inherited by devices with Layer2
 | 
						|
support.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Bridge> for details.
 | 
						|
 | 
						|
=item SNMP::Info::CiscoAgg
 | 
						|
 | 
						|
SNMP Interface to Cisco Aggregated Links
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::CiscoAgg> for details.
 | 
						|
 | 
						|
=item SNMP::Info::CDP
 | 
						|
 | 
						|
F<CISCO-CDP-MIB>.  Cisco Discovery Protocol (CDP) Support.  Inherited by
 | 
						|
Cisco, Enterasys, and HP devices.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::CDP> for details.
 | 
						|
 | 
						|
=item SNMP::Info::CiscoConfig
 | 
						|
 | 
						|
F<CISCO-CONFIG-COPY-MIB>, F<CISCO-FLASH-MIB>, and F<OLD-CISCO-SYS-MIB>.
 | 
						|
These OIDs facilitate the writing of configuration files.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::CiscoConfig> for details.
 | 
						|
 | 
						|
=item SNMP::Info::CiscoImage
 | 
						|
 | 
						|
F<CISCO-IMAGE-MIB>. A collection of OIDs providing IOS image characteristics.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::CiscoImage> for details.
 | 
						|
 | 
						|
=item SNMP::Info::CiscoPortSecurity
 | 
						|
 | 
						|
F<CISCO-PORT-SECURITY-MIB> and F<CISCO-PAE-MIB>.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::CiscoPortSecurity> for details.
 | 
						|
 | 
						|
=item SNMP::Info::CiscoPower
 | 
						|
 | 
						|
F<CISCO-POWER-ETHERNET-EXT-MIB>.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::CiscoPower> for details.
 | 
						|
 | 
						|
=item SNMP::Info::CiscoQOS
 | 
						|
 | 
						|
F<CISCO-CLASS-BASED-QOS-MIB>. A collection of OIDs providing information about
 | 
						|
a Cisco device's QOS config.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::CiscoQOS> for details.
 | 
						|
 | 
						|
=item SNMP::Info::CiscoRTT
 | 
						|
 | 
						|
F<CISCO-RTTMON-MIB>. A collection of OIDs providing information about a Cisco
 | 
						|
device's RTT values.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::CiscoRTT> for details.
 | 
						|
 | 
						|
=item SNMP::Info::CiscoStack
 | 
						|
 | 
						|
F<CISCO-STACK-MIB>.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::CiscoStack> for details.
 | 
						|
 | 
						|
=item SNMP::Info::CiscoStpExtensions
 | 
						|
 | 
						|
F<CISCO-STP-EXTENSIONS-MIB>
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::CiscoStpExtensions> for details.
 | 
						|
 | 
						|
=item SNMP::Info::CiscoStats
 | 
						|
 | 
						|
F<OLD-CISCO-CPU-MIB>, F<CISCO-PROCESS-MIB>, and F<CISCO-MEMORY-POOL-MIB>.
 | 
						|
Provides common interfaces for memory, cpu, and os statistics for Cisco
 | 
						|
devices.  
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::CiscoStats> for details.
 | 
						|
 | 
						|
=item SNMP::Info::CiscoVTP
 | 
						|
 | 
						|
F<CISCO-VTP-MIB>, F<CISCO-VLAN-MEMBERSHIP-MIB>,
 | 
						|
F<CISCO-VLAN-IFTABLE-RELATIONSHIP-MIB>
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::CiscoVTP> for details.
 | 
						|
 | 
						|
=item SNMP::Info::EDP
 | 
						|
 | 
						|
Extreme Discovery Protocol.  F<EXTREME-EDP-MIB>
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::EDP> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Entity
 | 
						|
 | 
						|
F<ENTITY-MIB>.  Used for device info in Cisco and other vendors.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Entity> for details.
 | 
						|
 | 
						|
=item SNMP::Info::EtherLike
 | 
						|
 | 
						|
F<EtherLike-MIB> (RFC1398) - Some Layer3 devices implement this MIB, as well
 | 
						|
as some Aironet Layer 2 devices (non Cisco).
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::EtherLike> for details.
 | 
						|
 | 
						|
=item SNMP::Info::FDP
 | 
						|
 | 
						|
Foundry (Brocade) Discovery Protocol.  F<FOUNDRY-SN-SWITCH-GROUP-MIB>
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::FDP> for details.
 | 
						|
 | 
						|
=item SNMP::Info::IPv6
 | 
						|
 | 
						|
SNMP Interface for obtaining configured IPv6 addresses and mapping IPv6
 | 
						|
addresses to MAC addresses and interfaces, using information from F<IP-MIB>,
 | 
						|
F<IPV6-MIB> and/or F<CISCO-IETF-IP-MIB>.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::IPv6> for details.
 | 
						|
 | 
						|
=item SNMP::Info::IEEE802dot11
 | 
						|
 | 
						|
F<IEEE802dot11-MIB>.  A collection of OIDs providing information about
 | 
						|
standards based 802.11 wireless devices.  
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::IEEE802dot11> for details.
 | 
						|
 | 
						|
=item SNMP::Info::IEEE802dot3ad
 | 
						|
 | 
						|
SNMP Interface to IEEE Aggregated Links.  F<IEEE8023-LAG-MIB>
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::IEEE802dot3ad> for details.
 | 
						|
 | 
						|
=item SNMP::Info::LLDP
 | 
						|
 | 
						|
F<LLDP-MIB>, F<LLDP-EXT-DOT1-MIB>, and F<LLDP-EXT-DOT3-MIB>.  Link Layer
 | 
						|
Discovery Protocol (LLDP) Support.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::LLDP> for details.
 | 
						|
 | 
						|
=item SNMP::Info::MAU
 | 
						|
 | 
						|
F<MAU-MIB> (RFC2668).  Some Layer2 devices use this for extended Ethernet
 | 
						|
(Media Access Unit) interface information.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::MAU> for details.
 | 
						|
 | 
						|
=item SNMP::Info::NortelStack
 | 
						|
 | 
						|
F<S5-AGENT-MIB>, F<S5-CHASSIS-MIB>.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::NortelStack> for details.
 | 
						|
 | 
						|
=item SNMP::Info::PowerEthernet
 | 
						|
 | 
						|
F<POWER-ETHERNET-MIB>
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::PowerEthernet> for details.
 | 
						|
 | 
						|
=item SNMP::Info::RapidCity
 | 
						|
 | 
						|
F<RAPID-CITY>.  Inherited by Avaya switches for duplex and VLAN information.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::RapidCity> for details.
 | 
						|
 | 
						|
=item SNMP::Info::SONMP
 | 
						|
 | 
						|
SynOptics Network Management Protocol (SONMP) F<SYNOPTICS-ROOT-MIB>,
 | 
						|
F<S5-ETH-MULTISEG-TOPOLOGY-MIB>.  Inherited by 
 | 
						|
Avaya/Nortel/Bay/Synoptics switches and hubs.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::SONMP> for details.
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head2 Device Subclasses
 | 
						|
 | 
						|
These subclasses inherit from one or more classes to provide a common
 | 
						|
interface to data obtainable from network devices. 
 | 
						|
 | 
						|
All the required MIB files are included in the netdisco-mib package.
 | 
						|
(See Above).
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item SNMP::Info::Layer1
 | 
						|
 | 
						|
Generic Layer1 Device subclass.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer1> for details.
 | 
						|
 | 
						|
=over 
 | 
						|
 | 
						|
=item SNMP::Info::Layer1::Allied
 | 
						|
 | 
						|
Subclass for Allied Telesis Repeaters / Hubs.  
 | 
						|
 | 
						|
Requires F<ATI-MIB>
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer1::Allied> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer1::Asante
 | 
						|
 | 
						|
Subclass for Asante 1012 Hubs. 
 | 
						|
 | 
						|
Requires F<ASANTE-HUB1012-MIB>
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer1::Asante> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer1::Bayhub
 | 
						|
 | 
						|
Subclass for Nortel/Bay hubs.  This includes System 5000, 100 series,
 | 
						|
200 series, and probably more.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer1::Bayhub> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer1::Cyclades
 | 
						|
 | 
						|
Subclass for Cyclades terminal servers.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer1::Cyclades> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer1::S3000
 | 
						|
 | 
						|
Subclass for Bay/Synoptics hubs.  This includes System 3000, 281X, and
 | 
						|
probably more.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer1::S3000> for details.
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=item SNMP::Info::Layer2
 | 
						|
 | 
						|
Generic Layer2 Device subclass.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2> for details.
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::Airespace
 | 
						|
 | 
						|
Subclass for Cisco (Airespace) wireless controllers.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::Airespace> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::Aironet
 | 
						|
 | 
						|
Class for Cisco Aironet wireless devices that run IOS.  See also
 | 
						|
Layer3::Aironet for Aironet devices that don't run IOS.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::Aironet> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::Allied
 | 
						|
 | 
						|
Allied Telesis switches.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::Allied> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::Baystack
 | 
						|
 | 
						|
Subclass for Avaya/Nortel/Bay Ethernet Switch/Baystack switches.  This
 | 
						|
includes 303, 304, 350, 380, 410, 420, 425, 450, 460, 470 series,
 | 
						|
2500 series, 4000 series, 5000 series, Business Ethernet Switch (BES),
 | 
						|
Business Policy Switch (BPS), VSP 7000 series, and probably others.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::Baystack> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::Kentrox
 | 
						|
 | 
						|
Class for Kentrox DataSMART DSU/CSU. See L<SNMP::Info::Layer2::Kentrox> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::C1900
 | 
						|
 | 
						|
Subclass for Cisco Catalyst 1900 and 1900c Devices running CatOS.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::C1900> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::C2900
 | 
						|
 | 
						|
Subclass for Cisco Catalyst 2900, 2950, 3500XL, and 3548 devices running IOS.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::C2900> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::Catalyst
 | 
						|
 | 
						|
Subclass for Cisco Catalyst switches running CatOS.  These switches usually
 | 
						|
report a model number that starts with C<wsc>.   Note that this class
 | 
						|
does not support everything that has the name Catalyst. 
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::Catalyst> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::Centillion
 | 
						|
 | 
						|
Subclass for Nortel/Bay Centillion and 5000BH ATM switches.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::Centillion> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::Cisco
 | 
						|
 | 
						|
Generic Cisco subclass for layer2 devices that are not yet supported
 | 
						|
in more specific subclasses.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::Cisco> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::CiscoSB
 | 
						|
 | 
						|
Subclass for Cisco's "Small Business" product line, acquired from 
 | 
						|
Linksys.  This currently comprises the Sx300/500 line of switches.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::CiscoSB> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::HP
 | 
						|
 | 
						|
Subclass for more recent HP Procurve Switches
 | 
						|
 | 
						|
Requires F<HP-ICF-OID> and F<ENTITY-MIB> downloaded from HP.  
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::HP> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::HP4000
 | 
						|
 | 
						|
Subclass for older HP Procurve Switches
 | 
						|
 | 
						|
Requires F<HP-ICF-OID> and F<ENTITY-MIB> downloaded from HP.  
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::HP4000> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::HPVC
 | 
						|
 | 
						|
Subclass for HP Virtual Connect Switches
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::HPVC> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::N2270
 | 
						|
 | 
						|
Subclass for Nortel 2270 wireless switches.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::N2270> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::NAP222x
 | 
						|
 | 
						|
Subclass for Nortel 222x series wireless access points.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::NAP222x> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::Netgear
 | 
						|
 | 
						|
Subclass for Netgear switches
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::Netgear> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::NWSS2300
 | 
						|
 | 
						|
SNMP Interface to Avaya (Trapeze) Wireless Controllers
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::NWSS2300> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::Orinoco
 | 
						|
 | 
						|
Subclass for Orinoco/Proxim wireless access points.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::Orinoco> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::Trapeze
 | 
						|
 | 
						|
SNMP Interface to Juniper (Trapeze) Wireless Controllers
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::Trapeze> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer2::ZyXEL_DSLAM
 | 
						|
 | 
						|
Zyxel DSLAMs.  Need I say more?
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer2::ZyXEL_DSLAM> for details.
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=item SNMP::Info::Layer3
 | 
						|
 | 
						|
Generic Layer3 and Layer2+3 Device subclass.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3> for details.
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Aironet
 | 
						|
 | 
						|
Subclass for Cisco Aironet wireless access points (AP) not running IOS. These
 | 
						|
are usually older devices.
 | 
						|
 | 
						|
MIBs for these devices now included in v2.tar.gz available from ftp.cisco.com.
 | 
						|
 | 
						|
Note Layer2::Aironet 
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Aironet> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::AlcatelLucent
 | 
						|
 | 
						|
Alcatel-Lucent OmniSwitch Class.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::AlcatelLucent> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::AlteonAD
 | 
						|
 | 
						|
Subclass for Radware Alteon Series ADC switches and Nortel BladeCenter
 | 
						|
Layer2-3 GbE Switch Modules.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::AlteonAD> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Altiga
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Altiga> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Arista
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Arista> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Aruba
 | 
						|
 | 
						|
Subclass for Aruba wireless switches.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Aruba> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::BayRS
 | 
						|
 | 
						|
Subclass for Avaya/Nortel/Bay Multiprotocol/BayRS routers.  This includes
 | 
						|
BCN, BLN, ASN, ARN, AN, 2430, and 5430 routers.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::BayRS> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::BlueCoatSG
 | 
						|
 | 
						|
Subclass for Blue Coat SG series proxy devices.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::BlueCoatSG> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::C3550
 | 
						|
 | 
						|
Subclass for Cisco Catalyst 3550,3540,3560 2/3 switches running IOS.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::C3550> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::C4000
 | 
						|
 | 
						|
This class covers Catalyst 4000s and 4500s.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::C4000> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::C6500
 | 
						|
 | 
						|
This class covers Catalyst 6500s in native mode, hybrid mode.  Catalyst
 | 
						|
3750's, 2970's and probably others.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::C6500> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Cisco
 | 
						|
 | 
						|
This is a simple wrapper around Layer3 for IOS devices.  It adds on CiscoVTP.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Cisco> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::CiscoASA
 | 
						|
 | 
						|
Subclass for Cisco Adaptive Security Appliances.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::CiscoASA> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::CiscoFWSM
 | 
						|
 | 
						|
Subclass for Cisco Firewall Services Modules.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::CiscoFWSM> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Contivity
 | 
						|
 | 
						|
Subclass for Avaya/Nortel Contivity/VPN Routers.  
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Contivity> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Dell
 | 
						|
 | 
						|
Subclass for Dell PowerConnect switches. D-Link, the IBM BladeCenter
 | 
						|
Gigabit Ethernet Switch Module and some Linksys switches
 | 
						|
also use this module based upon MIB support.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Dell> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Enterasys
 | 
						|
 | 
						|
Subclass for Enterasys devices.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Enterasys> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Extreme
 | 
						|
 | 
						|
Subclass for Extreme Networks switches.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Extreme> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::F5
 | 
						|
 | 
						|
Subclass for F5 devices.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::F5> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Force10
 | 
						|
 | 
						|
Subclass for Force10 devices.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Force10> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Foundry
 | 
						|
 | 
						|
Subclass for Brocade (Foundry) Network devices.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Foundry> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::H3C
 | 
						|
 | 
						|
SNMP Interface to Layer 3 Devices, H3C & HP A-series.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::H3C> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::HP9300
 | 
						|
 | 
						|
Subclass for HP network devices which Foundry Networks was the
 | 
						|
Original Equipment Manufacturer (OEM) such as the HP ProCurve 9300 and 6300 series.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::HP9300> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::IBMGbTor
 | 
						|
 | 
						|
SNMP Interface to IBM Rackswitch (formerly Blade Network Technologies)
 | 
						|
network devices.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::IBMGbTor> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Juniper
 | 
						|
 | 
						|
Subclass for Juniper devices
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Juniper> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Lantronix
 | 
						|
 | 
						|
Subclass for Lantronix devices
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Lantronix> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Microsoft
 | 
						|
 | 
						|
Subclass for Generic Microsoft Routers running Microsoft Windows OS.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Microsoft> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Mikrotik
 | 
						|
 | 
						|
Subclass for Mikrotik devices running RouterOS.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Mikrotik> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::N1600
 | 
						|
 | 
						|
Subclass for Avaya/Nortel Ethernet Routing Switch 1600 series.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::N1600> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::NetSNMP
 | 
						|
 | 
						|
Subclass for host systems running Net-SNMP.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::NetSNMP> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Netscreen
 | 
						|
 | 
						|
Subclass for Juniper NetScreen.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Netscreen> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Nexus
 | 
						|
 | 
						|
Subclass for Cisco Nexus devices running NX-OS
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Nexus> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::PacketFront
 | 
						|
 | 
						|
Subclass for PacketFront DRG series CPE.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::PacketFront> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Passport
 | 
						|
 | 
						|
Subclass for Avaya/Nortel Ethernet Routing Switch/Passport 8000 series,
 | 
						|
Accelar, and VSP 9000 series switches.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Passport> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Pf
 | 
						|
 | 
						|
Subclass for FreeBSD-Based Firewalls using Pf /Pf Sense
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Pf> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Pica8
 | 
						|
 | 
						|
Subclass for Pica8 devices.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Pica8> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::SonicWALL
 | 
						|
 | 
						|
Subclass for generic SonicWALL devices. See documentation in
 | 
						|
L<SNMP::Info::Layer3::SonicWALL> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Steelhead
 | 
						|
 | 
						|
Subclass for  Riverbed Steelhead WAN optimization appliances. See
 | 
						|
documentation in L<SNMP::Info::Layer3::Steelhead> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Sun
 | 
						|
 | 
						|
Subclass for Generic Sun Routers running SunOS.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Sun> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Tasman
 | 
						|
 | 
						|
Subclass for Avaya Secure Routers.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Tasman> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer3::Timetra
 | 
						|
 | 
						|
Alcatel-Lucent SR Class.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer3::Timetra> for details.
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=over 4
 | 
						|
 | 
						|
=item SNMP::Info::Layer7
 | 
						|
 | 
						|
Generic Layer7 Devices.
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer7> for details.
 | 
						|
 | 
						|
=over 4
 | 
						|
 | 
						|
=item SNMP::Info::Layer7::APC
 | 
						|
 | 
						|
SNMP Interface to APC UPS devices
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer7::APC> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer7::Netscaler
 | 
						|
 | 
						|
SNMP Interface to Citrix Netscaler appliances
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer7::Netscaler> for details.
 | 
						|
 | 
						|
=item SNMP::Info::Layer7::Neoteris
 | 
						|
 | 
						|
SNMP Interface to Juniper SSL VPN appliances
 | 
						|
 | 
						|
See documentation in L<SNMP::Info::Layer7::Neoteris> for details.
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head1 Thanks
 | 
						|
 | 
						|
Thanks for testing and coding help (in no particular order) to :
 | 
						|
Alexander Barthel, Andy Ford, Alexander Hartmaier, Andrew Herrick, Alex
 | 
						|
Kramarov, Bernhard Augenstein, Bradley Baetz, Brian Chow, Brian Wilson,
 | 
						|
Carlos Vicente, Dana Watanabe, David Pinkoski, David Sieborger, Douglas
 | 
						|
McKeown, Greg King, Ivan Auger, Jean-Philippe Luiggi, Jeroen van Ingen,
 | 
						|
Justin Hunter, Kent Hamilton, Matthew Tuttle, Michael Robbert, Mike Hunter,
 | 
						|
Nicolai Petri, Ralf Gross, Robert Kerr and people listed on the Netdisco
 | 
						|
README!
 | 
						|
 | 
						|
=head1 USAGE
 | 
						|
 | 
						|
=head2 Constructor
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item new()
 | 
						|
 | 
						|
Creates a new object and connects via SNMP::Session. 
 | 
						|
 | 
						|
 my $info = new SNMP::Info( 'Debug'             => 1,
 | 
						|
                            'AutoSpecify'       => 1,
 | 
						|
                            'BigInt'            => 1,
 | 
						|
                            'BulkWalk'          => 1,
 | 
						|
                            'BulkRepeaters'     => 20,
 | 
						|
                            'IgnoreNetSNMPConf' => 1,
 | 
						|
                            'LoopDetect'        => 1,
 | 
						|
                            'DestHost'          => 'myrouter',
 | 
						|
                            'Community'         => 'public',
 | 
						|
                            'Version'           => 2,
 | 
						|
                            'MibDirs'           => ['dir1','dir2','dir3'],
 | 
						|
                          ) or die;
 | 
						|
 | 
						|
SNMP::Info Specific Arguments :
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item AutoSpecify
 | 
						|
 | 
						|
Returns an object of a more specific device class
 | 
						|
 | 
						|
(default 0, which means "off")
 | 
						|
 | 
						|
=item BigInt
 | 
						|
 | 
						|
Return Math::BigInt objects for 64 bit counters.  Sets on a global scope,
 | 
						|
not object.
 | 
						|
 | 
						|
(default 0, which means "off")
 | 
						|
 | 
						|
=item BulkWalk
 | 
						|
 | 
						|
Set to C<0> to turn off BULKWALK commands for SNMPv2 connections.
 | 
						|
 | 
						|
Note that BULKWALK is turned off for Net-SNMP versions 5.1.x because of a bug.
 | 
						|
 | 
						|
(default 1, which means "on")
 | 
						|
 | 
						|
=item BulkRepeaters
 | 
						|
 | 
						|
Set number of MaxRepeaters for BULKWALK operation.  See
 | 
						|
C<perldoc SNMP> -> bulkwalk() for more info.
 | 
						|
 | 
						|
(default 20)
 | 
						|
 | 
						|
=item LoopDetect
 | 
						|
 | 
						|
Detects looping during getnext table column walks by comparing IIDs for each
 | 
						|
instance.  A loop is detected if the same IID is seen more than once and the
 | 
						|
walk is aborted.  Note:  This will not detect loops during a bulkwalk
 | 
						|
operation, Net-SNMP's internal bulkwalk function must detect the loop. 
 | 
						|
 | 
						|
Set to C<0> to turn off loop detection.
 | 
						|
 | 
						|
(default 1, which means "on")
 | 
						|
 | 
						|
=item IgnoreNetSNMPConf
 | 
						|
 | 
						|
Net-SNMP version 5.0 and higher read configuration files, snmp.conf or
 | 
						|
snmp.local.conf, from /etc/snmp, /usr/share/snmp, /usr/lib(64)/snmp, or
 | 
						|
$HOME/.snmp and uses those settings to automatically parse MIB files, etc.
 | 
						|
 | 
						|
Set to C<1> "on" to ignore Net-SNMP configuration files by overriding the
 | 
						|
C<SNMPCONFPATH> environmental variable during object initialization. Note:
 | 
						|
MibDirs must be defined or Net-SNMP will not be able to load MIBs and
 | 
						|
initialize the object.
 | 
						|
 | 
						|
(default 0, which means "off")
 | 
						|
 | 
						|
=item Debug
 | 
						|
 | 
						|
Prints Lots of debugging messages.
 | 
						|
Pass 2 to print even more debugging messages.
 | 
						|
 | 
						|
(default 0, which means "off")
 | 
						|
 | 
						|
=item DebugSNMP
 | 
						|
 | 
						|
Set $SNMP::debugging level for Net-SNMP.
 | 
						|
 | 
						|
See F<SNMP> for more details.
 | 
						|
 | 
						|
=item MibDirs
 | 
						|
 | 
						|
Array ref to list of directories in which to look for MIBs.  Note this will
 | 
						|
be in addition to the ones setup in snmp.conf at the system level.
 | 
						|
 | 
						|
(default use net-snmp settings only)
 | 
						|
 | 
						|
=item RetryNoSuch
 | 
						|
 | 
						|
When using SNMP Version 1, try reading values even if they come back as "no
 | 
						|
such variable in this MIB".  Set to false if so desired.  This feature lets
 | 
						|
you read SNMPv2 data from an SNMP version 1 connection, and should probably
 | 
						|
be left on.
 | 
						|
 | 
						|
(default 1, which means "on")
 | 
						|
 | 
						|
=item Session
 | 
						|
 | 
						|
SNMP::Session object to use instead of connecting on own.
 | 
						|
 | 
						|
(default creates session automatically)
 | 
						|
 | 
						|
=item Offline
 | 
						|
 | 
						|
Causes SNMP::Info to avoid network activity and return data only from its
 | 
						|
cache. If you ask for something not in the cache, an error is thrown.  See
 | 
						|
also the C<cache()> and C<offline()> methods.
 | 
						|
 | 
						|
(default 0, which means "online")
 | 
						|
 | 
						|
=item Cache
 | 
						|
 | 
						|
Pass in a HashRef to prime the cache of retrieved data. Useful for creating an
 | 
						|
instance in C<Offline> mode from a previously dumped cache. See also the
 | 
						|
C<cache()> method to retrieve a cache after running actial queries.
 | 
						|
 | 
						|
=item OTHER
 | 
						|
 | 
						|
All other arguments are passed to SNMP::Session.
 | 
						|
 | 
						|
See SNMP::Session for a list of other possible arguments.
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
A Note about the wrong Community string or wrong SNMP Version:
 | 
						|
 | 
						|
If a connection is using the wrong community string or the wrong SNMP version,
 | 
						|
the creation of the object will not fail.  The device still answers the call
 | 
						|
on the SNMP port, but will not return information.  Check the error() method
 | 
						|
after you create the device object to see if there was a problem in
 | 
						|
connecting.
 | 
						|
 | 
						|
A note about SNMP Versions :
 | 
						|
 | 
						|
Some older devices don't support SNMP version 2, and will not return anything
 | 
						|
when a connection under Version 2 is attempted.
 | 
						|
 | 
						|
Some newer devices will support Version 1, but will not return all the data
 | 
						|
they might have if you had connected under Version 1 
 | 
						|
 | 
						|
When trying to get info from a new device, you may have to try version 2 and
 | 
						|
then fallback to version 1.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub new {
 | 
						|
    my $proto     = shift;
 | 
						|
    my $class     = ref($proto) || $proto;
 | 
						|
    my %args      = @_;
 | 
						|
    my %sess_args = %args;
 | 
						|
    my $new_obj   = {};
 | 
						|
    bless $new_obj, $class;
 | 
						|
 | 
						|
    $new_obj->{class} = $class;
 | 
						|
 | 
						|
    # load references to all the subclass data structures
 | 
						|
    {
 | 
						|
        no strict 'refs';    ## no critic (ProhibitNoStrict ProhibitProlongedStrictureOverride)
 | 
						|
        $new_obj->{init}    = \${ $class . '::INIT' };
 | 
						|
        $new_obj->{mibs}    = \%{ $class . '::MIBS' };
 | 
						|
        $new_obj->{globals} = \%{ $class . '::GLOBALS' };
 | 
						|
        $new_obj->{funcs}   = \%{ $class . '::FUNCS' };
 | 
						|
        $new_obj->{munge}   = \%{ $class . '::MUNGE' };
 | 
						|
    }
 | 
						|
 | 
						|
    # SNMP::Info specific args :
 | 
						|
    if ( defined $args{Debug} ) {
 | 
						|
        $new_obj->debug( $args{Debug} );
 | 
						|
        delete $sess_args{Debug};
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        $new_obj->debug( defined $DEBUG ? $DEBUG : 0 );
 | 
						|
    }
 | 
						|
 | 
						|
    if ( defined $args{DebugSNMP} ) {
 | 
						|
        $SNMP::debugging = $args{DebugSNMP};
 | 
						|
        delete $sess_args{DebugSNMP};
 | 
						|
    }
 | 
						|
 | 
						|
    my $auto_specific = 0;
 | 
						|
    if ( defined $args{AutoSpecify} ) {
 | 
						|
        $auto_specific = $args{AutoSpecify} || 0;
 | 
						|
        delete $sess_args{AutoSpecify};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( defined $args{BulkRepeaters} ) {
 | 
						|
        $new_obj->{BulkRepeaters} = $args{BulkRepeaters};
 | 
						|
        delete $sess_args{BulkRepeaters};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( defined $args{BulkWalk} ) {
 | 
						|
        $new_obj->{BulkWalk} = $args{BulkWalk};
 | 
						|
        delete $sess_args{BulkWalk};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( defined $args{LoopDetect} ) {
 | 
						|
        $new_obj->{LoopDetect} = $args{LoopDetect};
 | 
						|
        delete $sess_args{LoopDetect};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( defined $args{IgnoreNetSNMPConf} ) {
 | 
						|
        $new_obj->{IgnoreNetSNMPConf} = $args{IgnoreNetSNMPConf} || 0;
 | 
						|
        delete $sess_args{IgnoreNetSNMPConf};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( defined $args{Offline} ) {
 | 
						|
        $new_obj->{Offline} = $args{Offline} || 0;
 | 
						|
        delete $sess_args{Offline};
 | 
						|
    }
 | 
						|
 | 
						|
    if ( defined $args{Cache} and ref {} eq ref $args{Cache} ) {
 | 
						|
        $new_obj->{$_} = $args{Cache}->{$_} for keys %{$args{Cache}};
 | 
						|
        delete $sess_args{Cache};
 | 
						|
    }
 | 
						|
 | 
						|
    my $sess = undef;
 | 
						|
    if ( defined $args{Session} ) {
 | 
						|
        $sess = $args{Session};
 | 
						|
        delete $sess_args{Session};
 | 
						|
    }
 | 
						|
    if ( defined $args{BigInt} ) {
 | 
						|
        $BIGINT = $args{BigInt};
 | 
						|
        delete $sess_args{BigInt};
 | 
						|
    }
 | 
						|
    if ( defined $args{MibDirs} ) {
 | 
						|
        $new_obj->{mibdirs} = $args{MibDirs};
 | 
						|
        delete $sess_args{MibDirs};
 | 
						|
    }
 | 
						|
 | 
						|
    $new_obj->{nosuch} = $args{RetryNoSuch} || $NOSUCH;
 | 
						|
 | 
						|
    # Initialize mibs if not done
 | 
						|
    my $init_ref = $new_obj->{init};
 | 
						|
    unless ( defined $$init_ref and $$init_ref ) {
 | 
						|
        $new_obj->init();
 | 
						|
        $$init_ref = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    # Connects to device unless open session is provided.
 | 
						|
    $sess = new SNMP::Session(
 | 
						|
        'UseEnums' => 1,
 | 
						|
        %sess_args, 'RetryNoSuch' => $new_obj->{nosuch}
 | 
						|
    ) unless defined $sess;
 | 
						|
 | 
						|
    # No session object created
 | 
						|
    unless ( defined $sess ) {
 | 
						|
        $new_obj->error_throw("SNMP::Info::new() Failed to Create Session. ");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    # Session object created but SNMP connection failed.
 | 
						|
    my $sess_err = $sess->{ErrorStr} || '';
 | 
						|
    if ($sess_err) {
 | 
						|
        $new_obj->error_throw(
 | 
						|
            "SNMP::Info::new() Net-SNMP session creation failed. $sess_err");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    # Table function store
 | 
						|
    my $store = {};
 | 
						|
 | 
						|
    # Save Args for later
 | 
						|
    $new_obj->{store}     = $store;
 | 
						|
    $new_obj->{sess}      = $sess;
 | 
						|
    $new_obj->{args}      = \%args;
 | 
						|
    $new_obj->{snmp_ver}  = $args{Version} || 2;
 | 
						|
    $new_obj->{snmp_comm} = $args{Community} || 'public';
 | 
						|
    $new_obj->{snmp_user} = $args{SecName} || 'initial';
 | 
						|
 | 
						|
    return $auto_specific ? $new_obj->specify() : $new_obj;
 | 
						|
}
 | 
						|
 | 
						|
=item update()
 | 
						|
 | 
						|
Replace the existing session with a new one with updated values,
 | 
						|
without re-identifying the device.  The only supported changes are
 | 
						|
to Community or Context.
 | 
						|
 | 
						|
Clears the object cache.
 | 
						|
 | 
						|
This is useful, e.g., when a device supports multiple contexts
 | 
						|
(via changes to the Community string, or via the SNMPv3 Context
 | 
						|
parameter), but a context that you want to access does not support
 | 
						|
the objects (e.g., C<sysObjectID>, C<sysDescr>) that we use to identify
 | 
						|
the device.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub update {
 | 
						|
    my $obj         = shift;
 | 
						|
    my %update_args = @_;
 | 
						|
    my %sess_args   = ( %{ $obj->{args} }, %update_args );
 | 
						|
 | 
						|
    # silently only update "the right" args
 | 
						|
    delete $sess_args{Debug};
 | 
						|
    delete $sess_args{DebugSNMP};
 | 
						|
    delete $sess_args{AutoSpecify};
 | 
						|
    delete $sess_args{BulkRepeaters};
 | 
						|
    delete $sess_args{BulkWalk};
 | 
						|
    delete $sess_args{LoopDetect};
 | 
						|
    delete $sess_args{IgnoreNetSNMPConf};
 | 
						|
    delete $sess_args{BigInt};
 | 
						|
    delete $sess_args{MibDirs};
 | 
						|
 | 
						|
    my $sess = new SNMP::Session(
 | 
						|
        'UseEnums' => 1,
 | 
						|
        %sess_args, 'RetryNoSuch' => $obj->{nosuch}
 | 
						|
    );
 | 
						|
    unless ( defined $sess ) {
 | 
						|
        $obj->error_throw(
 | 
						|
            "SNMP::Info::update() Failed to Create new Session. ");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    # Session object created but SNMP connection failed.
 | 
						|
    my $sess_err = $sess->{ErrorStr} || '';
 | 
						|
    if ($sess_err) {
 | 
						|
        $obj->error_throw(
 | 
						|
            "SNMP::Info::update() Net-SNMP session creation failed. $sess_err"
 | 
						|
        );
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    $obj->clear_cache();
 | 
						|
    return $obj->session($sess);
 | 
						|
}
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head2 Data is Cached
 | 
						|
 | 
						|
Methods and subroutines requesting data from a device will only load the data
 | 
						|
once, and then return cached versions of that data. 
 | 
						|
 | 
						|
Run $info->load_METHOD() where method is something like 'i_name' to reload
 | 
						|
data from a method.
 | 
						|
 | 
						|
Run $info->clear_cache() to clear the cache to allow reload of both globals
 | 
						|
and table methods.
 | 
						|
 | 
						|
The cache can be retreved or set using the $info->cache() method. This works
 | 
						|
together with the C<Offline> option.
 | 
						|
 | 
						|
=head2 Object Scalar Methods
 | 
						|
 | 
						|
These are for package related data, not directly supplied
 | 
						|
from SNMP.
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item $info->clear_cache()
 | 
						|
 | 
						|
Clears the cached data.  This includes GLOBALS data and TABLE METHOD data.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub clear_cache {
 | 
						|
    my $self = shift;
 | 
						|
 | 
						|
    print "SNMP::Info::clear_cache() - Cache Cleared.\n" if $self->debug();
 | 
						|
 | 
						|
    # Clear cached global values and table method flag for being cached
 | 
						|
    foreach my $key ( keys %$self ) {
 | 
						|
        next unless defined $key;
 | 
						|
        next unless $key =~ /^_/;
 | 
						|
        delete $self->{$key};
 | 
						|
    }
 | 
						|
 | 
						|
    # Clear store for tables
 | 
						|
    return $self->store( {} );
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
=item $info->debug(1)
 | 
						|
 | 
						|
Returns current debug status, and optionally toggles debugging info for this
 | 
						|
object.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub debug {
 | 
						|
    my $self  = shift;
 | 
						|
    my $debug = shift;
 | 
						|
 | 
						|
    if ( defined $debug ) {
 | 
						|
        $self->{debug} = $debug;
 | 
						|
    }
 | 
						|
 | 
						|
    return $self->{debug};
 | 
						|
}
 | 
						|
 | 
						|
=item $info->offline([1|0])
 | 
						|
 | 
						|
Returns if offline mode is currently turned on for this object.
 | 
						|
 | 
						|
Optionally sets the Offline parameter.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub offline {
 | 
						|
    my $self = shift;
 | 
						|
    my $ol   = shift;
 | 
						|
 | 
						|
    if ( defined $ol ) {
 | 
						|
        $self->{Offline} = $ol;
 | 
						|
    }
 | 
						|
    return $self->{Offline};
 | 
						|
}
 | 
						|
 | 
						|
=item $info->cache([new_cache])
 | 
						|
 | 
						|
Returns a HashRef of all cached data in this object. There will be a C<store>
 | 
						|
key for table data and then one key for each leaf.
 | 
						|
 | 
						|
Optionally sets the cache parameters if passed a HashRef.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub cache {
 | 
						|
    my $self = shift;
 | 
						|
    my $data = shift;
 | 
						|
 | 
						|
    if ( defined $data and ref {} eq ref $data ) {
 | 
						|
        $self->{$_} = $data->{$_} for keys %$data;
 | 
						|
    }
 | 
						|
 | 
						|
    my $cache = { store => $self->{store} };
 | 
						|
    foreach my $key ( keys %$self ) {
 | 
						|
        next unless defined $key;
 | 
						|
        next unless $key =~ /^_/;
 | 
						|
        $cache->{$key} = $self->{$key};
 | 
						|
    }
 | 
						|
    return $cache;
 | 
						|
}
 | 
						|
 | 
						|
=item $info->bulkwalk([1|0])
 | 
						|
 | 
						|
Returns if bulkwalk is currently turned on for this object.
 | 
						|
 | 
						|
Optionally sets the bulkwalk parameter.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub bulkwalk {
 | 
						|
    my $self = shift;
 | 
						|
    my $bw   = shift;
 | 
						|
 | 
						|
    if ( defined $bw ) {
 | 
						|
        $self->{BulkWalk} = $bw;
 | 
						|
    }
 | 
						|
    return $self->{BulkWalk};
 | 
						|
}
 | 
						|
 | 
						|
=item $info->loopdetect([1|0])
 | 
						|
 | 
						|
Returns if loopdetect is currently turned on for this object.
 | 
						|
 | 
						|
Optionally sets the loopdetect parameter.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub loopdetect {
 | 
						|
    my $self = shift;
 | 
						|
    my $ld   = shift;
 | 
						|
 | 
						|
    if ( defined $ld ) {
 | 
						|
        $self->{LoopDetect} = $ld;
 | 
						|
    }
 | 
						|
    return $self->{LoopDetect};
 | 
						|
}
 | 
						|
 | 
						|
=item $info->device_type()
 | 
						|
 | 
						|
Returns the Subclass name for this device.  C<SNMP::Info> is returned if no
 | 
						|
more specific class is available.
 | 
						|
 | 
						|
First the device is checked for Layer 3 support and a specific subclass,
 | 
						|
then Layer 2 support and subclasses are checked.
 | 
						|
 | 
						|
This means that Layer 2 / 3  switches and routers will fall under the
 | 
						|
SNMP::Info::Layer3 subclasses.
 | 
						|
 | 
						|
If the device still can be connected to via SNMP::Info, then 
 | 
						|
SNMP::Info is returned.  
 | 
						|
 | 
						|
See L<http://netdisco.org/doc/DeviceMatrix.html> or L<DeviceMatrix.txt> for more details
 | 
						|
about device support, or view C<device_type()> in F<Info.pm>.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub device_type {
 | 
						|
    my $info = shift;
 | 
						|
 | 
						|
    my $objtype = "SNMP::Info";
 | 
						|
 | 
						|
    my $layers = $info->layers() || '00000000';
 | 
						|
 | 
						|
    my $desc = $info->description() || 'undef';
 | 
						|
    $desc =~ s/[\r\n\l]+/ /g;
 | 
						|
 | 
						|
    # Some devices don't implement sysServices, but do return a description. 
 | 
						|
    # In that case, log a warning and continue.
 | 
						|
    if ( $layers eq '00000000' ) {
 | 
						|
        if ($desc ne 'undef') {
 | 
						|
            carp("Device doesn't implement sysServices but did return sysDescr. Might give unexpected results.\n") if $info->debug();
 | 
						|
        } else {
 | 
						|
            # No sysServices, no sysDescr 
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    my $id = $info->id() || 'undef';
 | 
						|
    my $soid = $id;
 | 
						|
 | 
						|
    # Hash for generic fallback to a device class if unable to determine using
 | 
						|
    # the sysDescr regex.
 | 
						|
    my %l3sysoidmap = (
 | 
						|
        9    => 'SNMP::Info::Layer3::Cisco',
 | 
						|
        11   => 'SNMP::Info::Layer2::HP',
 | 
						|
        18   => 'SNMP::Info::Layer3::BayRS',
 | 
						|
        42   => 'SNMP::Info::Layer3::Sun',
 | 
						|
        45   => 'SNMP::Info::Layer2::Baystack',
 | 
						|
        171  => 'SNMP::Info::Layer3::Dell',
 | 
						|
        244  => 'SNMP::Info::Layer3::Lantronix',
 | 
						|
        311  => 'SNMP::Info::Layer3::Microsoft',
 | 
						|
        674  => 'SNMP::Info::Layer3::Dell',
 | 
						|
        1872 => 'SNMP::Info::Layer3::AlteonAD',
 | 
						|
        1916 => 'SNMP::Info::Layer3::Extreme',
 | 
						|
        1991 => 'SNMP::Info::Layer3::Foundry',
 | 
						|
        2021 => 'SNMP::Info::Layer3::NetSNMP',
 | 
						|
        2272 => 'SNMP::Info::Layer3::Passport',
 | 
						|
        2636 => 'SNMP::Info::Layer3::Juniper',
 | 
						|
        2925 => 'SNMP::Info::Layer1::Cyclades',
 | 
						|
        3076 => 'SNMP::Info::Layer3::Altiga',
 | 
						|
        3224 => 'SNMP::Info::Layer3::Netscreen',
 | 
						|
        3375 => 'SNMP::Info::Layer3::F5',
 | 
						|
        3417 => 'SNMP::Info::Layer3::BlueCoatSG',
 | 
						|
        4526 => 'SNMP::Info::Layer2::Netgear',
 | 
						|
        5624 => 'SNMP::Info::Layer3::Enterasys',
 | 
						|
        6027 => 'SNMP::Info::Layer3::Force10',
 | 
						|
        6486 => 'SNMP::Info::Layer3::AlcatelLucent',
 | 
						|
        6527 => 'SNMP::Info::Layer3::Timetra',
 | 
						|
        8072 => 'SNMP::Info::Layer3::NetSNMP',
 | 
						|
        9303 => 'SNMP::Info::Layer3::PacketFront',
 | 
						|
        12325 => 'SNMP::Info::Layer3::Pf',
 | 
						|
        14525 => 'SNMP::Info::Layer2::Trapeze',
 | 
						|
        14988 => 'SNMP::Info::Layer3::Mikrotik',
 | 
						|
        17163 => 'SNMP::Info::Layer3::Steelhead',
 | 
						|
        25506 => 'SNMP::Info::Layer3::H3C',
 | 
						|
        26543 => 'SNMP::Info::Layer3::IBMGbTor',
 | 
						|
        30065 => 'SNMP::Info::Layer3::Arista',
 | 
						|
        35098 => 'SNMP::Info::Layer3::Pica8',
 | 
						|
    );
 | 
						|
 | 
						|
    my %l2sysoidmap = (
 | 
						|
        9     => 'SNMP::Info::Layer2::Cisco',
 | 
						|
        11    => 'SNMP::Info::Layer2::HP',
 | 
						|
        45    => 'SNMP::Info::Layer2::Baystack',
 | 
						|
        171   => 'SNMP::Info::Layer3::Dell',
 | 
						|
        207   => 'SNMP::Info::Layer2::Allied',
 | 
						|
        674   => 'SNMP::Info::Layer3::Dell',
 | 
						|
        1872  => 'SNMP::Info::Layer3::AlteonAD',
 | 
						|
        1916  => 'SNMP::Info::Layer3::Extreme',
 | 
						|
        1991  => 'SNMP::Info::Layer3::Foundry',
 | 
						|
        2272  => 'SNMP::Info::Layer3::Passport',
 | 
						|
        2925  => 'SNMP::Info::Layer1::Cyclades',
 | 
						|
        3224  => 'SNMP::Info::Layer3::Netscreen',
 | 
						|
        3375  => 'SNMP::Info::Layer3::F5',
 | 
						|
        4526  => 'SNMP::Info::Layer2::Netgear',
 | 
						|
        5624  => 'SNMP::Info::Layer3::Enterasys',
 | 
						|
        6486  => 'SNMP::Info::Layer3::AlcatelLucent',
 | 
						|
        11898 => 'SNMP::Info::Layer2::Orinoco',
 | 
						|
        14179 => 'SNMP::Info::Layer2::Airespace',
 | 
						|
        14525 => 'SNMP::Info::Layer2::Trapeze',
 | 
						|
        14823 => 'SNMP::Info::Layer3::Aruba',
 | 
						|
        17163 => 'SNMP::Info::Layer3::Steelhead',
 | 
						|
        26543 => 'SNMP::Info::Layer3::IBMGbTor',
 | 
						|
    );
 | 
						|
 | 
						|
    my %l7sysoidmap = (
 | 
						|
        318   => 'SNMP::Info::Layer7::APC',
 | 
						|
        5951  => 'SNMP::Info::Layer7::Netscaler',
 | 
						|
        14525 => 'SNMP::Info::Layer2::Trapeze',
 | 
						|
        12532 => 'SNMP::Info::Layer7::Neoteris',
 | 
						|
    );
 | 
						|
 | 
						|
    # Get just the enterprise number for generic mapping
 | 
						|
    $id = $1 if ( defined($id) && $id =~ /^\.1\.3\.6\.1\.4\.1\.(\d+)/ );
 | 
						|
 | 
						|
    if ($info->debug()) {
 | 
						|
        print "SNMP::Info $VERSION\n";
 | 
						|
        print "SNMP::Info::device_type() layers:$layers id:$id sysDescr:\"$desc\"\n";
 | 
						|
    }
 | 
						|
 | 
						|
    # Layer 3 Supported
 | 
						|
    #   (usually has layer2 as well, so we check for 3 first)
 | 
						|
    if ( $info->has_layer(3) ) {
 | 
						|
        $objtype = 'SNMP::Info::Layer3';
 | 
						|
 | 
						|
        # Device Type Overrides
 | 
						|
 | 
						|
        return $objtype unless ( defined $desc and length($desc) );
 | 
						|
 | 
						|
        $objtype = 'SNMP::Info::Layer3::C3550' if $desc =~ /(C3550|C3560)/;
 | 
						|
        $objtype = 'SNMP::Info::Layer3::C4000' if $desc =~ /Catalyst 4[05]00/;
 | 
						|
        $objtype = 'SNMP::Info::Layer3::Foundry' if $desc =~ /foundry/i;
 | 
						|
 | 
						|
        # Aironet - older non-IOS
 | 
						|
        $objtype = 'SNMP::Info::Layer3::Aironet'
 | 
						|
            if ($desc =~ /Cisco/
 | 
						|
            and $desc =~ /\D(CAP340|AP340|CAP350|350|1200)\D/ );
 | 
						|
        $objtype = 'SNMP::Info::Layer3::Aironet'
 | 
						|
            if ( $desc =~ /Aironet/ and $desc =~ /\D(AP4800)\D/ );
 | 
						|
 | 
						|
        # Cat6k with older SUPs (hybrid CatOS/IOS?)
 | 
						|
        $objtype = 'SNMP::Info::Layer3::C6500' if $desc =~ /(c6sup2|c6sup1)/;
 | 
						|
 | 
						|
        # Cat6k with Sup720, Sup720 or Sup2T (and Sup2 running native IOS?)
 | 
						|
        $objtype = 'SNMP::Info::Layer3::C6500'
 | 
						|
            if $desc =~ /(s72033_rp|s3223_rp|s32p3_rp|s222_rp|s2t54)/;
 | 
						|
 | 
						|
        # Next one untested. Reported working by DA
 | 
						|
        $objtype = 'SNMP::Info::Layer3::C6500'
 | 
						|
            if ( $desc =~ /cisco/i and $desc =~ /3750/ );
 | 
						|
 | 
						|
        # IOS 15.x on Catalyst 3850
 | 
						|
        $objtype = 'SNMP::Info::Layer3::C6500'
 | 
						|
            if ( $desc =~ /cisco/i and $desc =~ /CAT3K/ );
 | 
						|
 | 
						|
        #   Cisco 2970
 | 
						|
        $objtype = 'SNMP::Info::Layer3::C6500'
 | 
						|
            if ( $desc =~ /(C2970|C2960)/ );
 | 
						|
 | 
						|
        #   Cisco 3400 w/ Layer3 capable image
 | 
						|
        $objtype = 'SNMP::Info::Layer3::C3550'
 | 
						|
            if ( $desc =~ /(ME340x)/ );
 | 
						|
 | 
						|
        # Various Cisco blade switches, CBS30x0 and CBS31x0 models
 | 
						|
        $objtype = 'SNMP::Info::Layer3::C6500'
 | 
						|
            if ( $desc =~ /cisco/i and $desc =~ /CBS3[0-9A-Za-z]{3}/ );
 | 
						|
 | 
						|
        # Cisco Nexus running NX-OS
 | 
						|
        $objtype = 'SNMP::Info::Layer3::Nexus'
 | 
						|
            if ( $desc =~ /^Cisco\s+NX-OS/ );
 | 
						|
 | 
						|
        # HP, older ProCurve models (1600, 2400, 2424m, 4000, 8000)
 | 
						|
        $objtype = 'SNMP::Info::Layer2::HP4000'
 | 
						|
            if $desc =~ /\b(J4093A|J4110A|J4120A|J4121A|J4122A|J4122B)\b/;
 | 
						|
 | 
						|
        # HP, Foundry OEM
 | 
						|
        $objtype = 'SNMP::Info::Layer3::HP9300'
 | 
						|
            if $desc =~ /\b(J4874A|J4138A|J4139A|J4840A|J4841A)\b/;
 | 
						|
 | 
						|
        # Nortel ERS (Passport) 1600 Series < version 2.1
 | 
						|
        $objtype = 'SNMP::Info::Layer3::N1600'
 | 
						|
            if $desc =~ /(Passport|Ethernet\s+Routing\s+Switch)-16/i;
 | 
						|
 | 
						|
        #  ERS - BayStack Numbered
 | 
						|
        $objtype = 'SNMP::Info::Layer2::Baystack'
 | 
						|
            if ( $desc
 | 
						|
            =~ /^(BayStack|Ethernet\s+Routing\s+Switch)\s[2345](\d){2,3}/i );
 | 
						|
 | 
						|
        # Nortel Contivity
 | 
						|
        $objtype = 'SNMP::Info::Layer3::Contivity' if $desc =~ /(\bCES\b|\bNVR\sV\d)/;
 | 
						|
 | 
						|
        # SonicWALL
 | 
						|
        $objtype = 'SNMP::Info::Layer3::SonicWALL' if $desc =~ /SonicWALL/i;
 | 
						|
 | 
						|
        # Allied Telesis Layer2 managed switches. They report they have L3 support
 | 
						|
        $objtype = 'SNMP::Info::Layer2::Allied'
 | 
						|
            if ( $desc =~ /Allied.*AT-80\d{2}\S*/i );
 | 
						|
 | 
						|
        # Cisco ASA, newer versions which report layer 3 functionality
 | 
						|
        # version >= 8.2 are known to do this
 | 
						|
        $objtype = 'SNMP::Info::Layer3::CiscoASA'
 | 
						|
            if ( $desc =~ /Cisco Adaptive Security Appliance/i );
 | 
						|
 | 
						|
        # Cisco FWSM
 | 
						|
        $objtype = 'SNMP::Info::Layer3::CiscoFWSM'
 | 
						|
            if ( $desc =~ /Cisco Firewall Services Module/i );
 | 
						|
        
 | 
						|
        # Avaya Secure Router
 | 
						|
        $objtype = 'SNMP::Info::Layer3::Tasman'
 | 
						|
            if ( $desc =~ /^(avaya|nortel)\s+(SR|secure\srouter)\s+\d{4}/i );
 | 
						|
 | 
						|
        # HP Virtual Connect blade switches
 | 
						|
        $objtype = 'SNMP::Info::Layer2::HPVC'
 | 
						|
            if ( $desc =~ /HP\sVC\s/ );
 | 
						|
 | 
						|
        # Aironet - IOS
 | 
						|
        # Starting with IOS 15, Aironet reports sysServices 6, even though
 | 
						|
        # it still is the same layer2 access point.
 | 
						|
        $objtype = 'SNMP::Info::Layer2::Aironet'
 | 
						|
            if ($desc =~ /\b(C1100|C1130|C1140|AP1200|C350|C1200|C1240|C1250)\b/
 | 
						|
            and $desc =~ /\bIOS\b/ );
 | 
						|
 | 
						|
        # Generic device classification based upon sysObjectID
 | 
						|
        if (    ( $objtype eq 'SNMP::Info::Layer3' )
 | 
						|
            and ( defined($id) )
 | 
						|
            and ( exists( $l3sysoidmap{$id} ) ) )
 | 
						|
        {
 | 
						|
            $objtype = $l3sysoidmap{$id};
 | 
						|
        }
 | 
						|
 | 
						|
        # Layer 2 Supported
 | 
						|
    }
 | 
						|
    elsif ( $info->has_layer(2) ) {
 | 
						|
        $objtype = 'SNMP::Info::Layer2';
 | 
						|
 | 
						|
        return $objtype unless ( defined $desc and $desc !~ /^\s*$/ );
 | 
						|
 | 
						|
        # Device Type Overrides
 | 
						|
 | 
						|
        #   Catalyst 1900 series override
 | 
						|
        $objtype = 'SNMP::Info::Layer2::C1900'
 | 
						|
            if ( $desc =~ /catalyst/i and $desc =~ /\D19\d{2}/ );
 | 
						|
 | 
						|
        #   Catalyst 2900 and 3500XL (IOS) series override
 | 
						|
        $objtype = 'SNMP::Info::Layer2::C2900'
 | 
						|
            if ( $desc =~ /(C2900XL|C2950|C3500XL|C2940|CGESM|CIGESM)/i );
 | 
						|
 | 
						|
        #   Catalyst WS-C series override 2926,4k,5k,6k in Hybrid
 | 
						|
        $objtype = 'SNMP::Info::Layer2::Catalyst' if ( $desc =~ /WS-C\d{4}/ );
 | 
						|
 | 
						|
        #   Catalyst 3550 / 3548 Layer2 only switches
 | 
						|
        #   Cisco 3400 w/ MetroBase Image
 | 
						|
        $objtype = 'SNMP::Info::Layer3::C3550'
 | 
						|
            if ( $desc =~ /(C3550|ME340x)/ );
 | 
						|
 | 
						|
        # Cisco blade switches, CBS30x0 and CBS31x0 models with L2 only
 | 
						|
        $objtype = 'SNMP::Info::Layer3::C6500'
 | 
						|
            if ( $desc =~ /cisco/i and $desc =~ /CBS3[0-9A-Za-z]{3}/ );
 | 
						|
 | 
						|
        #   Cisco 2970
 | 
						|
        $objtype = 'SNMP::Info::Layer3::C6500'
 | 
						|
            if ( $desc =~ /(C2970|C2960)/ );
 | 
						|
 | 
						|
        #   Cisco Small Business (300 500) series override
 | 
						|
        #   This is for enterprises(1).cisco(9).otherEnterprises(6).ciscosb(1)
 | 
						|
        $objtype = 'SNMP::Info::Layer2::CiscoSB'
 | 
						|
            if ( $soid =~ /^\.1\.3\.6\.1\.4\.1\.9\.6\.1/ );
 | 
						|
        
 | 
						|
        # HP, older ProCurve models (1600, 2400, 2424m, 4000, 8000)
 | 
						|
        $objtype = 'SNMP::Info::Layer2::HP4000'
 | 
						|
            if $desc =~ /\b(J4093A|J4110A|J4120A|J4121A|J4122A|J4122B)\b/;
 | 
						|
 | 
						|
        # HP, Foundry OEM
 | 
						|
        $objtype = 'SNMP::Info::Layer3::HP9300'
 | 
						|
            if $desc =~ /\b(J4874A|J4138A|J4139A|J4840A|J4841A)\b/;
 | 
						|
 | 
						|
        # IBM BladeCenter 4-Port GB Ethernet Switch Module
 | 
						|
        $objtype = 'SNMP::Info::Layer3::Dell'
 | 
						|
            if ( $desc =~ /^IBM Gigabit Ethernet Switch Module$/ );
 | 
						|
 | 
						|
        # Linksys 2024/2048
 | 
						|
        $objtype = 'SNMP::Info::Layer3::Dell'
 | 
						|
            if (
 | 
						|
            $desc =~ /^(24|48)-Port 10\/100\/1000 Gigabit Switch (with |w\/)WebView$/ );
 | 
						|
 | 
						|
        #  Centillion ATM
 | 
						|
        $objtype = 'SNMP::Info::Layer2::Centillion' if ( $desc =~ /MCP/ );
 | 
						|
 | 
						|
        #  BPS
 | 
						|
        $objtype = 'SNMP::Info::Layer2::Baystack'
 | 
						|
            if ( $desc =~ /Business\sPolicy\sSwitch/i );
 | 
						|
 | 
						|
        #  BayStack Numbered
 | 
						|
        $objtype = 'SNMP::Info::Layer2::Baystack'
 | 
						|
            if ( $desc
 | 
						|
            =~ /^(BayStack|Ethernet\s+(Routing\s+)??Switch)\s[2345](\d){2,3}/i
 | 
						|
            );
 | 
						|
 | 
						|
        # Kentrox DataSMART DSU/CSU
 | 
						|
        $objtype = 'SNMP::Info::Layer2::Kentrox'
 | 
						|
            if ( $desc =~ /^DataSMART/i );
 | 
						|
 | 
						|
        #  Nortel Business Ethernet Switch
 | 
						|
        $objtype = 'SNMP::Info::Layer2::Baystack'
 | 
						|
            if ( $desc =~ /^Business Ethernet Switch\s[12]\d\d/i );
 | 
						|
 | 
						|
        #  Nortel AP 222X
 | 
						|
        $objtype = 'SNMP::Info::Layer2::NAP222x'
 | 
						|
            if ( $desc =~ /Access\s+Point\s+222/ );
 | 
						|
 | 
						|
        #  Orinoco
 | 
						|
        $objtype = 'SNMP::Info::Layer2::Orinoco'
 | 
						|
            if ( $desc =~ /(AP-\d{3}|WavePOINT)/ );
 | 
						|
 | 
						|
        #  Aironet - IOS
 | 
						|
        $objtype = 'SNMP::Info::Layer2::Aironet'
 | 
						|
            if ($desc =~ /\b(C1100|C1130|C1140|AP1200|C350|C1200|C1240|C1250)\b/
 | 
						|
            and $desc =~ /\bIOS\b/ );
 | 
						|
 | 
						|
        # Aironet - non IOS
 | 
						|
        $objtype = 'SNMP::Info::Layer3::Aironet'
 | 
						|
            if ( $desc =~ /Cisco/ and $desc =~ /\D(BR500)\D/ );
 | 
						|
 | 
						|
        # Airespace (WLC) Module
 | 
						|
        $objtype = 'SNMP::Info::Layer2::Airespace'
 | 
						|
            if ( $desc =~ /Cisco Controller/ );
 | 
						|
 | 
						|
        #Nortel 2270
 | 
						|
        $objtype = 'SNMP::Info::Layer2::N2270'
 | 
						|
            if (
 | 
						|
            $desc =~ /Nortel\s+(Networks\s+)??WLAN\s+-\s+Security\s+Switch/ );
 | 
						|
 | 
						|
        # HP Virtual Connect blade switches
 | 
						|
        $objtype = 'SNMP::Info::Layer2::HPVC'
 | 
						|
            if ( $desc =~ /HP\sVC\s/ );
 | 
						|
 | 
						|
        # Generic device classification based upon sysObjectID
 | 
						|
        if (    ( $objtype eq 'SNMP::Info::Layer2' )
 | 
						|
            and ( defined($id) )
 | 
						|
            and ( exists( $l2sysoidmap{$id} ) ) )
 | 
						|
        {
 | 
						|
            $objtype = $l2sysoidmap{$id};
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
    elsif ( $info->has_layer(1) ) {
 | 
						|
        $objtype = 'SNMP::Info::Layer1';
 | 
						|
 | 
						|
        #  Allied crap-o-hub
 | 
						|
        $objtype = 'SNMP::Info::Layer1::Allied' if ( $desc =~ /allied/i );
 | 
						|
        $objtype = 'SNMP::Info::Layer1::Asante' if ( $desc =~ /asante/i );
 | 
						|
 | 
						|
        #  Bay Hub
 | 
						|
        $objtype = 'SNMP::Info::Layer1::Bayhub'
 | 
						|
            if ( $desc =~ /\bNMM.*Agent/ );
 | 
						|
        $objtype = 'SNMP::Info::Layer1::Bayhub'
 | 
						|
            if ( $desc =~ /\bBay\s*Stack.*Hub/i );
 | 
						|
 | 
						|
        #  Synoptics Hub
 | 
						|
        #  This will override Bay Hub only for specific devices supported by this class
 | 
						|
        $objtype = 'SNMP::Info::Layer1::S3000'
 | 
						|
            if ( $desc =~ /\bNMM\s+(281|3000|3030)/i );
 | 
						|
 | 
						|
        # These devices don't claim to have Layer1-3 but we like em anyways.
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        $objtype = 'SNMP::Info::Layer2::ZyXEL_DSLAM'
 | 
						|
            if ( $desc =~ /8-port .DSL Module\(Annex .\)/i );
 | 
						|
 | 
						|
        # Aruba wireless switches
 | 
						|
        $objtype = 'SNMP::Info::Layer3::Aruba'
 | 
						|
            if ( $desc =~ /(ArubaOS|AirOS)/ );
 | 
						|
 | 
						|
        # Alcatel-Lucent branded Aruba
 | 
						|
        $objtype = 'SNMP::Info::Layer3::Aruba'
 | 
						|
            if ( $desc =~ /^AOS-W/ );
 | 
						|
 | 
						|
        # Cisco PIX
 | 
						|
        $objtype = 'SNMP::Info::Layer3::Cisco'
 | 
						|
            if ( $desc =~ /Cisco PIX Security Appliance/i );
 | 
						|
 | 
						|
        # Cisco ASA, older version which doesn't report layer 3 functionality
 | 
						|
        $objtype = 'SNMP::Info::Layer3::CiscoASA'
 | 
						|
            if ( $desc =~ /Cisco Adaptive Security Appliance/i );
 | 
						|
 | 
						|
        # HP Virtual Connect blade switches
 | 
						|
        $objtype = 'SNMP::Info::Layer2::HPVC'
 | 
						|
            if ( $desc =~ /HP\sVC\s/ );
 | 
						|
 | 
						|
        # Nortel (Trapeze) WSS 2300 Series
 | 
						|
        $objtype = 'SNMP::Info::Layer2::NWSS2300'    
 | 
						|
            if ( $desc =~ /\bWireless\sSecurity\sSwitch\s23[568][012]\b/);
 | 
						|
 | 
						|
        # Generic device classification based upon sysObjectID
 | 
						|
        if ( defined($id) and $objtype eq 'SNMP::Info') {
 | 
						|
            if ( defined $l3sysoidmap{$id} ) {
 | 
						|
                $objtype = $l3sysoidmap{$id};
 | 
						|
            } elsif ( defined $l2sysoidmap{$id}) {
 | 
						|
                $objtype = $l2sysoidmap{$id};
 | 
						|
            } elsif ( defined $l7sysoidmap{$id}) {
 | 
						|
                $objtype = $l7sysoidmap{$id};
 | 
						|
            } elsif ($info->has_layer(7)) {
 | 
						|
                $objtype = 'SNMP::Info::Layer7'
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return $objtype;
 | 
						|
}
 | 
						|
 | 
						|
=item $info->error(no_clear)
 | 
						|
 | 
						|
Returns Error message if there is an error, or undef if there is not.
 | 
						|
 | 
						|
Reading the error will clear the error unless you set the no_clear flag.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub error {
 | 
						|
    my $self     = shift;
 | 
						|
    my $no_clear = shift;
 | 
						|
    my $err      = $self->{error};
 | 
						|
 | 
						|
    $self->{error} = undef unless defined $no_clear and $no_clear;
 | 
						|
    return $err;
 | 
						|
}
 | 
						|
 | 
						|
=item $info->has_layer(3)
 | 
						|
 | 
						|
Returns non-zero if the device has the supplied layer in the OSI Model
 | 
						|
 | 
						|
Returns if the device doesn't support the layers() call.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub has_layer {
 | 
						|
    my $self      = shift;
 | 
						|
    my $check_for = shift;
 | 
						|
 | 
						|
    my $layers = $self->layers();
 | 
						|
    return unless defined $layers;
 | 
						|
    return unless length($layers);
 | 
						|
    return substr( $layers, 8 - $check_for, 1 );
 | 
						|
}
 | 
						|
 | 
						|
=item $info->snmp_comm()
 | 
						|
 | 
						|
Returns SNMP Community string used in connection.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub snmp_comm {
 | 
						|
    my $self = shift;
 | 
						|
    if ( $self->{snmp_ver} == 3 ) {
 | 
						|
        return $self->{snmp_user};
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        return $self->{snmp_comm};
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
=item $info->snmp_ver()
 | 
						|
 | 
						|
Returns SNMP Version used for this connection
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub snmp_ver {
 | 
						|
    my $self = shift;
 | 
						|
    return $self->{snmp_ver};
 | 
						|
}
 | 
						|
 | 
						|
=item $info->specify()
 | 
						|
 | 
						|
Returns an object of a more-specific subclass.  
 | 
						|
 | 
						|
 my $info = new SNMP::Info(...);
 | 
						|
 # Returns more specific object type
 | 
						|
 $info = $info->specific();
 | 
						|
 | 
						|
Usually this method is called internally from new(AutoSpecify => 1)
 | 
						|
 | 
						|
See device_type() entry for how a subclass is chosen.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub specify {
 | 
						|
    my $self = shift;
 | 
						|
 | 
						|
    my $device_type = $self->device_type();
 | 
						|
    unless ( defined $device_type ) {
 | 
						|
        $self->error_throw(
 | 
						|
            "SNMP::Info::specify() - Could not get info from device");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    return $self if $device_type eq 'SNMP::Info';
 | 
						|
 | 
						|
    # Load Subclass
 | 
						|
    # By evaling a string the contents of device_type now becomes a bareword.
 | 
						|
    eval "require $device_type;";    ## no critic
 | 
						|
    if ($@) {
 | 
						|
        croak "SNMP::Info::specify() Loading $device_type Failed. $@\n";
 | 
						|
    }
 | 
						|
 | 
						|
    my $args    = $self->args();
 | 
						|
    my $session = $self->session();
 | 
						|
    my $sub_obj = $device_type->new(
 | 
						|
        %$args,
 | 
						|
        'Session'     => $session,
 | 
						|
        'AutoSpecify' => 0
 | 
						|
    );
 | 
						|
 | 
						|
    unless ( defined $sub_obj ) {
 | 
						|
        $self->error_throw(
 | 
						|
            "SNMP::Info::specify() - Could not connect with new class ($device_type)"
 | 
						|
        );
 | 
						|
        return $self;
 | 
						|
    }
 | 
						|
 | 
						|
    $self->debug()
 | 
						|
        and print "SNMP::Info::specify() - Changed Class to $device_type.\n";
 | 
						|
    return $sub_obj;
 | 
						|
}
 | 
						|
 | 
						|
=item $info->cisco_comm_indexing()
 | 
						|
 | 
						|
Returns 0.  Is an overridable method used for vlan indexing for
 | 
						|
snmp calls on certain Cisco devices. 
 | 
						|
 | 
						|
See L<ftp://ftp.cisco.com/pub/mibs/supportlists/wsc5000/wsc5000-communityIndexing.html>
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub cisco_comm_indexing {
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head2 Globals (Scalar Methods)
 | 
						|
 | 
						|
These are methods to return scalar data from RFC1213.  
 | 
						|
 | 
						|
Some subset of these is probably available for any network device that speaks
 | 
						|
SNMP.
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item $info->uptime()
 | 
						|
 | 
						|
Uptime in hundredths of seconds since device became available.
 | 
						|
 | 
						|
(C<sysUpTime>)
 | 
						|
 | 
						|
=item $info->contact()
 | 
						|
 | 
						|
(C<sysContact>)
 | 
						|
 | 
						|
=item $info->name()
 | 
						|
 | 
						|
(C<sysName>)
 | 
						|
 | 
						|
=item $info->location() 
 | 
						|
 | 
						|
(C<sysLocation>)
 | 
						|
 | 
						|
=item $info->layers()
 | 
						|
 | 
						|
This returns a binary encoded string where each
 | 
						|
digit represents a layer of the OSI model served
 | 
						|
by the device.  
 | 
						|
 | 
						|
    eg: 01000010  means layers 2 (physical) and 7 (Application) 
 | 
						|
                  are served.
 | 
						|
 | 
						|
Note:  This string is 8 digits long.  
 | 
						|
 | 
						|
See $info->has_layer()
 | 
						|
 | 
						|
(C<sysServices>)
 | 
						|
 | 
						|
=item $info->ports()
 | 
						|
 | 
						|
Number of interfaces available on this device.
 | 
						|
 | 
						|
Not too useful as the number of SNMP interfaces usually does not 
 | 
						|
correspond with the number of physical ports
 | 
						|
 | 
						|
(C<ifNumber>)
 | 
						|
 | 
						|
=item $info->ipforwarding()
 | 
						|
 | 
						|
The indication of whether the entity is acting as an IP gateway
 | 
						|
 | 
						|
Returns either forwarding or not-forwarding
 | 
						|
 | 
						|
(C<ipForwarding>)
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head2 Table Methods
 | 
						|
 | 
						|
Each of these methods returns a hash_reference to a hash keyed on the
 | 
						|
interface index in SNMP.
 | 
						|
 | 
						|
Example : $info->interfaces() might return  
 | 
						|
 | 
						|
    { '1.12' => 'FastEthernet/0',
 | 
						|
      '2.15' => 'FastEthernet/1',
 | 
						|
      '9.99' => 'FastEthernet/2'
 | 
						|
    }
 | 
						|
 | 
						|
The key is what you would see if you were to do an snmpwalk, and in some cases
 | 
						|
changes between reboots of the network device.
 | 
						|
 | 
						|
=head2 Partial Table Fetches
 | 
						|
 | 
						|
If you want to get only a part of an SNMP table or a single instance from the
 | 
						|
table and you know the IID for the part of the table that you want, you can
 | 
						|
specify it in the call:
 | 
						|
 | 
						|
    $local_routes = $info->ipr_route('192.168.0');
 | 
						|
 | 
						|
This will only fetch entries in the table that start with C<192.168.0>, which
 | 
						|
in this case are routes on the local network. 
 | 
						|
 | 
						|
Remember that you must supply the partial IID (a numeric OID).
 | 
						|
 | 
						|
Partial table results are not cached.
 | 
						|
 | 
						|
=head2 Interface Information
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item $info->interfaces()
 | 
						|
 | 
						|
This methods is overridden in each subclass to provide a 
 | 
						|
mapping between the Interface Table Index (iid) and the physical port name.
 | 
						|
 | 
						|
=item $info->if_ignore()
 | 
						|
 | 
						|
Returns a reference to a hash where key values that exist are 
 | 
						|
interfaces to ignore.
 | 
						|
 | 
						|
Ignored interfaces are ones that are usually not physical ports or Virtual
 | 
						|
Lans (VLANs) such as the Loopback interface, or the CPU interface. 
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub if_ignore {
 | 
						|
    my %nothing;
 | 
						|
    return \%nothing;
 | 
						|
}
 | 
						|
 | 
						|
=item $info->bulkwalk_no()
 | 
						|
 | 
						|
Returns 0.  Is an overridable method used for turn off bulkwalk for the
 | 
						|
device class. 
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub bulkwalk_no {
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
=item $info->i_index()
 | 
						|
 | 
						|
Default SNMP IID to Interface index.
 | 
						|
 | 
						|
(C<ifIndex>)
 | 
						|
 | 
						|
=item $info->i_description() 
 | 
						|
 | 
						|
Description of the interface. Usually a little longer single word name that is
 | 
						|
both human and machine friendly.  Not always.
 | 
						|
 | 
						|
(C<ifDescr>)
 | 
						|
 | 
						|
=item $info->i_type()
 | 
						|
 | 
						|
Interface type, such as Vlan, Ethernet, Serial
 | 
						|
 | 
						|
(C<ifType>)
 | 
						|
 | 
						|
=item $info->i_mtu()
 | 
						|
 | 
						|
INTEGER. Interface MTU value.
 | 
						|
 | 
						|
(C<ifMtu>)
 | 
						|
 | 
						|
=item $info->i_speed()
 | 
						|
 | 
						|
Speed of the link, human format.  See munge_speed() later in document for
 | 
						|
details.
 | 
						|
 | 
						|
(C<ifSpeed>, C<ifHighSpeed> if necessary)
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub i_speed {
 | 
						|
    my $info    = shift;
 | 
						|
    my $partial = shift;
 | 
						|
 | 
						|
    my $i_speed = $info->orig_i_speed($partial);
 | 
						|
 | 
						|
    my $i_speed_high = undef;
 | 
						|
    foreach my $i ( keys %$i_speed ) {
 | 
						|
        if ( $i_speed->{$i} eq "4294967295" ) {
 | 
						|
            $i_speed_high = $info->i_speed_high($partial)
 | 
						|
                unless defined($i_speed_high);
 | 
						|
            $i_speed->{$i} = $i_speed_high->{$i} if ( $i_speed_high->{$i} );
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return $i_speed;
 | 
						|
}
 | 
						|
 | 
						|
=item $info->i_speed_raw()
 | 
						|
 | 
						|
Speed of the link in bits per second without munging.
 | 
						|
If i_speed_high is available it will be used and multiplied by 1_000_000.
 | 
						|
 | 
						|
(C<ifSpeed>, C<ifHighSpeed> if necessary)
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub i_speed_raw {
 | 
						|
    my $info    = shift;
 | 
						|
    my $partial = shift;
 | 
						|
 | 
						|
    # remove the speed formating
 | 
						|
    my $munge_i_speed = delete $info->{munge}{i_speed};
 | 
						|
    # also for highspeed interfaces e.g. TenGigabitEthernet
 | 
						|
    my $munge_i_speed_high = delete $info->{munge}{i_speed_high};
 | 
						|
 | 
						|
    my $i_speed_raw = $info->orig_i_speed($partial);
 | 
						|
 | 
						|
    my $i_speed_high = undef;
 | 
						|
    foreach my $i ( keys %$i_speed_raw ) {
 | 
						|
        if ( $i_speed_raw->{$i} eq "4294967295" ) {
 | 
						|
            $i_speed_high = $info->i_speed_high($partial)
 | 
						|
                unless defined($i_speed_high);
 | 
						|
            $i_speed_raw->{$i} = ( $i_speed_high->{$i} * 1_000_000 )
 | 
						|
                if ( $i_speed_high->{$i} );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # restore the speed formating
 | 
						|
    $info->{munge}{i_speed} = $munge_i_speed;
 | 
						|
    $info->{munge}{i_speed_high} = $munge_i_speed_high;
 | 
						|
 | 
						|
    return $i_speed_raw;
 | 
						|
}
 | 
						|
 | 
						|
=item $info->i_speed_high()
 | 
						|
 | 
						|
Speed of a high-speed link, human format.  See munge_highspeed() later in
 | 
						|
document for details.  You should not need to call this directly, as
 | 
						|
i_speed() will call it if it needs to.
 | 
						|
 | 
						|
(C<ifHighSpeed>)
 | 
						|
 | 
						|
=item $info->i_mac() 
 | 
						|
 | 
						|
MAC address of the interface.  Note this is just the MAC of the port, not
 | 
						|
anything connected to it.
 | 
						|
 | 
						|
(C<ifPhysAddress>)
 | 
						|
 | 
						|
=item $info->i_up() 
 | 
						|
 | 
						|
Link Status of the interface.  Typical values are 'up' and 'down'.
 | 
						|
 | 
						|
(C<ifOperStatus>)
 | 
						|
 | 
						|
=item $info->i_up_admin()
 | 
						|
 | 
						|
Administrative status of the port.  Typical values are 'enabled' and 'disabled'.
 | 
						|
 | 
						|
(C<ifAdminStatus>)
 | 
						|
 | 
						|
=item $info->i_lastchange()
 | 
						|
 | 
						|
The value of C<sysUpTime> when this port last changed states (up,down).
 | 
						|
 | 
						|
(C<ifLastChange>)
 | 
						|
 | 
						|
=item $info->i_name()
 | 
						|
 | 
						|
Interface Name field.  Supported by a smaller subset of devices, this fields
 | 
						|
is often human set.
 | 
						|
 | 
						|
(C<ifName>)
 | 
						|
 | 
						|
=item $info->i_alias()
 | 
						|
 | 
						|
Interface Name field.  For certain devices this is a more human friendly form
 | 
						|
of i_description().  For others it is a human set field like i_name().
 | 
						|
 | 
						|
(C<ifAlias>)
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head2 Interface Statistics
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item $info->i_octet_in(), $info->i_octets_out(),
 | 
						|
$info->i_octet_in64(), $info->i_octets_out64()
 | 
						|
 | 
						|
Bandwidth.
 | 
						|
 | 
						|
Number of octets sent/received on the interface including framing characters.
 | 
						|
 | 
						|
64 bit version may not exist on all devices. 
 | 
						|
 | 
						|
NOTE: To manipulate 64 bit counters you need to use Math::BigInt, since the
 | 
						|
values are too large for a normal Perl scalar.   Set the global
 | 
						|
$SNMP::Info::BIGINT to 1 , or pass the BigInt value to new() if you want
 | 
						|
SNMP::Info to do it for you.
 | 
						|
 | 
						|
 | 
						|
(C<ifInOctets>) (C<ifOutOctets>)
 | 
						|
(C<ifHCInOctets>) (C<ifHCOutOctets>)
 | 
						|
 | 
						|
=item $info->i_errors_in(), $info->i_errors_out()
 | 
						|
 | 
						|
Number of packets that contained an error preventing delivery.  See C<IF-MIB>
 | 
						|
for more info.
 | 
						|
 | 
						|
(C<ifInErrors>) (C<ifOutErrors>)
 | 
						|
 | 
						|
=item $info->i_pkts_ucast_in(), $info->i_pkts_ucast_out(),
 | 
						|
$info->i_pkts_ucast_in64(), $info->i_pkts_ucast_out64()
 | 
						|
 | 
						|
Number of packets not sent to a multicast or broadcast address.
 | 
						|
 | 
						|
64 bit version may not exist on all devices. 
 | 
						|
 | 
						|
(C<ifInUcastPkts>) (C<ifOutUcastPkts>)
 | 
						|
(C<ifHCInUcastPkts>) (C<ifHCOutUcastPkts>)
 | 
						|
 | 
						|
=item $info->i_pkts_nucast_in(), $info->i_pkts_nucast_out(),
 | 
						|
 | 
						|
Number of packets sent to a multicast or broadcast address.
 | 
						|
 | 
						|
These methods are deprecated by i_pkts_multi_in() and i_pkts_bcast_in()
 | 
						|
according to C<IF-MIB>.  Actual device usage may vary.
 | 
						|
 | 
						|
(C<ifInNUcastPkts>) (C<ifOutNUcastPkts>)
 | 
						|
 | 
						|
=item $info->i_pkts_multi_in() $info->i_pkts_multi_out(),
 | 
						|
$info->i_pkts_multi_in64(), $info->i_pkts_multi_out64()
 | 
						|
 | 
						|
Number of packets sent to a multicast address.
 | 
						|
 | 
						|
64 bit version may not exist on all devices. 
 | 
						|
 | 
						|
(C<ifInMulticastPkts>) (C<ifOutMulticastPkts>)
 | 
						|
(C<ifHCInMulticastPkts>) (C<ifHCOutMulticastPkts>)
 | 
						|
 | 
						|
=item $info->i_pkts_bcast_in() $info->i_pkts_bcast_out(),
 | 
						|
$info->i_pkts_bcast_in64() $info->i_pkts_bcast_out64()
 | 
						|
 | 
						|
Number of packets sent to a broadcast address on an interface.
 | 
						|
 | 
						|
64 bit version may not exist on all devices. 
 | 
						|
 | 
						|
(C<ifInBroadcastPkts>) (C<ifOutBroadcastPkts>)
 | 
						|
(C<ifHCInBroadcastPkts>) (C<ifHCOutBroadcastPkts>)
 | 
						|
 | 
						|
=item $info->i_discards_in() $info->i_discards_out()
 | 
						|
 | 
						|
"The number of inbound packets which were chosen to be discarded even though
 | 
						|
no errors had been detected to prevent their being deliverable to a
 | 
						|
higher-layer protocol.  One possible reason for discarding such a packet could
 | 
						|
be to free up buffer space."  (C<IF-MIB>)
 | 
						|
 | 
						|
(C<ifInDiscards>) (C<ifOutDiscards>)
 | 
						|
 | 
						|
=item $info->i_bad_proto_in()
 | 
						|
 | 
						|
"For packet-oriented interfaces, the number of packets received via the
 | 
						|
interface which were discarded because of an unknown or unsupported protocol.
 | 
						|
For character-oriented or fixed-length interfaces that support protocol
 | 
						|
multiplexing the number of transmission units received via the interface which
 | 
						|
were discarded because of an unknown or unsupported protocol.  For any
 | 
						|
interface that does not support protocol multiplexing, this counter will always
 | 
						|
be 0."
 | 
						|
 | 
						|
(C<ifInUnknownProtos>)
 | 
						|
 | 
						|
=item $info->i_qlen_out()
 | 
						|
 | 
						|
"The length of the output packet queue (in packets)."
 | 
						|
 | 
						|
(C<ifOutQLen>)
 | 
						|
 | 
						|
=item $info->i_specific()
 | 
						|
 | 
						|
See C<IF-MIB> for full description
 | 
						|
 | 
						|
(C<ifSpecific>)
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head2 IP Address Table
 | 
						|
 | 
						|
Each entry in this table is an IP address in use on this device.  Usually 
 | 
						|
this is implemented in Layer3 Devices.
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item $info->ip_index()
 | 
						|
 | 
						|
Maps the IP Table to the IID
 | 
						|
 | 
						|
(C<ipAdEntIfIndex>)
 | 
						|
 | 
						|
=item $info->ip_table()
 | 
						|
 | 
						|
Maps the Table to the IP address
 | 
						|
 | 
						|
(C<ipAdEntAddr>)
 | 
						|
 | 
						|
=item $info->ip_netmask()
 | 
						|
 | 
						|
Gives netmask setting for IP table entry.
 | 
						|
 | 
						|
(C<ipAdEntNetMask>)
 | 
						|
 | 
						|
=item $info->ip_broadcast()
 | 
						|
 | 
						|
Gives broadcast address for IP table entry.
 | 
						|
 | 
						|
(C<ipAdEntBcastAddr>)
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head2 IP Routing Table
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item $info->ipr_route()
 | 
						|
 | 
						|
The route in question.  A value of 0.0.0.0 is the default gateway route.
 | 
						|
 | 
						|
(C<ipRouteDest>)
 | 
						|
 | 
						|
=item $info->ipr_if()
 | 
						|
 | 
						|
The interface (IID) that the route is on.  Use interfaces() to map.
 | 
						|
 | 
						|
(C<ipRouteIfIndex>)
 | 
						|
 | 
						|
=item $info->ipr_1()
 | 
						|
 | 
						|
Primary routing metric for this route. 
 | 
						|
 | 
						|
(C<ipRouteMetric1>)
 | 
						|
 | 
						|
=item $info->ipr_2()
 | 
						|
 | 
						|
If metrics are not used, they should be set to -1
 | 
						|
 | 
						|
(C<ipRouteMetric2>)
 | 
						|
 | 
						|
=item $info->ipr_3()
 | 
						|
 | 
						|
(C<ipRouteMetric3>)
 | 
						|
 | 
						|
=item $info->ipr_4()
 | 
						|
 | 
						|
(C<ipRouteMetric4>)
 | 
						|
 | 
						|
=item $info->ipr_5()
 | 
						|
 | 
						|
(C<ipRouteMetric5>)
 | 
						|
 | 
						|
=item $info->ipr_dest()
 | 
						|
 | 
						|
From RFC1213:
 | 
						|
 | 
						|
  "The IP address of the next hop of this route.
 | 
						|
  (In the case of a route bound to an interface
 | 
						|
  which is realized via a broadcast media, the value
 | 
						|
  of this field is the agent's IP address on that
 | 
						|
  interface.)"
 | 
						|
 | 
						|
(C<ipRouteNextHop>)
 | 
						|
 | 
						|
=item $info->ipr_type()
 | 
						|
 | 
						|
From RFC1213:
 | 
						|
 | 
						|
    other(1),        -- none of the following
 | 
						|
    invalid(2),      -- an invalidated route
 | 
						|
                     -- route to directly
 | 
						|
    direct(3),       -- connected (sub-)network
 | 
						|
                     -- route to a non-local
 | 
						|
    indirect(4)      -- host/network/sub-network
 | 
						|
 | 
						|
 | 
						|
      "The type of route.  Note that the values
 | 
						|
      direct(3) and indirect(4) refer to the notion of
 | 
						|
      direct and indirect routing in the IP
 | 
						|
      architecture.
 | 
						|
 | 
						|
      Setting this object to the value invalid(2) has
 | 
						|
      the effect of invalidating the corresponding entry
 | 
						|
      in the ipRouteTable object.  That is, it
 | 
						|
      effectively disassociates the destination
 | 
						|
      identified with said entry from the route
 | 
						|
      identified with said entry.  It is an
 | 
						|
      implementation-specific matter as to whether the
 | 
						|
      agent removes an invalidated entry from the table.
 | 
						|
      Accordingly, management stations must be prepared
 | 
						|
      to receive tabular information from agents that
 | 
						|
      corresponds to entries not currently in use.
 | 
						|
      Proper interpretation of such entries requires
 | 
						|
      examination of the relevant ipRouteType object."
 | 
						|
 | 
						|
(C<ipRouteType>)
 | 
						|
 | 
						|
=item $info->ipr_proto()
 | 
						|
 | 
						|
From RFC1213:
 | 
						|
 | 
						|
    other(1),       -- none of the following
 | 
						|
                    -- non-protocol information,
 | 
						|
                    -- e.g., manually configured
 | 
						|
    local(2),       -- entries
 | 
						|
                    -- set via a network
 | 
						|
    netmgmt(3),     -- management protocol
 | 
						|
                    -- obtained via ICMP,
 | 
						|
    icmp(4),        -- e.g., Redirect
 | 
						|
                    -- the remaining values are
 | 
						|
                    -- all gateway routing
 | 
						|
                    -- protocols
 | 
						|
    egp(5),
 | 
						|
    ggp(6),
 | 
						|
    hello(7),
 | 
						|
    rip(8),
 | 
						|
    is-is(9),
 | 
						|
    es-is(10),
 | 
						|
    ciscoIgrp(11),
 | 
						|
    bbnSpfIgp(12),
 | 
						|
    ospf(13),
 | 
						|
    bgp(14)
 | 
						|
 | 
						|
(C<ipRouteProto>)
 | 
						|
 | 
						|
=item $info->ipr_age()
 | 
						|
 | 
						|
Seconds since route was last updated or validated.
 | 
						|
 | 
						|
(C<ipRouteAge>)
 | 
						|
 | 
						|
=item $info->ipr_mask()
 | 
						|
 | 
						|
Subnet Mask of route. 0.0.0.0 for default gateway.
 | 
						|
 | 
						|
(C<ipRouteMask>)
 | 
						|
 | 
						|
=item $info->ipr_info()
 | 
						|
 | 
						|
Reference to MIB definition specific to routing protocol.
 | 
						|
 | 
						|
(C<ipRouteInfo>)
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head2 Topology Information
 | 
						|
 | 
						|
Based upon the manufacturer and software version devices may support some 
 | 
						|
combination of Layer 2 topology protocol information.  SNMP::Info
 | 
						|
supports querying Link Layer Discovery Protocol (LLDP), Cisco Discovery
 | 
						|
Protocol (CDP), SynOptics/Bay/Nortel/Avaya Network Management Protocol
 | 
						|
(SONMP), Foundry/Brocade Discovery Protocol (FDP), Extreme Discovery
 | 
						|
Protocol (EDP), and Alcatel Mapping Adjacency Protocol (AMAP). 
 | 
						|
 | 
						|
For protocol specific information and implementation:
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item LLDP: See L<SNMP::Info::LLDP> for details.
 | 
						|
 | 
						|
=item CDP: See L<SNMP::Info::CDP> for details.
 | 
						|
 | 
						|
=item SONMP: See L<SNMP::Info::SONMP> for details.
 | 
						|
 | 
						|
=item FDP: See L<SNMP::Info::FDP> for details.
 | 
						|
 | 
						|
=item EDP: See L<SNMP::Info::EDP> for details.
 | 
						|
 | 
						|
=item AMAP: See L<SNMP::Info::AMAP> for details.
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head3 Topology Capabilities
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item $info->has_topo()
 | 
						|
 | 
						|
Reports Layer 2 topology protocols which are supported and running on
 | 
						|
a device.
 | 
						|
 | 
						|
Returns either a reference to an array of protocols, possible values
 | 
						|
being: C<lldp>, C<cdp>, C<sonmp>, C<fdp>, C<edp>, C<amap> or C<undef> if
 | 
						|
no protocols are supported or running.
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub has_topo {
 | 
						|
    my $self = shift;
 | 
						|
 | 
						|
    my @topo_cap;
 | 
						|
    push( @topo_cap, 'lldp' )
 | 
						|
        if ( $self->can('hasLLDP') && $self->hasLLDP() );
 | 
						|
    push( @topo_cap, 'cdp' ) if $self->can('hasCDP') && $self->hasCDP();
 | 
						|
    push( @topo_cap, 'sonmp' )
 | 
						|
        if $self->can('hasSONMP') && $self->hasSONMP();
 | 
						|
    push( @topo_cap, 'fdp' ) if $self->can('hasFDP') && $self->hasFDP();
 | 
						|
    push( @topo_cap, 'edp' ) if $self->can('hasEDP') && $self->hasEDP();
 | 
						|
    push( @topo_cap, 'amap' ) if $self->can('hasAMAP') && $self->hasAMAP();
 | 
						|
 | 
						|
    if (@topo_cap) {
 | 
						|
        return \@topo_cap;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub _get_topo_data {
 | 
						|
    my $self     = shift;
 | 
						|
    my $partial  = shift;
 | 
						|
    my $topo_cap = shift;
 | 
						|
    my $method   = shift;
 | 
						|
 | 
						|
    return unless $method =~ /(ip|if|port|id|platform|cap)/;
 | 
						|
 | 
						|
    my %t_data;
 | 
						|
    foreach my $proto (@$topo_cap) {
 | 
						|
        next unless $proto =~ /(lldp|cdp|sonmp|fdp|edp|amap)/;
 | 
						|
        my $method_name = "$proto" . "_$method";
 | 
						|
        my $cdp = $self->$method_name($partial) || {};
 | 
						|
 | 
						|
        foreach my $iid ( keys %$cdp ) {
 | 
						|
            my $ip = $cdp->{$iid};
 | 
						|
            next unless defined $ip;
 | 
						|
 | 
						|
            $t_data{$iid} = $ip;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return \%t_data; 
 | 
						|
}
 | 
						|
 | 
						|
=head3 Common Topology Table Information
 | 
						|
 | 
						|
The common topology table methods below will query the
 | 
						|
device for information from the specified topology protocols and return a
 | 
						|
single hash combining all information. As a result, there may be identical
 | 
						|
topology information returned from the two protocols causing duplicate
 | 
						|
entries.  It is the calling program's responsibility to identify any
 | 
						|
duplicate entries and remove duplicates if necessary.  If it is necessary
 | 
						|
to understand which protocol provided the information, utilize the protocol
 | 
						|
specific methods directly rather than the generic methods.
 | 
						|
 | 
						|
The methods support partial table fetches by providing a partial as the
 | 
						|
first argument.
 | 
						|
 | 
						|
If a reference to an array is provided as the second argument, those
 | 
						|
protocols will be queried for information.  The supported array values are:
 | 
						|
C<lldp>, C<cdp>, C<sonmp>, C<fdp>, C<edp>, C<amap>.
 | 
						|
 | 
						|
If nothing is passed in as the second argument, the methods will call
 | 
						|
has_topo() to determine supported and running topology protocols on the
 | 
						|
device. 
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item $info->c_ip(partial, topology_protocol_arrayref)
 | 
						|
 | 
						|
Returns reference to hash.  Key: iid, Value: remote IPv4 address
 | 
						|
 | 
						|
If multiple entries exist with the same local port, c_if(), with the
 | 
						|
same IPv4 address, c_ip(), it may be a duplicate entry.
 | 
						|
 | 
						|
If multiple entries exist with the same local port, c_if(), with different
 | 
						|
IPv4 addresses, c_ip(), there is either a device in between two or
 | 
						|
more devices utilizing a different topology protocol or multiple devices
 | 
						|
which are not directly connected.  
 | 
						|
 | 
						|
Use the protocol specific methods to dig deeper.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub c_ip {
 | 
						|
    my $self     = shift;
 | 
						|
    my $partial  = shift;
 | 
						|
    my $topo_cap = shift;
 | 
						|
 | 
						|
    # Default to old behavior if not called with topo_cap
 | 
						|
    if ( !$topo_cap ) {
 | 
						|
        my $topo_test = $self->has_topo();
 | 
						|
        if ($topo_test) {
 | 
						|
            $topo_cap = $topo_test;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return _get_topo_data ($self, $partial, $topo_cap, 'ip');
 | 
						|
}
 | 
						|
 | 
						|
=item $info->c_if(partial, topology_protocol_arrayref)
 | 
						|
 | 
						|
Returns reference to hash.  Key: iid, Value: local device port (interfaces)
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub c_if {
 | 
						|
    my $self     = shift;
 | 
						|
    my $partial  = shift;
 | 
						|
    my $topo_cap = shift;
 | 
						|
 | 
						|
    # Default to old behavior if not called with topo_cap
 | 
						|
    if ( !$topo_cap ) {
 | 
						|
        my $topo_test = $self->has_topo();
 | 
						|
        if ($topo_test) {
 | 
						|
            $topo_cap = $topo_test;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return _get_topo_data ($self, $partial, $topo_cap, 'if');
 | 
						|
}
 | 
						|
 | 
						|
=item $info->c_port(partial, topology_protocol_arrayref)
 | 
						|
 | 
						|
Returns reference to hash. Key: iid, Value: remote port (interfaces)
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub c_port {
 | 
						|
    my $self     = shift;
 | 
						|
    my $partial  = shift;
 | 
						|
    my $topo_cap = shift;
 | 
						|
 | 
						|
    # Default to old behavior if not called with topo_cap
 | 
						|
    if ( !$topo_cap ) {
 | 
						|
        my $topo_test = $self->has_topo();
 | 
						|
        if ($topo_test) {
 | 
						|
            $topo_cap = $topo_test;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return _get_topo_data ($self, $partial, $topo_cap, 'port');
 | 
						|
}
 | 
						|
 | 
						|
=item $info->c_id(partial, topology_protocol_arrayref)
 | 
						|
 | 
						|
Returns reference to hash. Key: iid, Value: string value used to identify the
 | 
						|
chassis component associated with the remote system.
 | 
						|
 | 
						|
Note: SONMP does not return this information.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub c_id {
 | 
						|
    my $self     = shift;
 | 
						|
    my $partial  = shift;
 | 
						|
    my $topo_cap = shift;
 | 
						|
 | 
						|
    # Default to old behavior if not called with topo_cap
 | 
						|
    if ( !$topo_cap ) {
 | 
						|
        my $topo_test = $self->has_topo();
 | 
						|
        if ($topo_test) {
 | 
						|
            $topo_cap = $topo_test;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return _get_topo_data ($self, $partial, $topo_cap, 'id');
 | 
						|
}
 | 
						|
 | 
						|
=item $info->c_platform(partial, topology_protocol_arrayref)
 | 
						|
 | 
						|
Returns reference to hash.  Key: iid, Value: Remote Device Type
 | 
						|
 | 
						|
Note:  EDP does not provide this information.  LLDP uses (C<lldpRemSysDesc>)
 | 
						|
or C<lldp_rem_sysname> as the closest match.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub c_platform {
 | 
						|
    my $self     = shift;
 | 
						|
    my $partial  = shift;
 | 
						|
    my $topo_cap = shift;
 | 
						|
 | 
						|
    # Default to old behavior if not called with topo_cap
 | 
						|
    if ( !$topo_cap ) {
 | 
						|
        my $topo_test = $self->has_topo();
 | 
						|
        if ($topo_test) {
 | 
						|
            $topo_cap = $topo_test;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return _get_topo_data ($self, $partial, $topo_cap, 'platform');
 | 
						|
}
 | 
						|
 | 
						|
=item $info->c_cap(partial, topology_protocol_arrayref)
 | 
						|
 | 
						|
Returns reference to hash of arrays.  Key: iid, Value: Array of capabilities 
 | 
						|
supported by the device.  See the specific protocol class for string values
 | 
						|
which could be elements within the array. 
 | 
						|
 | 
						|
Note:  Only CDP and LLDP support this method.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub c_cap {
 | 
						|
    my $self     = shift;
 | 
						|
    my $partial  = shift;
 | 
						|
    my $topo_cap = shift;
 | 
						|
 | 
						|
    # Default to old behavior if not called with topo_cap
 | 
						|
    if ( !$topo_cap ) {
 | 
						|
        my $topo_test = $self->has_topo();
 | 
						|
        if ($topo_test) {
 | 
						|
            $topo_cap = $topo_test;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return _get_topo_data ($self, $partial, $topo_cap, 'cap');
 | 
						|
}
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head1 SETTING DATA VIA SNMP
 | 
						|
 | 
						|
This section explains how to use SNMP::Info to do SNMP Set operations.
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item $info->set_METHOD($value)
 | 
						|
 | 
						|
Sets the global METHOD to value.  Assumes that iid is .0
 | 
						|
 | 
						|
Returns if failed, or the return value from SNMP::Session::set() (snmp_errno)
 | 
						|
 | 
						|
 $info->set_location("Here!");
 | 
						|
 | 
						|
=item $info->set_METHOD($value,$iid)
 | 
						|
 | 
						|
Table Methods. Set iid of method to value. 
 | 
						|
 | 
						|
Returns if failed, or the return value from SNMP::Session::set() (snmp_errno)
 | 
						|
 | 
						|
 # Disable a port administratively
 | 
						|
 my %if_map = reverse %{$info->interfaces()}
 | 
						|
 $info->set_i_up_admin('down', $if_map{'FastEthernet0/0'}) 
 | 
						|
    or die "Couldn't disable the port. ",$info->error(1);
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
NOTE: You must be connected to your device with a C<ReadWrite> community
 | 
						|
string in order for set operations to work.
 | 
						|
 | 
						|
NOTE: This will only set data listed in %FUNCS and %GLOBALS.  For data
 | 
						|
acquired from overridden methods (subroutines) specific set_METHOD()
 | 
						|
subroutines will need to be added if they haven't been already.
 | 
						|
 | 
						|
=head1 Quiet Mode
 | 
						|
 | 
						|
SNMP::Info will not chirp anything to STDOUT unless there is a serious error
 | 
						|
(in which case it will probably die).
 | 
						|
 | 
						|
To get lots of debug info, set the Debug flag when calling new() or
 | 
						|
call $info->debug(1);
 | 
						|
 | 
						|
When calling a method check the return value.  If the return value is undef
 | 
						|
then check $info->error()
 | 
						|
 | 
						|
Beware, calling $info->error() clears the error.
 | 
						|
 | 
						|
 my $name = $info->name() or die "Couldn't get sysName!" . $name->error();
 | 
						|
 | 
						|
=head1 EXTENDING SNMP::INFO
 | 
						|
 | 
						|
To support a new class (vendor or platform) of device, add a Perl package with
 | 
						|
the data structures and methods listed below.
 | 
						|
 | 
						|
If this seems a little scary, then the SNMP::Info developers are usually happy
 | 
						|
to accept the SNMP data from your device and make an attempt at the class
 | 
						|
themselves. Usually a "beta" release will go to CPAN for you to verify the
 | 
						|
implementation.
 | 
						|
 | 
						|
=head2 Gathering MIB data for SNMP::Info Developers
 | 
						|
 | 
						|
The preference is to open a feature request in the SourceForge project.  This
 | 
						|
allows all developers to have visibility into the request.  Please include
 | 
						|
pointers to the applicable platform MIBs.  For development we will need an
 | 
						|
C<snmpwalk> of the device.  There is a tool now included in the SNMP::Info
 | 
						|
distribution to help with this task, although you'll most likely need to
 | 
						|
download the distribution from CPAN as it's included in the "C<t/util>"
 | 
						|
directory.
 | 
						|
 | 
						|
The utility is named C<make_snmpdata.pl>. Run it with a command line like:
 | 
						|
 | 
						|
 ./make_snmpdata.pl -c community -i -d device_ip \
 | 
						|
  -m /home/netdisco-mibs/rfc:/home/netdisco-mibs/net-snmp:/home/netdisco-mibs/dir3 \
 | 
						|
  SNMPv2-MIB IF-MIB EtherLike-MIB BRIDGE-MIB Q-BRIDGE-MIB ENTITY-MIB \
 | 
						|
  POWER-ETHERNET-MIB IPV6-MIB LLDP-MIB DEVICE-SPECIFIC-MIB-NAME(s) > output.txt
 | 
						|
 | 
						|
This will print to the file every MIB entry with data in a format that the
 | 
						|
developers can use to emulate read operations without needing access to the
 | 
						|
device.  Preference would be to mask any sensitive data in the output, zip the
 | 
						|
file, and upload as an attachment to the Sourceforge tracker.  However, if you
 | 
						|
do not feel comfortable  uploading the output to the tracker you could e-mail
 | 
						|
it to the developer that has claimed the ticket.
 | 
						|
 | 
						|
=head2 Data Structures required in new Subclass
 | 
						|
 | 
						|
A class inheriting this class must implement these data structures : 
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item  $INIT
 | 
						|
 | 
						|
Used to flag if the MIBs have been loaded yet.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
$INIT = 0;
 | 
						|
 | 
						|
=item %GLOBALS
 | 
						|
 | 
						|
Contains a hash in the form ( method_name => SNMP MIB leaf name )
 | 
						|
These are scalar values such as name, uptime, etc. 
 | 
						|
 | 
						|
To resolve MIB leaf name conflicts between private MIBs, you may prefix the
 | 
						|
leaf name with the MIB replacing each - (dash) and : (colon) with
 | 
						|
an _ (underscore).  For example, ALTEON_TIGON_SWITCH_MIB__agSoftwareVersion
 | 
						|
would be used as the hash value instead of the net-snmp notation
 | 
						|
ALTEON-TIGON-SWITCH-MIB::agSoftwareVersion.
 | 
						|
 | 
						|
When choosing the name for the methods, be aware that other new
 | 
						|
Sub Modules might inherit this one to get it's features.  Try to
 | 
						|
choose a prefix for methods that will give it's own name space inside
 | 
						|
the SNMP::Info methods.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
%GLOBALS = (
 | 
						|
 | 
						|
    # from SNMPv2-MIB
 | 
						|
    'id'           => 'sysObjectID',
 | 
						|
    'description'  => 'sysDescr',
 | 
						|
    'uptime'       => 'sysUpTime',
 | 
						|
    'contact'      => 'sysContact',
 | 
						|
    'name'         => 'sysName',
 | 
						|
    'location'     => 'sysLocation',
 | 
						|
    'layers'       => 'sysServices',
 | 
						|
    'ports'        => 'ifNumber',
 | 
						|
    'ipforwarding' => 'ipForwarding',
 | 
						|
);
 | 
						|
 | 
						|
=item %FUNCS
 | 
						|
 | 
						|
Contains a hash in the form ( method_name => SNMP MIB leaf name)
 | 
						|
These are table entries, such as the C<ifIndex>
 | 
						|
 | 
						|
To resolve MIB leaf name conflicts between private MIBs, you may prefix the
 | 
						|
leaf name with the MIB replacing each - (dash) and : (colon) with
 | 
						|
an _ (underscore).  For example, ALTEON_TS_PHYSICAL_MIB__agPortCurCfgPortName
 | 
						|
would be used as the hash value instead of the net-snmp notation
 | 
						|
ALTEON-TS-PHYSICAL-MIB::agPortCurCfgPortName.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
%FUNCS = (
 | 
						|
    'interfaces' => 'ifIndex',
 | 
						|
    'i_name'     => 'ifName',
 | 
						|
 | 
						|
    # IF-MIB::IfEntry
 | 
						|
    'i_index'           => 'ifIndex',
 | 
						|
    'i_description'     => 'ifDescr',
 | 
						|
    'i_type'            => 'ifType',
 | 
						|
    'i_mtu'             => 'ifMtu',
 | 
						|
    'i_speed'           => 'ifSpeed',
 | 
						|
    'i_mac'             => 'ifPhysAddress',
 | 
						|
    'i_up_admin'        => 'ifAdminStatus',
 | 
						|
    'i_up'              => 'ifOperStatus',
 | 
						|
    'i_lastchange'      => 'ifLastChange',
 | 
						|
    'i_octet_in'        => 'ifInOctets',
 | 
						|
    'i_pkts_ucast_in'   => 'ifInUcastPkts',
 | 
						|
    'i_pkts_nucast_in'  => 'ifInNUcastPkts',
 | 
						|
    'i_discards_in'     => 'ifInDiscards',
 | 
						|
    'i_errors_in'       => 'ifInErrors',
 | 
						|
    'i_bad_proto_in'    => 'ifInUnknownProtos',
 | 
						|
    'i_octet_out'       => 'ifOutOctets',
 | 
						|
    'i_pkts_ucast_out'  => 'ifOutUcastPkts',
 | 
						|
    'i_pkts_nucast_out' => 'ifOutNUcastPkts',
 | 
						|
    'i_discards_out'    => 'ifOutDiscards',
 | 
						|
    'i_errors_out'      => 'ifOutErrors',
 | 
						|
    'i_qlen_out'        => 'ifOutQLen',
 | 
						|
    'i_specific'        => 'ifSpecific',
 | 
						|
 | 
						|
    # IF-MIB::IfStackTable
 | 
						|
    'i_stack_status'    => 'ifStackStatus',
 | 
						|
 | 
						|
    # IP Address Table
 | 
						|
    'ip_index'     => 'ipAdEntIfIndex',
 | 
						|
    'ip_table'     => 'ipAdEntAddr',
 | 
						|
    'ip_netmask'   => 'ipAdEntNetMask',
 | 
						|
    'ip_broadcast' => 'ipAdEntBcastAddr',
 | 
						|
 | 
						|
    # ifXTable - Extension Table
 | 
						|
    'i_speed_high'       => 'ifHighSpeed',
 | 
						|
    'i_pkts_multi_in'    => 'ifInMulticastPkts',
 | 
						|
    'i_pkts_multi_out'   => 'ifOutMulticastPkts',
 | 
						|
    'i_pkts_bcast_in'    => 'ifInBroadcastPkts',
 | 
						|
    'i_pkts_bcast_out'   => 'ifOutBroadcastPkts',
 | 
						|
    'i_octet_in64'       => 'ifHCInOctets',
 | 
						|
    'i_octet_out64'      => 'ifHCOutOctets',
 | 
						|
    'i_pkts_ucast_in64'  => 'ifHCInUcastPkts',
 | 
						|
    'i_pkts_ucast_out64' => 'ifHCOutUcastPkts',
 | 
						|
    'i_pkts_multi_in64'  => 'ifHCInMulticastPkts',
 | 
						|
    'i_pkts_multi_out64' => 'ifHCOutMulticastPkts',
 | 
						|
    'i_pkts_bcast_in64'  => 'ifHCInBroadcastPkts',
 | 
						|
    'i_pkts_bcast_out64' => 'ifHCOutBroadcastPkts',
 | 
						|
    'i_alias'            => 'ifAlias',
 | 
						|
 | 
						|
    # IP Routing Table
 | 
						|
    'ipr_route' => 'ipRouteDest',
 | 
						|
    'ipr_if'    => 'ipRouteIfIndex',
 | 
						|
    'ipr_1'     => 'ipRouteMetric1',
 | 
						|
    'ipr_2'     => 'ipRouteMetric2',
 | 
						|
    'ipr_3'     => 'ipRouteMetric3',
 | 
						|
    'ipr_4'     => 'ipRouteMetric4',
 | 
						|
    'ipr_5'     => 'ipRouteMetric5',
 | 
						|
    'ipr_dest'  => 'ipRouteNextHop',
 | 
						|
    'ipr_type'  => 'ipRouteType',
 | 
						|
    'ipr_proto' => 'ipRouteProto',
 | 
						|
    'ipr_age'   => 'ipRouteAge',
 | 
						|
    'ipr_mask'  => 'ipRouteMask',
 | 
						|
    'ipr_info'  => 'ipRouteInfo',
 | 
						|
);
 | 
						|
 | 
						|
=item %MIBS
 | 
						|
 | 
						|
A list of each mib needed.  
 | 
						|
 | 
						|
    ('MIB-NAME' => 'itemToTestForPresence')
 | 
						|
 | 
						|
The value for each entry should be a MIB object to check for to make sure 
 | 
						|
that the MIB is present and has loaded correctly. 
 | 
						|
 | 
						|
$info->init() will throw an exception if a MIB does not load. 
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
%MIBS = (
 | 
						|
 | 
						|
    # The "main" MIBs are automagically loaded in Net-SNMP now.
 | 
						|
);
 | 
						|
 | 
						|
=item %MUNGE
 | 
						|
 | 
						|
A map between method calls (from %FUNCS or %GLOBALS) and subroutine methods.
 | 
						|
The subroutine called will be passed the data as it gets it from SNMP and 
 | 
						|
it should return that same data in a more human friendly format. 
 | 
						|
 | 
						|
Sample %MUNGE:
 | 
						|
 | 
						|
 (my_ip     => \&munge_ip,
 | 
						|
  my_mac    => \&munge_mac,
 | 
						|
  my_layers => \&munge_dec2bin
 | 
						|
 )
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
%MUNGE = (
 | 
						|
    'ip'                 => \&munge_ip,
 | 
						|
    'mac'                => \&munge_mac,
 | 
						|
    'i_mac'              => \&munge_mac,
 | 
						|
    'layers'             => \&munge_dec2bin,
 | 
						|
    'i_speed'            => \&munge_speed,
 | 
						|
    'i_speed_high'       => \&munge_highspeed,
 | 
						|
    'i_octet_in64'       => \&munge_counter64,
 | 
						|
    'i_octet_out64'      => \&munge_counter64,
 | 
						|
    'i_pkts_ucast_in64'  => \&munge_counter64,
 | 
						|
    'i_pkts_ucast_out64' => \&munge_counter64,
 | 
						|
    'i_pkts_mutli_in64'  => \&munge_counter64,
 | 
						|
    'i_pkts_multi_out64' => \&munge_counter64,
 | 
						|
    'i_pkts_bcast_in64'  => \&munge_counter64,
 | 
						|
    'i_pkts_bcast_out64' => \&munge_counter64,
 | 
						|
    'i_up'               => \&munge_i_up,
 | 
						|
);
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head2 Sample Subclass
 | 
						|
 | 
						|
Let's make a sample Layer 2 Device subclass.  This class
 | 
						|
will inherit the Cisco Vlan module as an example.
 | 
						|
 | 
						|
----------------------- snip --------------------------------
 | 
						|
 | 
						|
 # SNMP::Info::Layer2::Sample
 | 
						|
 | 
						|
 package SNMP::Info::Layer2::Sample;
 | 
						|
 | 
						|
 $VERSION = 0.1;
 | 
						|
 | 
						|
 use strict;
 | 
						|
 | 
						|
 use Exporter;
 | 
						|
 use SNMP::Info::Layer2;
 | 
						|
 use SNMP::Info::CiscoVTP;
 | 
						|
 | 
						|
 @SNMP::Info::Layer2::Sample::ISA = qw/SNMP::Info::Layer2
 | 
						|
                                       SNMP::Info::CiscoVTP Exporter/;
 | 
						|
 @SNMP::Info::Layer2::Sample::EXPORT_OK = qw//;
 | 
						|
 | 
						|
 use vars qw/$VERSION %FUNCS %GLOBALS %MIBS %MUNGE $AUTOLOAD $INIT $DEBUG/;
 | 
						|
 | 
						|
 %MIBS    = (%SNMP::Info::Layer2::MIBS,
 | 
						|
             %SNMP::Info::CiscoVTP::MIBS,
 | 
						|
             'SUPER-DOOPER-MIB'  => 'supermibobject'
 | 
						|
            );
 | 
						|
 | 
						|
 %GLOBALS = (%SNMP::Info::Layer2::GLOBALS,
 | 
						|
             %SNMP::Info::CiscoVTP::GLOBALS,
 | 
						|
             'name'              => 'supermib_supername',
 | 
						|
             'favorite_color'    => 'supermib_fav_color_object',
 | 
						|
             'favorite_movie'    => 'supermib_fav_movie_val'
 | 
						|
             );
 | 
						|
 | 
						|
 %FUNCS   = (%SNMP::Info::Layer2::FUNCS,
 | 
						|
             %SNMP::Info::CiscoVTP::FUNCS,
 | 
						|
             # Super Dooper MIB - Super Hero Table
 | 
						|
             'super_hero_index'  => 'SuperHeroIfIndex',
 | 
						|
             'super_hero_name'   => 'SuperHeroIfName',
 | 
						|
             'super_hero_powers' => 'SuperHeroIfPowers'
 | 
						|
            );
 | 
						|
 | 
						|
 | 
						|
 %MUNGE   = (%SNMP::Info::Layer2::MUNGE,
 | 
						|
             %SNMP::Info::CiscoVTP::MUNGE,
 | 
						|
             'super_hero_powers' => \&munge_powers
 | 
						|
            );
 | 
						|
 | 
						|
 # OverRide uptime() method from %SNMP::Info::GLOBALS
 | 
						|
 sub uptime {
 | 
						|
     my $sample = shift;
 | 
						|
 | 
						|
     my $name   = $sample->name();
 | 
						|
 | 
						|
     # this is silly but you get the idea
 | 
						|
     return '600' if defined $name ;
 | 
						|
 }
 | 
						|
 | 
						|
 # Create our own munge function
 | 
						|
 sub munge_powers {
 | 
						|
     my $power = shift;
 | 
						|
 | 
						|
     # Take the returned obscure value and return something useful.
 | 
						|
     return 'Fire' if $power =~ /reallyhot/i;
 | 
						|
     return 'Ice'  if $power =~ /reallycold/i;
 | 
						|
 | 
						|
     # Else 
 | 
						|
     return $power;
 | 
						|
 }
 | 
						|
 | 
						|
 # Copious Documentation here!!!
 | 
						|
 =head1 NAME
 | 
						|
 =head1 AUTHOR
 | 
						|
 =head1 SYNOPSIS
 | 
						|
 =head1 DESCRIPTION
 | 
						|
 =head2 Inherited Classes
 | 
						|
 =head2 Required MIBs
 | 
						|
 =head1 GLOBALS
 | 
						|
 =head2 Overrides
 | 
						|
 =head1 TABLE METHODS
 | 
						|
 =head2 Overrides
 | 
						|
 =cut
 | 
						|
 | 
						|
 1; # don't forget this line
 | 
						|
----------------------- snip --------------------------------
 | 
						|
 | 
						|
Be sure and send the debugged version to snmp-info-users@lists.sourceforge.net to be 
 | 
						|
included in the next version of SNMP::Info.
 | 
						|
 | 
						|
=head1 SNMP::INFO INTERNALS
 | 
						|
 | 
						|
=head2 Object Namespace
 | 
						|
 | 
						|
Internal data is stored with bareword keys. For example $info->{debug}
 | 
						|
 | 
						|
SNMP Data is stored or marked cached with keys starting with an underscore. 
 | 
						|
For example $info->{_name} is the cache for $info->name().
 | 
						|
 | 
						|
Cached Table data is stored in $info->store() and marked cached per above.
 | 
						|
 | 
						|
=head2 Package Globals
 | 
						|
 | 
						|
These set the default value for an object upon creation.
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item $DEBUG
 | 
						|
 | 
						|
Default 0.  Sends copious debug info to stdout.  This global sets the object's
 | 
						|
debug status in new() unless 'Debug' argument passed in new().  Change
 | 
						|
objects' debug status with $info->debug().
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
$DEBUG = 0;
 | 
						|
 | 
						|
=item $BIGINT
 | 
						|
 | 
						|
Default 0.   Set to true to have 64 bit counters return Math::BigInt objects
 | 
						|
instead of scalar string values.  See note under Interface Statistics about
 | 
						|
64 bit values.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
$BIGINT = 0;
 | 
						|
 | 
						|
=item $NOSUCH
 | 
						|
 | 
						|
Default 1.  Set to false to disable RetryNoSuch option for SNMP::Session.  Or
 | 
						|
see method in new() to do it on an object scope.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
$NOSUCH = 1;
 | 
						|
 | 
						|
=item $REPEATERS
 | 
						|
 | 
						|
Default 20.  MaxRepeaters for BULKWALK operations.  See C<perldoc SNMP> for
 | 
						|
more info.  Can change by passing L<BulkRepeaters> option in new()
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
$REPEATERS = 20;
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head2 Data Munging Callback Subroutines
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item munge_speed()
 | 
						|
 | 
						|
Makes human friendly speed ratings using %SPEED_MAP
 | 
						|
 | 
						|
 %SPEED_MAP = (
 | 
						|
                '56000'      => '56 kbps',
 | 
						|
                '64000'      => '64 kbps',
 | 
						|
                '115000'     => '115 kpbs',
 | 
						|
                '1500000'    => '1.5 Mbps',
 | 
						|
                '1536000'    => 'T1',      
 | 
						|
                '1544000'    => 'T1',
 | 
						|
                '2000000'    => '2.0 Mbps',
 | 
						|
                '2048000'    => '2.048 Mbps',
 | 
						|
                '3072000'    => 'Dual T1',
 | 
						|
                '3088000'    => 'Dual T1',   
 | 
						|
                '4000000'    => '4.0 Mbps',
 | 
						|
                '10000000'   => '10 Mbps',
 | 
						|
                '11000000'   => '11 Mbps',
 | 
						|
                '20000000'   => '20 Mbps',
 | 
						|
                '16000000'   => '16 Mbps',
 | 
						|
                '16777216'   => '16 Mbps',
 | 
						|
                '44210000'   => 'T3',
 | 
						|
                '44736000'   => 'T3',
 | 
						|
                '45000000'   => '45 Mbps',
 | 
						|
                '45045000'   => 'DS3',
 | 
						|
                '46359642'   => 'DS3',
 | 
						|
                '51850000'   => 'OC-1',
 | 
						|
                '54000000'   => '54 Mbps',
 | 
						|
                '64000000'   => '64 Mbps',
 | 
						|
                '100000000'  => '100 Mbps',
 | 
						|
                '149760000'  => 'ATM on OC-3',
 | 
						|
                '155000000'  => 'OC-3',
 | 
						|
                '155519000'  => 'OC-3',
 | 
						|
                '155520000'  => 'OC-3',
 | 
						|
                '400000000'  => '400 Mbps',
 | 
						|
                '599040000'  => 'ATM on OC-12', 
 | 
						|
                '622000000'  => 'OC-12',
 | 
						|
                '622080000'  => 'OC-12',
 | 
						|
                '1000000000' => '1.0 Gbps',
 | 
						|
                '2488000000' => 'OC-48',
 | 
						|
             )
 | 
						|
 | 
						|
Note: high speed interfaces (usually 1 Gbps or faster) have their link 
 | 
						|
speed in C<ifHighSpeed>. i_speed() automatically determines whether to use 
 | 
						|
C<ifSpeed> or C<ifHighSpeed>; if the latter is used, the value is munged by 
 | 
						|
munge_highspeed(). SNMP::Info can return speeds up to terabit levels this way.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
%SPEED_MAP = (
 | 
						|
    '56000'      => '56 kbps',
 | 
						|
    '64000'      => '64 kbps',
 | 
						|
    '115000'     => '115 kpbs',
 | 
						|
    '1500000'    => '1.5 Mbps',
 | 
						|
    '1536000'    => 'T1',
 | 
						|
    '1544000'    => 'T1',
 | 
						|
    '2000000'    => '2.0 Mbps',
 | 
						|
    '2048000'    => '2.048 Mbps',
 | 
						|
    '3072000'    => 'Dual T1',
 | 
						|
    '3088000'    => 'Dual T1',
 | 
						|
    '4000000'    => '4.0 Mbps',
 | 
						|
    '10000000'   => '10 Mbps',
 | 
						|
    '11000000'   => '11 Mbps',
 | 
						|
    '20000000'   => '20 Mbps',
 | 
						|
    '16000000'   => '16 Mbps',
 | 
						|
    '16777216'   => '16 Mbps',
 | 
						|
    '44210000'   => 'T3',
 | 
						|
    '44736000'   => 'T3',
 | 
						|
    '45000000'   => '45 Mbps',
 | 
						|
    '45045000'   => 'DS3',
 | 
						|
    '46359642'   => 'DS3',
 | 
						|
    '51850000'   => 'OC-1',
 | 
						|
    '54000000'   => '54 Mbps',
 | 
						|
    '64000000'   => '64 Mbps',
 | 
						|
    '100000000'  => '100 Mbps',
 | 
						|
    '149760000'  => 'ATM on OC-3',
 | 
						|
    '155000000'  => 'OC-3',
 | 
						|
    '155519000'  => 'OC-3',
 | 
						|
    '155520000'  => 'OC-3',
 | 
						|
    '400000000'  => '400 Mbps',
 | 
						|
    '599040000'  => 'ATM on OC-12',
 | 
						|
    '622000000'  => 'OC-12',
 | 
						|
    '622080000'  => 'OC-12',
 | 
						|
    '1000000000' => '1.0 Gbps',
 | 
						|
    '2488000000' => 'OC-48',
 | 
						|
);
 | 
						|
 | 
						|
sub munge_speed {
 | 
						|
    my $speed = shift;
 | 
						|
    my $map   = $SPEED_MAP{$speed};
 | 
						|
 | 
						|
    #print "  $speed -> $map  " if (defined $map);
 | 
						|
    return $map || $speed;
 | 
						|
}
 | 
						|
 | 
						|
=item munge_highspeed()
 | 
						|
 | 
						|
Makes human friendly speed ratings for C<ifHighSpeed>
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub munge_highspeed {
 | 
						|
    my $speed = shift;
 | 
						|
    my $fmt   = "%d Mbps";
 | 
						|
 | 
						|
    if ( $speed > 9999999 ) {
 | 
						|
        $fmt = "%d Tbps";
 | 
						|
        $speed /= 1000000;
 | 
						|
    }
 | 
						|
    elsif ( $speed > 999999 ) {
 | 
						|
        $fmt = "%.1f Tbps";
 | 
						|
        $speed /= 1000000.0;
 | 
						|
    }
 | 
						|
    elsif ( $speed > 9999 ) {
 | 
						|
        $fmt = "%d Gbps";
 | 
						|
        $speed /= 1000;
 | 
						|
    }
 | 
						|
    elsif ( $speed > 999 ) {
 | 
						|
        $fmt = "%.1f Gbps";
 | 
						|
        $speed /= 1000.0;
 | 
						|
    }
 | 
						|
    return sprintf( $fmt, $speed );
 | 
						|
}
 | 
						|
 | 
						|
=item munge_ip() 
 | 
						|
 | 
						|
Takes a binary IP and makes it dotted ASCII
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub munge_ip {
 | 
						|
    my $ip = shift;
 | 
						|
    return join( '.', unpack( 'C4', $ip ) );
 | 
						|
}
 | 
						|
 | 
						|
=item munge_mac()
 | 
						|
 | 
						|
Takes an octet stream (HEX-STRING) and returns a colon separated ASCII hex
 | 
						|
string.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub munge_mac {
 | 
						|
    my $mac = shift;
 | 
						|
    return unless defined $mac;
 | 
						|
    return unless length $mac;
 | 
						|
    $mac = join( ':', map { sprintf "%02x", $_ } unpack( 'C*', $mac ) );
 | 
						|
    return $mac if $mac =~ /^([0-9A-F][0-9A-F]:){5}[0-9A-F][0-9A-F]$/i;
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
=item munge_prio_mac()
 | 
						|
 | 
						|
Takes an 8-byte octet stream (HEX-STRING) and returns a colon separated ASCII
 | 
						|
hex string.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub munge_prio_mac {
 | 
						|
    my $mac = shift;
 | 
						|
    return unless defined $mac;
 | 
						|
    return unless length $mac;
 | 
						|
    $mac = join( ':', map { sprintf "%02x", $_ } unpack( 'C*', $mac ) );
 | 
						|
    return $mac if $mac =~ /^([0-9A-F][0-9A-F]:){7}[0-9A-F][0-9A-F]$/i;
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
=item munge_octet2hex()
 | 
						|
 | 
						|
Takes a binary octet stream and returns an ASCII hex string
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub munge_octet2hex {
 | 
						|
    my $oct = shift;
 | 
						|
    return join( '', map { sprintf "%x", $_ } unpack( 'C*', $oct ) );
 | 
						|
}
 | 
						|
 | 
						|
=item munge_dec2bin()
 | 
						|
 | 
						|
Takes a binary char and returns its ASCII binary representation
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub munge_dec2bin {
 | 
						|
    my $num = shift;
 | 
						|
    return unless defined $num;
 | 
						|
 | 
						|
    #return unless length($num);
 | 
						|
    $num = unpack( "B32", pack( "N", $num ) );
 | 
						|
 | 
						|
    # return last 8 characters only
 | 
						|
    $num =~ s/.*(.{8})$/$1/;
 | 
						|
    return $num;
 | 
						|
}
 | 
						|
 | 
						|
=item munge_bits
 | 
						|
 | 
						|
Takes a SNMP2 'BITS' field and returns the ASCII bit string
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub munge_bits {
 | 
						|
    my $bits = shift;
 | 
						|
    return unless defined $bits;
 | 
						|
 | 
						|
    return unpack( "B*", $bits );
 | 
						|
}
 | 
						|
 | 
						|
=item munge_counter64
 | 
						|
 | 
						|
If $BIGINT is set to true, then a Math::BigInt object is returned.
 | 
						|
See Math::BigInt for details.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub munge_counter64 {
 | 
						|
    my $counter = shift;
 | 
						|
    return          unless defined $counter;
 | 
						|
    return $counter unless $BIGINT;
 | 
						|
    my $bigint = Math::BigInt->new($counter);
 | 
						|
    return $bigint;
 | 
						|
}
 | 
						|
 | 
						|
=item munge_i_up
 | 
						|
 | 
						|
Net-SNMP tends to load C<RFC1213-MIB> first, and so ignores the
 | 
						|
updated enumeration for C<ifOperStatus> in C<IF-MIB>.  This munge
 | 
						|
handles the "newer" definitions for the enumeration in IF-MIB.
 | 
						|
 | 
						|
TODO: Get the precedence of MIBs and overriding of MIB data in Net-SNMP
 | 
						|
figured out.  Heirarchy/precendence of MIBS in SNMP::Info.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub munge_i_up {
 | 
						|
    my $i_up = shift;
 | 
						|
    return unless defined $i_up;
 | 
						|
 | 
						|
    my %ifOperStatusMap = ( '4' => 'unknown',
 | 
						|
                            '5' => 'dormant',
 | 
						|
                            '6' => 'notPresent',
 | 
						|
                            '7' => 'lowerLayerDown' );
 | 
						|
    return $ifOperStatusMap{$i_up} || $i_up;
 | 
						|
}
 | 
						|
 | 
						|
=item munge_port_list
 | 
						|
 | 
						|
Takes an octet string representing a set of ports and returns a reference
 | 
						|
to an array of binary values each array element representing a port. 
 | 
						|
 | 
						|
If the element has a value of '1', then that port is included in the set of
 | 
						|
ports; the port is not included if it has a value of '0'.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub munge_port_list {
 | 
						|
    my $oct = shift;
 | 
						|
    return unless defined $oct;
 | 
						|
 | 
						|
    my $list = [ split( //, unpack( "B*", $oct ) ) ];
 | 
						|
 | 
						|
    return $list;
 | 
						|
}
 | 
						|
 | 
						|
=item munge_null()
 | 
						|
 | 
						|
Removes control characters from a string
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
# munge_null() - removes nulls (\0) and other control characters
 | 
						|
sub munge_null {
 | 
						|
    my $text = shift || return;
 | 
						|
 | 
						|
    $text =~ s/[[:cntrl:]]//g;
 | 
						|
    return $text;
 | 
						|
}
 | 
						|
 | 
						|
=item munge_e_type()
 | 
						|
 | 
						|
Takes an OID and return the object name if the right MIB is loaded.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub munge_e_type {
 | 
						|
    my $oid = shift;
 | 
						|
 | 
						|
    my $name = &SNMP::translateObj($oid);
 | 
						|
    return $name if defined($name);
 | 
						|
    return $oid;
 | 
						|
}
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head2 Internally Used Functions
 | 
						|
 | 
						|
=over
 | 
						|
 | 
						|
=item $info->init()
 | 
						|
 | 
						|
Used internally.  Loads all entries in %MIBS.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub init {
 | 
						|
    my $self = shift;
 | 
						|
 | 
						|
    # Get MibDirs if provided
 | 
						|
    my $mibdirs = $self->{mibdirs} || [];
 | 
						|
    
 | 
						|
    # SNMP::initMib and SNMP::addMibDirs both look for some initial MIBs
 | 
						|
    # so if we are not using Net-SNMP configuration files we need to
 | 
						|
    # specify where the MIBs are before those calls.
 | 
						|
 | 
						|
    # Ignore snmp.conf and snmp.local.conf files if IgnoreNetSNMPConf
 | 
						|
    # specified
 | 
						|
    local $ENV{'SNMPCONFPATH'} = '' if $self->{IgnoreNetSNMPConf};
 | 
						|
    # We need to provide MIBDIRS if we are not getting them from a
 | 
						|
    # configuration file
 | 
						|
    my $mibdir = join (':', @$mibdirs);
 | 
						|
    local $ENV{'MIBDIRS'} = "$mibdir" if $self->{IgnoreNetSNMPConf};
 | 
						|
 | 
						|
    SNMP::initMib;
 | 
						|
 | 
						|
    my $version = $SNMP::VERSION;
 | 
						|
    my ( $major, $minor, $rev ) = split( '\.', $version );
 | 
						|
 | 
						|
    if ( $major < 5 ) {
 | 
						|
 | 
						|
        # Seems to work under 4.2.0
 | 
						|
    }
 | 
						|
    elsif ( $major == 5 and $minor == 0 and $rev < 2 ) {
 | 
						|
        carp("Net-SNMP 5.0.1 seems to be rather buggy. Upgrade.\n");
 | 
						|
 | 
						|
        # This is a bug in net-snmp 5.0.1 perl module
 | 
						|
        # see http://groups.google.com/groups?th=47aed6bf7be6a0f5
 | 
						|
        SNMP::init_snmp("perl");
 | 
						|
    }
 | 
						|
 | 
						|
    foreach my $d (@$mibdirs) {
 | 
						|
        next unless -d $d;
 | 
						|
        print "SNMP::Info::init() - Adding new mibdir:$d\n" if $self->debug();
 | 
						|
        SNMP::addMibDirs($d);
 | 
						|
    }
 | 
						|
 | 
						|
    my $mibs = $self->mibs();
 | 
						|
 | 
						|
    foreach my $mib ( keys %$mibs ) {
 | 
						|
 | 
						|
        #print "SNMP::Info::init() - Loading mib:$mib\n" if $self->debug();
 | 
						|
        SNMP::loadModules("$mib");
 | 
						|
 | 
						|
        unless ( defined $SNMP::MIB{ $mibs->{$mib} } ) {
 | 
						|
            croak "The $mib did not load. See README for $self->{class}\n";
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
=item $info->args()
 | 
						|
 | 
						|
Returns a reference to the argument hash supplied to SNMP::Session
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub args {
 | 
						|
    my $self = shift;
 | 
						|
    return $self->{args};
 | 
						|
}
 | 
						|
 | 
						|
=item $info->class()
 | 
						|
 | 
						|
Returns the class name of the object.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub class {
 | 
						|
    my $self = shift;
 | 
						|
    return $self->{class};
 | 
						|
}
 | 
						|
 | 
						|
=item $info->error_throw(error message)
 | 
						|
 | 
						|
Stores the error message for use by $info->error()
 | 
						|
 | 
						|
If $info->debug() is true, then the error message is carped too.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub error_throw {
 | 
						|
    my $self  = shift;
 | 
						|
    my $error = shift;
 | 
						|
 | 
						|
    return unless defined $error;
 | 
						|
    $self->{error} = $error;
 | 
						|
 | 
						|
    if ( $self->debug() ) {
 | 
						|
        $error =~ s/\n+$//;
 | 
						|
        carp($error);
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
=item $info->funcs()
 | 
						|
 | 
						|
Returns a reference to the %FUNCS hash.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub funcs {
 | 
						|
    my $self = shift;
 | 
						|
    return $self->{funcs};
 | 
						|
}
 | 
						|
 | 
						|
=item $info->globals()
 | 
						|
 | 
						|
Returns a reference to the %GLOBALS hash.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub globals {
 | 
						|
    my $self = shift;
 | 
						|
    return $self->{globals};
 | 
						|
}
 | 
						|
 | 
						|
=item $info->mibs()
 | 
						|
 | 
						|
Returns a reference to the %MIBS hash.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub mibs {
 | 
						|
    my $self = shift;
 | 
						|
    return $self->{mibs};
 | 
						|
}
 | 
						|
 | 
						|
=item $info->munge()
 | 
						|
 | 
						|
Returns a reference of the %MUNGE hash.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub munge {
 | 
						|
    my $self = shift;
 | 
						|
    return $self->{munge};
 | 
						|
}
 | 
						|
 | 
						|
=item $info->nosuch()
 | 
						|
 | 
						|
Returns NoSuch value set or not in new()
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub nosuch {
 | 
						|
    my $self = shift;
 | 
						|
    return $self->{nosuch};
 | 
						|
}
 | 
						|
 | 
						|
=item $info->session()
 | 
						|
 | 
						|
Gets or Sets the SNMP::Session object.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub session {
 | 
						|
    my $self = shift;
 | 
						|
    $self->{sess} = $_[0] if @_;
 | 
						|
    return $self->{sess};
 | 
						|
}
 | 
						|
 | 
						|
=item $info->store(new_store)
 | 
						|
 | 
						|
Returns or sets hash store for Table functions.
 | 
						|
 | 
						|
Store is a hash reference in this format :
 | 
						|
 | 
						|
$info->store = { attribute => { iid => value , iid2 => value2, ... } };
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub store {
 | 
						|
    my $self = shift;
 | 
						|
    $self->{store} = $_[0] if @_;
 | 
						|
    return $self->{store};
 | 
						|
}
 | 
						|
 | 
						|
=item $info->_global()
 | 
						|
 | 
						|
Used internally by AUTOLOAD to create dynamic methods from %GLOBALS or a
 | 
						|
single instance MIB Leaf node name from a loaded MIB.
 | 
						|
 | 
						|
Example: $info->name() on the first call dispatches to AUTOLOAD() which
 | 
						|
calls $info->_global('name') creating the method name().
 | 
						|
 | 
						|
These methods return data as a scalar.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub _global {
 | 
						|
    my $method = shift;
 | 
						|
    my $oid    = shift;
 | 
						|
 | 
						|
    return sub {
 | 
						|
        my $self = shift;
 | 
						|
 | 
						|
        my $sess = $self->session();
 | 
						|
        return unless defined $sess;
 | 
						|
 | 
						|
        my $load = $method =~ /^load/;
 | 
						|
        my $raw  = $method =~ /raw$/;
 | 
						|
 | 
						|
        my $attr = $method;
 | 
						|
        $attr =~ s/^(load|orig)_//;
 | 
						|
        $attr =~ s/_raw$//;
 | 
						|
 | 
						|
        # Return cached data unless loading
 | 
						|
        # We now store in raw format so munge before returning
 | 
						|
        # unless expecting raw data
 | 
						|
        if ( defined $self->{"_$attr"} && !$load ) {
 | 
						|
            my $val = $self->{"_$attr"};
 | 
						|
 | 
						|
            if ( !$raw ) {
 | 
						|
                return $self->_munge($attr, $val);
 | 
						|
            } else{
 | 
						|
                return $val;
 | 
						|
            } 
 | 
						|
        }
 | 
						|
 | 
						|
        if ( $self->{Offline} ) {
 | 
						|
            $self->error_throw(
 | 
						|
                "SNMP::Info::_global: Offline but $attr is not in cache\n" );
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        if ( $self->debug() ) {
 | 
						|
            # Let's get the MIB Module and leaf name along with the OID
 | 
						|
            my $qual_leaf = SNMP::translateObj($oid,0,1) || '';
 | 
						|
            print "SNMP::Info::_global $method : $qual_leaf : $oid\n";
 | 
						|
        }
 | 
						|
        my $val = $sess->get($oid);
 | 
						|
 | 
						|
        # Mark as gotten. Even if it fails below, we don't want to keep failing.
 | 
						|
        $self->{"_$attr"} = undef;
 | 
						|
 | 
						|
        if ( $sess->{ErrorStr} ) {
 | 
						|
            $self->error_throw(
 | 
						|
                "SNMP::Info::_global($method) $sess->{ErrorStr}");
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        if ( defined $val and $val eq 'NOSUCHOBJECT' ) {
 | 
						|
            $self->error_throw("SNMP::Info::_global($method) NOSUCHOBJECT");
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        if ( defined $val and $val eq 'NOSUCHINSTANCE' ) {
 | 
						|
            $self->error_throw("SNMP::Info::_global($method) NOSUCHINSTANCE");
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        # Save Cached Value
 | 
						|
        $self->_cache($attr, $val);
 | 
						|
 | 
						|
        # Data Munging
 | 
						|
        if ( !$raw ) {
 | 
						|
            $val = $self->_munge($attr, $val);
 | 
						|
        }
 | 
						|
 | 
						|
        return $val;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
=item $info->_set(attr,val,iid,type)
 | 
						|
 | 
						|
Used internally by set_multi() to run an SNMP set command.  When run
 | 
						|
clears attr cache.
 | 
						|
 | 
						|
Attr can be passed as either a scalar or a reference to an array or array
 | 
						|
of arrays when used with set_multi().
 | 
						|
 | 
						|
Example:  $info->set_name('dog',3) uses autoload to resolve to
 | 
						|
$info->_set('name','dog',3);
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub _set {
 | 
						|
    my ( $self, $attr, $val, $iid, $type ) = @_;
 | 
						|
    my $varbind_list_ref;
 | 
						|
 | 
						|
    if ( !ref($attr) ) {
 | 
						|
        $varbind_list_ref = [ [ $attr, $iid, $val, $type ] ];
 | 
						|
    }
 | 
						|
    elsif ( ref($attr) =~ /ARRAY/ ) {
 | 
						|
        $varbind_list_ref = [$attr];
 | 
						|
        $varbind_list_ref = $attr if ref( $$attr[0] ) =~ /ARRAY/;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        $self->error_throw(
 | 
						|
            "SNMP::Info::_set($attr,$val) - Failed. Invalid argument for attr."
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    my $sess = $self->session();
 | 
						|
    return unless defined $sess;
 | 
						|
 | 
						|
    my $funcs   = $self->funcs();
 | 
						|
    my $globals = $self->globals();
 | 
						|
 | 
						|
    foreach my $var_list (@$varbind_list_ref) {
 | 
						|
        my $list_attr = $var_list->[0];
 | 
						|
        my $list_iid  = $var_list->[1];
 | 
						|
        my $list_val  = $var_list->[2];
 | 
						|
 | 
						|
        # Get rid of non-printable chars in $list_val for debug statements
 | 
						|
        $list_val =~ s/\W//;
 | 
						|
 | 
						|
        # Instance is 0 for scalars without a supplied instance
 | 
						|
        $var_list->[1] = $list_iid = defined $list_iid ? $list_iid : '0';
 | 
						|
 | 
						|
        # Check if this method is from a sub or from the tables.
 | 
						|
        if ( $self->can($list_attr) ) {
 | 
						|
            $self->error_throw(
 | 
						|
                "SNMP::Info::_set($list_attr,$list_val) - Failed. $list_attr is generated in a sub(). set_$list_attr sub required."
 | 
						|
            );
 | 
						|
 | 
						|
            # if sub set_attr() existed, we wouldn't have gotten this far.
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        # Lookup oid
 | 
						|
        my $oid = undef;
 | 
						|
        $oid = $list_attr             if SNMP::translateObj($list_attr);
 | 
						|
        $oid = $globals->{$list_attr} if defined $globals->{$list_attr};
 | 
						|
        $oid = $funcs->{$list_attr}   if defined $funcs->{$list_attr};
 | 
						|
 | 
						|
        unless ( defined $oid ) {
 | 
						|
            $self->error_throw(
 | 
						|
                "SNMP::Info::_set($list_attr,$list_val) - Failed to find $list_attr in \%GLOBALS or \%FUNCS or loaded MIB."
 | 
						|
            );
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        # Check for fully qualified attr
 | 
						|
        if ( $oid =~ /__/ ) {
 | 
						|
            $oid =~ s/__/::/;
 | 
						|
            $oid =~ s/_/-/g;
 | 
						|
        }
 | 
						|
 | 
						|
        $var_list->[0] = $oid;
 | 
						|
 | 
						|
        $self->debug()
 | 
						|
            and print
 | 
						|
            "SNMP::Info::_set $list_attr.$list_iid ($oid.$list_iid) = $list_val\n";
 | 
						|
        delete $self->{"_$list_attr"};
 | 
						|
    }
 | 
						|
 | 
						|
    my $rv = $sess->set($varbind_list_ref);
 | 
						|
 | 
						|
    if ( $sess->{ErrorStr} ) {
 | 
						|
        $self->error_throw("SNMP::Info::_set $sess->{ErrorStr}");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    return $rv;
 | 
						|
}
 | 
						|
 | 
						|
=item $info->_make_setter(val,iid)
 | 
						|
 | 
						|
Used internally by AUTOLOAD to create dynamic methods from either %GLOBALS,
 | 
						|
%FUNCS, or a valid mib leaf from a loaded MIB which runs an SNMP set command.  
 | 
						|
When run clears the attribute cache.
 | 
						|
 | 
						|
Example:  $info->set_name('dog',3) dispatches to autoload to resolve to
 | 
						|
$info->_set('name','dog',3) and _make_setter creates the set_name() method.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub _make_setter {
 | 
						|
    my $method = shift;
 | 
						|
    my $oid    = shift;
 | 
						|
 | 
						|
    return sub {
 | 
						|
        my $self = shift;
 | 
						|
        my $val  = shift;
 | 
						|
        my $iid  = shift;
 | 
						|
 | 
						|
        my $set_oid = $oid;
 | 
						|
        my $globals = $self->globals();
 | 
						|
        my $attr = $method;
 | 
						|
        $attr =~ s/^set_//;
 | 
						|
        
 | 
						|
        # The only thing which may give us the iid in $oid should be
 | 
						|
        # a %GLOBALS entry appended with a number.  In that case strip it
 | 
						|
        # from the OID and use it as $iid
 | 
						|
        if ( defined $globals->{$attr} && $globals->{$attr} =~ /(\.\d+$)/ ) {
 | 
						|
            $iid = $1;
 | 
						|
            $set_oid =~ s/$iid//;
 | 
						|
        }
 | 
						|
 | 
						|
        # If we don't have $iid now we should be a %GLOBALS entry or single
 | 
						|
        # instance MIB leaf so default to zero
 | 
						|
        $iid = defined $iid ? $iid : '.0';
 | 
						|
 | 
						|
        # prepend dot if necessary to $iid
 | 
						|
        $iid = ".$iid" unless $iid =~ /^\./;
 | 
						|
 | 
						|
        my $sess = $self->session();
 | 
						|
        return unless defined $sess;
 | 
						|
 | 
						|
        $set_oid .= "$iid";
 | 
						|
 | 
						|
        $self->debug()
 | 
						|
            and print "SNMP::Info::_set $method$iid ($set_oid) = $val\n";
 | 
						|
        delete $self->{"_$attr"};
 | 
						|
 | 
						|
        my $rv = $sess->set( $set_oid, $val );
 | 
						|
 | 
						|
        if ( $sess->{ErrorStr} ) {
 | 
						|
            $self->error_throw("SNMP::Info::_set $sess->{ErrorStr}");
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        return $rv;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
=item $info->set_multi(arrayref)
 | 
						|
 | 
						|
Used to run an SNMP set command on several new values in the one request.
 | 
						|
Returns the result of $info->_set(method).
 | 
						|
 | 
						|
Pass either a reference to a 4 element array [<obj>, <iid>, <val>, <type>] or
 | 
						|
a reference to an array of 4 element arrays to specify multiple values.
 | 
						|
 | 
						|
    <obj> - One of the following forms:
 | 
						|
        1) leaf identifier (e.g., C<'sysContact'>)
 | 
						|
        2) An entry in either %FUNCS, %GLOBALS (e.g., 'contact')
 | 
						|
    <iid> - The dotted-decimal, instance identifier. For scalar MIB objects
 | 
						|
             use '0'
 | 
						|
    <val>  - The SNMP data value being set (e.g., 'netdisco')
 | 
						|
    <type> - Optional as the MIB should be loaded.
 | 
						|
 | 
						|
If one of the set assignments is invalid, then the request will be rejected
 | 
						|
without applying any of the new values - regardless of the order they appear
 | 
						|
in the list.
 | 
						|
 | 
						|
Example:
 | 
						|
    my $vlan_set = [
 | 
						|
        ['qb_v_untagged',"$old_vlan_id","$old_untagged_portlist"],
 | 
						|
        ['qb_v_egress',"$new_vlan_id","$new_egress_portlist"],
 | 
						|
        ['qb_v_egress',"$old_vlan_id","$old_egress_portlist"],
 | 
						|
        ['qb_v_untagged',"$new_vlan_id","$new_untagged_portlist"],
 | 
						|
        ['qb_i_vlan',"$port","$new_vlan_id"],
 | 
						|
    ];
 | 
						|
 | 
						|
    $info->set_multi($vlan_set);
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub set_multi {
 | 
						|
    my $self = shift;
 | 
						|
 | 
						|
    return $self->_set(@_);
 | 
						|
}
 | 
						|
 | 
						|
=item $info->load_all()
 | 
						|
 | 
						|
Debugging routine.  This does not include any overridden method or method
 | 
						|
implemented by subroutine.
 | 
						|
 | 
						|
Runs $info->load_METHOD() for each entry in $info->funcs();
 | 
						|
 | 
						|
Returns $info->store() -- See store() entry.
 | 
						|
 | 
						|
Note return value has changed since version 0.3
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub load_all {
 | 
						|
    my $self = shift;
 | 
						|
    my $sess = $self->session();
 | 
						|
    return unless defined $sess;
 | 
						|
 | 
						|
    my $funcs = $self->funcs();
 | 
						|
 | 
						|
    foreach my $attrib ( keys %$funcs ) {
 | 
						|
        $attrib = "load_$attrib";
 | 
						|
        $self->$attrib();
 | 
						|
    }
 | 
						|
 | 
						|
    $self->{_all}++;
 | 
						|
 | 
						|
    return unless defined wantarray;
 | 
						|
 | 
						|
    return $self->store();
 | 
						|
}
 | 
						|
 | 
						|
=item $info->all()
 | 
						|
 | 
						|
Runs $info->load_all() once then returns $info->store();
 | 
						|
 | 
						|
Use $info->load_all() to reload the data.
 | 
						|
 | 
						|
Note return value has changed since version 0.3
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub all {
 | 
						|
    my $self = shift;
 | 
						|
    my $sess = $self->session();
 | 
						|
    return unless defined $sess;
 | 
						|
 | 
						|
    $self->load_all() unless defined $self->{_all};
 | 
						|
 | 
						|
    return $self->store();
 | 
						|
}
 | 
						|
 | 
						|
=item $info->_load_attr()
 | 
						|
 | 
						|
Used internally by AUTOLOAD to create dynamic methods from %FUNCS 
 | 
						|
or a MIB Leaf node name contained within a table of a loaded MIB.
 | 
						|
 | 
						|
Supports partial table fetches and single instance table fetches.
 | 
						|
See L<SNMP::Info/"Partial Table Fetches">.
 | 
						|
 | 
						|
These methods return data as a reference to a hash.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub _load_attr {
 | 
						|
    my $method = shift;
 | 
						|
    my $oid    = shift;
 | 
						|
 | 
						|
    return sub {
 | 
						|
        my $self    = shift;
 | 
						|
        my $partial = shift;
 | 
						|
 | 
						|
        my $sess = $self->session();
 | 
						|
        return unless defined $sess;
 | 
						|
 | 
						|
        my $ver    = $self->snmp_ver();
 | 
						|
        my $nosuch = $self->nosuch();
 | 
						|
        my $store  = $self->store();
 | 
						|
 | 
						|
        my $load = $method =~ /^load/;
 | 
						|
        my $raw  = $method =~ /raw$/;
 | 
						|
 | 
						|
        my $attr = $method;
 | 
						|
        $attr =~ s/^(load|orig)_//;
 | 
						|
        $attr =~ s/_raw$//;
 | 
						|
 | 
						|
        # Return cached data unless loading or partial
 | 
						|
        # We now store in raw format so munge before returning
 | 
						|
        # unless expecting raw data
 | 
						|
        return $self->_show_attr($attr, $raw)
 | 
						|
            if ( defined $self->{"_${attr}"}
 | 
						|
            && !$load
 | 
						|
            && !defined $partial );
 | 
						|
 | 
						|
        if ( $self->{Offline} ) {
 | 
						|
            $self->error_throw(
 | 
						|
                "SNMP::Info::_load_atrr: Offline but $attr is not in cache\n" );
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        # We want the qualified leaf name so that we can
 | 
						|
        # specify the Module (MIB) in the case of private leaf naming
 | 
						|
        # conflicts.  Example: ALTEON-TIGON-SWITCH-MIB::agSoftwareVersion
 | 
						|
        # and ALTEON-CHEETAH-SWITCH-MIB::agSoftwareVersion
 | 
						|
        # Third argument to translateObj specifies the Module prefix
 | 
						|
        
 | 
						|
        my $qual_leaf = SNMP::translateObj($oid,0,1) || '';
 | 
						|
        
 | 
						|
        # We still want just the leaf since a SNMP get in the case of a
 | 
						|
        # partial fetch may strip the Module portion upon return.  We need
 | 
						|
        # the match to make sure we didn't leave the table during getnext
 | 
						|
        # requests
 | 
						|
        
 | 
						|
        my ($leaf) = $qual_leaf =~ /::(\w+)$/;
 | 
						|
 | 
						|
        $self->debug()
 | 
						|
            and print "SNMP::Info::_load_attr $method : $qual_leaf",
 | 
						|
            defined $partial ? "($partial)" : '', " : $oid" ,
 | 
						|
            defined $partial ? ".$partial" : '', "\n";
 | 
						|
 | 
						|
        my $var = new SNMP::Varbind( [$qual_leaf, $partial] );
 | 
						|
 | 
						|
        # So devices speaking SNMP v.1 are not supposed to give out
 | 
						|
        # data from SNMP2, but most do.  Net-SNMP, being very precise
 | 
						|
        # will tell you that the SNMP OID doesn't exist for the device.
 | 
						|
        # They have a flag RetryNoSuch that is used for get() operations,
 | 
						|
        # but not for getnext().  We set this flag normally, and if we're
 | 
						|
        # using V1, let's try and fetch the data even if we get one of those.
 | 
						|
 | 
						|
        my $localstore = undef;
 | 
						|
        my $errornum   = 0;
 | 
						|
        my %seen       = ();
 | 
						|
 | 
						|
        my $vars = [];
 | 
						|
        my $bulkwalk_no
 | 
						|
            = $self->can('bulkwalk_no') ? $self->bulkwalk_no() : 0;
 | 
						|
        my $bulkwalk_on = defined $self->{BulkWalk} ? $self->{BulkWalk} : 1;
 | 
						|
        my $can_bulkwalk = $bulkwalk_on && !$bulkwalk_no;
 | 
						|
        my $repeaters = $self->{BulkRepeaters} || $REPEATERS;
 | 
						|
        my $bulkwalk = $can_bulkwalk && $ver != 1;
 | 
						|
        my $loopdetect
 | 
						|
            = defined $self->{LoopDetect} ? $self->{LoopDetect} : 1;
 | 
						|
 | 
						|
        if ( defined $partial ) {
 | 
						|
 | 
						|
            # Try a GET, in case the partial is a leaf OID.
 | 
						|
            # Would like to only do this if we know the OID is
 | 
						|
            # long enough; implementing that would require a
 | 
						|
            # lot of MIB mucking.
 | 
						|
            my $try = $sess->get($var);
 | 
						|
            $errornum = $sess->{ErrorNum};
 | 
						|
            if ( defined($try) && $errornum == 0 && $try !~ /^NOSUCH/ ) {
 | 
						|
                $var->[2] = $try;
 | 
						|
                $vars     = [$var];
 | 
						|
                $bulkwalk = 1;        # fake a bulkwalk return
 | 
						|
            }
 | 
						|
 | 
						|
            # We want to execute the while loop below for the getnext request.
 | 
						|
            if (    $ver == 1
 | 
						|
                and $sess->{ErrorNum}
 | 
						|
                and $sess->{ErrorStr} =~ /nosuch/i )
 | 
						|
            {
 | 
						|
                $errornum = 0;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        # Use BULKWALK if we can because its faster
 | 
						|
        if ( $bulkwalk && @$vars == 0 ) {
 | 
						|
            ($vars) = $sess->bulkwalk( 0, $repeaters, $var );
 | 
						|
            if ( $sess->{ErrorNum} ) {
 | 
						|
                $self->error_throw(
 | 
						|
                    "SNMP::Info::_load_atrr: BULKWALK " . $sess->{ErrorStr},
 | 
						|
                    "\n" );
 | 
						|
                return;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        while ( !$errornum ) {
 | 
						|
            if ($bulkwalk) {
 | 
						|
                $var = shift @$vars or last;
 | 
						|
            }
 | 
						|
            else {
 | 
						|
 | 
						|
                # GETNEXT instead of BULKWALK
 | 
						|
                $sess->getnext($var);
 | 
						|
                $errornum = $sess->{ErrorNum};
 | 
						|
            }
 | 
						|
 | 
						|
            if ( $self->debug() > 1 ) {
 | 
						|
                use Data::Dumper;
 | 
						|
                print "SNMP::Info::_load_attr $method : leaf = $oid , var = ",
 | 
						|
                    Dumper($var);
 | 
						|
            }
 | 
						|
 | 
						|
            # Check if we've left the requested subtree
 | 
						|
            last if $var->[0] !~ /$leaf$/;
 | 
						|
            my $iid = $var->[1];
 | 
						|
            my $val = $var->[2];
 | 
						|
 | 
						|
            unless ( defined $iid ) {
 | 
						|
                $self->error_throw(
 | 
						|
                    "SNMP::Info::_load_attr: $method not here");
 | 
						|
                next;
 | 
						|
            }
 | 
						|
 | 
						|
            # Check to make sure we are still in partial land
 | 
						|
            if (    defined $partial
 | 
						|
                and $iid !~ /^$partial$/
 | 
						|
                and $iid !~ /^$partial\./ )
 | 
						|
            {
 | 
						|
                $self->debug()
 | 
						|
                    and print "$iid makes us leave partial land.\n";
 | 
						|
                last;
 | 
						|
            }
 | 
						|
 | 
						|
           # Check if last element, V2 devices may report ENDOFMIBVIEW even if
 | 
						|
           # instance or object doesn't exist.
 | 
						|
            if ( $val eq 'ENDOFMIBVIEW' ) {
 | 
						|
                last;
 | 
						|
            }
 | 
						|
 | 
						|
            # Similarly for SNMPv1 - noSuchName return results in both $iid
 | 
						|
            # and $val being empty strings.
 | 
						|
            if ( $val eq '' and $iid eq '' ) {
 | 
						|
                last;
 | 
						|
            }
 | 
						|
 | 
						|
         # Another check for SNMPv1 - noSuchName return may results in an $iid
 | 
						|
         # we've already seen and $val an empty string.  If we don't catch
 | 
						|
         # this here we erronously report a loop below.
 | 
						|
            if ( defined $seen{$iid} and $seen{$iid} and $val eq '' ) {
 | 
						|
                last;
 | 
						|
            }
 | 
						|
 | 
						|
            if ($loopdetect) {
 | 
						|
 | 
						|
                # Check to see if we've already seen this IID (looping)
 | 
						|
                if ( defined $seen{$iid} and $seen{$iid} ) {
 | 
						|
                    $self->error_throw("Looping on: $method iid:$iid. ");
 | 
						|
                    last;
 | 
						|
                }
 | 
						|
                else {
 | 
						|
                    $seen{$iid}++;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            if ( $val eq 'NOSUCHOBJECT' ) {
 | 
						|
                $self->error_throw(
 | 
						|
                    "SNMP::Info::_load_attr: $method :  NOSUCHOBJECT");
 | 
						|
                next;
 | 
						|
            }
 | 
						|
            if ( $val eq 'NOSUCHINSTANCE' ) {
 | 
						|
                $self->error_throw(
 | 
						|
                    "SNMP::Info::_load_attr: $method :  NOSUCHINSTANCE");
 | 
						|
                next;
 | 
						|
            }
 | 
						|
 | 
						|
            $localstore->{$iid} = $val;
 | 
						|
 | 
						|
        }
 | 
						|
 | 
						|
        # Cache data if we are not getting partial data:
 | 
						|
        if ( !defined $partial ) {
 | 
						|
            $self->_cache($attr, $localstore);
 | 
						|
        }
 | 
						|
 | 
						|
        # Data Munging
 | 
						|
        if ( !$raw ) {
 | 
						|
            $localstore = $self->_munge($attr, $localstore);
 | 
						|
        }
 | 
						|
 | 
						|
        return $localstore;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
=item $info->_show_attr()
 | 
						|
 | 
						|
Used internally by AUTOLOAD to return data called by methods listed in %FUNCS.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub _show_attr {
 | 
						|
    my $self = shift;
 | 
						|
    my $attr = shift;
 | 
						|
    my $raw  = shift;
 | 
						|
 | 
						|
    my $store = $self->store();
 | 
						|
 | 
						|
    if ( !$raw ) {
 | 
						|
        my $localstore = $store->{$attr};
 | 
						|
        return $self->_munge($attr, $localstore);
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        return $store->{$attr};
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
=item $info->snmp_connect_ip(ip) 
 | 
						|
 | 
						|
Returns true or false based upon snmp connectivity to an IP.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub snmp_connect_ip {
 | 
						|
    my $self = shift;
 | 
						|
    my $ip   = shift;
 | 
						|
    my $ver  = $self->snmp_ver();
 | 
						|
    my $comm = $self->snmp_comm();
 | 
						|
 | 
						|
    return if $self->{Offline};
 | 
						|
    return if ( $ip eq '0.0.0.0' ) or ( $ip =~ /^127\./ );
 | 
						|
 | 
						|
    # Create session object
 | 
						|
    my $snmp_test = new SNMP::Session(
 | 
						|
        'DestHost'  => $ip,
 | 
						|
        'Community' => $comm,
 | 
						|
        'Version'   => $ver
 | 
						|
    );
 | 
						|
 | 
						|
    # No session object created
 | 
						|
    unless ( defined $snmp_test ) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    # Session object created but SNMP connection failed.
 | 
						|
    my $sess_err = $snmp_test->{ErrorStr} || '';
 | 
						|
    if ($sess_err) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    # Try to get some data from IP
 | 
						|
    my $layers = $snmp_test->get('sysServices.0');
 | 
						|
 | 
						|
    $sess_err = $snmp_test->{ErrorStr} || '';
 | 
						|
    if ($sess_err) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    return 1;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
=item modify_port_list(portlist,offset,replacement)
 | 
						|
 | 
						|
Replaces the specified bit in a port_list array and
 | 
						|
returns the packed bitmask 
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub modify_port_list {
 | 
						|
    my ( $self, $portlist, $offset, $replacement ) = @_;
 | 
						|
 | 
						|
    print "Original port list: @$portlist \n" if $self->debug();
 | 
						|
    @$portlist[$offset] = $replacement;
 | 
						|
 | 
						|
    # Some devices do not populate the portlist with all possible ports.
 | 
						|
    # If we have lengthened the list fill all undefined elements with zero.
 | 
						|
    foreach my $item (@$portlist) {
 | 
						|
        $item = '0' unless ( defined($item) );
 | 
						|
    }
 | 
						|
    print "Modified port list: @$portlist \n" if $self->debug();
 | 
						|
 | 
						|
    return pack( "B*", join( '', @$portlist ) );
 | 
						|
}
 | 
						|
 | 
						|
=item $info->_cache(attr, data)
 | 
						|
 | 
						|
Cache retrieved data so that if it's asked for again, we use the cache instead
 | 
						|
of going back to Net-SNMP. Data is cached inside the blessed hashref C<$self>.
 | 
						|
 | 
						|
Accepts the leaf and value (scalar, or hashref for a table). Does not return
 | 
						|
anything useful.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub _cache {
 | 
						|
    my $self = shift;
 | 
						|
    my ($attr, $data) = @_;
 | 
						|
    my $store = $self->store();
 | 
						|
 | 
						|
    if (ref {} eq ref $data) {
 | 
						|
        $self->{"_${attr}"}++;
 | 
						|
        $store->{$attr} = $data;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        $self->{"_$attr"} = $data;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
=item $info->_munge(attr, data)
 | 
						|
 | 
						|
Raw data returned from Net-SNMP might not be formatted correctly or might have
 | 
						|
platform-specific bugs or mistakes. The MUNGE feature of SNMP::Info allows for
 | 
						|
fixups to take place.
 | 
						|
 | 
						|
Accepts the leaf and value (scalar, or hashref for a table) and returns the raw
 | 
						|
or the munged data, as appropriate. That is, you do not need to know whether
 | 
						|
MUNGE is installed, and it's safe to call this method regardless.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub _munge {
 | 
						|
    my $self = shift;
 | 
						|
    my ($attr, $data) = @_;
 | 
						|
    my $munge = $self->munge();
 | 
						|
 | 
						|
    return $data unless defined $munge->{$attr};
 | 
						|
 | 
						|
    if (ref {} eq ref $data) {
 | 
						|
        my $subref = $munge->{$attr};
 | 
						|
        my %munged;
 | 
						|
        foreach my $key ( keys %$data ) {
 | 
						|
            my $value = $data->{$key};
 | 
						|
            next unless defined $value;
 | 
						|
            $munged{$key} = $subref->($value);
 | 
						|
        }
 | 
						|
        return \%munged;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        return unless $data;
 | 
						|
        my $subref = $munge->{$attr};
 | 
						|
        return $subref->($data);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
=item _validate_autoload_method(method)
 | 
						|
 | 
						|
Used internally by AUTOLOAD to validate that a dynamic method should be
 | 
						|
created.  Returns the OID of the MIB leaf node the method will get or set.
 | 
						|
 | 
						|
=over 
 | 
						|
 | 
						|
=item 1. Returns unless method is listed in %FUNCS, %GLOBALS, or is MIB Leaf
 | 
						|
node name in a loaded MIB for given class.
 | 
						|
 | 
						|
=item 2. Translates the MIB Leaf node name to an OID.
 | 
						|
 | 
						|
=item 3. Checks to see if the method access type is allowed for the resolved
 | 
						|
OID.  Write access for set_ methods, read access for others.
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub _validate_autoload_method {
 | 
						|
    my $self   = shift;
 | 
						|
    my $method = shift;
 | 
						|
 | 
						|
    my $setter = $method =~ /^set/;
 | 
						|
    my $attr = $method;
 | 
						|
    $attr =~ s/^(load|set|orig)_//;
 | 
						|
    $attr =~ s/_raw$//;
 | 
						|
 | 
						|
    my $globals = $self->globals();
 | 
						|
    my $funcs   = $self->funcs();
 | 
						|
 | 
						|
    my $leaf_name = $globals->{$attr} || $funcs->{$attr} || $attr;
 | 
						|
 | 
						|
    # Check for fully qualified name
 | 
						|
    if ( $leaf_name =~ /__/ ) {
 | 
						|
        $leaf_name =~ s/__/::/;
 | 
						|
        $leaf_name =~ s/_/-/g;
 | 
						|
    }
 | 
						|
 | 
						|
    # Translate MIB leaf node name to OID
 | 
						|
    my $oid = SNMP::translateObj($leaf_name);
 | 
						|
 | 
						|
    if ( $leaf_name =~ /^[.]?\d[\.\d]+$/ ) {
 | 
						|
        $oid = $leaf_name;
 | 
						|
    }
 | 
						|
 | 
						|
    unless ( defined $oid ) {
 | 
						|
        print
 | 
						|
            "SNMP::Info::_validate_autoload_method($leaf_name) Unable to resolve method.\n"
 | 
						|
            if $self->debug();
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    # Validate that we have proper access for the operation
 | 
						|
    my $access = $SNMP::MIB{$oid}{'access'} || '';
 | 
						|
 | 
						|
    # If we were given a fully qualified OID because we don't have the MIB
 | 
						|
    # file, it will translate above but we won't be able to check access so
 | 
						|
    # skip the check and return
 | 
						|
    if ($access) {
 | 
						|
        unless ( ( $method =~ /^set/ && $access =~ /Write|Create/ )
 | 
						|
            || $access =~ /Read|Create/ )
 | 
						|
        {
 | 
						|
            print
 | 
						|
                "SNMP::Info::_validate_autoload_method($attr : $oid) Not accessable for requested operation.\n"
 | 
						|
                if $self->debug();
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # If the parent of the leaf has indexes it is contained within a table
 | 
						|
    my $indexes    = $SNMP::MIB{$oid}{'parent'}{'indexes'};
 | 
						|
    my $table_leaf = 0;
 | 
						|
 | 
						|
    if ( !$globals->{$attr}
 | 
						|
        && ( defined $indexes && scalar( @{$indexes} ) > 0 ) )
 | 
						|
    {
 | 
						|
        $table_leaf = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    # Tag on .0 for %GLOBALS and single instance MIB leafs unless
 | 
						|
    # the leaf ends in a digit or we are going to use for a set operation
 | 
						|
    if ( $table_leaf == 0 && ( $globals->{$attr} || $leaf_name ne $oid ) ) {
 | 
						|
 | 
						|
        unless ( $leaf_name =~ /\d$/ || $setter ) {
 | 
						|
            $oid .= ".0";
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    my $return = [ $oid, $table_leaf ];
 | 
						|
    return $return;
 | 
						|
}
 | 
						|
 | 
						|
=item $info->can()
 | 
						|
 | 
						|
Overrides UNIVERSAL::can() so that objects will correctly report their
 | 
						|
capabilities to include dynamic methods generated at run time via AUTOLOAD.
 | 
						|
 | 
						|
Calls parent can() first to see if method exists, if not validates that a
 | 
						|
method should be created then dispatches to the appropriate internal method
 | 
						|
for creation.  The newly created method is inserted into the symbol table
 | 
						|
returning to AUTOLOAD only for the initial method call.
 | 
						|
 | 
						|
Returns undef if the method does not exist and can not be created.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub can {
 | 
						|
    my $self   = shift;
 | 
						|
    my $method = shift;
 | 
						|
 | 
						|
    # use results of parent can()
 | 
						|
    return $self->SUPER::can($method) if $self->SUPER::can($method);
 | 
						|
 | 
						|
    my $validated = $self->_validate_autoload_method($method);
 | 
						|
    return unless $validated;
 | 
						|
 | 
						|
    my ($oid, $table) = @$validated;
 | 
						|
 | 
						|
    # _validate_autoload_method validates, so we need to check for
 | 
						|
    # set_ , funcs, table leafs, and everything else goes to _global
 | 
						|
    my $funcs = $self->funcs();
 | 
						|
 | 
						|
    # We need to resolve funcs with a prefix or suffix
 | 
						|
    my $f_method = $method;
 | 
						|
    $f_method =~ s/^(load|orig)_//;
 | 
						|
    $f_method =~ s/_raw$//;
 | 
						|
 | 
						|
    no strict 'refs';    ## no critic (ProhibitNoStrict )
 | 
						|
 | 
						|
    # Check for set_ ing.
 | 
						|
    if ( $method =~ /^set_/ ) {
 | 
						|
        return *{$AUTOLOAD} = _make_setter( $method, $oid, @_ );
 | 
						|
    }
 | 
						|
    elsif ( defined $funcs->{$f_method} || $table ) {
 | 
						|
        return *{$AUTOLOAD} = _load_attr( $method, $oid, @_ );
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        return *{$AUTOLOAD} = _global( $method, $oid );
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
=head2 AUTOLOAD
 | 
						|
 | 
						|
Each entry in either %FUNCS, %GLOBALS, or MIB Leaf node names present in
 | 
						|
loaded MIBs are used by AUTOLOAD() to create dynamic methods.  Generated
 | 
						|
methods are inserted into the symbol table so that subsequent calls can avoid
 | 
						|
AUTOLOAD() and dispatch directly.
 | 
						|
 | 
						|
=over 
 | 
						|
 | 
						|
=item 1. Returns unless method is listed in %FUNCS, %GLOBALS, or is a MIB
 | 
						|
Leaf node name in a loaded MIB for given class.
 | 
						|
 | 
						|
=item 2. If the method exists in %GLOBALS or is a single instance MIB Leaf
 | 
						|
node name from a loaded MIB, _global() generates the method. 
 | 
						|
 | 
						|
=item 3. If a set_ prefix is present _make_setter() generates the method.
 | 
						|
 | 
						|
=item 4. If the method exists in %FUNCS or is a MIB Leaf node name contained
 | 
						|
within a table from a loaded MIB, _load_attr() generates the method.
 | 
						|
 | 
						|
=item 5. A load_ prefix forces reloading of data and does not use cached data.
 | 
						|
 | 
						|
=item 6. A _raw suffix returns data ignoring any munge routines.
 | 
						|
 | 
						|
=back
 | 
						|
 | 
						|
Override any dynamic method listed in %GLOBALS, %FUNCS, or MIB Leaf node
 | 
						|
name a by creating a subroutine with the same name.
 | 
						|
 | 
						|
For example to override $info->name() create `` sub name {...}'' in your
 | 
						|
subclass.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub AUTOLOAD {
 | 
						|
    my $self = shift;
 | 
						|
    my ($sub_name) = $AUTOLOAD =~ /::(\w+)$/;
 | 
						|
 | 
						|
    return if $sub_name =~ /DESTROY$/;
 | 
						|
 | 
						|
    # Typos in function calls in SNMP::Info subclasses turn into
 | 
						|
    # AUTOLOAD requests for non-methods.  While this is deprecated,
 | 
						|
    # we'll still get called, so report a less confusing error.
 | 
						|
    if ( ref($self) !~ /^SNMP::Info/ ) {
 | 
						|
 | 
						|
        # croak reports one level too high.  die reports here.
 | 
						|
        # I would really like to get the place that's likely to
 | 
						|
        # have the typo, but perl doesn't want me to.
 | 
						|
        croak(
 | 
						|
            "SNMP::Info::AUTOLOAD($AUTOLOAD) called with no class (probably typo of function call to $sub_name)"
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    # This enables us to use SUPER:: for AUTOLOAD methods as well
 | 
						|
    # as the true OO methods.  Method needs to be renamed to prevent
 | 
						|
    # namespace collision when we insert into the symbol table later.
 | 
						|
    if ( $AUTOLOAD =~ /SUPER::$sub_name$/ ) {
 | 
						|
        $AUTOLOAD =~ s/SUPER::$sub_name/orig_$sub_name/;
 | 
						|
        $sub_name = "orig_$sub_name";
 | 
						|
    }
 | 
						|
 | 
						|
    return unless my $meth_ref = $self->can($sub_name, @_);
 | 
						|
    return $self->$meth_ref(@_);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
1;
 | 
						|
 | 
						|
=head1 COPYRIGHT AND LICENSE
 | 
						|
 | 
						|
Changes from SNMP::Info Version 0.7 and on are:
 | 
						|
Copyright (c) 2003-2010 Max Baker and SNMP::Info Developers
 | 
						|
All rights reserved.
 | 
						|
 | 
						|
Original Code is:
 | 
						|
Copyright (c) 2002-2003, Regents of the University of California
 | 
						|
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.
 | 
						|
 | 
						|
=cut
 |