File Coverage

blib/lib/SNMP/Info.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             # SNMP::Info
2             #
3             # Copyright (c) 2003-2012 Max Baker and SNMP::Info Developers
4             # All rights reserved.
5             #
6             # Portions Copyright (c) 2002-2003, Regents of the University of California
7             # All rights reserved.
8             #
9             # See COPYRIGHT at bottom
10              
11             package SNMP::Info;
12              
13 1     1   16508 use warnings;
  1         2  
  1         41  
14 1     1   8 use strict;
  1         10  
  1         25  
15 1     1   4 use Exporter;
  1         8  
  1         33  
16 1     1   224 use SNMP;
  0            
  0            
17             use Carp;
18             use Math::BigInt;
19              
20             @SNMP::Info::ISA = qw/Exporter/;
21             @SNMP::Info::EXPORT_OK = qw//;
22              
23             use vars
24             qw/$VERSION %FUNCS %GLOBALS %MIBS %MUNGE $AUTOLOAD $INIT $DEBUG %SPEED_MAP
25             $NOSUCH $BIGINT $REPEATERS/;
26              
27             $VERSION = '3.36';
28              
29             =head1 NAME
30              
31             SNMP::Info - OO Interface to Network devices and MIBs through SNMP
32              
33             =head1 VERSION
34              
35             SNMP::Info - Version 3.36
36              
37             =head1 AUTHOR
38              
39             SNMP::Info is maintained by team of Open Source authors headed by Eric Miller,
40             Bill Fenner, Max Baker, Jeroen van Ingen and Oliver Gorwits.
41              
42             Please visit L for most up-to-date
43             list of developers.
44              
45             SNMP::Info was originally created at UCSC for the Netdisco project L
46             by Max Baker.
47              
48             =head1 DEVICES SUPPORTED
49              
50             There are now generic classes for most types of device and so the authors
51             recommend loading SNMP::Info with AutoSpecify, and then reporting to the mail
52             list any missing functionality (such as neighbor discovery tables).
53              
54             =head1 SYNOPSIS
55              
56             use SNMP::Info;
57              
58             my $info = new SNMP::Info(
59             # Auto Discover more specific Device Class
60             AutoSpecify => 1,
61             Debug => 1,
62             # The rest is passed to SNMP::Session
63             DestHost => 'router',
64             Community => 'public',
65             Version => 2
66             ) or die "Can't connect to device.\n";
67              
68             my $err = $info->error();
69             die "SNMP Community or Version probably wrong connecting to device. $err\n" if defined $err;
70              
71             $name = $info->name();
72             $class = $info->class();
73             print "SNMP::Info is using this device class : $class\n";
74              
75             # Find out the Duplex status for the ports
76             my $interfaces = $info->interfaces();
77             my $i_duplex = $info->i_duplex();
78              
79             # Get CDP Neighbor info
80             my $c_if = $info->c_if();
81             my $c_ip = $info->c_ip();
82             my $c_port = $info->c_port();
83              
84             # Print out data per port
85             foreach my $iid (keys %$interfaces){
86             my $duplex = $i_duplex->{$iid};
87             # Print out physical port name, not snmp iid
88             my $port = $interfaces->{$iid};
89              
90             print "$port: ";
91             print "$duplex duplex" if defined $duplex;
92              
93             # The CDP Table has table entries different than the interface tables.
94             # So we use c_if to get the map from cdp table to interface table.
95              
96             my %c_map = reverse %$c_if;
97             my $c_key = $c_map{$iid};
98             unless (defined $c_key) {
99             print "\n\n";
100             next;
101             }
102             my $neighbor_ip = $c_ip->{$c_key};
103             my $neighbor_port = $c_port->{$c_key};
104              
105             print " connected to $neighbor_ip / $neighbor_port\n" if defined $neighbor_ip;
106             print "\n";
107              
108             }
109              
110             =head1 SUPPORT
111              
112             Please direct all support, help, and bug requests to the snmp-info-users
113             Mailing List at L.
114              
115             =head1 DESCRIPTION
116              
117             SNMP::Info gives an object oriented interface to information obtained through
118             SNMP.
119              
120             This module is geared towards network devices. Subclasses exist for a number
121             of network devices and common MIBs.
122              
123             The idea behind this module is to give a common interface to data from network
124             devices, leaving the device-specific hacks behind the scenes in subclasses.
125              
126             In the SYNOPSIS example we fetch the name of all the ports on the device and
127             the duplex setting for that port with two methods -- interfaces() and
128             i_duplex().
129              
130             The information may be coming from any number of MIB files and is very vendor
131             specific. SNMP::Info provides you a common method for all supported devices.
132              
133             Adding support for your own device is easy, and takes little SNMP knowledge.
134              
135             The module is not limited to network devices. Any MIB or device can be given
136             an objected oriented front-end by making a module that consists of a couple
137             hashes. See EXTENDING SNMP::INFO.
138              
139             =head1 REQUIREMENTS
140              
141             =over
142              
143             =item 1. Net-SNMP
144              
145             To use this module, you must have Net-SNMP installed on your system.
146             More specifically you need the Perl modules that come with it.
147              
148             DO NOT INSTALL SNMP:: or Net::SNMP from CPAN!
149              
150             The SNMP module is matched to an install of net-snmp, and must be installed
151             from the net-snmp source tree.
152              
153             The Perl module C is found inside the net-snmp distribution. Go to the
154             F directory of the distribution to install it, or run
155             C<./configure --with-perl-modules> from the top directory of the net-snmp
156             distribution.
157              
158             Net-SNMP can be found at http://net-snmp.sourceforge.net
159              
160             Version 5.3.2 or greater is recommended.
161              
162             Versions 5.0.1, 5.0301 and 5.0203 have issues with bulkwalk and are not supported.
163              
164             B: Some versions that come with certain versions of
165             Redhat/Fedora don't have the Perl library installed. Uninstall the RPM and
166             install by hand.
167              
168             =item 2. MIBS
169              
170             SNMP::Info operates on textual descriptors found in MIBs.
171              
172             If you are using SNMP::Info separate from Netdisco,
173             download the Netdisco MIB package at L
174              
175             Make sure that your snmp.conf is updated to point to your MIB directory
176             and that the MIBs are world-readable.
177              
178             =back
179              
180             =head1 DESIGN GOALS
181              
182             =over
183              
184             =item 1. Use of textual MIB leaf identifier and enumerated values
185              
186             =over
187              
188             =item * All values are retrieved via MIB Leaf node names
189              
190             For example SNMP::Info has an entry in its %GLOBALS hash for ``sysName''
191             instead of 1.3.6.1.2.1.1.5.
192              
193             =item * Data returned is in the enumerated value form.
194              
195             For Example instead of looking up 1.3.6.1.2.1.2.2.1.3 and getting back C<23>
196              
197             SNMP::Info will ask for C and will get back C.
198              
199             =back
200              
201             =item 2. SNMP::Info is easily extended to new devices
202              
203             You can create a new subclass for a device by providing four hashes :
204             %GLOBALS, %MIBS, %FUNCS, and %MUNGE.
205              
206             Or you can override any existing methods from a parent class by making a short
207             subroutine.
208              
209             See the section EXTENDING SNMP::INFO for more details.
210              
211             When you make a new subclass for a device, please be sure to send it back to
212             the developers (via Source Forge or the mailing list) for inclusion in the
213             next version.
214              
215             =back
216              
217             =head1 SUBCLASSES
218              
219             These are the subclasses that implement MIBs and support devices:
220              
221             Required MIBs not included in the install instructions above are noted here.
222              
223             =head2 MIB Subclasses
224              
225             These subclasses implement method to access one or more MIBs. These are not
226             used directly, but rather inherited from device subclasses.
227              
228             For more info run C on any of the following module names.
229              
230             =over
231              
232             =item SNMP::Info::AdslLine
233              
234             SNMP Interface to the ADSL-LINE-MIB for ADSL interfaces.
235              
236             Requires the F, down loadable from Cisco.
237              
238             See documentation in L for details.
239              
240             =item SNMP::Info::Aggregate
241              
242             SNMP Interface to F C Aggregated Links
243              
244             See documentation in L for details.
245              
246             =item SNMP::Info::Airespace
247              
248             F and F. Inherited by
249             devices based on the Airespace wireless platform.
250              
251             See documentation in L for details.
252              
253             =item SNMP::Info::AMAP
254              
255             F. Alcatel Mapping Adjacency
256             Protocol (AMAP) Support.
257              
258             See documentation in L for details.
259              
260             =item SNMP::Info::Bridge
261              
262             F (RFC1286). F. Inherited by devices with Layer2
263             support.
264              
265             See documentation in L for details.
266              
267             =item SNMP::Info::CiscoAgg
268              
269             SNMP Interface to Cisco Aggregated Links
270              
271             See documentation in L for details.
272              
273             =item SNMP::Info::CDP
274              
275             F. Cisco Discovery Protocol (CDP) Support. Inherited by
276             Cisco, Enterasys, and HP devices.
277              
278             See documentation in L for details.
279              
280             =item SNMP::Info::CiscoConfig
281              
282             F, F, and F.
283             These OIDs facilitate the writing of configuration files.
284              
285             See documentation in L for details.
286              
287             =item SNMP::Info::CiscoPortSecurity
288              
289             F and F.
290              
291             See documentation in L for details.
292              
293             =item SNMP::Info::CiscoPower
294              
295             F.
296              
297             See documentation in L for details.
298              
299             =item SNMP::Info::CiscoQOS
300              
301             F. A collection of OIDs providing information about
302             a Cisco device's QOS config.
303              
304             See documentation in L for details.
305              
306             =item SNMP::Info::CiscoRTT
307              
308             F. A collection of OIDs providing information about a Cisco
309             device's RTT values.
310              
311             See documentation in L for details.
312              
313             =item SNMP::Info::CiscoStack
314              
315             F.
316              
317             See documentation in L for details.
318              
319             =item SNMP::Info::CiscoStpExtensions
320              
321             F
322              
323             See documentation in L for details.
324              
325             =item SNMP::Info::CiscoStats
326              
327             F, F, and F.
328             Provides common interfaces for memory, cpu, and os statistics for Cisco
329             devices.
330              
331             See documentation in L for details.
332              
333             =item SNMP::Info::CiscoVTP
334              
335             F, F,
336             F
337              
338             See documentation in L for details.
339              
340             =item SNMP::Info::EDP
341              
342             Extreme Discovery Protocol. F
343              
344             See documentation in L for details.
345              
346             =item SNMP::Info::Entity
347              
348             F. Used for device info in Cisco and other vendors.
349              
350             See documentation in L for details.
351              
352             =item SNMP::Info::EtherLike
353              
354             F (RFC1398) - Some Layer3 devices implement this MIB, as well
355             as some Aironet Layer 2 devices (non Cisco).
356              
357             See documentation in L for details.
358              
359             =item SNMP::Info::FDP
360              
361             Foundry (Brocade) Discovery Protocol. F
362              
363             See documentation in L for details.
364              
365             =item SNMP::Info::IPv6
366              
367             SNMP Interface for obtaining configured IPv6 addresses and mapping IPv6
368             addresses to MAC addresses and interfaces, using information from F,
369             F and/or F.
370              
371             See documentation in L for details.
372              
373             =item SNMP::Info::IEEE802dot11
374              
375             F. A collection of OIDs providing information about
376             standards based 802.11 wireless devices.
377              
378             See documentation in L for details.
379              
380             =item SNMP::Info::IEEE802dot3ad
381              
382             SNMP Interface to IEEE Aggregated Links. F
383              
384             See documentation in L for details.
385              
386             =item SNMP::Info::LLDP
387              
388             F, F, and F. Link Layer
389             Discovery Protocol (LLDP) Support.
390              
391             See documentation in L for details.
392              
393             =item SNMP::Info::MAU
394              
395             F (RFC2668). Some Layer2 devices use this for extended Ethernet
396             (Media Access Unit) interface information.
397              
398             See documentation in L for details.
399              
400             =item SNMP::Info::MRO
401              
402             Method resolution introspection for SNMP::Info
403              
404             See documentation in L for details.
405              
406             =item SNMP::Info::NortelStack
407              
408             F, F.
409              
410             See documentation in L for details.
411              
412             =item SNMP::Info::PowerEthernet
413              
414             F
415              
416             See documentation in L for details.
417              
418             =item SNMP::Info::RapidCity
419              
420             F. Inherited by Avaya switches for duplex and VLAN information.
421              
422             See documentation in L for details.
423              
424             =item SNMP::Info::SONMP
425              
426             SynOptics Network Management Protocol (SONMP) F,
427             F. Inherited by
428             Avaya/Nortel/Bay/Synoptics switches and hubs.
429              
430             See documentation in L for details.
431              
432             =back
433              
434             =head2 Device Subclasses
435              
436             These subclasses inherit from one or more classes to provide a common
437             interface to data obtainable from network devices.
438              
439             All the required MIB files are included in the netdisco-mib package.
440             (See Above).
441              
442             =over
443              
444             =item SNMP::Info::Layer1
445              
446             Generic Layer1 Device subclass.
447              
448             See documentation in L for details.
449              
450             =over
451              
452             =item SNMP::Info::Layer1::Allied
453              
454             Subclass for Allied Telesis Repeaters / Hubs.
455              
456             Requires F
457              
458             See documentation in L for details.
459              
460             =item SNMP::Info::Layer1::Asante
461              
462             Subclass for Asante 1012 Hubs.
463              
464             Requires F
465              
466             See documentation in L for details.
467              
468             =item SNMP::Info::Layer1::Bayhub
469              
470             Subclass for Nortel/Bay hubs. This includes System 5000, 100 series,
471             200 series, and probably more.
472              
473             See documentation in L for details.
474              
475             =item SNMP::Info::Layer1::Cyclades
476              
477             Subclass for Cyclades terminal servers.
478              
479             See documentation in L for details.
480              
481             =item SNMP::Info::Layer1::S3000
482              
483             Subclass for Bay/Synoptics hubs. This includes System 3000, 281X, and
484             probably more.
485              
486             See documentation in L for details.
487              
488             =back
489              
490             =item SNMP::Info::Layer2
491              
492             Generic Layer2 Device subclass.
493              
494             See documentation in L for details.
495              
496             =over
497              
498             =item SNMP::Info::Layer2::3Com
499              
500             SNMP::Info::Layer2::3Com - SNMP Interface to L2 3Com Switches
501              
502             See documentation in L for details.
503              
504             =item SNMP::Info::Layer2::Airespace
505              
506             Subclass for Cisco (Airespace) wireless controllers.
507              
508             See documentation in L for details.
509              
510             =item SNMP::Info::Layer2::Aironet
511              
512             Class for Cisco Aironet wireless devices that run IOS. See also
513             Layer3::Aironet for Aironet devices that don't run IOS.
514              
515             See documentation in L for details.
516              
517             =item SNMP::Info::Layer2::Allied
518              
519             Allied Telesis switches.
520              
521             See documentation in L for details.
522              
523             =item SNMP::Info::Layer2::Baystack
524              
525             Subclass for Avaya/Nortel/Bay Ethernet Switch/Baystack switches. This
526             includes 303, 304, 350, 380, 410, 420, 425, 450, 460, 470 series,
527             2500 series, 4000 series, 5000 series, Business Ethernet Switch (BES),
528             Business Policy Switch (BPS), VSP 7000 series, and probably others.
529              
530             See documentation in L for details.
531              
532             =item SNMP::Info::Layer2::Kentrox
533              
534             Class for Kentrox DataSMART DSU/CSU. See L for details.
535              
536             =item SNMP::Info::Layer2::C1900
537              
538             Subclass for Cisco Catalyst 1900 and 1900c Devices running CatOS.
539              
540             See documentation in L for details.
541              
542             =item SNMP::Info::Layer2::C2900
543              
544             Subclass for Cisco Catalyst 2900, 2950, 3500XL, and 3548 devices running IOS.
545              
546             See documentation in L for details.
547              
548             =item SNMP::Info::Layer2::Catalyst
549              
550             Subclass for Cisco Catalyst switches running CatOS. These switches usually
551             report a model number that starts with C. Note that this class
552             does not support everything that has the name Catalyst.
553              
554             See documentation in L for details.
555              
556             =item SNMP::Info::Layer2::Centillion
557              
558             Subclass for Nortel/Bay Centillion and 5000BH ATM switches.
559              
560             See documentation in L for details.
561              
562             =item SNMP::Info::Layer2::Cisco
563              
564             Generic Cisco subclass for layer 2 devices that are not yet supported
565             in more specific subclassesand the base layer 2 Cisco class for
566             other device specific layer 2 Cisco classes.
567              
568             See documentation in L for details.
569              
570             =item SNMP::Info::Layer2::CiscoSB
571              
572             Subclass for Cisco's "Small Business" product line, acquired from
573             Linksys. This currently comprises the Sx300/500 line of switches.
574              
575             See documentation in L for details.
576              
577             =item SNMP::Info::Layer2::HP
578              
579             Subclass for more recent HP Procurve Switches
580              
581             Requires F and F downloaded from HP.
582              
583             See documentation in L for details.
584              
585             =item SNMP::Info::Layer2::HP4000
586              
587             Subclass for older HP Procurve Switches
588              
589             Requires F and F downloaded from HP.
590              
591             See documentation in L for details.
592              
593             =item SNMP::Info::Layer2::HPVC
594              
595             Subclass for HP Virtual Connect Switches
596              
597             See documentation in L for details.
598              
599             =item SNMP::Info::Layer2::N2270
600              
601             Subclass for Nortel 2270 wireless switches.
602              
603             See documentation in L for details.
604              
605             =item SNMP::Info::Layer2::NAP222x
606              
607             Subclass for Nortel 222x series wireless access points.
608              
609             See documentation in L for details.
610              
611             =item SNMP::Info::Layer2::Netgear
612              
613             Subclass for Netgear switches
614              
615             See documentation in L for details.
616              
617             =item SNMP::Info::Layer2::NWSS2300
618              
619             SNMP Interface to Avaya (Trapeze) Wireless Controllers
620              
621             See documentation in L for details.
622              
623             =item SNMP::Info::Layer2::Orinoco
624              
625             Subclass for Orinoco/Proxim wireless access points.
626              
627             See documentation in L for details.
628              
629             =item SNMP::Info::Layer2::Trapeze
630              
631             SNMP Interface to Juniper (Trapeze) Wireless Controllers
632              
633             See documentation in L for details.
634              
635             =item SNMP::Info::Layer2::Ubiquiti
636              
637             SNMP Interface to Ubiquiti Access Points
638              
639             See documentation in L for details.
640              
641             =item SNMP::Info::Layer2::ZyXEL_DSLAM
642              
643             Zyxel DSLAMs. Need I say more?
644              
645             See documentation in L for details.
646              
647             =back
648              
649             =item SNMP::Info::Layer3
650              
651             Generic Layer3 and Layer2+3 Device subclass.
652              
653             See documentation in L for details.
654              
655             =over
656              
657             =item SNMP::Info::Layer3::Aironet
658              
659             Subclass for Cisco Aironet wireless access points (AP) not running IOS. These
660             are usually older devices.
661              
662             MIBs for these devices now included in v2.tar.gz available from ftp.cisco.com.
663              
664             Note Layer2::Aironet
665              
666             See documentation in L for details.
667              
668             =item SNMP::Info::Layer3::AlcatelLucent
669              
670             Alcatel-Lucent OmniSwitch Class.
671              
672             See documentation in L for details.
673              
674             =item SNMP::Info::Layer3::AlteonAD
675              
676             Subclass for Radware Alteon Series ADC switches and Nortel BladeCenter
677             Layer2-3 GbE Switch Modules.
678              
679             See documentation in L for details.
680              
681             =item SNMP::Info::Layer3::Altiga
682              
683             See documentation in L for details.
684              
685             =item SNMP::Info::Layer3::Arista
686              
687             See documentation in L for details.
688              
689             =item SNMP::Info::Layer3::Aruba
690              
691             Subclass for Aruba wireless switches.
692              
693             See documentation in L for details.
694              
695             =item SNMP::Info::Layer3::BayRS
696              
697             Subclass for Avaya/Nortel/Bay Multiprotocol/BayRS routers. This includes
698             BCN, BLN, ASN, ARN, AN, 2430, and 5430 routers.
699              
700             See documentation in L for details.
701              
702             =item SNMP::Info::Layer3::BlueCoatSG
703              
704             Subclass for Blue Coat SG series proxy devices.
705              
706             See documentation in L for details.
707              
708             =item SNMP::Info::Layer3::C3550
709              
710             Subclass for Cisco Catalyst 3550,3540,3560 2/3 switches running IOS.
711              
712             See documentation in L for details.
713              
714             =item SNMP::Info::Layer3::C4000
715              
716             This class covers Catalyst 4000s and 4500s.
717              
718             See documentation in L for details.
719              
720             =item SNMP::Info::Layer3::C6500
721              
722             This class covers Catalyst 6500s in native mode, hybrid mode. Catalyst
723             3750's, 2970's and probably others.
724              
725             See documentation in L for details.
726              
727             =item SNMP::Info::Layer3::Cisco
728              
729             This is a simple wrapper around layer 3 for IOS devices and the base layer 3
730             Cisco class for other device specific layer 3 Cisco classes.
731              
732             See documentation in L for details.
733              
734             =item SNMP::Info::Layer3::CiscoASA
735              
736             Subclass for Cisco Adaptive Security Appliances.
737              
738             See documentation in L for details.
739              
740             =item SNMP::Info::Layer3::CiscoFWSM
741              
742             Subclass for Cisco Firewall Services Modules.
743              
744             See documentation in L for details.
745              
746             =item SNMP::Info::Layer3::CiscoSwitch
747              
748             Base class for L3 Cisco switches. See documentation in
749             L for details.
750              
751             =item SNMP::Info::Layer3::Contivity
752              
753             Subclass for Avaya/Nortel Contivity/VPN Routers.
754              
755             See documentation in L for details.
756              
757             =item SNMP::Info::Layer3::Dell
758              
759             Subclass for Dell PowerConnect switches. D-Link, the IBM BladeCenter
760             Gigabit Ethernet Switch Module and some Linksys switches
761             also use this module based upon MIB support.
762              
763             See documentation in L for details.
764              
765             =item SNMP::Info::Layer3::Enterasys
766              
767             Subclass for Enterasys devices.
768              
769             See documentation in L for details.
770              
771             =item SNMP::Info::Layer3::Extreme
772              
773             Subclass for Extreme Networks switches.
774              
775             See documentation in L for details.
776              
777             =item SNMP::Info::Layer3::F5
778              
779             Subclass for F5 devices.
780              
781             See documentation in L for details.
782              
783             =item SNMP::Info::Layer3::Force10
784              
785             Subclass for Force10 devices.
786              
787             See documentation in L for details.
788              
789             =item SNMP::Info::Layer3::Fortinet
790              
791             Subclass for Fortinet devices.
792              
793             See documentation in L for details.
794              
795             =item SNMP::Info::Layer3::Foundry
796              
797             Subclass for Brocade (Foundry) Network devices.
798              
799             See documentation in L for details.
800              
801             =item SNMP::Info::Layer3::H3C
802              
803             SNMP Interface to Layer 3 Devices, H3C & HP A-series.
804              
805             See documentation in L for details.
806              
807             =item SNMP::Info::Layer3::HP9300
808              
809             Subclass for HP network devices which Foundry Networks was the
810             Original Equipment Manufacturer (OEM) such as the HP ProCurve 9300 and 6300 series.
811              
812             See documentation in L for details.
813              
814             =item SNMP::Info::Layer3::Huawei
815              
816             SNMP Interface to Huawei Layer 3 switches and routers.
817              
818             See documentation in L for details.
819              
820             =item SNMP::Info::Layer3::IBMGbTor
821              
822             SNMP Interface to IBM Rackswitch (formerly Blade Network Technologies)
823             network devices.
824              
825             See documentation in L for details.
826              
827             =item SNMP::Info::Layer3::Juniper
828              
829             Subclass for Juniper devices
830              
831             See documentation in L for details.
832              
833             =item SNMP::Info::Layer3::Lantronix
834              
835             Subclass for Lantronix devices
836              
837             See documentation in L for details.
838              
839             =item SNMP::Info::Layer3::Microsoft
840              
841             Subclass for Generic Microsoft Routers running Microsoft Windows OS.
842              
843             See documentation in L for details.
844              
845             =item SNMP::Info::Layer3::Mikrotik
846              
847             Subclass for Mikrotik devices running RouterOS.
848              
849             See documentation in L for details.
850              
851             =item SNMP::Info::Layer3::N1600
852              
853             Subclass for Avaya/Nortel Ethernet Routing Switch 1600 series.
854              
855             See documentation in L for details.
856              
857             =item SNMP::Info::Layer3::NetSNMP
858              
859             Subclass for host systems running Net-SNMP.
860              
861             See documentation in L for details.
862              
863             =item SNMP::Info::Layer3::Netscreen
864              
865             Subclass for Juniper NetScreen.
866              
867             See documentation in L for details.
868              
869             =item SNMP::Info::Layer3::Nexus
870              
871             Subclass for Cisco Nexus devices running NX-OS
872              
873             See documentation in L for details.
874              
875             =item SNMP::Info::Layer3::PacketFront
876              
877             Subclass for PacketFront DRG series CPE.
878              
879             See documentation in L for details.
880              
881             =item SNMP::Info::Layer3::PaloAlto
882              
883             Subclass for Palo Alto firewalls.
884              
885             See documentation in L for details.
886              
887             =item SNMP::Info::Layer3::Passport
888              
889             Subclass for Avaya/Nortel Ethernet Routing Switch/Passport 8000 series,
890             Accelar, and VSP 9000 series switches.
891              
892             See documentation in L for details.
893              
894             =item SNMP::Info::Layer3::Pf
895              
896             Subclass for FreeBSD-Based Firewalls using Pf /Pf Sense
897              
898             See documentation in L for details.
899              
900             =item SNMP::Info::Layer3::Pica8
901              
902             Subclass for Pica8 devices.
903              
904             See documentation in L for details.
905              
906             =item SNMP::Info::Layer3::SonicWALL
907              
908             Subclass for generic SonicWALL devices. See documentation in
909             L for details.
910              
911             =item SNMP::Info::Layer3::Steelhead
912              
913             Subclass for Riverbed Steelhead WAN optimization appliances. See
914             documentation in L for details.
915              
916             =item SNMP::Info::Layer3::Sun
917              
918             Subclass for Generic Sun Routers running SunOS.
919              
920             See documentation in L for details.
921              
922             =item SNMP::Info::Layer3::Tasman
923              
924             Subclass for Avaya Secure Routers.
925              
926             See documentation in L for details.
927              
928             =item SNMP::Info::Layer3::Timetra
929              
930             Alcatel-Lucent SR Class.
931              
932             See documentation in L for details.
933              
934             =item SNMP::Info::Layer3::VMware
935              
936             Subclass for VMware ESXi hosts.
937              
938             See documentation in L for details.
939              
940             =back
941              
942             =back
943              
944             =over 4
945              
946             =item SNMP::Info::Layer7
947              
948             Generic Layer7 Devices.
949              
950             See documentation in L for details.
951              
952             =over 4
953              
954             =item SNMP::Info::Layer7::APC
955              
956             SNMP Interface to APC UPS devices
957              
958             See documentation in L for details.
959              
960             =item SNMP::Info::Layer7::Netscaler
961              
962             SNMP Interface to Citrix Netscaler appliances
963              
964             See documentation in L for details.
965              
966             =item SNMP::Info::Layer7::Neoteris
967              
968             SNMP Interface to Juniper SSL VPN appliances
969              
970             See documentation in L for details.
971              
972             =back
973              
974             =back
975              
976             =head1 Thanks
977              
978             Thanks for testing and coding help (in no particular order) to :
979             Alexander Barthel, Andy Ford, Alexander Hartmaier, Andrew Herrick, Alex
980             Kramarov, Bernhard Augenstein, Bradley Baetz, Brian Chow, Brian Wilson,
981             Carlos Vicente, Dana Watanabe, David Pinkoski, David Sieborger, Douglas
982             McKeown, Greg King, Ivan Auger, Jean-Philippe Luiggi, Jeroen van Ingen,
983             Justin Hunter, Kent Hamilton, Matthew Tuttle, Michael Robbert, Mike Hunter,
984             Nicolai Petri, Ralf Gross, Robert Kerr and people listed on the Netdisco
985             README!
986              
987             =head1 USAGE
988              
989             =head2 Constructor
990              
991             =over
992              
993             =item new()
994              
995             Creates a new object and connects via SNMP::Session.
996              
997             my $info = new SNMP::Info( 'Debug' => 1,
998             'AutoSpecify' => 1,
999             'BigInt' => 1,
1000             'BulkWalk' => 1,
1001             'BulkRepeaters' => 20,
1002             'IgnoreNetSNMPConf' => 1,
1003             'LoopDetect' => 1,
1004             'DestHost' => 'myrouter',
1005             'Community' => 'public',
1006             'Version' => 2,
1007             'MibDirs' => ['dir1','dir2','dir3'],
1008             ) or die;
1009              
1010             SNMP::Info Specific Arguments :
1011              
1012             =over
1013              
1014             =item AutoSpecify
1015              
1016             Returns an object of a more specific device class
1017              
1018             (default 0, which means "off")
1019              
1020             =item BigInt
1021              
1022             Return Math::BigInt objects for 64 bit counters. Sets on a global scope,
1023             not object.
1024              
1025             (default 0, which means "off")
1026              
1027             =item BulkWalk
1028              
1029             Set to C<0> to turn off BULKWALK commands for SNMPv2 connections.
1030              
1031             Note that BULKWALK is turned off for Net-SNMP versions 5.1.x because of a bug.
1032              
1033             (default 1, which means "on")
1034              
1035             =item BulkRepeaters
1036              
1037             Set number of MaxRepeaters for BULKWALK operation. See
1038             C -> bulkwalk() for more info.
1039              
1040             (default 20)
1041              
1042             =item LoopDetect
1043              
1044             Detects looping during getnext table column walks by comparing IIDs for each
1045             instance. A loop is detected if the same IID is seen more than once and the
1046             walk is aborted. Note: This will not detect loops during a bulkwalk
1047             operation, Net-SNMP's internal bulkwalk function must detect the loop.
1048              
1049             Set to C<0> to turn off loop detection.
1050              
1051             (default 1, which means "on")
1052              
1053             =item IgnoreNetSNMPConf
1054              
1055             Net-SNMP version 5.0 and higher read configuration files, snmp.conf or
1056             snmp.local.conf, from /etc/snmp, /usr/share/snmp, /usr/lib(64)/snmp, or
1057             $HOME/.snmp and uses those settings to automatically parse MIB files, etc.
1058              
1059             Set to C<1> "on" to ignore Net-SNMP configuration files by overriding the
1060             C environmental variable during object initialization. Note:
1061             MibDirs must be defined or Net-SNMP will not be able to load MIBs and
1062             initialize the object.
1063              
1064             (default 0, which means "off")
1065              
1066             =item Debug
1067              
1068             Prints Lots of debugging messages.
1069             Pass 2 to print even more debugging messages.
1070              
1071             (default 0, which means "off")
1072              
1073             =item DebugSNMP
1074              
1075             Set $SNMP::debugging level for Net-SNMP.
1076              
1077             See F for more details.
1078              
1079             =item MibDirs
1080              
1081             Array ref to list of directories in which to look for MIBs. Note this will
1082             be in addition to the ones setup in snmp.conf at the system level.
1083              
1084             (default use net-snmp settings only)
1085              
1086             =item RetryNoSuch
1087              
1088             When using SNMP Version 1, try reading values even if they come back as "no
1089             such variable in this MIB". Set to false if so desired. This feature lets
1090             you read SNMPv2 data from an SNMP version 1 connection, and should probably
1091             be left on.
1092              
1093             (default 1, which means "on")
1094              
1095             =item Session
1096              
1097             SNMP::Session object to use instead of connecting on own.
1098              
1099             (default creates session automatically)
1100              
1101             =item Offline
1102              
1103             Causes SNMP::Info to avoid network activity and return data only from its
1104             cache. If you ask for something not in the cache, an error is thrown. See
1105             also the C and C methods.
1106              
1107             (default 0, which means "online")
1108              
1109             =item Cache
1110              
1111             Pass in a HashRef to prime the cache of retrieved data. Useful for creating an
1112             instance in C mode from a previously dumped cache. See also the
1113             C method to retrieve a cache after running actial queries.
1114              
1115             =item OTHER
1116              
1117             All other arguments are passed to SNMP::Session.
1118              
1119             See SNMP::Session for a list of other possible arguments.
1120              
1121             =back
1122              
1123             A Note about the wrong Community string or wrong SNMP Version:
1124              
1125             If a connection is using the wrong community string or the wrong SNMP version,
1126             the creation of the object will not fail. The device still answers the call
1127             on the SNMP port, but will not return information. Check the error() method
1128             after you create the device object to see if there was a problem in
1129             connecting.
1130              
1131             A note about SNMP Versions :
1132              
1133             Some older devices don't support SNMP version 2, and will not return anything
1134             when a connection under Version 2 is attempted.
1135              
1136             Some newer devices will support Version 1, but will not return all the data
1137             they might have if you had connected under Version 1
1138              
1139             When trying to get info from a new device, you may have to try version 2 and
1140             then fallback to version 1.
1141              
1142             =cut
1143              
1144             sub new {
1145             my $proto = shift;
1146             my $class = ref($proto) || $proto;
1147             my %args = @_;
1148             my %sess_args = %args;
1149             my $new_obj = {};
1150             bless $new_obj, $class;
1151              
1152             $new_obj->{class} = $class;
1153              
1154             # load references to all the subclass data structures
1155             {
1156             no strict 'refs'; ## no critic (ProhibitNoStrict ProhibitProlongedStrictureOverride)
1157             $new_obj->{init} = \${ $class . '::INIT' };
1158             $new_obj->{mibs} = \%{ $class . '::MIBS' };
1159             $new_obj->{globals} = \%{ $class . '::GLOBALS' };
1160             $new_obj->{funcs} = \%{ $class . '::FUNCS' };
1161             $new_obj->{munge} = \%{ $class . '::MUNGE' };
1162             }
1163              
1164             # SNMP::Info specific args :
1165             if ( defined $args{Debug} ) {
1166             $new_obj->debug( $args{Debug} );
1167             delete $sess_args{Debug};
1168             }
1169             else {
1170             $new_obj->debug( defined $DEBUG ? $DEBUG : 0 );
1171             }
1172              
1173             if ( defined $args{DebugSNMP} ) {
1174             $SNMP::debugging = $args{DebugSNMP};
1175             delete $sess_args{DebugSNMP};
1176             }
1177              
1178             my $auto_specific = 0;
1179             if ( defined $args{AutoSpecify} ) {
1180             $auto_specific = $args{AutoSpecify} || 0;
1181             delete $sess_args{AutoSpecify};
1182             }
1183              
1184             if ( defined $args{BulkRepeaters} ) {
1185             $new_obj->{BulkRepeaters} = $args{BulkRepeaters};
1186             delete $sess_args{BulkRepeaters};
1187             }
1188              
1189             if ( defined $args{BulkWalk} ) {
1190             $new_obj->{BulkWalk} = $args{BulkWalk};
1191             delete $sess_args{BulkWalk};
1192             }
1193              
1194             if ( defined $args{LoopDetect} ) {
1195             $new_obj->{LoopDetect} = $args{LoopDetect};
1196             delete $sess_args{LoopDetect};
1197             }
1198              
1199             if ( defined $args{IgnoreNetSNMPConf} ) {
1200             $new_obj->{IgnoreNetSNMPConf} = $args{IgnoreNetSNMPConf} || 0;
1201             delete $sess_args{IgnoreNetSNMPConf};
1202             }
1203              
1204             if ( defined $args{Offline} ) {
1205             $new_obj->{Offline} = $args{Offline} || 0;
1206             delete $sess_args{Offline};
1207             }
1208              
1209             if ( defined $args{Cache} and ref {} eq ref $args{Cache} ) {
1210             $new_obj->{$_} = $args{Cache}->{$_} for keys %{$args{Cache}};
1211             delete $sess_args{Cache};
1212             }
1213              
1214             my $sess = undef;
1215             if ( defined $args{Session} ) {
1216             $sess = $args{Session};
1217             delete $sess_args{Session};
1218             }
1219             if ( defined $args{BigInt} ) {
1220             $BIGINT = $args{BigInt};
1221             delete $sess_args{BigInt};
1222             }
1223             if ( defined $args{MibDirs} ) {
1224             $new_obj->{mibdirs} = $args{MibDirs};
1225             delete $sess_args{MibDirs};
1226             }
1227              
1228             $new_obj->{nosuch} = $args{RetryNoSuch} || $NOSUCH;
1229              
1230             # Initialize mibs if not done
1231             my $init_ref = $new_obj->{init};
1232             unless ( defined $$init_ref and $$init_ref ) {
1233             $new_obj->init();
1234             $$init_ref = 1;
1235             }
1236              
1237             # Connects to device unless open session is provided.
1238             $sess = new SNMP::Session(
1239             'UseEnums' => 1,
1240             %sess_args, 'RetryNoSuch' => $new_obj->{nosuch}
1241             ) unless defined $sess;
1242              
1243             # No session object created
1244             unless ( defined $sess ) {
1245             $new_obj->error_throw("SNMP::Info::new() Failed to Create Session. ");
1246             return;
1247             }
1248              
1249             # Session object created but SNMP connection failed.
1250             my $sess_err = $sess->{ErrorStr} || '';
1251             if ($sess_err) {
1252             $new_obj->error_throw(
1253             "SNMP::Info::new() Net-SNMP session creation failed. $sess_err");
1254             return;
1255             }
1256              
1257             # Save Args for later
1258             $new_obj->{store} ||= {};
1259             $new_obj->{sess} = $sess;
1260             $new_obj->{args} = \%args;
1261             $new_obj->{snmp_ver} = $sess->{Version} || $args{Version} || 2;
1262             $new_obj->{snmp_comm} = $sess->{Community} || $args{Community} || 'public';
1263             $new_obj->{snmp_user} = $sess->{SecName} || $args{SecName} || 'initial';
1264              
1265             return $auto_specific ? $new_obj->specify() : $new_obj;
1266             }
1267              
1268             =item update()
1269              
1270             Replace the existing session with a new one with updated values,
1271             without re-identifying the device. The only supported changes are
1272             to Community or Context.
1273              
1274             Clears the object cache.
1275              
1276             This is useful, e.g., when a device supports multiple contexts
1277             (via changes to the Community string, or via the SNMPv3 Context
1278             parameter), but a context that you want to access does not support
1279             the objects (e.g., C, C) that we use to identify
1280             the device.
1281              
1282             =cut
1283              
1284             sub update {
1285             my $obj = shift;
1286             my %update_args = @_;
1287             my %sess_args = ( %{ $obj->{args} }, %update_args );
1288              
1289             # silently only update "the right" args
1290             delete $sess_args{Debug};
1291             delete $sess_args{DebugSNMP};
1292             delete $sess_args{AutoSpecify};
1293             delete $sess_args{BulkRepeaters};
1294             delete $sess_args{BulkWalk};
1295             delete $sess_args{LoopDetect};
1296             delete $sess_args{IgnoreNetSNMPConf};
1297             delete $sess_args{BigInt};
1298             delete $sess_args{MibDirs};
1299              
1300             my $sess = new SNMP::Session(
1301             'UseEnums' => 1,
1302             %sess_args, 'RetryNoSuch' => $obj->{nosuch}
1303             );
1304             unless ( defined $sess ) {
1305             $obj->error_throw(
1306             "SNMP::Info::update() Failed to Create new Session. ");
1307             return;
1308             }
1309              
1310             # Session object created but SNMP connection failed.
1311             my $sess_err = $sess->{ErrorStr} || '';
1312             if ($sess_err) {
1313             $obj->error_throw(
1314             "SNMP::Info::update() Net-SNMP session creation failed. $sess_err"
1315             );
1316             return;
1317             }
1318             $obj->clear_cache();
1319             return $obj->session($sess);
1320             }
1321              
1322             =back
1323              
1324             =head2 Data is Cached
1325              
1326             Methods and subroutines requesting data from a device will only load the data
1327             once, and then return cached versions of that data.
1328              
1329             Run $info->load_METHOD() where method is something like 'i_name' to reload
1330             data from a method.
1331              
1332             Run $info->clear_cache() to clear the cache to allow reload of both globals
1333             and table methods.
1334              
1335             The cache can be retrieved or set using the $info->cache() method. This works
1336             together with the C option.
1337              
1338             =head2 Object Scalar Methods
1339              
1340             These are for package related data, not directly supplied
1341             from SNMP.
1342              
1343             =over
1344              
1345             =item $info->clear_cache()
1346              
1347             Clears the cached data. This includes GLOBALS data and TABLE METHOD data.
1348              
1349             =cut
1350              
1351             sub clear_cache {
1352             my $self = shift;
1353              
1354             print "SNMP::Info::clear_cache() - Cache Cleared.\n" if $self->debug();
1355              
1356             # Clear cached global values and table method flag for being cached
1357             foreach my $key ( keys %$self ) {
1358             next unless defined $key;
1359             next unless $key =~ /^_/;
1360             delete $self->{$key};
1361             }
1362              
1363             # Clear store for tables
1364             return $self->store( {} );
1365              
1366             }
1367              
1368             =item $info->debug(1)
1369              
1370             Returns current debug status, and optionally toggles debugging info for this
1371             object.
1372              
1373             =cut
1374              
1375             sub debug {
1376             my $self = shift;
1377             my $debug = shift;
1378              
1379             if ( defined $debug ) {
1380             $self->{debug} = $debug;
1381             }
1382              
1383             return $self->{debug};
1384             }
1385              
1386             =item $info->offline([1|0])
1387              
1388             Returns if offline mode is currently turned on for this object.
1389              
1390             Optionally sets the Offline parameter.
1391              
1392             =cut
1393              
1394             sub offline {
1395             my $self = shift;
1396             my $ol = shift;
1397              
1398             if ( defined $ol ) {
1399             $self->{Offline} = $ol;
1400             }
1401             return $self->{Offline};
1402             }
1403              
1404             =item $info->cache([new_cache])
1405              
1406             Returns a HashRef of all cached data in this object. There will be a C
1407             key for table data and then one key for each leaf.
1408              
1409             Optionally sets the cache parameters if passed a HashRef.
1410              
1411             =cut
1412              
1413             sub cache {
1414             my $self = shift;
1415             my $data = shift;
1416              
1417             if ( defined $data and ref {} eq ref $data ) {
1418             $self->{$_} = $data->{$_} for keys %$data;
1419             }
1420              
1421             my $cache = { store => $self->{store} };
1422             foreach my $key ( keys %$self ) {
1423             next unless defined $key;
1424             next unless $key =~ /^_/;
1425             $cache->{$key} = $self->{$key};
1426             }
1427             return $cache;
1428             }
1429              
1430             =item $info->bulkwalk([1|0])
1431              
1432             Returns if bulkwalk is currently turned on for this object.
1433              
1434             Optionally sets the bulkwalk parameter.
1435              
1436             =cut
1437              
1438             sub bulkwalk {
1439             my $self = shift;
1440             my $bw = shift;
1441              
1442             if ( defined $bw ) {
1443             $self->{BulkWalk} = $bw;
1444             }
1445             return $self->{BulkWalk};
1446             }
1447              
1448             =item $info->loopdetect([1|0])
1449              
1450             Returns if loopdetect is currently turned on for this object.
1451              
1452             Optionally sets the loopdetect parameter.
1453              
1454             =cut
1455              
1456             sub loopdetect {
1457             my $self = shift;
1458             my $ld = shift;
1459              
1460             if ( defined $ld ) {
1461             $self->{LoopDetect} = $ld;
1462             }
1463             return $self->{LoopDetect};
1464             }
1465              
1466             =item $info->device_type()
1467              
1468             Returns the Subclass name for this device. C is returned if no
1469             more specific class is available.
1470              
1471             First the device is checked for Layer 3 support and a specific subclass,
1472             then Layer 2 support and subclasses are checked.
1473              
1474             This means that Layer 2 / 3 switches and routers will fall under the
1475             SNMP::Info::Layer3 subclasses.
1476              
1477             If the device still can be connected to via SNMP::Info, then
1478             SNMP::Info is returned.
1479              
1480             =cut
1481              
1482             sub device_type {
1483             my $info = shift;
1484              
1485             my $objtype = "SNMP::Info";
1486              
1487             my $layers = $info->layers() || '00000000';
1488              
1489             my $desc = $info->description() || 'undef';
1490             $desc =~ s/[\r\n\l]+/ /g;
1491              
1492             # Some devices don't implement sysServices, but do return a description.
1493             # In that case, log a warning and continue.
1494             if ( $layers eq '00000000' ) {
1495             if ($desc ne 'undef') {
1496             carp("Device doesn't implement sysServices but did return sysDescr. Might give unexpected results.\n") if $info->debug();
1497             } else {
1498             # No sysServices, no sysDescr
1499             return;
1500             }
1501             }
1502              
1503             my $id = $info->id() || 'undef';
1504             my $soid = $id;
1505              
1506             # Hash for generic fallback to a device class if unable to determine using
1507             # the sysDescr regex.
1508             my %l3sysoidmap = (
1509             9 => 'SNMP::Info::Layer3::Cisco',
1510             11 => 'SNMP::Info::Layer2::HP',
1511             18 => 'SNMP::Info::Layer3::BayRS',
1512             42 => 'SNMP::Info::Layer3::Sun',
1513             43 => 'SNMP::Info::Layer2::3Com',
1514             45 => 'SNMP::Info::Layer2::Baystack',
1515             171 => 'SNMP::Info::Layer3::DLink',
1516             244 => 'SNMP::Info::Layer3::Lantronix',
1517             311 => 'SNMP::Info::Layer3::Microsoft',
1518             674 => 'SNMP::Info::Layer3::Dell',
1519             1872 => 'SNMP::Info::Layer3::AlteonAD',
1520             1916 => 'SNMP::Info::Layer3::Extreme',
1521             1991 => 'SNMP::Info::Layer3::Foundry',
1522             2011 => 'SNMP::Info::Layer3::Huawei',
1523             2021 => 'SNMP::Info::Layer3::NetSNMP',
1524             2272 => 'SNMP::Info::Layer3::Passport',
1525             2636 => 'SNMP::Info::Layer3::Juniper',
1526             2925 => 'SNMP::Info::Layer1::Cyclades',
1527             3076 => 'SNMP::Info::Layer3::Altiga',
1528             3224 => 'SNMP::Info::Layer3::Netscreen',
1529             3375 => 'SNMP::Info::Layer3::F5',
1530             3417 => 'SNMP::Info::Layer3::BlueCoatSG',
1531             4526 => 'SNMP::Info::Layer2::Netgear',
1532             5624 => 'SNMP::Info::Layer3::Enterasys',
1533             6027 => 'SNMP::Info::Layer3::Force10',
1534             6486 => 'SNMP::Info::Layer3::AlcatelLucent',
1535             6527 => 'SNMP::Info::Layer3::Timetra',
1536             6876 => 'SNMP::Info::Layer3::VMware',
1537             8072 => 'SNMP::Info::Layer3::NetSNMP',
1538             9303 => 'SNMP::Info::Layer3::PacketFront',
1539             10002 => 'SNMP::Info::Layer2::Ubiquiti',
1540             12325 => 'SNMP::Info::Layer3::Pf',
1541             12356 => 'SNMP::Info::Layer3::Fortinet',
1542             14179 => 'SNMP::Info::Layer2::Airespace',
1543             14525 => 'SNMP::Info::Layer2::Trapeze',
1544             14823 => 'SNMP::Info::Layer3::Aruba',
1545             14988 => 'SNMP::Info::Layer3::Mikrotik',
1546             17163 => 'SNMP::Info::Layer3::Steelhead',
1547             25506 => 'SNMP::Info::Layer3::H3C',
1548             25461 => 'SNMP::Info::Layer3::PaloAlto',
1549             26543 => 'SNMP::Info::Layer3::IBMGbTor',
1550             30065 => 'SNMP::Info::Layer3::Arista',
1551             35098 => 'SNMP::Info::Layer3::Pica8',
1552             41112 => 'SNMP::Info::Layer2::Ubiquiti',
1553             );
1554              
1555             my %l2sysoidmap = (
1556             9 => 'SNMP::Info::Layer2::Cisco',
1557             11 => 'SNMP::Info::Layer2::HP',
1558             43 => 'SNMP::Info::Layer2::3Com',
1559             45 => 'SNMP::Info::Layer2::Baystack',
1560             171 => 'SNMP::Info::Layer3::DLink',
1561             207 => 'SNMP::Info::Layer2::Allied',
1562             674 => 'SNMP::Info::Layer3::Dell',
1563             1872 => 'SNMP::Info::Layer3::AlteonAD',
1564             1916 => 'SNMP::Info::Layer3::Extreme',
1565             1991 => 'SNMP::Info::Layer3::Foundry',
1566             2011 => 'SNMP::Info::Layer3::Huawei',
1567             2272 => 'SNMP::Info::Layer3::Passport',
1568             2925 => 'SNMP::Info::Layer1::Cyclades',
1569             3224 => 'SNMP::Info::Layer3::Netscreen',
1570             3375 => 'SNMP::Info::Layer3::F5',
1571             4526 => 'SNMP::Info::Layer2::Netgear',
1572             5624 => 'SNMP::Info::Layer3::Enterasys',
1573             6486 => 'SNMP::Info::Layer3::AlcatelLucent',
1574             9303 => 'SNMP::Info::Layer3::PacketFront',
1575             11898 => 'SNMP::Info::Layer2::Orinoco',
1576             14179 => 'SNMP::Info::Layer2::Airespace',
1577             14525 => 'SNMP::Info::Layer2::Trapeze',
1578             14823 => 'SNMP::Info::Layer3::Aruba',
1579             17163 => 'SNMP::Info::Layer3::Steelhead',
1580             26543 => 'SNMP::Info::Layer3::IBMGbTor',
1581             );
1582              
1583             my %l1sysoidmap = (
1584             2925 => 'SNMP::Info::Layer1::Cyclades',
1585             );
1586              
1587             my %l7sysoidmap = (
1588             318 => 'SNMP::Info::Layer7::APC',
1589             5951 => 'SNMP::Info::Layer7::Netscaler',
1590             14525 => 'SNMP::Info::Layer2::Trapeze',
1591             12532 => 'SNMP::Info::Layer7::Neoteris',
1592             );
1593              
1594             # Get just the enterprise number for generic mapping
1595             $id = $1 if ( defined($id) && $id =~ /^\.1\.3\.6\.1\.4\.1\.(\d+)/ );
1596              
1597             if ($info->debug()) {
1598             print "SNMP::Info $VERSION\n";
1599             print "SNMP::Info::device_type() layers:$layers id:$id sysDescr:\"$desc\"\n";
1600             }
1601              
1602             # Layer 3 Supported
1603             # (usually has layer2 as well, so we check for 3 first)
1604             if ( $info->has_layer(3) ) {
1605             $objtype = 'SNMP::Info::Layer3';
1606              
1607             # Device Type Overrides
1608              
1609             return $objtype unless ( defined $desc and length($desc) );
1610              
1611             $objtype = 'SNMP::Info::Layer3::C3550' if $desc =~ /(C3550|C3560)/;
1612             $objtype = 'SNMP::Info::Layer3::C4000' if $desc =~ /Catalyst 4[05]00/;
1613             $objtype = 'SNMP::Info::Layer3::Foundry' if $desc =~ /foundry/i;
1614              
1615             # Aironet - older non-IOS
1616             $objtype = 'SNMP::Info::Layer3::Aironet'
1617             if ($desc =~ /Cisco/
1618             and $desc =~ /\D(CAP340|AP340|CAP350|350|1200)\D/ );
1619             $objtype = 'SNMP::Info::Layer3::Aironet'
1620             if ( $desc =~ /Aironet/ and $desc =~ /\D(AP4800)\D/ );
1621              
1622             # Override voice gateway device (VG350) showing up as Aironet
1623             $objtype = 'SNMP::Info::Layer3::Cisco' if $desc =~ /VG350/;
1624              
1625             # Cat6k with older SUPs (hybrid CatOS/IOS?)
1626             $objtype = 'SNMP::Info::Layer3::C6500' if $desc =~ /(c6sup2|c6sup1)/;
1627              
1628             # Cat6k with Sup720, Sup720 or Sup2T (and Sup2 running native IOS?)
1629             $objtype = 'SNMP::Info::Layer3::C6500'
1630             if $desc =~ /(s72033_rp|s3223_rp|s32p3_rp|s222_rp|s2t54)/;
1631              
1632             # Next one untested. Reported working by DA
1633             $objtype = 'SNMP::Info::Layer3::C6500'
1634             if ( $desc =~ /cisco/i and $desc =~ /3750/ );
1635              
1636             # IOS 15.x on Catalyst 3850
1637             $objtype = 'SNMP::Info::Layer3::C6500'
1638             if ( $desc =~ /cisco/i and $desc =~ /CAT3K/ );
1639              
1640             # Cisco 2970
1641             $objtype = 'SNMP::Info::Layer3::C6500'
1642             if ( $desc =~ /(C2970|C2960)/ );
1643              
1644             # Cisco 3400 w/ Layer3 capable image
1645             $objtype = 'SNMP::Info::Layer3::C3550'
1646             if ( $desc =~ /(ME340x)/ );
1647              
1648             # Various Cisco blade switches, CBS30x0 and CBS31x0 models
1649             $objtype = 'SNMP::Info::Layer3::C6500'
1650             if ( $desc =~ /cisco/i and $desc =~ /CBS3[0-9A-Za-z]{3}/ );
1651              
1652             # Cisco Nexus running NX-OS
1653             $objtype = 'SNMP::Info::Layer3::Nexus'
1654             if ( $desc =~ /^Cisco\s+NX-OS/ );
1655              
1656             # HP, older ProCurve models (1600, 2400, 2424m, 4000, 8000)
1657             $objtype = 'SNMP::Info::Layer2::HP4000'
1658             if $desc =~ /\b(J4093A|J4110A|J4120A|J4121A|J4122A|J4122B)\b/;
1659              
1660             # HP, Foundry OEM
1661             $objtype = 'SNMP::Info::Layer3::HP9300'
1662             if $desc =~ /\b(J4874A|J4138A|J4139A|J4840A|J4841A)\b/;
1663              
1664             # Nortel ERS (Passport) 1600 Series < version 2.1
1665             $objtype = 'SNMP::Info::Layer3::N1600'
1666             if $desc =~ /(Passport|Ethernet\s+Routing\s+Switch)-16/i;
1667              
1668             # ERS - BayStack Numbered
1669             $objtype = 'SNMP::Info::Layer2::Baystack'
1670             if ( $desc
1671             =~ /^(BayStack|Ethernet\s+Routing\s+Switch)\s[2345](\d){2,3}/i );
1672              
1673             # Nortel Contivity
1674             $objtype = 'SNMP::Info::Layer3::Contivity' if $desc =~ /(\bCES\b|\bNVR\sV\d)/;
1675              
1676             # SonicWALL
1677             $objtype = 'SNMP::Info::Layer3::SonicWALL' if $desc =~ /SonicWALL/i;
1678              
1679             # Allied Telesis Layer2 managed switches. They report they have L3 support
1680             $objtype = 'SNMP::Info::Layer2::Allied'
1681             if ( $desc =~ /Allied.*AT-80\d{2}\S*/i );
1682              
1683             # Cisco ASA, newer versions which report layer 3 functionality
1684             # version >= 8.2 are known to do this
1685             $objtype = 'SNMP::Info::Layer3::CiscoASA'
1686             if ( $desc =~ /Cisco Adaptive Security Appliance/i );
1687              
1688             # Cisco FWSM
1689             $objtype = 'SNMP::Info::Layer3::CiscoFWSM'
1690             if ( $desc =~ /Cisco Firewall Services Module/i );
1691            
1692             # Avaya Secure Router
1693             $objtype = 'SNMP::Info::Layer3::Tasman'
1694             if ( $desc =~ /^(avaya|nortel)\s+(SR|secure\srouter)\s+\d{4}/i );
1695              
1696             # HP Virtual Connect blade switches
1697             $objtype = 'SNMP::Info::Layer2::HPVC'
1698             if ( $desc =~ /HP\sVC\s/ );
1699              
1700             # Aironet - IOS
1701             # Starting with IOS 15, Aironet reports sysServices 6, even though
1702             # it still is the same layer2 access point.
1703             $objtype = 'SNMP::Info::Layer2::Aironet'
1704             if ($desc =~ /\b(C1100|C1130|C1140|AP1200|C350|C1200|C1240|C1250|C2700|C3700)\b/
1705             and $desc =~ /\bIOS\b/ );
1706              
1707             # Airespace (WLC) Module
1708             $objtype = 'SNMP::Info::Layer2::Airespace'
1709             if ( $desc =~ /^Cisco Controller$/ );
1710              
1711             #Nortel 2270
1712             $objtype = 'SNMP::Info::Layer2::N2270'
1713             if (
1714             $desc =~ /Nortel\s+(Networks\s+)??WLAN\s+-\s+Security\s+Switch/ );
1715              
1716             # Nortel (Trapeze) WSS 2300 Series
1717             $objtype = 'SNMP::Info::Layer2::NWSS2300'
1718             if (
1719             $desc =~ /^(Nortel\s)??Wireless\sSecurity\sSwitch\s23[568][012]\b/);
1720              
1721             # Generic device classification based upon sysObjectID
1722             if ( ( $objtype eq 'SNMP::Info::Layer3' )
1723             and ( defined($id) )
1724             and ( exists( $l3sysoidmap{$id} ) ) )
1725             {
1726             $objtype = $l3sysoidmap{$id};
1727             }
1728              
1729             # Layer 2 Supported
1730             }
1731             elsif ( $info->has_layer(2) ) {
1732             $objtype = 'SNMP::Info::Layer2';
1733              
1734             return $objtype unless ( defined $desc and $desc !~ /^\s*$/ );
1735              
1736             # Device Type Overrides
1737              
1738             # Bay Hub (Needed here for layers override)
1739             $objtype = 'SNMP::Info::Layer1::Bayhub'
1740             if ( $desc =~ /\bNMM.*Agent/ );
1741             $objtype = 'SNMP::Info::Layer1::Bayhub'
1742             if ( $desc =~ /\bBay\s*Stack.*Hub/i );
1743              
1744             # Synoptics Hub (Needed here for layers override)
1745             # This will override Bay Hub only for specific devices supported
1746             # by this class
1747             $objtype = 'SNMP::Info::Layer1::S3000'
1748             if ( $desc =~ /\bNMM\s+(281|3000|3030)/i );
1749              
1750             # Catalyst 1900 series override
1751             $objtype = 'SNMP::Info::Layer2::C1900'
1752             if ( $desc =~ /catalyst/i and $desc =~ /\D19\d{2}/ );
1753              
1754             # Catalyst 2900 and 3500XL (IOS) series override
1755             $objtype = 'SNMP::Info::Layer2::C2900'
1756             if ( $desc =~ /(C2900XL|C2950|C3500XL|C2940|CGESM|CIGESM)/i );
1757              
1758             # Catalyst WS-C series override 2926,4k,5k,6k in Hybrid
1759             $objtype = 'SNMP::Info::Layer2::Catalyst' if ( $desc =~ /WS-C\d{4}/ );
1760              
1761             # Catalyst 3550 / 3548 Layer2 only switches
1762             # Cisco 3400 w/ MetroBase Image
1763             $objtype = 'SNMP::Info::Layer3::C3550'
1764             if ( $desc =~ /(C3550|ME340x)/ );
1765              
1766             # Cisco blade switches, CBS30x0 and CBS31x0 models with L2 only
1767             $objtype = 'SNMP::Info::Layer3::C6500'
1768             if ( $desc =~ /cisco/i and $desc =~ /CBS3[0-9A-Za-z]{3}/ );
1769              
1770             # Cisco 2970
1771             $objtype = 'SNMP::Info::Layer3::C6500'
1772             if ( $desc =~ /(C2970|C2960)/ );
1773              
1774             # Cisco Small Business (300 500) series override
1775             # This is for enterprises(1).cisco(9).otherEnterprises(6).ciscosb(1)
1776             $objtype = 'SNMP::Info::Layer2::CiscoSB'
1777             if ( $soid =~ /^\.1\.3\.6\.1\.4\.1\.9\.6\.1/ );
1778            
1779             # HP, older ProCurve models (1600, 2400, 2424m, 4000, 8000)
1780             $objtype = 'SNMP::Info::Layer2::HP4000'
1781             if $desc =~ /\b(J4093A|J4110A|J4120A|J4121A|J4122A|J4122B)\b/;
1782              
1783             # HP, Foundry OEM
1784             $objtype = 'SNMP::Info::Layer3::HP9300'
1785             if $desc =~ /\b(J4874A|J4138A|J4139A|J4840A|J4841A)\b/;
1786              
1787             # IBM BladeCenter 4-Port GB Ethernet Switch Module
1788             $objtype = 'SNMP::Info::Layer3::Dell'
1789             if ( $desc =~ /^IBM Gigabit Ethernet Switch Module$/ );
1790              
1791             # Linksys 2024/2048
1792             $objtype = 'SNMP::Info::Layer3::Dell'
1793             if (
1794             $desc =~ /^(24|48)-Port 10\/100\/1000 Gigabit Switch (with |w\/)WebView$/ );
1795              
1796             # Centillion ATM
1797             $objtype = 'SNMP::Info::Layer2::Centillion' if ( $desc =~ /MCP/ );
1798              
1799             # BPS
1800             $objtype = 'SNMP::Info::Layer2::Baystack'
1801             if ( $desc =~ /Business\sPolicy\sSwitch/i );
1802              
1803             # BayStack Numbered
1804             $objtype = 'SNMP::Info::Layer2::Baystack'
1805             if ( $desc
1806             =~ /^(BayStack|Ethernet\s+(Routing\s+)??Switch)\s[2345](\d){2,3}/i
1807             );
1808              
1809             # Kentrox DataSMART DSU/CSU
1810             $objtype = 'SNMP::Info::Layer2::Kentrox'
1811             if ( $desc =~ /^DataSMART/i );
1812              
1813             # Nortel Business Ethernet Switch
1814             $objtype = 'SNMP::Info::Layer2::Baystack'
1815             if ( $desc =~ /^Business Ethernet Switch\s[12]\d\d/i );
1816              
1817             # Nortel AP 222X
1818             $objtype = 'SNMP::Info::Layer2::NAP222x'
1819             if ( $desc =~ /Access\s+Point\s+222/ );
1820              
1821             # Orinoco
1822             $objtype = 'SNMP::Info::Layer2::Orinoco'
1823             if ( $desc =~ /(AP-\d{3}|WavePOINT)/ );
1824              
1825             # Aironet - IOS
1826             $objtype = 'SNMP::Info::Layer2::Aironet'
1827             if ($desc =~ /\b(C1100|C1130|C1140|AP1200|C350|C1200|C1240|C1250)\b/
1828             and $desc =~ /\bIOS\b/ );
1829              
1830             # Aironet - non IOS
1831             $objtype = 'SNMP::Info::Layer3::Aironet'
1832             if ( $desc =~ /Cisco/ and $desc =~ /\D(BR500)\D/ );
1833              
1834             # Airespace (WLC) Module
1835             $objtype = 'SNMP::Info::Layer2::Airespace'
1836             if ( $desc =~ /^Cisco Controller$/ );
1837              
1838             #Nortel 2270
1839             $objtype = 'SNMP::Info::Layer2::N2270'
1840             if (
1841             $desc =~ /Nortel\s+(Networks\s+)??WLAN\s+-\s+Security\s+Switch/ );
1842              
1843             # HP Virtual Connect blade switches
1844             $objtype = 'SNMP::Info::Layer2::HPVC'
1845             if ( $desc =~ /HP\sVC\s/ );
1846              
1847             $objtype = 'SNMP::Info::Layer2::ZyXEL_DSLAM'
1848             if ( $desc =~ /8-port .DSL Module\(Annex .\)/i );
1849              
1850             # Generic device classification based upon sysObjectID
1851             if ( ( $objtype eq 'SNMP::Info::Layer2' )
1852             and ( defined($id) )
1853             and ( exists( $l2sysoidmap{$id} ) ) )
1854             {
1855             $objtype = $l2sysoidmap{$id};
1856             }
1857              
1858             }
1859             elsif ( $info->has_layer(1) ) {
1860             $objtype = 'SNMP::Info::Layer1';
1861              
1862             # Allied crap-o-hub
1863             $objtype = 'SNMP::Info::Layer1::Allied' if ( $desc =~ /allied/i );
1864             $objtype = 'SNMP::Info::Layer1::Asante' if ( $desc =~ /asante/i );
1865              
1866             # Bay Hub
1867             $objtype = 'SNMP::Info::Layer1::Bayhub'
1868             if ( $desc =~ /\bNMM.*Agent/ );
1869             $objtype = 'SNMP::Info::Layer1::Bayhub'
1870             if ( $desc =~ /\bBay\s*Stack.*Hub/i );
1871              
1872             # Synoptics Hub
1873             # This will override Bay Hub only for specific devices supported
1874             # by this class
1875             $objtype = 'SNMP::Info::Layer1::S3000'
1876             if ( $desc =~ /\bNMM\s+(281|3000|3030)/i );
1877              
1878             # Generic device classification based upon sysObjectID
1879             if ( ( $objtype eq 'SNMP::Info::Layer1' )
1880             and ( defined($id) )
1881             and ( exists( $l1sysoidmap{$id} ) ) )
1882             {
1883             $objtype = $l1sysoidmap{$id};
1884             }
1885             }
1886             # These devices don't claim to have Layer1-3 but we like em anyways.
1887             else {
1888             $objtype = 'SNMP::Info::Layer2::ZyXEL_DSLAM'
1889             if ( $desc =~ /8-port .DSL Module\(Annex .\)/i );
1890              
1891             # Aruba wireless switches
1892             $objtype = 'SNMP::Info::Layer3::Aruba'
1893             if ( $desc =~ /(ArubaOS|AirOS)/ );
1894              
1895             # Alcatel-Lucent branded Aruba
1896             $objtype = 'SNMP::Info::Layer3::Aruba'
1897             if ( $desc =~ /^AOS-W/ );
1898              
1899             # Cisco PIX
1900             $objtype = 'SNMP::Info::Layer3::Cisco'
1901             if ( $desc =~ /Cisco PIX Security Appliance/i );
1902              
1903             # Cisco ASA, older version which doesn't report layer 3 functionality
1904             $objtype = 'SNMP::Info::Layer3::CiscoASA'
1905             if ( $desc =~ /Cisco Adaptive Security Appliance/i );
1906              
1907             # HP Virtual Connect blade switches
1908             $objtype = 'SNMP::Info::Layer2::HPVC'
1909             if ( $desc =~ /HP\sVC\s/ );
1910              
1911             # Nortel (Trapeze) WSS 2300 Series
1912             $objtype = 'SNMP::Info::Layer2::NWSS2300'
1913             if (
1914             $desc =~ /^(Nortel\s)??Wireless\sSecurity\sSwitch\s23[568][012]\b/);
1915            
1916             # Cisco IPS, older version which doesn't report layer 3 functionality
1917             $objtype = 'SNMP::Info::Layer7::CiscoIPS'
1918             if ( $soid =~ /\.1\.3\.6\.1\.4\.1\.9\.1\.1545/i );
1919              
1920             # Generic device classification based upon sysObjectID
1921             if ( defined($id) and $objtype eq 'SNMP::Info') {
1922             if ( defined $l3sysoidmap{$id} ) {
1923             $objtype = $l3sysoidmap{$id};
1924             } elsif ( defined $l2sysoidmap{$id}) {
1925             $objtype = $l2sysoidmap{$id};
1926             } elsif ( defined $l7sysoidmap{$id}) {
1927             $objtype = $l7sysoidmap{$id};
1928             } elsif ($info->has_layer(7)) {
1929             $objtype = 'SNMP::Info::Layer7'
1930             }
1931             }
1932             }
1933              
1934             return $objtype;
1935             }
1936              
1937             =item $info->error(no_clear)
1938              
1939             Returns Error message if there is an error, or undef if there is not.
1940              
1941             Reading the error will clear the error unless you set the no_clear flag.
1942              
1943             =cut
1944              
1945             sub error {
1946             my $self = shift;
1947             my $no_clear = shift;
1948             my $err = $self->{error};
1949              
1950             $self->{error} = undef unless defined $no_clear and $no_clear;
1951             return $err;
1952             }
1953              
1954             =item $info->has_layer(3)
1955              
1956             Returns non-zero if the device has the supplied layer in the OSI Model
1957              
1958             Returns if the device doesn't support the layers() call.
1959              
1960             =cut
1961              
1962             sub has_layer {
1963             my $self = shift;
1964             my $check_for = shift;
1965              
1966             my $layers = $self->layers();
1967             return unless defined $layers;
1968             return unless length($layers);
1969             return substr( $layers, 8 - $check_for, 1 );
1970             }
1971              
1972             =item $info->snmp_comm()
1973              
1974             Returns SNMP Community string used in connection.
1975              
1976             =cut
1977              
1978             sub snmp_comm {
1979             my $self = shift;
1980             if ( $self->{snmp_ver} == 3 ) {
1981             return $self->{snmp_user};
1982             }
1983             else {
1984             return $self->{snmp_comm};
1985             }
1986             }
1987              
1988             =item $info->snmp_ver()
1989              
1990             Returns SNMP Version used for this connection
1991              
1992             =cut
1993              
1994             sub snmp_ver {
1995             my $self = shift;
1996             return $self->{snmp_ver};
1997             }
1998              
1999             =item $info->specify()
2000              
2001             Returns an object of a more-specific subclass.
2002              
2003             my $info = new SNMP::Info(...);
2004             # Returns more specific object type
2005             $info = $info->specific();
2006              
2007             Usually this method is called internally from new(AutoSpecify => 1)
2008              
2009             See device_type() entry for how a subclass is chosen.
2010              
2011             =cut
2012              
2013             sub specify {
2014             my $self = shift;
2015              
2016             my $device_type = $self->device_type();
2017             unless ( defined $device_type ) {
2018             $self->error_throw(
2019             "SNMP::Info::specify() - Could not get info from device");
2020             return;
2021             }
2022             return $self if $device_type eq 'SNMP::Info';
2023              
2024             # Load Subclass
2025             # By evaling a string the contents of device_type now becomes a bareword.
2026             eval "require $device_type;"; ## no critic
2027             if ($@) {
2028             croak "SNMP::Info::specify() Loading $device_type Failed. $@\n";
2029             }
2030              
2031             my $args = $self->args();
2032             my $session = $self->session();
2033             my $sub_obj = $device_type->new(
2034             %$args,
2035             'Session' => $session,
2036             'AutoSpecify' => 0
2037             );
2038              
2039             unless ( defined $sub_obj ) {
2040             $self->error_throw(
2041             "SNMP::Info::specify() - Could not connect with new class ($device_type)"
2042             );
2043             return $self;
2044             }
2045              
2046             $self->debug()
2047             and print "SNMP::Info::specify() - Changed Class to $device_type.\n";
2048             return $sub_obj;
2049             }
2050              
2051             =item $info->cisco_comm_indexing()
2052              
2053             Returns 0. Is an overridable method used for vlan indexing for
2054             snmp calls on certain Cisco devices.
2055              
2056             See L
2057              
2058             =cut
2059              
2060             sub cisco_comm_indexing {
2061             return 0;
2062             }
2063              
2064             =back
2065              
2066             =head2 Globals (Scalar Methods)
2067              
2068             These are methods to return scalar data from RFC1213.
2069              
2070             Some subset of these is probably available for any network device that speaks
2071             SNMP.
2072              
2073             =over
2074              
2075             =item $info->uptime()
2076              
2077             Uptime in hundredths of seconds since device became available.
2078              
2079             (C)
2080              
2081             =item $info->contact()
2082              
2083             (C)
2084              
2085             =item $info->name()
2086              
2087             (C)
2088              
2089             =item $info->location()
2090              
2091             (C)
2092              
2093             =item $info->layers()
2094              
2095             This returns a binary encoded string where each
2096             digit represents a layer of the OSI model served
2097             by the device.
2098              
2099             eg: 01000010 means layers 2 (physical) and 7 (Application)
2100             are served.
2101              
2102             Note: This string is 8 digits long.
2103              
2104             See $info->has_layer()
2105              
2106             (C)
2107              
2108             =item $info->ports()
2109              
2110             Number of interfaces available on this device.
2111              
2112             Not too useful as the number of SNMP interfaces usually does not
2113             correspond with the number of physical ports
2114              
2115             (C)
2116              
2117             =item $info->ipforwarding()
2118              
2119             The indication of whether the entity is acting as an IP gateway
2120              
2121             Returns either forwarding or not-forwarding
2122              
2123             (C)
2124              
2125             =back
2126              
2127             =head2 Table Methods
2128              
2129             Each of these methods returns a hash_reference to a hash keyed on the
2130             interface index in SNMP.
2131              
2132             Example : $info->interfaces() might return
2133              
2134             { '1.12' => 'FastEthernet/0',
2135             '2.15' => 'FastEthernet/1',
2136             '9.99' => 'FastEthernet/2'
2137             }
2138              
2139             The key is what you would see if you were to do an snmpwalk, and in some cases
2140             changes between reboots of the network device.
2141              
2142             =head2 Partial Table Fetches
2143              
2144             If you want to get only a part of an SNMP table or a single instance from the
2145             table and you know the IID for the part of the table that you want, you can
2146             specify it in the call:
2147              
2148             $local_routes = $info->ipr_route('192.168.0');
2149              
2150             This will only fetch entries in the table that start with C<192.168.0>, which
2151             in this case are routes on the local network.
2152              
2153             Remember that you must supply the partial IID (a numeric OID).
2154              
2155             Partial table results are not cached.
2156              
2157             =head2 Interface Information
2158              
2159             =over
2160              
2161             =item $info->interfaces()
2162              
2163             This methods is overridden in each subclass to provide a
2164             mapping between the Interface Table Index (iid) and the physical port name.
2165              
2166             =item $info->if_ignore()
2167              
2168             Returns a reference to a hash where key values that exist are
2169             interfaces to ignore.
2170              
2171             Ignored interfaces are ones that are usually not physical ports or Virtual
2172             Lans (VLANs) such as the Loopback interface, or the CPU interface.
2173              
2174             =cut
2175              
2176             sub if_ignore {
2177             my %nothing;
2178             return \%nothing;
2179             }
2180              
2181             =item $info->bulkwalk_no()
2182              
2183             Returns 0. Is an overridable method used for turn off bulkwalk for the
2184             device class.
2185              
2186             =cut
2187              
2188             sub bulkwalk_no {
2189             return 0;
2190             }
2191              
2192             =item $info->i_index()
2193              
2194             Default SNMP IID to Interface index.
2195              
2196             (C)
2197              
2198             =item $info->i_description()
2199              
2200             Description of the interface. Usually a little longer single word name that is
2201             both human and machine friendly. Not always.
2202              
2203             (C)
2204              
2205             =item $info->i_type()
2206              
2207             Interface type, such as Vlan, Ethernet, Serial
2208              
2209             (C)
2210              
2211             =item $info->i_mtu()
2212              
2213             INTEGER. Interface MTU value.
2214              
2215             (C)
2216              
2217             =item $info->i_speed()
2218              
2219             Speed of the link, human format. See munge_speed() later in document for
2220             details.
2221              
2222             (C, C if necessary)
2223              
2224             =cut
2225              
2226             sub i_speed {
2227             my $info = shift;
2228             my $partial = shift;
2229              
2230             my $i_speed = $info->orig_i_speed($partial);
2231              
2232             my $i_speed_high = undef;
2233             foreach my $i ( keys %$i_speed ) {
2234             if ( $i_speed->{$i} eq "4294967295" ) {
2235             $i_speed_high = $info->i_speed_high($partial)
2236             unless defined($i_speed_high);
2237             $i_speed->{$i} = $i_speed_high->{$i} if ( $i_speed_high->{$i} );
2238             }
2239             }
2240             return $i_speed;
2241             }
2242              
2243             =item $info->i_speed_raw()
2244              
2245             Speed of the link in bits per second without munging.
2246             If i_speed_high is available it will be used and multiplied by 1_000_000.
2247              
2248             (C, C if necessary)
2249              
2250             =cut
2251              
2252             sub i_speed_raw {
2253             my $info = shift;
2254             my $partial = shift;
2255              
2256             # remove the speed formating
2257             my $munge_i_speed = delete $info->{munge}{i_speed};
2258             # also for highspeed interfaces e.g. TenGigabitEthernet
2259             my $munge_i_speed_high = delete $info->{munge}{i_speed_high};
2260              
2261             my $i_speed_raw = $info->orig_i_speed($partial);
2262              
2263             my $i_speed_high = undef;
2264             foreach my $i ( keys %$i_speed_raw ) {
2265             if ( $i_speed_raw->{$i} eq "4294967295" ) {
2266             $i_speed_high = $info->i_speed_high($partial)
2267             unless defined($i_speed_high);
2268             $i_speed_raw->{$i} = ( $i_speed_high->{$i} * 1_000_000 )
2269             if ( $i_speed_high->{$i} );
2270             }
2271             }
2272              
2273             # restore the speed formating
2274             $info->{munge}{i_speed} = $munge_i_speed;
2275             $info->{munge}{i_speed_high} = $munge_i_speed_high;
2276              
2277             return $i_speed_raw;
2278             }
2279              
2280             =item $info->i_speed_high()
2281              
2282             Speed of a high-speed link, human format. See munge_highspeed() later in
2283             document for details. You should not need to call this directly, as
2284             i_speed() will call it if it needs to.
2285              
2286             (C)
2287              
2288             =item $info->i_mac()
2289              
2290             MAC address of the interface. Note this is just the MAC of the port, not
2291             anything connected to it.
2292              
2293             (C)
2294              
2295             =item $info->i_up()
2296              
2297             Link Status of the interface. Typical values are 'up' and 'down'.
2298              
2299             (C)
2300              
2301             =item $info->i_up_admin()
2302              
2303             Administrative status of the port. Typical values are 'enabled' and 'disabled'.
2304              
2305             (C)
2306              
2307             =item $info->i_lastchange()
2308              
2309             The value of C when this port last changed states (up,down).
2310              
2311             (C)
2312              
2313             =item $info->i_name()
2314              
2315             Interface Name field. Supported by a smaller subset of devices, this fields
2316             is often human set.
2317              
2318             (C)
2319              
2320             =item $info->i_alias()
2321              
2322             Interface Name field. For certain devices this is a more human friendly form
2323             of i_description(). For others it is a human set field like i_name().
2324              
2325             (C)
2326              
2327             =back
2328              
2329             =head2 Interface Statistics
2330              
2331             =over
2332              
2333             =item $info->i_octet_in(), $info->i_octets_out(),
2334             $info->i_octet_in64(), $info->i_octets_out64()
2335              
2336             Bandwidth.
2337              
2338             Number of octets sent/received on the interface including framing characters.
2339              
2340             64 bit version may not exist on all devices.
2341              
2342             NOTE: To manipulate 64 bit counters you need to use Math::BigInt, since the
2343             values are too large for a normal Perl scalar. Set the global
2344             $SNMP::Info::BIGINT to 1 , or pass the BigInt value to new() if you want
2345             SNMP::Info to do it for you.
2346              
2347              
2348             (C) (C)
2349             (C) (C)
2350              
2351             =item $info->i_errors_in(), $info->i_errors_out()
2352              
2353             Number of packets that contained an error preventing delivery. See C
2354             for more info.
2355              
2356             (C) (C)
2357              
2358             =item $info->i_pkts_ucast_in(), $info->i_pkts_ucast_out(),
2359             $info->i_pkts_ucast_in64(), $info->i_pkts_ucast_out64()
2360              
2361             Number of packets not sent to a multicast or broadcast address.
2362              
2363             64 bit version may not exist on all devices.
2364              
2365             (C) (C)
2366             (C) (C)
2367              
2368             =item $info->i_pkts_nucast_in(), $info->i_pkts_nucast_out(),
2369              
2370             Number of packets sent to a multicast or broadcast address.
2371              
2372             These methods are deprecated by i_pkts_multi_in() and i_pkts_bcast_in()
2373             according to C. Actual device usage may vary.
2374              
2375             (C) (C)
2376              
2377             =item $info->i_pkts_multi_in() $info->i_pkts_multi_out(),
2378             $info->i_pkts_multi_in64(), $info->i_pkts_multi_out64()
2379              
2380             Number of packets sent to a multicast address.
2381              
2382             64 bit version may not exist on all devices.
2383              
2384             (C) (C)
2385             (C) (C)
2386              
2387             =item $info->i_pkts_bcast_in() $info->i_pkts_bcast_out(),
2388             $info->i_pkts_bcast_in64() $info->i_pkts_bcast_out64()
2389              
2390             Number of packets sent to a broadcast address on an interface.
2391              
2392             64 bit version may not exist on all devices.
2393              
2394             (C) (C)
2395             (C) (C)
2396              
2397             =item $info->i_discards_in() $info->i_discards_out()
2398              
2399             "The number of inbound packets which were chosen to be discarded even though
2400             no errors had been detected to prevent their being deliverable to a
2401             higher-layer protocol. One possible reason for discarding such a packet could
2402             be to free up buffer space." (C)
2403              
2404             (C) (C)
2405              
2406             =item $info->i_bad_proto_in()
2407              
2408             "For packet-oriented interfaces, the number of packets received via the
2409             interface which were discarded because of an unknown or unsupported protocol.
2410             For character-oriented or fixed-length interfaces that support protocol
2411             multiplexing the number of transmission units received via the interface which
2412             were discarded because of an unknown or unsupported protocol. For any
2413             interface that does not support protocol multiplexing, this counter will always
2414             be 0."
2415              
2416             (C)
2417              
2418             =item $info->i_qlen_out()
2419              
2420             "The length of the output packet queue (in packets)."
2421              
2422             (C)
2423              
2424             =item $info->i_specific()
2425              
2426             See C for full description
2427              
2428             (C)
2429              
2430             =back
2431              
2432             =head2 IP Address Table
2433              
2434             Each entry in this table is an IP address in use on this device. Usually
2435             this is implemented in Layer3 Devices.
2436              
2437             =over
2438              
2439             =item $info->ip_index()
2440              
2441             Maps the IP Table to the IID
2442              
2443             (C)
2444              
2445             =item $info->ip_table()
2446              
2447             Maps the Table to the IP address
2448              
2449             (C)
2450              
2451             =item $info->ip_netmask()
2452              
2453             Gives netmask setting for IP table entry.
2454              
2455             (C)
2456              
2457             =item $info->ip_broadcast()
2458              
2459             Gives broadcast address for IP table entry.
2460              
2461             (C)
2462              
2463             =back
2464              
2465             =head2 IP Routing Table
2466              
2467             =over
2468              
2469             =item $info->ipr_route()
2470              
2471             The route in question. A value of 0.0.0.0 is the default gateway route.
2472              
2473             (C)
2474              
2475             =item $info->ipr_if()
2476              
2477             The interface (IID) that the route is on. Use interfaces() to map.
2478              
2479             (C)
2480              
2481             =item $info->ipr_1()
2482              
2483             Primary routing metric for this route.
2484              
2485             (C)
2486              
2487             =item $info->ipr_2()
2488              
2489             If metrics are not used, they should be set to -1
2490              
2491             (C)
2492              
2493             =item $info->ipr_3()
2494              
2495             (C)
2496              
2497             =item $info->ipr_4()
2498              
2499             (C)
2500              
2501             =item $info->ipr_5()
2502              
2503             (C)
2504              
2505             =item $info->ipr_dest()
2506              
2507             From RFC1213:
2508              
2509             "The IP address of the next hop of this route.
2510             (In the case of a route bound to an interface
2511             which is realized via a broadcast media, the value
2512             of this field is the agent's IP address on that
2513             interface.)"
2514              
2515             (C)
2516              
2517             =item $info->ipr_type()
2518              
2519             From RFC1213:
2520              
2521             other(1), -- none of the following
2522             invalid(2), -- an invalidated route
2523             -- route to directly
2524             direct(3), -- connected (sub-)network
2525             -- route to a non-local
2526             indirect(4) -- host/network/sub-network
2527              
2528              
2529             "The type of route. Note that the values
2530             direct(3) and indirect(4) refer to the notion of
2531             direct and indirect routing in the IP
2532             architecture.
2533              
2534             Setting this object to the value invalid(2) has
2535             the effect of invalidating the corresponding entry
2536             in the ipRouteTable object. That is, it
2537             effectively disassociates the destination
2538             identified with said entry from the route
2539             identified with said entry. It is an
2540             implementation-specific matter as to whether the
2541             agent removes an invalidated entry from the table.
2542             Accordingly, management stations must be prepared
2543             to receive tabular information from agents that
2544             corresponds to entries not currently in use.
2545             Proper interpretation of such entries requires
2546             examination of the relevant ipRouteType object."
2547              
2548             (C)
2549              
2550             =item $info->ipr_proto()
2551              
2552             From RFC1213:
2553              
2554             other(1), -- none of the following
2555             -- non-protocol information,
2556             -- e.g., manually configured
2557             local(2), -- entries
2558             -- set via a network
2559             netmgmt(3), -- management protocol
2560             -- obtained via ICMP,
2561             icmp(4), -- e.g., Redirect
2562             -- the remaining values are
2563             -- all gateway routing
2564             -- protocols
2565             egp(5),
2566             ggp(6),
2567             hello(7),
2568             rip(8),
2569             is-is(9),
2570             es-is(10),
2571             ciscoIgrp(11),
2572             bbnSpfIgp(12),
2573             ospf(13),
2574             bgp(14)
2575              
2576             (C)
2577              
2578             =item $info->ipr_age()
2579              
2580             Seconds since route was last updated or validated.
2581              
2582             (C)
2583              
2584             =item $info->ipr_mask()
2585              
2586             Subnet Mask of route. 0.0.0.0 for default gateway.
2587              
2588             (C)
2589              
2590             =item $info->ipr_info()
2591              
2592             Reference to MIB definition specific to routing protocol.
2593              
2594             (C)
2595              
2596             =back
2597              
2598             =head2 Topology Information
2599              
2600             Based upon the manufacturer and software version devices may support some
2601             combination of Layer 2 topology protocol information. SNMP::Info
2602             supports querying Link Layer Discovery Protocol (LLDP), Cisco Discovery
2603             Protocol (CDP), SynOptics/Bay/Nortel/Avaya Network Management Protocol
2604             (SONMP), Foundry/Brocade Discovery Protocol (FDP), Extreme Discovery
2605             Protocol (EDP), and Alcatel Mapping Adjacency Protocol (AMAP).
2606              
2607             For protocol specific information and implementation:
2608              
2609             =over
2610              
2611             =item LLDP: See L for details.
2612              
2613             =item CDP: See L for details.
2614              
2615             =item SONMP: See L for details.
2616              
2617             =item FDP: See L for details.
2618              
2619             =item EDP: See L for details.
2620              
2621             =item AMAP: See L for details.
2622              
2623             =back
2624              
2625             =head3 Topology Capabilities
2626              
2627             =over
2628              
2629             =item $info->has_topo()
2630              
2631             Reports Layer 2 topology protocols which are supported and running on
2632             a device.
2633              
2634             Returns either a reference to an array of protocols, possible values
2635             being: C, C, C, C, C, C or C if
2636             no protocols are supported or running.
2637              
2638             =back
2639              
2640             =cut
2641              
2642             sub has_topo {
2643             my $self = shift;
2644              
2645             my @topo_cap;
2646             push( @topo_cap, 'lldp' )
2647             if ( $self->can('hasLLDP') && $self->hasLLDP() );
2648             push( @topo_cap, 'cdp' ) if $self->can('hasCDP') && $self->hasCDP();
2649             push( @topo_cap, 'sonmp' )
2650             if $self->can('hasSONMP') && $self->hasSONMP();
2651             push( @topo_cap, 'fdp' ) if $self->can('hasFDP') && $self->hasFDP();
2652             push( @topo_cap, 'edp' ) if $self->can('hasEDP') && $self->hasEDP();
2653             push( @topo_cap, 'amap' ) if $self->can('hasAMAP') && $self->hasAMAP();
2654              
2655             if (@topo_cap) {
2656             return \@topo_cap;
2657             }
2658             else {
2659             return;
2660             }
2661             }
2662              
2663             sub _get_topo_data {
2664             my $self = shift;
2665             my $partial = shift;
2666             my $topo_cap = shift;
2667             my $method = shift;
2668              
2669             return unless $method =~ /(ip|if|port|id|platform|cap)/;
2670              
2671             my %t_data;
2672             foreach my $proto (@$topo_cap) {
2673             next unless $proto =~ /(lldp|cdp|sonmp|fdp|edp|amap)/;
2674             my $method_name = "$proto" . "_$method";
2675             my $cdp = $self->$method_name($partial) || {};
2676              
2677             foreach my $iid ( keys %$cdp ) {
2678             my $ip = $cdp->{$iid};
2679             next unless defined $ip;
2680              
2681             $t_data{$iid} = $ip;
2682             }
2683             }
2684             return \%t_data;
2685             }
2686              
2687             =head3 Common Topology Table Information
2688              
2689             The common topology table methods below will query the
2690             device for information from the specified topology protocols and return a
2691             single hash combining all information. As a result, there may be identical
2692             topology information returned from the two protocols causing duplicate
2693             entries. It is the calling program's responsibility to identify any
2694             duplicate entries and remove duplicates if necessary. If it is necessary
2695             to understand which protocol provided the information, utilize the protocol
2696             specific methods directly rather than the generic methods.
2697              
2698             The methods support partial table fetches by providing a partial as the
2699             first argument.
2700              
2701             If a reference to an array is provided as the second argument, those
2702             protocols will be queried for information. The supported array values are:
2703             C, C, C, C, C, C.
2704              
2705             If nothing is passed in as the second argument, the methods will call
2706             has_topo() to determine supported and running topology protocols on the
2707             device.
2708              
2709             =over
2710              
2711             =item $info->c_ip(partial, topology_protocol_arrayref)
2712              
2713             Returns reference to hash. Key: iid, Value: remote IPv4 address
2714              
2715             If multiple entries exist with the same local port, c_if(), with the
2716             same IPv4 address, c_ip(), it may be a duplicate entry.
2717              
2718             If multiple entries exist with the same local port, c_if(), with different
2719             IPv4 addresses, c_ip(), there is either a device in between two or
2720             more devices utilizing a different topology protocol or multiple devices
2721             which are not directly connected.
2722              
2723             Use the protocol specific methods to dig deeper.
2724              
2725             =cut
2726              
2727             sub c_ip {
2728             my $self = shift;
2729             my $partial = shift;
2730             my $topo_cap = shift;
2731              
2732             # Default to old behavior if not called with topo_cap
2733             if ( !$topo_cap ) {
2734             my $topo_test = $self->has_topo();
2735             if ($topo_test) {
2736             $topo_cap = $topo_test;
2737             }
2738             else {
2739             return;
2740             }
2741             }
2742             return _get_topo_data ($self, $partial, $topo_cap, 'ip');
2743             }
2744              
2745             =item $info->c_if(partial, topology_protocol_arrayref)
2746              
2747             Returns reference to hash. Key: iid, Value: local device port (interfaces)
2748              
2749             =cut
2750              
2751             sub c_if {
2752             my $self = shift;
2753             my $partial = shift;
2754             my $topo_cap = shift;
2755              
2756             # Default to old behavior if not called with topo_cap
2757             if ( !$topo_cap ) {
2758             my $topo_test = $self->has_topo();
2759             if ($topo_test) {
2760             $topo_cap = $topo_test;
2761             }
2762             else {
2763             return;
2764             }
2765             }
2766             return _get_topo_data ($self, $partial, $topo_cap, 'if');
2767             }
2768              
2769             =item $info->c_port(partial, topology_protocol_arrayref)
2770              
2771             Returns reference to hash. Key: iid, Value: remote port (interfaces)
2772              
2773             =cut
2774              
2775             sub c_port {
2776             my $self = shift;
2777             my $partial = shift;
2778             my $topo_cap = shift;
2779              
2780             # Default to old behavior if not called with topo_cap
2781             if ( !$topo_cap ) {
2782             my $topo_test = $self->has_topo();
2783             if ($topo_test) {
2784             $topo_cap = $topo_test;
2785             }
2786             else {
2787             return;
2788             }
2789             }
2790             return _get_topo_data ($self, $partial, $topo_cap, 'port');
2791             }
2792              
2793             =item $info->c_id(partial, topology_protocol_arrayref)
2794              
2795             Returns reference to hash. Key: iid, Value: string value used to identify the
2796             chassis component associated with the remote system.
2797              
2798             Note: SONMP does not return this information.
2799              
2800             =cut
2801              
2802             sub c_id {
2803             my $self = shift;
2804             my $partial = shift;
2805             my $topo_cap = shift;
2806              
2807             # Default to old behavior if not called with topo_cap
2808             if ( !$topo_cap ) {
2809             my $topo_test = $self->has_topo();
2810             if ($topo_test) {
2811             $topo_cap = $topo_test;
2812             }
2813             else {
2814             return;
2815             }
2816             }
2817             return _get_topo_data ($self, $partial, $topo_cap, 'id');
2818             }
2819              
2820             =item $info->c_platform(partial, topology_protocol_arrayref)
2821              
2822             Returns reference to hash. Key: iid, Value: Remote Device Type
2823              
2824             Note: EDP does not provide this information. LLDP uses (C)
2825             or C as the closest match.
2826              
2827             =cut
2828              
2829             sub c_platform {
2830             my $self = shift;
2831             my $partial = shift;
2832             my $topo_cap = shift;
2833              
2834             # Default to old behavior if not called with topo_cap
2835             if ( !$topo_cap ) {
2836             my $topo_test = $self->has_topo();
2837             if ($topo_test) {
2838             $topo_cap = $topo_test;
2839             }
2840             else {
2841             return;
2842             }
2843             }
2844             return _get_topo_data ($self, $partial, $topo_cap, 'platform');
2845             }
2846              
2847             =item $info->c_cap(partial, topology_protocol_arrayref)
2848              
2849             Returns reference to hash of arrays. Key: iid, Value: Array of capabilities
2850             supported by the device. See the specific protocol class for string values
2851             which could be elements within the array.
2852              
2853             Note: Only CDP and LLDP support this method.
2854              
2855             =cut
2856              
2857             sub c_cap {
2858             my $self = shift;
2859             my $partial = shift;
2860             my $topo_cap = shift;
2861              
2862             # Default to old behavior if not called with topo_cap
2863             if ( !$topo_cap ) {
2864             my $topo_test = $self->has_topo();
2865             if ($topo_test) {
2866             $topo_cap = $topo_test;
2867             }
2868             else {
2869             return;
2870             }
2871             }
2872             return _get_topo_data ($self, $partial, $topo_cap, 'cap');
2873             }
2874              
2875             =back
2876              
2877             =head1 SETTING DATA VIA SNMP
2878              
2879             This section explains how to use SNMP::Info to do SNMP Set operations.
2880              
2881             =over
2882              
2883             =item $info->set_METHOD($value)
2884              
2885             Sets the global METHOD to value. Assumes that iid is .0
2886              
2887             Returns if failed, or the return value from SNMP::Session::set() (snmp_errno)
2888              
2889             $info->set_location("Here!");
2890              
2891             =item $info->set_METHOD($value,$iid)
2892              
2893             Table Methods. Set iid of method to value.
2894              
2895             Returns if failed, or the return value from SNMP::Session::set() (snmp_errno)
2896              
2897             # Disable a port administratively
2898             my %if_map = reverse %{$info->interfaces()}
2899             $info->set_i_up_admin('down', $if_map{'FastEthernet0/0'})
2900             or die "Couldn't disable the port. ",$info->error(1);
2901              
2902             =back
2903              
2904             NOTE: You must be connected to your device with a C community
2905             string in order for set operations to work.
2906              
2907             NOTE: This will only set data listed in %FUNCS and %GLOBALS. For data
2908             acquired from overridden methods (subroutines) specific set_METHOD()
2909             subroutines will need to be added if they haven't been already.
2910              
2911             =head1 Quiet Mode
2912              
2913             SNMP::Info will not chirp anything to STDOUT unless there is a serious error
2914             (in which case it will probably die).
2915              
2916             To get lots of debug info, set the Debug flag when calling new() or
2917             call $info->debug(1);
2918              
2919             When calling a method check the return value. If the return value is undef
2920             then check $info->error()
2921              
2922             Beware, calling $info->error() clears the error.
2923              
2924             my $name = $info->name() or die "Couldn't get sysName!" . $name->error();
2925              
2926             =head1 EXTENDING SNMP::INFO
2927              
2928             To support a new class (vendor or platform) of device, add a Perl package with
2929             the data structures and methods listed below.
2930              
2931             If this seems a little scary, then the SNMP::Info developers are usually happy
2932             to accept the SNMP data from your device and make an attempt at the class
2933             themselves. Usually a "beta" release will go to CPAN for you to verify the
2934             implementation.
2935              
2936             =head2 Gathering MIB data for SNMP::Info Developers
2937              
2938             The preference is to open a feature request in the SourceForge project. This
2939             allows all developers to have visibility into the request. Please include
2940             pointers to the applicable platform MIBs. For development we will need an
2941             C of the device. There is a tool now included in the SNMP::Info
2942             distribution to help with this task, although you'll most likely need to
2943             download the distribution from CPAN as it's included in the "C"
2944             directory.
2945              
2946             The utility is named C. Run it with a command line like:
2947              
2948             ./make_snmpdata.pl -c community -i -d device_ip \
2949             -m /home/netdisco-mibs/rfc:/home/netdisco-mibs/net-snmp:/home/netdisco-mibs/dir3 \
2950             SNMPv2-MIB IF-MIB EtherLike-MIB BRIDGE-MIB Q-BRIDGE-MIB ENTITY-MIB \
2951             POWER-ETHERNET-MIB IPV6-MIB LLDP-MIB DEVICE-SPECIFIC-MIB-NAME(s) > output.txt
2952              
2953             This will print to the file every MIB entry with data in a format that the
2954             developers can use to emulate read operations without needing access to the
2955             device. Preference would be to mask any sensitive data in the output, zip the
2956             file, and upload as an attachment to the Sourceforge tracker. However, if you
2957             do not feel comfortable uploading the output to the tracker you could e-mail
2958             it to the developer that has claimed the ticket.
2959              
2960             =head2 Data Structures required in new Subclass
2961              
2962             A class inheriting this class must implement these data structures :
2963              
2964             =over
2965              
2966             =item $INIT
2967              
2968             Used to flag if the MIBs have been loaded yet.
2969              
2970             =cut
2971              
2972             $INIT = 0;
2973              
2974             =item %GLOBALS
2975              
2976             Contains a hash in the form ( method_name => SNMP MIB leaf name )
2977             These are scalar values such as name, uptime, etc.
2978              
2979             To resolve MIB leaf name conflicts between private MIBs, you may prefix the
2980             leaf name with the MIB replacing each - (dash) and : (colon) with
2981             an _ (underscore). For example, ALTEON_TIGON_SWITCH_MIB__agSoftwareVersion
2982             would be used as the hash value instead of the net-snmp notation
2983             ALTEON-TIGON-SWITCH-MIB::agSoftwareVersion.
2984              
2985             When choosing the name for the methods, be aware that other new
2986             Sub Modules might inherit this one to get it's features. Try to
2987             choose a prefix for methods that will give it's own name space inside
2988             the SNMP::Info methods.
2989              
2990             =cut
2991              
2992             %GLOBALS = (
2993              
2994             # from SNMPv2-MIB
2995             'id' => 'sysObjectID',
2996             'description' => 'sysDescr',
2997             'uptime' => 'sysUpTime',
2998             'contact' => 'sysContact',
2999             'name' => 'sysName',
3000             'location' => 'sysLocation',
3001             'layers' => 'sysServices',
3002             'ports' => 'ifNumber',
3003             'ipforwarding' => 'ipForwarding',
3004             );
3005              
3006             =item %FUNCS
3007              
3008             Contains a hash in the form ( method_name => SNMP MIB leaf name)
3009             These are table entries, such as the C
3010              
3011             To resolve MIB leaf name conflicts between private MIBs, you may prefix the
3012             leaf name with the MIB replacing each - (dash) and : (colon) with
3013             an _ (underscore). For example, ALTEON_TS_PHYSICAL_MIB__agPortCurCfgPortName
3014             would be used as the hash value instead of the net-snmp notation
3015             ALTEON-TS-PHYSICAL-MIB::agPortCurCfgPortName.
3016              
3017             =cut
3018              
3019             %FUNCS = (
3020             'interfaces' => 'ifIndex',
3021             'i_name' => 'ifName',
3022              
3023             # IF-MIB::IfEntry
3024             'i_index' => 'ifIndex',
3025             'i_description' => 'ifDescr',
3026             'i_type' => 'ifType',
3027             'i_mtu' => 'ifMtu',
3028             'i_speed' => 'ifSpeed',
3029             'i_mac' => 'ifPhysAddress',
3030             'i_up_admin' => 'ifAdminStatus',
3031             'i_up' => 'ifOperStatus',
3032             'i_lastchange' => 'ifLastChange',
3033             'i_octet_in' => 'ifInOctets',
3034             'i_pkts_ucast_in' => 'ifInUcastPkts',
3035             'i_pkts_nucast_in' => 'ifInNUcastPkts',
3036             'i_discards_in' => 'ifInDiscards',
3037             'i_errors_in' => 'ifInErrors',
3038             'i_bad_proto_in' => 'ifInUnknownProtos',
3039             'i_octet_out' => 'ifOutOctets',
3040             'i_pkts_ucast_out' => 'ifOutUcastPkts',
3041             'i_pkts_nucast_out' => 'ifOutNUcastPkts',
3042             'i_discards_out' => 'ifOutDiscards',
3043             'i_errors_out' => 'ifOutErrors',
3044             'i_qlen_out' => 'ifOutQLen',
3045             'i_specific' => 'ifSpecific',
3046              
3047             # IF-MIB::IfStackTable
3048             'i_stack_status' => 'ifStackStatus',
3049              
3050             # IP Address Table
3051             'ip_index' => 'ipAdEntIfIndex',
3052             'ip_table' => 'ipAdEntAddr',
3053             'ip_netmask' => 'ipAdEntNetMask',
3054             'ip_broadcast' => 'ipAdEntBcastAddr',
3055              
3056             # ifXTable - Extension Table
3057             'i_speed_high' => 'ifHighSpeed',
3058             'i_pkts_multi_in' => 'ifInMulticastPkts',
3059             'i_pkts_multi_out' => 'ifOutMulticastPkts',
3060             'i_pkts_bcast_in' => 'ifInBroadcastPkts',
3061             'i_pkts_bcast_out' => 'ifOutBroadcastPkts',
3062             'i_octet_in64' => 'ifHCInOctets',
3063             'i_octet_out64' => 'ifHCOutOctets',
3064             'i_pkts_ucast_in64' => 'ifHCInUcastPkts',
3065             'i_pkts_ucast_out64' => 'ifHCOutUcastPkts',
3066             'i_pkts_multi_in64' => 'ifHCInMulticastPkts',
3067             'i_pkts_multi_out64' => 'ifHCOutMulticastPkts',
3068             'i_pkts_bcast_in64' => 'ifHCInBroadcastPkts',
3069             'i_pkts_bcast_out64' => 'ifHCOutBroadcastPkts',
3070             'i_alias' => 'ifAlias',
3071              
3072             # IP Routing Table
3073             'ipr_route' => 'ipRouteDest',
3074             'ipr_if' => 'ipRouteIfIndex',
3075             'ipr_1' => 'ipRouteMetric1',
3076             'ipr_2' => 'ipRouteMetric2',
3077             'ipr_3' => 'ipRouteMetric3',
3078             'ipr_4' => 'ipRouteMetric4',
3079             'ipr_5' => 'ipRouteMetric5',
3080             'ipr_dest' => 'ipRouteNextHop',
3081             'ipr_type' => 'ipRouteType',
3082             'ipr_proto' => 'ipRouteProto',
3083             'ipr_age' => 'ipRouteAge',
3084             'ipr_mask' => 'ipRouteMask',
3085             'ipr_info' => 'ipRouteInfo',
3086             );
3087              
3088             =item %MIBS
3089              
3090             A list of each mib needed.
3091              
3092             ('MIB-NAME' => 'itemToTestForPresence')
3093              
3094             The value for each entry should be a MIB object to check for to make sure
3095             that the MIB is present and has loaded correctly.
3096              
3097             $info->init() will throw an exception if a MIB does not load.
3098              
3099             =cut
3100              
3101             %MIBS = (
3102              
3103             # The "main" MIBs are automagically loaded in Net-SNMP now.
3104             );
3105              
3106             =item %MUNGE
3107              
3108             A map between method calls (from %FUNCS or %GLOBALS) and subroutine methods.
3109             The subroutine called will be passed the data as it gets it from SNMP and
3110             it should return that same data in a more human friendly format.
3111              
3112             Sample %MUNGE:
3113              
3114             (my_ip => \&munge_ip,
3115             my_mac => \&munge_mac,
3116             my_layers => \&munge_dec2bin
3117             )
3118              
3119             =cut
3120              
3121             %MUNGE = (
3122             'ip' => \&munge_ip,
3123             'mac' => \&munge_mac,
3124             'i_mac' => \&munge_mac,
3125             'layers' => \&munge_dec2bin,
3126             'i_speed' => \&munge_speed,
3127             'i_speed_high' => \&munge_highspeed,
3128             'i_octet_in64' => \&munge_counter64,
3129             'i_octet_out64' => \&munge_counter64,
3130             'i_pkts_ucast_in64' => \&munge_counter64,
3131             'i_pkts_ucast_out64' => \&munge_counter64,
3132             'i_pkts_mutli_in64' => \&munge_counter64,
3133             'i_pkts_multi_out64' => \&munge_counter64,
3134             'i_pkts_bcast_in64' => \&munge_counter64,
3135             'i_pkts_bcast_out64' => \&munge_counter64,
3136             'i_up' => \&munge_i_up,
3137             );
3138              
3139             =back
3140              
3141             =head2 Sample Subclass
3142              
3143             Let's make a sample Layer 2 Device subclass. This class
3144             will inherit the Cisco Vlan module as an example.
3145              
3146             ----------------------- snip --------------------------------
3147              
3148             # SNMP::Info::Layer2::Sample
3149              
3150             package SNMP::Info::Layer2::Sample;
3151              
3152             $VERSION = 0.1;
3153              
3154             use strict;
3155              
3156             use Exporter;
3157             use SNMP::Info::Layer2;
3158             use SNMP::Info::CiscoVTP;
3159              
3160             @SNMP::Info::Layer2::Sample::ISA = qw/SNMP::Info::Layer2
3161             SNMP::Info::CiscoVTP Exporter/;
3162             @SNMP::Info::Layer2::Sample::EXPORT_OK = qw//;
3163              
3164             use vars qw/$VERSION %FUNCS %GLOBALS %MIBS %MUNGE $AUTOLOAD $INIT $DEBUG/;
3165              
3166             %MIBS = (%SNMP::Info::Layer2::MIBS,
3167             %SNMP::Info::CiscoVTP::MIBS,
3168             'SUPER-DOOPER-MIB' => 'supermibobject'
3169             );
3170              
3171             %GLOBALS = (%SNMP::Info::Layer2::GLOBALS,
3172             %SNMP::Info::CiscoVTP::GLOBALS,
3173             'name' => 'supermib_supername',
3174             'favorite_color' => 'supermib_fav_color_object',
3175             'favorite_movie' => 'supermib_fav_movie_val'
3176             );
3177              
3178             %FUNCS = (%SNMP::Info::Layer2::FUNCS,
3179             %SNMP::Info::CiscoVTP::FUNCS,
3180             # Super Dooper MIB - Super Hero Table
3181             'super_hero_index' => 'SuperHeroIfIndex',
3182             'super_hero_name' => 'SuperHeroIfName',
3183             'super_hero_powers' => 'SuperHeroIfPowers'
3184             );
3185              
3186              
3187             %MUNGE = (%SNMP::Info::Layer2::MUNGE,
3188             %SNMP::Info::CiscoVTP::MUNGE,
3189             'super_hero_powers' => \&munge_powers
3190             );
3191              
3192             # OverRide uptime() method from %SNMP::Info::GLOBALS
3193             sub uptime {
3194             my $sample = shift;
3195              
3196             my $name = $sample->name();
3197              
3198             # this is silly but you get the idea
3199             return '600' if defined $name ;
3200             }
3201              
3202             # Create our own munge function
3203             sub munge_powers {
3204             my $power = shift;
3205              
3206             # Take the returned obscure value and return something useful.
3207             return 'Fire' if $power =~ /reallyhot/i;
3208             return 'Ice' if $power =~ /reallycold/i;
3209              
3210             # Else
3211             return $power;
3212             }
3213              
3214             # Copious Documentation here!!!
3215             =head1 NAME
3216             =head1 AUTHOR
3217             =head1 SYNOPSIS
3218             =head1 DESCRIPTION
3219             =head2 Inherited Classes
3220             =head2 Required MIBs
3221             =head1 GLOBALS
3222             =head2 Overrides
3223             =head1 TABLE METHODS
3224             =head2 Overrides
3225             =cut
3226              
3227             1; # don't forget this line
3228             ----------------------- snip --------------------------------
3229              
3230             Be sure and send the debugged version to snmp-info-users@lists.sourceforge.net to be
3231             included in the next version of SNMP::Info.
3232              
3233             =head1 SNMP::INFO INTERNALS
3234              
3235             =head2 Object Namespace
3236              
3237             Internal data is stored with bareword keys. For example $info->{debug}
3238              
3239             SNMP Data is stored or marked cached with keys starting with an underscore.
3240             For example $info->{_name} is the cache for $info->name().
3241              
3242             Cached Table data is stored in $info->store() and marked cached per above.
3243              
3244             =head2 Package Globals
3245              
3246             These set the default value for an object upon creation.
3247              
3248             =over
3249              
3250             =item $DEBUG
3251              
3252             Default 0. Sends copious debug info to stdout. This global sets the object's
3253             debug status in new() unless 'Debug' argument passed in new(). Change
3254             objects' debug status with $info->debug().
3255              
3256             =cut
3257              
3258             $DEBUG = 0;
3259              
3260             =item $BIGINT
3261              
3262             Default 0. Set to true to have 64 bit counters return Math::BigInt objects
3263             instead of scalar string values. See note under Interface Statistics about
3264             64 bit values.
3265              
3266             =cut
3267              
3268             $BIGINT = 0;
3269              
3270             =item $NOSUCH
3271              
3272             Default 1. Set to false to disable RetryNoSuch option for SNMP::Session. Or
3273             see method in new() to do it on an object scope.
3274              
3275             =cut
3276              
3277             $NOSUCH = 1;
3278              
3279             =item $REPEATERS
3280              
3281             Default 20. MaxRepeaters for BULKWALK operations. See C for
3282             more info. Can change by passing L option in new()
3283              
3284             =cut
3285              
3286             $REPEATERS = 20;
3287              
3288             =back
3289              
3290             =head2 Data Munging Callback Subroutines
3291              
3292             =over
3293              
3294             =item munge_speed()
3295              
3296             Makes human friendly speed ratings using %SPEED_MAP
3297              
3298             %SPEED_MAP = (
3299             '56000' => '56 kbps',
3300             '64000' => '64 kbps',
3301             '115000' => '115 kpbs',
3302             '1500000' => '1.5 Mbps',
3303             '1536000' => 'T1',
3304             '1544000' => 'T1',
3305             '2000000' => '2.0 Mbps',
3306             '2048000' => '2.048 Mbps',
3307             '3072000' => 'Dual T1',
3308             '3088000' => 'Dual T1',
3309             '4000000' => '4.0 Mbps',
3310             '10000000' => '10 Mbps',
3311             '11000000' => '11 Mbps',
3312             '20000000' => '20 Mbps',
3313             '16000000' => '16 Mbps',
3314             '16777216' => '16 Mbps',
3315             '44210000' => 'T3',
3316             '44736000' => 'T3',
3317             '45000000' => '45 Mbps',
3318             '45045000' => 'DS3',
3319             '46359642' => 'DS3',
3320             '51850000' => 'OC-1',
3321             '54000000' => '54 Mbps',
3322             '64000000' => '64 Mbps',
3323             '100000000' => '100 Mbps',
3324             '200000000' => '200 Mbps',
3325             '149760000' => 'ATM on OC-3',
3326             '155000000' => 'OC-3',
3327             '155519000' => 'OC-3',
3328             '155520000' => 'OC-3',
3329             '400000000' => '400 Mbps',
3330             '599040000' => 'ATM on OC-12',
3331             '622000000' => 'OC-12',
3332             '622080000' => 'OC-12',
3333             '1000000000' => '1.0 Gbps',
3334             '2000000000' => '2.0 Gbps',
3335             '2488000000' => 'OC-48',
3336             )
3337              
3338             Note: high speed interfaces (usually 1 Gbps or faster) have their link
3339             speed in C. i_speed() automatically determines whether to use
3340             C or C; if the latter is used, the value is munged by
3341             munge_highspeed(). SNMP::Info can return speeds up to terabit levels this way.
3342              
3343             =cut
3344              
3345             %SPEED_MAP = (
3346             '56000' => '56 kbps',
3347             '64000' => '64 kbps',
3348             '115000' => '115 kpbs',
3349             '1500000' => '1.5 Mbps',
3350             '1536000' => 'T1',
3351             '1544000' => 'T1',
3352             '2000000' => '2.0 Mbps',
3353             '2048000' => '2.048 Mbps',
3354             '3072000' => 'Dual T1',
3355             '3088000' => 'Dual T1',
3356             '4000000' => '4.0 Mbps',
3357             '10000000' => '10 Mbps',
3358             '11000000' => '11 Mbps',
3359             '20000000' => '20 Mbps',
3360             '16000000' => '16 Mbps',
3361             '16777216' => '16 Mbps',
3362             '44210000' => 'T3',
3363             '44736000' => 'T3',
3364             '45000000' => '45 Mbps',
3365             '45045000' => 'DS3',
3366             '46359642' => 'DS3',
3367             '51850000' => 'OC-1',
3368             '54000000' => '54 Mbps',
3369             '64000000' => '64 Mbps',
3370             '100000000' => '100 Mbps',
3371             '200000000' => '200 Mbps',
3372             '149760000' => 'ATM on OC-3',
3373             '155000000' => 'OC-3',
3374             '155519000' => 'OC-3',
3375             '155520000' => 'OC-3',
3376             '400000000' => '400 Mbps',
3377             '599040000' => 'ATM on OC-12',
3378             '622000000' => 'OC-12',
3379             '622080000' => 'OC-12',
3380             '1000000000' => '1.0 Gbps',
3381             '2000000000' => '2.0 Gbps',
3382             '2488000000' => 'OC-48',
3383             );
3384              
3385             sub munge_speed {
3386             my $speed = shift;
3387             my $map = $SPEED_MAP{$speed};
3388              
3389             #print " $speed -> $map " if (defined $map);
3390             return $map || $speed;
3391             }
3392              
3393             =item munge_highspeed()
3394              
3395             Makes human friendly speed ratings for C
3396              
3397             =cut
3398              
3399             sub munge_highspeed {
3400             my $speed = shift;
3401             my $fmt = "%d Mbps";
3402              
3403             if ( $speed > 9999999 ) {
3404             $fmt = "%d Tbps";
3405             $speed /= 1000000;
3406             }
3407             elsif ( $speed > 999999 ) {
3408             $fmt = "%.1f Tbps";
3409             $speed /= 1000000.0;
3410             }
3411             elsif ( $speed > 9999 ) {
3412             $fmt = "%d Gbps";
3413             $speed /= 1000;
3414             }
3415             elsif ( $speed > 999 ) {
3416             $fmt = "%.1f Gbps";
3417             $speed /= 1000.0;
3418             }
3419             return sprintf( $fmt, $speed );
3420             }
3421              
3422             =item munge_ip()
3423              
3424             Takes a binary IP and makes it dotted ASCII
3425              
3426             =cut
3427              
3428             sub munge_ip {
3429             my $ip = shift;
3430             return join( '.', unpack( 'C4', $ip ) );
3431             }
3432              
3433             =item munge_mac()
3434              
3435             Takes an octet stream (HEX-STRING) and returns a colon separated ASCII hex
3436             string.
3437              
3438             =cut
3439              
3440             sub munge_mac {
3441             my $mac = shift;
3442             return unless defined $mac;
3443             return unless length $mac;
3444             $mac = join( ':', map { sprintf "%02x", $_ } unpack( 'C*', $mac ) );
3445             return $mac if $mac =~ /^([0-9A-F][0-9A-F]:){5}[0-9A-F][0-9A-F]$/i;
3446             return;
3447             }
3448              
3449             =item munge_prio_mac()
3450              
3451             Takes an 2-byte octet stream (HEX-STRING) and returns a colon separated ASCII
3452             hex string.
3453              
3454             =cut
3455              
3456             sub munge_prio_mac {
3457             my $mac = shift;
3458             return unless defined $mac;
3459             return unless length $mac;
3460             $mac = join( ':', map { sprintf "%02x", $_ } unpack( 'C*', $mac ) );
3461             return $mac if $mac =~ /^([0-9A-F][0-9A-F]:){7}[0-9A-F][0-9A-F]$/i;
3462             return;
3463             }
3464              
3465             =item munge_prio_port()
3466              
3467             Takes an 8-byte octet stream (HEX-STRING) and returns a colon separated ASCII
3468             hex string.
3469              
3470             =cut
3471              
3472             sub munge_prio_port {
3473             my $mac = shift;
3474             return unless defined $mac;
3475             return unless length $mac;
3476             $mac = join( ':', map { sprintf "%02x", $_ } unpack( 'C*', $mac ) );
3477             return $mac if $mac =~ /^([0-9A-F][0-9A-F]:){1}[0-9A-F][0-9A-F]$/i;
3478             return;
3479             }
3480              
3481             =item munge_octet2hex()
3482              
3483             Takes a binary octet stream and returns an ASCII hex string
3484              
3485             =cut
3486              
3487             sub munge_octet2hex {
3488             my $oct = shift;
3489             return join( '', map { sprintf "%x", $_ } unpack( 'C*', $oct ) );
3490             }
3491              
3492             =item munge_dec2bin()
3493              
3494             Takes a binary char and returns its ASCII binary representation
3495              
3496             =cut
3497              
3498             sub munge_dec2bin {
3499             my $num = shift;
3500             return unless defined $num;
3501              
3502             #return unless length($num);
3503             $num = unpack( "B32", pack( "N", $num ) );
3504              
3505             # return last 8 characters only
3506             $num =~ s/.*(.{8})$/$1/;
3507             return $num;
3508             }
3509              
3510             =item munge_bits
3511              
3512             Takes a SNMP2 'BITS' field and returns the ASCII bit string
3513              
3514             =cut
3515              
3516             sub munge_bits {
3517             my $bits = shift;
3518             return unless defined $bits;
3519              
3520             return unpack( "B*", $bits );
3521             }
3522              
3523             =item munge_counter64
3524              
3525             If $BIGINT is set to true, then a Math::BigInt object is returned.
3526             See Math::BigInt for details.
3527              
3528             =cut
3529              
3530             sub munge_counter64 {
3531             my $counter = shift;
3532             return unless defined $counter;
3533             return $counter unless $BIGINT;
3534             my $bigint = Math::BigInt->new($counter);
3535             return $bigint;
3536             }
3537              
3538             =item munge_i_up
3539              
3540             Net-SNMP tends to load C first, and so ignores the
3541             updated enumeration for C in C. This munge
3542             handles the "newer" definitions for the enumeration in IF-MIB.
3543              
3544             TODO: Get the precedence of MIBs and overriding of MIB data in Net-SNMP
3545             figured out. Heirarchy/precendence of MIBS in SNMP::Info.
3546              
3547             =cut
3548              
3549             sub munge_i_up {
3550             my $i_up = shift;
3551             return unless defined $i_up;
3552              
3553             my %ifOperStatusMap = ( '4' => 'unknown',
3554             '5' => 'dormant',
3555             '6' => 'notPresent',
3556             '7' => 'lowerLayerDown' );
3557             return $ifOperStatusMap{$i_up} || $i_up;
3558             }
3559              
3560             =item munge_port_list
3561              
3562             Takes an octet string representing a set of ports and returns a reference
3563             to an array of binary values each array element representing a port.
3564              
3565             If the element has a value of '1', then that port is included in the set of
3566             ports; the port is not included if it has a value of '0'.
3567              
3568             =cut
3569              
3570             sub munge_port_list {
3571             my $oct = shift;
3572             return unless defined $oct;
3573              
3574             my $list = [ split( //, unpack( "B*", $oct ) ) ];
3575              
3576             return $list;
3577             }
3578              
3579             =item munge_null()
3580              
3581             Removes control characters from a string
3582              
3583             =cut
3584              
3585             # munge_null() - removes nulls (\0) and other control characters
3586             sub munge_null {
3587             my $text = shift || return;
3588              
3589             $text =~ s/[[:cntrl:]]//g;
3590             return $text;
3591             }
3592              
3593             =item munge_e_type()
3594              
3595             Takes an OID and return the object name if the right MIB is loaded.
3596              
3597             =cut
3598              
3599             sub munge_e_type {
3600             my $oid = shift;
3601              
3602             my $name = &SNMP::translateObj($oid);
3603             return $name if defined($name);
3604             return $oid;
3605             }
3606              
3607             =back
3608              
3609             =head2 Internally Used Functions
3610              
3611             =over
3612              
3613             =item $info->init()
3614              
3615             Used internally. Loads all entries in %MIBS.
3616              
3617             =cut
3618              
3619             sub init {
3620             my $self = shift;
3621              
3622             # Get MibDirs if provided
3623             my $mibdirs = $self->{mibdirs} || [];
3624            
3625             # SNMP::initMib and SNMP::addMibDirs both look for some initial MIBs
3626             # so if we are not using Net-SNMP configuration files we need to
3627             # specify where the MIBs are before those calls.
3628              
3629             # Ignore snmp.conf and snmp.local.conf files if IgnoreNetSNMPConf
3630             # specified
3631             local $ENV{'SNMPCONFPATH'} = '' if $self->{IgnoreNetSNMPConf};
3632             # We need to provide MIBDIRS if we are not getting them from a
3633             # configuration file
3634             my $mibdir = join (':', @$mibdirs);
3635             local $ENV{'MIBDIRS'} = "$mibdir" if $self->{IgnoreNetSNMPConf};
3636              
3637             SNMP::initMib;
3638              
3639             my $version = $SNMP::VERSION;
3640             my ( $major, $minor, $rev ) = split( '\.', $version );
3641              
3642             if ( $major < 5 ) {
3643              
3644             # Seems to work under 4.2.0
3645             }
3646             elsif ( $major == 5 and $minor == 0 and $rev < 2 ) {
3647             carp("Net-SNMP 5.0.1 seems to be rather buggy. Upgrade.\n");
3648              
3649             # This is a bug in net-snmp 5.0.1 perl module
3650             # see http://groups.google.com/groups?th=47aed6bf7be6a0f5
3651             SNMP::init_snmp("perl");
3652             }
3653              
3654             foreach my $d (@$mibdirs) {
3655             next unless -d $d;
3656             print "SNMP::Info::init() - Adding new mibdir:$d\n"
3657             if $self->debug() > 1;
3658             SNMP::addMibDirs($d);
3659             }
3660              
3661             my $mibs = $self->mibs();
3662              
3663             foreach my $mib ( keys %$mibs ) {
3664              
3665             #print "SNMP::Info::init() - Loading mib:$mib\n" if $self->debug();
3666             SNMP::loadModules("$mib");
3667              
3668             unless ( defined $SNMP::MIB{ $mibs->{$mib} } ) {
3669             croak "The $mib did not load. See README for $self->{class}\n";
3670             }
3671             }
3672             return;
3673             }
3674              
3675             =item $info->args()
3676              
3677             Returns a reference to the argument hash supplied to SNMP::Session
3678              
3679             =cut
3680              
3681             sub args {
3682             my $self = shift;
3683             return $self->{args};
3684             }
3685              
3686             =item $info->class()
3687              
3688             Returns the class name of the object.
3689              
3690             =cut
3691              
3692             sub class {
3693             my $self = shift;
3694             return $self->{class};
3695             }
3696              
3697             =item $info->error_throw(error message)
3698              
3699             Stores the error message for use by $info->error()
3700              
3701             If $info->debug() is true, then the error message is carped too.
3702              
3703             =cut
3704              
3705             sub error_throw {
3706             my $self = shift;
3707             my $error = shift;
3708              
3709             return unless defined $error;
3710             $self->{error} = $error;
3711              
3712             if ( $self->debug() ) {
3713             $error =~ s/\n+$//;
3714             carp($error);
3715             }
3716             return;
3717             }
3718              
3719             =item $info->funcs()
3720              
3721             Returns a reference to the %FUNCS hash.
3722              
3723             =cut
3724              
3725             sub funcs {
3726             my $self = shift;
3727             return $self->{funcs};
3728             }
3729              
3730             =item $info->globals()
3731              
3732             Returns a reference to the %GLOBALS hash.
3733              
3734             =cut
3735              
3736             sub globals {
3737             my $self = shift;
3738             return $self->{globals};
3739             }
3740              
3741             =item $info->mibs()
3742              
3743             Returns a reference to the %MIBS hash.
3744              
3745             =cut
3746              
3747             sub mibs {
3748             my $self = shift;
3749             return $self->{mibs};
3750             }
3751              
3752             =item $info->munge()
3753              
3754             Returns a reference of the %MUNGE hash.
3755              
3756             =cut
3757              
3758             sub munge {
3759             my $self = shift;
3760             return $self->{munge};
3761             }
3762              
3763             =item $info->nosuch()
3764              
3765             Returns NoSuch value set or not in new()
3766              
3767             =cut
3768              
3769             sub nosuch {
3770             my $self = shift;
3771             return $self->{nosuch};
3772             }
3773              
3774             =item $info->session()
3775              
3776             Gets or Sets the SNMP::Session object.
3777              
3778             =cut
3779              
3780             sub session {
3781             my $self = shift;
3782             $self->{sess} = $_[0] if @_;
3783             return $self->{sess};
3784             }
3785              
3786             =item $info->store(new_store)
3787              
3788             Returns or sets hash store for Table functions.
3789              
3790             Store is a hash reference in this format :
3791              
3792             $info->store = { attribute => { iid => value , iid2 => value2, ... } };
3793              
3794             =cut
3795              
3796             sub store {
3797             my $self = shift;
3798             $self->{store} = $_[0] if @_;
3799             return $self->{store};
3800             }
3801              
3802             =item $info->_global()
3803              
3804             Used internally by AUTOLOAD to create dynamic methods from %GLOBALS or a
3805             single instance MIB Leaf node name from a loaded MIB.
3806              
3807             Example: $info->name() on the first call dispatches to AUTOLOAD() which
3808             calls $info->_global('name') creating the method name().
3809              
3810             These methods return data as a scalar.
3811              
3812             =cut
3813              
3814             sub _global {
3815             my $method = shift;
3816             my $oid = shift;
3817             return sub {} if $method eq 'CARP_TRACE';
3818              
3819             return sub {
3820             my $self = shift;
3821              
3822             my $sess = $self->session();
3823             return unless defined $sess;
3824              
3825             my $load = $method =~ /^load/;
3826             my $raw = $method =~ /raw$/;
3827              
3828             my $attr = $method;
3829             $attr =~ s/^(load|orig)_//;
3830             $attr =~ s/_raw$//;
3831              
3832             # Return cached data unless loading
3833             # We now store in raw format so munge before returning
3834             # unless expecting raw data
3835             if ( exists $self->{"_$attr"} && !$load ) {
3836             my $val = $self->{"_$attr"};
3837              
3838             if ( !$raw ) {
3839             return $self->_munge($attr, $val);
3840             } else{
3841             return $val;
3842             }
3843             }
3844              
3845             if ( $self->{Offline} ) {
3846             $self->error_throw(
3847             "SNMP::Info::_global: Offline but $attr is not in cache\n" );
3848             return;
3849             }
3850              
3851             if ( $self->debug() ) {
3852             # Let's get the MIB Module and leaf name along with the OID
3853             my $qual_leaf = SNMP::translateObj($oid,0,1) || '';
3854             print "SNMP::Info::_global $method : $qual_leaf : $oid\n";
3855             }
3856             my $val = $sess->get($oid);
3857              
3858             # Mark as gotten. Even if it fails below, we don't want to keep failing.
3859             $self->{"_$attr"} = undef;
3860              
3861             if ( $sess->{ErrorStr} ) {
3862             $self->error_throw(
3863             "SNMP::Info::_global($method) $sess->{ErrorStr}");
3864             return;
3865             }
3866              
3867             if ( defined $val and $val eq 'NOSUCHOBJECT' ) {
3868             $self->error_throw("SNMP::Info::_global($method) NOSUCHOBJECT");
3869             return;
3870             }
3871              
3872             if ( defined $val and $val eq 'NOSUCHINSTANCE' ) {
3873             $self->error_throw("SNMP::Info::_global($method) NOSUCHINSTANCE");
3874             return;
3875             }
3876              
3877             # Save Cached Value
3878             $self->_cache($attr, $val);
3879              
3880             # Data Munging
3881             if ( !$raw ) {
3882             $val = $self->_munge($attr, $val);
3883             }
3884              
3885             return $val;
3886             }
3887             }
3888              
3889             =item $info->_set(attr,val,iid,type)
3890              
3891             Used internally by set_multi() to run an SNMP set command. When run
3892             clears attr cache.
3893              
3894             Attr can be passed as either a scalar or a reference to an array or array
3895             of arrays when used with set_multi().
3896              
3897             Example: $info->set_name('dog',3) uses autoload to resolve to
3898             $info->_set('name','dog',3);
3899              
3900             =cut
3901              
3902             sub _set {
3903             my ( $self, $attr, $val, $iid, $type ) = @_;
3904             my $varbind_list_ref;
3905              
3906             if ( !ref($attr) ) {
3907             $varbind_list_ref = [ [ $attr, $iid, $val, $type ] ];
3908             }
3909             elsif ( ref($attr) =~ /ARRAY/ ) {
3910             $varbind_list_ref = [$attr];
3911             $varbind_list_ref = $attr if ref( $$attr[0] ) =~ /ARRAY/;
3912             }
3913             else {
3914             $self->error_throw(
3915             "SNMP::Info::_set($attr,$val) - Failed. Invalid argument for attr."
3916             );
3917             }
3918              
3919             my $sess = $self->session();
3920             return unless defined $sess;
3921              
3922             my $funcs = $self->funcs();
3923             my $globals = $self->globals();
3924              
3925             foreach my $var_list (@$varbind_list_ref) {
3926             my $list_attr = $var_list->[0];
3927             my $list_iid = $var_list->[1];
3928             my $list_val = $var_list->[2];
3929              
3930             # Get rid of non-printable chars in $list_val for debug statements
3931             $list_val =~ s/\W//;
3932              
3933             # Instance is 0 for scalars without a supplied instance
3934             $var_list->[1] = $list_iid = defined $list_iid ? $list_iid : '0';
3935              
3936             # Check if this method is from a sub or from the tables.
3937             if ( $self->can($list_attr) ) {
3938             $self->error_throw(
3939             "SNMP::Info::_set($list_attr,$list_val) - Failed. $list_attr is generated in a sub(). set_$list_attr sub required."
3940             );
3941              
3942             # if sub set_attr() existed, we wouldn't have gotten this far.
3943             return;
3944             }
3945              
3946             # Lookup oid
3947             my $oid = undef;
3948             $oid = $list_attr if SNMP::translateObj($list_attr);
3949             $oid = $globals->{$list_attr} if defined $globals->{$list_attr};
3950             $oid = $funcs->{$list_attr} if defined $funcs->{$list_attr};
3951              
3952             unless ( defined $oid ) {
3953             $self->error_throw(
3954             "SNMP::Info::_set($list_attr,$list_val) - Failed to find $list_attr in \%GLOBALS or \%FUNCS or loaded MIB."
3955             );
3956             return;
3957             }
3958              
3959             # Check for fully qualified attr
3960             if ( $oid =~ /__/ ) {
3961             $oid =~ s/__/::/;
3962             $oid =~ s/_/-/g;
3963             }
3964              
3965             $var_list->[0] = $oid;
3966              
3967             $self->debug()
3968             and print
3969             "SNMP::Info::_set $list_attr.$list_iid ($oid.$list_iid) = $list_val\n";
3970             delete $self->{"_$list_attr"};
3971             }
3972              
3973             my $rv = $sess->set($varbind_list_ref);
3974              
3975             if ( $sess->{ErrorStr} ) {
3976             $self->error_throw("SNMP::Info::_set $sess->{ErrorStr}");
3977             return;
3978             }
3979              
3980             return $rv;
3981             }
3982              
3983             =item $info->_make_setter(val,iid)
3984              
3985             Used internally by AUTOLOAD to create dynamic methods from either %GLOBALS,
3986             %FUNCS, or a valid mib leaf from a loaded MIB which runs an SNMP set command.
3987             When run clears the attribute cache.
3988              
3989             Example: $info->set_name('dog',3) dispatches to autoload to resolve to
3990             $info->_set('name','dog',3) and _make_setter creates the set_name() method.
3991              
3992             =cut
3993              
3994             sub _make_setter {
3995             my $method = shift;
3996             my $oid = shift;
3997              
3998             return sub {
3999             my $self = shift;
4000             my $val = shift;
4001             my $iid = shift;
4002              
4003             my $set_oid = $oid;
4004             my $globals = $self->globals();
4005             my $attr = $method;
4006             $attr =~ s/^set_//;
4007            
4008             # The only thing which may give us the iid in $oid should be
4009             # a %GLOBALS entry appended with a number. In that case strip it
4010             # from the OID and use it as $iid
4011             if ( defined $globals->{$attr} && $globals->{$attr} =~ /(\.\d+$)/ ) {
4012             $iid = $1;
4013             $set_oid =~ s/$iid//;
4014             }
4015              
4016             # If we don't have $iid now we should be a %GLOBALS entry or single
4017             # instance MIB leaf so default to zero
4018             $iid = defined $iid ? $iid : '.0';
4019              
4020             # prepend dot if necessary to $iid
4021             $iid = ".$iid" unless $iid =~ /^\./;
4022              
4023             my $sess = $self->session();
4024             return unless defined $sess;
4025              
4026             $set_oid .= "$iid";
4027              
4028             $self->debug()
4029             and print "SNMP::Info::_set $method$iid ($set_oid) = $val\n";
4030             delete $self->{"_$attr"};
4031              
4032             my $rv = $sess->set( $set_oid, $val );
4033              
4034             if ( $sess->{ErrorStr} ) {
4035             $self->error_throw("SNMP::Info::_set $sess->{ErrorStr}");
4036             return;
4037             }
4038             return $rv;
4039             }
4040             }
4041              
4042             =item $info->set_multi(arrayref)
4043              
4044             Used to run an SNMP set command on several new values in the one request.
4045             Returns the result of $info->_set(method).
4046              
4047             Pass either a reference to a 4 element array [, , , ] or
4048             a reference to an array of 4 element arrays to specify multiple values.
4049              
4050             - One of the following forms:
4051             1) leaf identifier (e.g., C<'sysContact'>)
4052             2) An entry in either %FUNCS, %GLOBALS (e.g., 'contact')
4053             - The dotted-decimal, instance identifier. For scalar MIB objects
4054             use '0'
4055             - The SNMP data value being set (e.g., 'netdisco')
4056             - Optional as the MIB should be loaded.
4057              
4058             If one of the set assignments is invalid, then the request will be rejected
4059             without applying any of the new values - regardless of the order they appear
4060             in the list.
4061              
4062             Example:
4063             my $vlan_set = [
4064             ['qb_v_untagged',"$old_vlan_id","$old_untagged_portlist"],
4065             ['qb_v_egress',"$new_vlan_id","$new_egress_portlist"],
4066             ['qb_v_egress',"$old_vlan_id","$old_egress_portlist"],
4067             ['qb_v_untagged',"$new_vlan_id","$new_untagged_portlist"],
4068             ['qb_i_vlan',"$port","$new_vlan_id"],
4069             ];
4070              
4071             $info->set_multi($vlan_set);
4072              
4073             =cut
4074              
4075             sub set_multi {
4076             my $self = shift;
4077              
4078             return $self->_set(@_);
4079             }
4080              
4081             =item $info->load_all()
4082              
4083             Debugging routine. This does not include any overridden method or method
4084             implemented by subroutine.
4085              
4086             Runs $info->load_METHOD() for each entry in $info->funcs();
4087              
4088             Returns $info->store() -- See store() entry.
4089              
4090             Note return value has changed since version 0.3
4091              
4092             =cut
4093              
4094             sub load_all {
4095             my $self = shift;
4096             my $sess = $self->session();
4097             return unless defined $sess;
4098              
4099             my $funcs = $self->funcs();
4100              
4101             foreach my $attrib ( keys %$funcs ) {
4102             $attrib = "load_$attrib";
4103             $self->$attrib();
4104             }
4105              
4106             $self->{_all}++;
4107              
4108             return unless defined wantarray;
4109              
4110             return $self->store();
4111             }
4112              
4113             =item $info->all()
4114              
4115             Runs $info->load_all() once then returns $info->store();
4116              
4117             Use $info->load_all() to reload the data.
4118              
4119             Note return value has changed since version 0.3
4120              
4121             =cut
4122              
4123             sub all {
4124             my $self = shift;
4125             my $sess = $self->session();
4126             return unless defined $sess;
4127              
4128             $self->load_all() unless defined $self->{_all};
4129              
4130             return $self->store();
4131             }
4132              
4133             =item $info->_load_attr()
4134              
4135             Used internally by AUTOLOAD to create dynamic methods from %FUNCS
4136             or a MIB Leaf node name contained within a table of a loaded MIB.
4137              
4138             Supports partial table fetches and single instance table fetches.
4139             See L.
4140              
4141             These methods return data as a reference to a hash.
4142              
4143             =cut
4144              
4145             sub _load_attr {
4146             my $method = shift;
4147             my $oid = shift;
4148              
4149             return sub {
4150             my $self = shift;
4151             my $partial = shift;
4152              
4153             my $sess = $self->session();
4154             return unless defined $sess;
4155              
4156             my $ver = $self->snmp_ver();
4157             my $nosuch = $self->nosuch();
4158             my $store = $self->store();
4159              
4160             my $load = $method =~ /^load/;
4161             my $raw = $method =~ /raw$/;
4162              
4163             my $attr = $method;
4164             $attr =~ s/^(load|orig)_//;
4165             $attr =~ s/_raw$//;
4166              
4167             # Return cached data unless loading or partial
4168             # We now store in raw format so munge before returning
4169             # unless expecting raw data
4170             return $self->_show_attr($attr, $raw)
4171             if ( defined $self->{"_${attr}"}
4172             && !$load
4173             && !defined $partial );
4174              
4175             if ( $self->{Offline} ) {
4176             $self->error_throw(
4177             "SNMP::Info::_load_atrr: Offline but $attr is not in cache\n" );
4178             return;
4179             }
4180              
4181             # We want the qualified leaf name so that we can
4182             # specify the Module (MIB) in the case of private leaf naming
4183             # conflicts. Example: ALTEON-TIGON-SWITCH-MIB::agSoftwareVersion
4184             # and ALTEON-CHEETAH-SWITCH-MIB::agSoftwareVersion
4185             # Third argument to translateObj specifies the Module prefix
4186            
4187             my $qual_leaf = SNMP::translateObj($oid,0,1) || '';
4188            
4189             # We still want just the leaf since a SNMP get in the case of a
4190             # partial fetch may strip the Module portion upon return. We need
4191             # the match to make sure we didn't leave the table during getnext
4192             # requests
4193            
4194             my ($leaf) = $qual_leaf =~ /::(\w+)$/;
4195              
4196             $self->debug()
4197             and print "SNMP::Info::_load_attr $method : $qual_leaf",
4198             defined $partial ? "($partial)" : '', " : $oid" ,
4199             defined $partial ? ".$partial" : '', "\n";
4200              
4201             my $var = new SNMP::Varbind( [$qual_leaf, $partial] );
4202              
4203             # So devices speaking SNMP v.1 are not supposed to give out
4204             # data from SNMP2, but most do. Net-SNMP, being very precise
4205             # will tell you that the SNMP OID doesn't exist for the device.
4206             # They have a flag RetryNoSuch that is used for get() operations,
4207             # but not for getnext(). We set this flag normally, and if we're
4208             # using V1, let's try and fetch the data even if we get one of those.
4209              
4210             my $localstore = undef;
4211             my $errornum = 0;
4212             my %seen = ();
4213              
4214             my $vars = [];
4215             my $bulkwalk_no
4216             = $self->can('bulkwalk_no') ? $self->bulkwalk_no() : 0;
4217             my $bulkwalk_on = defined $self->{BulkWalk} ? $self->{BulkWalk} : 1;
4218             my $can_bulkwalk = $bulkwalk_on && !$bulkwalk_no;
4219             my $repeaters = $self->{BulkRepeaters} || $REPEATERS;
4220             my $bulkwalk = $can_bulkwalk && $ver != 1;
4221             my $loopdetect
4222             = defined $self->{LoopDetect} ? $self->{LoopDetect} : 1;
4223              
4224             if ( defined $partial ) {
4225              
4226             # Try a GET, in case the partial is a leaf OID.
4227             # Would like to only do this if we know the OID is
4228             # long enough; implementing that would require a
4229             # lot of MIB mucking.
4230             my $try = $sess->get($var);
4231             $errornum = $sess->{ErrorNum};
4232             if ( defined($try) && $errornum == 0 && $try !~ /^NOSUCH/ ) {
4233             $var->[2] = $try;
4234             $vars = [$var];
4235             $bulkwalk = 1; # fake a bulkwalk return
4236             }
4237              
4238             # We want to execute the while loop below for the getnext request.
4239             if ( $ver == 1
4240             and $sess->{ErrorNum}
4241             and $sess->{ErrorStr} =~ /nosuch/i )
4242             {
4243             $errornum = 0;
4244             }
4245             }
4246              
4247             # Use BULKWALK if we can because its faster
4248             if ( $bulkwalk && @$vars == 0 ) {
4249             ($vars) = $sess->bulkwalk( 0, $repeaters, $var );
4250             if ( $sess->{ErrorNum} ) {
4251             $self->error_throw(
4252             "SNMP::Info::_load_atrr: BULKWALK " . $sess->{ErrorStr},
4253             "\n" );
4254             return;
4255             }
4256             }
4257              
4258             while ( !$errornum ) {
4259             if ($bulkwalk) {
4260             $var = shift @$vars or last;
4261             }
4262             else {
4263              
4264             # GETNEXT instead of BULKWALK
4265             $sess->getnext($var);
4266             $errornum = $sess->{ErrorNum};
4267             }
4268              
4269             if ( $self->debug() > 1 ) {
4270             use Data::Dumper;
4271             print "SNMP::Info::_load_attr $method : leaf = $oid , var = ",
4272             Dumper($var);
4273             }
4274              
4275             # Check if we've left the requested subtree
4276             last if $var->[0] !~ /$leaf$/;
4277             my $iid = $var->[1];
4278             my $val = $var->[2];
4279              
4280             unless ( defined $iid ) {
4281             $self->error_throw(
4282             "SNMP::Info::_load_attr: $method not here");
4283             next;
4284             }
4285              
4286             # Check to make sure we are still in partial land
4287             if ( defined $partial
4288             and $iid !~ /^$partial$/
4289             and $iid !~ /^$partial\./ )
4290             {
4291             $self->debug()
4292             and print "$iid makes us leave partial land.\n";
4293             last;
4294             }
4295              
4296             # Check if last element, V2 devices may report ENDOFMIBVIEW even if
4297             # instance or object doesn't exist.
4298             if ( $val eq 'ENDOFMIBVIEW' ) {
4299             last;
4300             }
4301              
4302             # Similarly for SNMPv1 - noSuchName return results in both $iid
4303             # and $val being empty strings.
4304             if ( $val eq '' and $iid eq '' ) {
4305             last;
4306             }
4307              
4308             # Another check for SNMPv1 - noSuchName return may results in an $iid
4309             # we've already seen and $val an empty string. If we don't catch
4310             # this here we erronously report a loop below.
4311             if ( defined $seen{$iid} and $seen{$iid} and $val eq '' ) {
4312             last;
4313             }
4314              
4315             if ($loopdetect) {
4316              
4317             # Check to see if we've already seen this IID (looping)
4318             if ( defined $seen{$iid} and $seen{$iid} ) {
4319             $self->error_throw("Looping on: $method iid:$iid. ");
4320             last;
4321             }
4322             else {
4323             $seen{$iid}++;
4324             }
4325             }
4326              
4327             if ( $val eq 'NOSUCHOBJECT' ) {
4328             $self->error_throw(
4329             "SNMP::Info::_load_attr: $method : NOSUCHOBJECT");
4330             next;
4331             }
4332             if ( $val eq 'NOSUCHINSTANCE' ) {
4333             $self->error_throw(
4334             "SNMP::Info::_load_attr: $method : NOSUCHINSTANCE");
4335             next;
4336             }
4337              
4338             $localstore->{$iid} = $val;
4339              
4340             }
4341              
4342             # Cache data if we are not getting partial data:
4343             if ( !defined $partial ) {
4344             $self->_cache($attr, $localstore);
4345             }
4346              
4347             # Data Munging
4348             if ( !$raw ) {
4349             $localstore = $self->_munge($attr, $localstore);
4350             }
4351              
4352             return $localstore;
4353             }
4354             }
4355              
4356             =item $info->_show_attr()
4357              
4358             Used internally by AUTOLOAD to return data called by methods listed in %FUNCS.
4359              
4360             =cut
4361              
4362             sub _show_attr {
4363             my $self = shift;
4364             my $attr = shift;
4365             my $raw = shift;
4366              
4367             my $store = $self->store();
4368              
4369             if ( !$raw ) {
4370             my $localstore = $store->{$attr};
4371             return $self->_munge($attr, $localstore);
4372             }
4373             else {
4374             return $store->{$attr};
4375             }
4376             }
4377              
4378             =item $info->snmp_connect_ip(ip)
4379              
4380             Returns true or false based upon snmp connectivity to an IP.
4381              
4382             =cut
4383              
4384             sub snmp_connect_ip {
4385             my $self = shift;
4386             my $ip = shift;
4387             my $ver = $self->snmp_ver();
4388             my $comm = $self->snmp_comm();
4389              
4390             return if $self->{Offline};
4391             return if ( $ip eq '0.0.0.0' ) or ( $ip =~ /^127\./ );
4392              
4393             # Create session object
4394             my $snmp_test = new SNMP::Session(
4395             'DestHost' => $ip,
4396             'Community' => $comm,
4397             'Version' => $ver
4398             );
4399              
4400             # No session object created
4401             unless ( defined $snmp_test ) {
4402             return;
4403             }
4404              
4405             # Session object created but SNMP connection failed.
4406             my $sess_err = $snmp_test->{ErrorStr} || '';
4407             if ($sess_err) {
4408             return;
4409             }
4410              
4411             # Try to get some data from IP
4412             my $layers = $snmp_test->get('sysServices.0');
4413              
4414             $sess_err = $snmp_test->{ErrorStr} || '';
4415             if ($sess_err) {
4416             return;
4417             }
4418              
4419             return 1;
4420              
4421             }
4422              
4423             =item modify_port_list(portlist,offset,replacement)
4424              
4425             Replaces the specified bit in a port_list array and
4426             returns the packed bitmask
4427              
4428             =cut
4429              
4430             sub modify_port_list {
4431             my ( $self, $portlist, $offset, $replacement ) = @_;
4432              
4433             print "Original port list: @$portlist \n" if $self->debug();
4434             @$portlist[$offset] = $replacement;
4435              
4436             # Some devices do not populate the portlist with all possible ports.
4437             # If we have lengthened the list fill all undefined elements with zero.
4438             foreach my $item (@$portlist) {
4439             $item = '0' unless ( defined($item) );
4440             }
4441             print "Modified port list: @$portlist \n" if $self->debug();
4442              
4443             return pack( "B*", join( '', @$portlist ) );
4444             }
4445              
4446             =item $info->_cache(attr, data)
4447              
4448             Cache retrieved data so that if it's asked for again, we use the cache instead
4449             of going back to Net-SNMP. Data is cached inside the blessed hashref C<$self>.
4450              
4451             Accepts the leaf and value (scalar, or hashref for a table). Does not return
4452             anything useful.
4453              
4454             =cut
4455              
4456             sub _cache {
4457             my $self = shift;
4458             my ($attr, $data) = @_;
4459             my $store = $self->store();
4460              
4461             if (ref {} eq ref $data) {
4462             $self->{"_${attr}"}++;
4463             $store->{$attr} = $data;
4464             }
4465             else {
4466             $self->{"_$attr"} = $data;
4467             }
4468             }
4469              
4470             =item $info->_munge(attr, data)
4471              
4472             Raw data returned from Net-SNMP might not be formatted correctly or might have
4473             platform-specific bugs or mistakes. The MUNGE feature of SNMP::Info allows for
4474             fixups to take place.
4475              
4476             Accepts the leaf and value (scalar, or hashref for a table) and returns the raw
4477             or the munged data, as appropriate. That is, you do not need to know whether
4478             MUNGE is installed, and it's safe to call this method regardless.
4479              
4480             =cut
4481              
4482             sub _munge {
4483             my $self = shift;
4484             my ($attr, $data) = @_;
4485             my $munge = $self->munge();
4486              
4487             return $data unless defined $munge->{$attr};
4488              
4489             if (ref {} eq ref $data) {
4490             my $subref = $munge->{$attr};
4491             my %munged;
4492             foreach my $key ( keys %$data ) {
4493             my $value = $data->{$key};
4494             next unless defined $value;
4495             $munged{$key} = $subref->($value);
4496             }
4497             return \%munged;
4498             }
4499             else {
4500             return unless $data;
4501             my $subref = $munge->{$attr};
4502             return $subref->($data);
4503             }
4504             }
4505              
4506             =item _validate_autoload_method(method)
4507              
4508             Used internally by AUTOLOAD to validate that a dynamic method should be
4509             created. Returns the OID of the MIB leaf node the method will get or set.
4510              
4511             =over
4512              
4513             =item 1. Returns unless method is listed in %FUNCS, %GLOBALS, or is MIB Leaf
4514             node name in a loaded MIB for given class.
4515              
4516             =item 2. Translates the MIB Leaf node name to an OID.
4517              
4518             =item 3. Checks to see if the method access type is allowed for the resolved
4519             OID. Write access for set_ methods, read access for others.
4520              
4521             =back
4522              
4523             =cut
4524              
4525             sub _validate_autoload_method {
4526             my $self = shift;
4527             my $method = shift;
4528              
4529             my $setter = $method =~ /^set/;
4530             my $attr = $method;
4531             $attr =~ s/^(load|set|orig)_//;
4532             $attr =~ s/_raw$//;
4533              
4534             my $globals = $self->globals();
4535             my $funcs = $self->funcs();
4536              
4537             my $leaf_name = $globals->{$attr} || $funcs->{$attr} || $attr;
4538              
4539             # Check for fully qualified name
4540             if ( $leaf_name =~ /__/ ) {
4541             $leaf_name =~ s/__/::/;
4542             $leaf_name =~ s/_/-/g;
4543             }
4544              
4545             # skip if offline
4546             if ( $self->{Offline} ) {
4547             return [1,(exists $self->{store}->{$method} ? 1: 0)];
4548             }
4549              
4550             # Translate MIB leaf node name to OID
4551             my $oid = SNMP::translateObj($leaf_name);
4552              
4553             if ( $leaf_name =~ /^[.]?\d[\.\d]+$/ ) {
4554             $oid = $leaf_name;
4555             }
4556              
4557             unless ( defined $oid ) {
4558             print
4559             "SNMP::Info::_validate_autoload_method($leaf_name) Unable to resolve method.\n"
4560             if $self->debug();
4561             return;
4562             }
4563              
4564             # Validate that we have proper access for the operation
4565             my $access = $SNMP::MIB{$oid}{'access'} || '';
4566              
4567             # If we were given a fully qualified OID because we don't have the MIB
4568             # file, it will translate above but we won't be able to check access so
4569             # skip the check and return
4570             if ($access) {
4571             unless ( ( $method =~ /^set/ && $access =~ /Write|Create/ )
4572             || $access =~ /Read|Create/ )
4573             {
4574             print
4575             "SNMP::Info::_validate_autoload_method($attr : $oid) Not accessable for requested operation.\n"
4576             if $self->debug();
4577             return;
4578             }
4579             }
4580              
4581             # If the parent of the leaf has indexes it is contained within a table
4582             my $indexes = $SNMP::MIB{$oid}{'parent'}{'indexes'};
4583             my $table_leaf = 0;
4584              
4585             if ( !$globals->{$attr}
4586             && ( ( defined $indexes && scalar( @{$indexes} ) > 0 )
4587             || $funcs->{$attr} ))
4588             {
4589             $table_leaf = 1;
4590             }
4591              
4592             # Tag on .0 for %GLOBALS and single instance MIB leafs unless
4593             # the leaf ends in a digit or we are going to use for a set operation
4594             if ( $table_leaf == 0 && ( $globals->{$attr} || $leaf_name ne $oid ) ) {
4595              
4596             unless ( $leaf_name =~ /\d$/ || $setter ) {
4597             $oid .= ".0";
4598             }
4599             }
4600              
4601             my $return = [ $oid, $table_leaf ];
4602             return $return;
4603             }
4604              
4605             =item $info->can()
4606              
4607             Overrides UNIVERSAL::can() so that objects will correctly report their
4608             capabilities to include dynamic methods generated at run time via AUTOLOAD.
4609              
4610             Calls parent can() first to see if method exists, if not validates that a
4611             method should be created then dispatches to the appropriate internal method
4612             for creation. The newly created method is inserted into the symbol table
4613             returning to AUTOLOAD only for the initial method call.
4614              
4615             Returns undef if the method does not exist and can not be created.
4616              
4617             =cut
4618              
4619             sub can {
4620             my $self = shift;
4621             my $method = shift;
4622              
4623             # use results of parent can()
4624             return $self->SUPER::can($method) if $self->SUPER::can($method);
4625              
4626             my $validated = $self->_validate_autoload_method($method);
4627             return unless $validated;
4628              
4629             my ($oid, $table) = @$validated;
4630              
4631             # _validate_autoload_method validates, so we need to check for
4632             # set_ , funcs, table leafs, and everything else goes to _global
4633             my $funcs = $self->funcs();
4634              
4635             # We need to resolve funcs with a prefix or suffix
4636             my $f_method = $method;
4637             $f_method =~ s/^(load|orig)_//;
4638             $f_method =~ s/_raw$//;
4639              
4640             no strict 'refs'; ## no critic (ProhibitNoStrict )
4641              
4642             # Check for set_ ing.
4643             if ( $method =~ /^set_/ ) {
4644             return *{$AUTOLOAD} = _make_setter( $method, $oid, @_ );
4645             }
4646             elsif ( defined $funcs->{$f_method} || $table ) {
4647             return *{$AUTOLOAD} = _load_attr( $method, $oid, @_ );
4648             }
4649             else {
4650             return *{$AUTOLOAD} = _global( $method, $oid );
4651             }
4652             }
4653              
4654             =back
4655              
4656             =head2 AUTOLOAD
4657              
4658             Each entry in either %FUNCS, %GLOBALS, or MIB Leaf node names present in
4659             loaded MIBs are used by AUTOLOAD() to create dynamic methods. Generated
4660             methods are inserted into the symbol table so that subsequent calls can avoid
4661             AUTOLOAD() and dispatch directly.
4662              
4663             =over
4664              
4665             =item 1. Returns unless method is listed in %FUNCS, %GLOBALS, or is a MIB
4666             Leaf node name in a loaded MIB for given class.
4667              
4668             =item 2. If the method exists in %GLOBALS or is a single instance MIB Leaf
4669             node name from a loaded MIB, _global() generates the method.
4670              
4671             =item 3. If a set_ prefix is present _make_setter() generates the method.
4672              
4673             =item 4. If the method exists in %FUNCS or is a MIB Leaf node name contained
4674             within a table from a loaded MIB, _load_attr() generates the method.
4675              
4676             =item 5. A load_ prefix forces reloading of data and does not use cached data.
4677              
4678             =item 6. A _raw suffix returns data ignoring any munge routines.
4679              
4680             =back
4681              
4682             Override any dynamic method listed in %GLOBALS, %FUNCS, or MIB Leaf node
4683             name a by creating a subroutine with the same name.
4684              
4685             For example to override $info->name() create `` sub name {...}'' in your
4686             subclass.
4687              
4688             =cut
4689              
4690             sub AUTOLOAD {
4691             my $self = shift;
4692             my ($sub_name) = $AUTOLOAD =~ /::(\w+)$/;
4693              
4694             return if $sub_name =~ /DESTROY$/;
4695              
4696             # Typos in function calls in SNMP::Info subclasses turn into
4697             # AUTOLOAD requests for non-methods. While this is deprecated,
4698             # we'll still get called, so report a less confusing error.
4699             if ( ref($self) !~ /SNMP::Info/ ) {
4700              
4701             # croak reports one level too high. die reports here.
4702             # I would really like to get the place that's likely to
4703             # have the typo, but perl doesn't want me to.
4704             croak(
4705             "SNMP::Info::AUTOLOAD($AUTOLOAD) called with no class (probably typo of function call to $sub_name)"
4706             );
4707             }
4708              
4709             # This enables us to use SUPER:: for AUTOLOAD methods as well
4710             # as the true OO methods. Method needs to be renamed to prevent
4711             # namespace collision when we insert into the symbol table later.
4712             if ( $AUTOLOAD =~ /SUPER::$sub_name$/ ) {
4713             $AUTOLOAD =~ s/SUPER::$sub_name/orig_$sub_name/;
4714             $sub_name = "orig_$sub_name";
4715             }
4716              
4717             return unless my $meth_ref = $self->can($sub_name, @_);
4718             return $self->$meth_ref(@_);
4719              
4720             }
4721              
4722             1;
4723              
4724             =head1 COPYRIGHT AND LICENSE
4725              
4726             Changes from SNMP::Info Version 0.7 and on are:
4727             Copyright (c) 2003-2010 Max Baker and SNMP::Info Developers
4728             All rights reserved.
4729              
4730             Original Code is:
4731             Copyright (c) 2002-2003, Regents of the University of California
4732             All rights reserved.
4733              
4734             Redistribution and use in source and binary forms, with or without
4735             modification, are permitted provided that the following conditions are met:
4736              
4737             * Redistributions of source code must retain the above copyright notice,
4738             this list of conditions and the following disclaimer.
4739             * Redistributions in binary form must reproduce the above copyright
4740             notice, this list of conditions and the following disclaimer in the
4741             documentation and/or other materials provided with the distribution.
4742             * Neither the name of the University of California, Santa Cruz nor the
4743             names of its contributors may be used to endorse or promote products
4744             derived from this software without specific prior written permission.
4745              
4746             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4747             AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4748             IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
4749             DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
4750             FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4751             DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
4752             SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
4753             CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
4754             OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
4755             OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4756              
4757             =cut