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