Net_SNMP_util.pm
上传用户:shbosideng
上传日期:2013-05-04
资源大小:1555k
文件大小:63k
源码类别:

SNMP编程

开发平台:

C/C++

  1. ### - *- mode: Perl -*-
  2. ######################################################################
  3. ### Net_SNMP_util -- SNMP utilities using Net::SNMP
  4. ######################################################################
  5. ### Copyright (c) 2005, Mike Mitchell.
  6. ###
  7. ### This program is free software; you can redistribute it under the
  8. ### "Artistic License" included in this distribution (file "Artistic").
  9. ######################################################################
  10. ### Created by:  Mike Mitchell   <Mike.Mitchell@sas.com>
  11. ###
  12. ### Contributions and fixes by:
  13. ###
  14. ### Laszlo Herczeg <laszlo.herczeg@austinenergy.com>
  15. ### ignore unimplemented SNMP_Session.pm options
  16. ######################################################################
  17. package Net_SNMP_util;
  18. =head1 NAME
  19. Net_SNMP_util - SNMP utilities based on Net::SNMP
  20. =head1 SYNOPSIS
  21. The Net_SNMP_util module implements SNMP utilities using the Net::SNMP module.
  22. It implements snmpget, snmpgetnext, snmpwalk, snmpset, snmptrap, and
  23. snmpgetbulk.  The Net_SNMP_util module assumes that the user has a basic
  24. understanding of the Simple Network Management Protocol and related network
  25. management concepts.
  26. =head1 DESCRIPTION
  27. The Net_SNMP_util module simplifies SNMP queries even more than Net::SNMP  
  28. alone.  Easy-to-use "get", "getnext", "walk", "set", "trap", and "getbulk"
  29. routines are provided, hiding all the details of a SNMP query.
  30. =cut
  31. # ==========================================================================
  32. use strict;
  33. ## Validate the version of Perl
  34. BEGIN
  35. {
  36.     die('Perl version 5.6.0 or greater is required') if ($] < 5.006);
  37. }
  38. ## Handle importing/exporting of symbols
  39. use vars qw( @ISA @EXPORT $VERSION );
  40. use Exporter;
  41. our @ISA = qw( Exporter );
  42. our @EXPORT = qw(
  43.     snmpget snmpgetnext snmpwalk snmpset snmptrap snmpgetbulk snmpmaptable
  44.     snmpmaptable4 snmpwalkhash snmpmapOID snmpMIB_to_OID snmpLoad_OID_Cache
  45.     snmpQueue_MIB_File
  46. );
  47. ## Version of the Net_SNMP_util module
  48. our $VERSION = v1.0.5;
  49. use Carp;
  50. use Net::SNMP v5.0;
  51. # The OID numbers from RFC1213 (MIB-II) and RFC1315 (Frame Relay)
  52. # are pre-loaded below.
  53. %Net_SNMP_util::OIDS = 
  54.   (
  55.     'iso' => '1',
  56.     'org' => '1.3',
  57.     'dod' => '1.3.6',
  58.     'internet' => '1.3.6.1',
  59.     'directory' => '1.3.6.1.1',
  60.     'mgmt' => '1.3.6.1.2',
  61.     'mib-2' => '1.3.6.1.2.1',
  62.     'system' => '1.3.6.1.2.1.1',
  63.     'sysDescr' => '1.3.6.1.2.1.1.1.0',
  64.     'sysObjectID' => '1.3.6.1.2.1.1.2.0',
  65.     'sysUpTime' => '1.3.6.1.2.1.1.3.0',
  66.     'sysUptime' => '1.3.6.1.2.1.1.3.0',
  67.     'sysContact' => '1.3.6.1.2.1.1.4.0',
  68.     'sysName' => '1.3.6.1.2.1.1.5.0',
  69.     'sysLocation' => '1.3.6.1.2.1.1.6.0',
  70.     'sysServices' => '1.3.6.1.2.1.1.7.0',
  71.     'interfaces' => '1.3.6.1.2.1.2',
  72.     'ifNumber' => '1.3.6.1.2.1.2.1.0',
  73.     'ifTable' => '1.3.6.1.2.1.2.2',
  74.     'ifEntry' => '1.3.6.1.2.1.2.2.1',
  75.     'ifIndex' => '1.3.6.1.2.1.2.2.1.1',
  76.     'ifInOctets' => '1.3.6.1.2.1.2.2.1.10',
  77.     'ifInUcastPkts' => '1.3.6.1.2.1.2.2.1.11',
  78.     'ifInNUcastPkts' => '1.3.6.1.2.1.2.2.1.12',
  79.     'ifInDiscards' => '1.3.6.1.2.1.2.2.1.13',
  80.     'ifInErrors' => '1.3.6.1.2.1.2.2.1.14',
  81.     'ifInUnknownProtos' => '1.3.6.1.2.1.2.2.1.15',
  82.     'ifOutOctets' => '1.3.6.1.2.1.2.2.1.16',
  83.     'ifOutUcastPkts' => '1.3.6.1.2.1.2.2.1.17',
  84.     'ifOutNUcastPkts' => '1.3.6.1.2.1.2.2.1.18',
  85.     'ifOutDiscards' => '1.3.6.1.2.1.2.2.1.19',
  86.     'ifDescr' => '1.3.6.1.2.1.2.2.1.2',
  87.     'ifOutErrors' => '1.3.6.1.2.1.2.2.1.20',
  88.     'ifOutQLen' => '1.3.6.1.2.1.2.2.1.21',
  89.     'ifSpecific' => '1.3.6.1.2.1.2.2.1.22',
  90.     'ifType' => '1.3.6.1.2.1.2.2.1.3',
  91.     'ifMtu' => '1.3.6.1.2.1.2.2.1.4',
  92.     'ifSpeed' => '1.3.6.1.2.1.2.2.1.5',
  93.     'ifPhysAddress' => '1.3.6.1.2.1.2.2.1.6',
  94.     'ifAdminHack' => '1.3.6.1.2.1.2.2.1.7',  
  95.     'ifAdminStatus' => '1.3.6.1.2.1.2.2.1.7',
  96.     'ifOperHack' => '1.3.6.1.2.1.2.2.1.8',             
  97.     'ifOperStatus' => '1.3.6.1.2.1.2.2.1.8',
  98.     'ifLastChange' => '1.3.6.1.2.1.2.2.1.9',
  99.     'at' => '1.3.6.1.2.1.3',
  100.     'atTable' => '1.3.6.1.2.1.3.1',
  101.     'atEntry' => '1.3.6.1.2.1.3.1.1',
  102.     'atIfIndex' => '1.3.6.1.2.1.3.1.1.1',
  103.     'atPhysAddress' => '1.3.6.1.2.1.3.1.1.2',
  104.     'atNetAddress' => '1.3.6.1.2.1.3.1.1.3',
  105.     'ip' => '1.3.6.1.2.1.4',
  106.     'ipForwarding' => '1.3.6.1.2.1.4.1',
  107.     'ipOutRequests' => '1.3.6.1.2.1.4.10',
  108.     'ipOutDiscards' => '1.3.6.1.2.1.4.11',
  109.     'ipOutNoRoutes' => '1.3.6.1.2.1.4.12',
  110.     'ipReasmTimeout' => '1.3.6.1.2.1.4.13',
  111.     'ipReasmReqds' => '1.3.6.1.2.1.4.14',
  112.     'ipReasmOKs' => '1.3.6.1.2.1.4.15',
  113.     'ipReasmFails' => '1.3.6.1.2.1.4.16',
  114.     'ipFragOKs' => '1.3.6.1.2.1.4.17',
  115.     'ipFragFails' => '1.3.6.1.2.1.4.18',
  116.     'ipFragCreates' => '1.3.6.1.2.1.4.19',
  117.     'ipDefaultTTL' => '1.3.6.1.2.1.4.2',
  118.     'ipAddrTable' => '1.3.6.1.2.1.4.20',
  119.     'ipAddrEntry' => '1.3.6.1.2.1.4.20.1',
  120.     'ipAdEntAddr' => '1.3.6.1.2.1.4.20.1.1',
  121.     'ipAdEntIfIndex' => '1.3.6.1.2.1.4.20.1.2',
  122.     'ipAdEntNetMask' => '1.3.6.1.2.1.4.20.1.3',
  123.     'ipAdEntBcastAddr' => '1.3.6.1.2.1.4.20.1.4',
  124.     'ipAdEntReasmMaxSize' => '1.3.6.1.2.1.4.20.1.5',
  125.     'ipRouteTable' => '1.3.6.1.2.1.4.21',
  126.     'ipRouteEntry' => '1.3.6.1.2.1.4.21.1',
  127.     'ipRouteDest' => '1.3.6.1.2.1.4.21.1.1',
  128.     'ipRouteAge' => '1.3.6.1.2.1.4.21.1.10',
  129.     'ipRouteMask' => '1.3.6.1.2.1.4.21.1.11',
  130.     'ipRouteMetric5' => '1.3.6.1.2.1.4.21.1.12',
  131.     'ipRouteInfo' => '1.3.6.1.2.1.4.21.1.13',
  132.     'ipRouteIfIndex' => '1.3.6.1.2.1.4.21.1.2',
  133.     'ipRouteMetric1' => '1.3.6.1.2.1.4.21.1.3',
  134.     'ipRouteMetric2' => '1.3.6.1.2.1.4.21.1.4',
  135.     'ipRouteMetric3' => '1.3.6.1.2.1.4.21.1.5',
  136.     'ipRouteMetric4' => '1.3.6.1.2.1.4.21.1.6',
  137.     'ipRouteNextHop' => '1.3.6.1.2.1.4.21.1.7',
  138.     'ipRouteType' => '1.3.6.1.2.1.4.21.1.8',
  139.     'ipRouteProto' => '1.3.6.1.2.1.4.21.1.9',
  140.     'ipNetToMediaTable' => '1.3.6.1.2.1.4.22',
  141.     'ipNetToMediaEntry' => '1.3.6.1.2.1.4.22.1',
  142.     'ipNetToMediaIfIndex' => '1.3.6.1.2.1.4.22.1.1',
  143.     'ipNetToMediaPhysAddress' => '1.3.6.1.2.1.4.22.1.2',
  144.     'ipNetToMediaNetAddress' => '1.3.6.1.2.1.4.22.1.3',
  145.     'ipNetToMediaType' => '1.3.6.1.2.1.4.22.1.4',
  146.     'ipRoutingDiscards' => '1.3.6.1.2.1.4.23',
  147.     'ipInReceives' => '1.3.6.1.2.1.4.3',
  148.     'ipInHdrErrors' => '1.3.6.1.2.1.4.4',
  149.     'ipInAddrErrors' => '1.3.6.1.2.1.4.5',
  150.     'ipForwDatagrams' => '1.3.6.1.2.1.4.6',
  151.     'ipInUnknownProtos' => '1.3.6.1.2.1.4.7',
  152.     'ipInDiscards' => '1.3.6.1.2.1.4.8',
  153.     'ipInDelivers' => '1.3.6.1.2.1.4.9',
  154.     'icmp' => '1.3.6.1.2.1.5',
  155.     'icmpInMsgs' => '1.3.6.1.2.1.5.1',
  156.     'icmpInTimestamps' => '1.3.6.1.2.1.5.10',
  157.     'icmpInTimestampReps' => '1.3.6.1.2.1.5.11',
  158.     'icmpInAddrMasks' => '1.3.6.1.2.1.5.12',
  159.     'icmpInAddrMaskReps' => '1.3.6.1.2.1.5.13',
  160.     'icmpOutMsgs' => '1.3.6.1.2.1.5.14',
  161.     'icmpOutErrors' => '1.3.6.1.2.1.5.15',
  162.     'icmpOutDestUnreachs' => '1.3.6.1.2.1.5.16',
  163.     'icmpOutTimeExcds' => '1.3.6.1.2.1.5.17',
  164.     'icmpOutParmProbs' => '1.3.6.1.2.1.5.18',
  165.     'icmpOutSrcQuenchs' => '1.3.6.1.2.1.5.19',
  166.     'icmpInErrors' => '1.3.6.1.2.1.5.2',
  167.     'icmpOutRedirects' => '1.3.6.1.2.1.5.20',
  168.     'icmpOutEchos' => '1.3.6.1.2.1.5.21',
  169.     'icmpOutEchoReps' => '1.3.6.1.2.1.5.22',
  170.     'icmpOutTimestamps' => '1.3.6.1.2.1.5.23',
  171.     'icmpOutTimestampReps' => '1.3.6.1.2.1.5.24',
  172.     'icmpOutAddrMasks' => '1.3.6.1.2.1.5.25',
  173.     'icmpOutAddrMaskReps' => '1.3.6.1.2.1.5.26',
  174.     'icmpInDestUnreachs' => '1.3.6.1.2.1.5.3',
  175.     'icmpInTimeExcds' => '1.3.6.1.2.1.5.4',
  176.     'icmpInParmProbs' => '1.3.6.1.2.1.5.5',
  177.     'icmpInSrcQuenchs' => '1.3.6.1.2.1.5.6',
  178.     'icmpInRedirects' => '1.3.6.1.2.1.5.7',
  179.     'icmpInEchos' => '1.3.6.1.2.1.5.8',
  180.     'icmpInEchoReps' => '1.3.6.1.2.1.5.9',
  181.     'tcp' => '1.3.6.1.2.1.6',
  182.     'tcpRtoAlgorithm' => '1.3.6.1.2.1.6.1',
  183.     'tcpInSegs' => '1.3.6.1.2.1.6.10',
  184.     'tcpOutSegs' => '1.3.6.1.2.1.6.11',
  185.     'tcpRetransSegs' => '1.3.6.1.2.1.6.12',
  186.     'tcpConnTable' => '1.3.6.1.2.1.6.13',
  187.     'tcpConnEntry' => '1.3.6.1.2.1.6.13.1',
  188.     'tcpConnState' => '1.3.6.1.2.1.6.13.1.1',
  189.     'tcpConnLocalAddress' => '1.3.6.1.2.1.6.13.1.2',
  190.     'tcpConnLocalPort' => '1.3.6.1.2.1.6.13.1.3',
  191.     'tcpConnRemAddress' => '1.3.6.1.2.1.6.13.1.4',
  192.     'tcpConnRemPort' => '1.3.6.1.2.1.6.13.1.5',
  193.     'tcpInErrs' => '1.3.6.1.2.1.6.14',
  194.     'tcpOutRsts' => '1.3.6.1.2.1.6.15',
  195.     'tcpRtoMin' => '1.3.6.1.2.1.6.2',
  196.     'tcpRtoMax' => '1.3.6.1.2.1.6.3',
  197.     'tcpMaxConn' => '1.3.6.1.2.1.6.4',
  198.     'tcpActiveOpens' => '1.3.6.1.2.1.6.5',
  199.     'tcpPassiveOpens' => '1.3.6.1.2.1.6.6',
  200.     'tcpAttemptFails' => '1.3.6.1.2.1.6.7',
  201.     'tcpEstabResets' => '1.3.6.1.2.1.6.8',
  202.     'tcpCurrEstab' => '1.3.6.1.2.1.6.9',
  203.     'udp' => '1.3.6.1.2.1.7',
  204.     'udpInDatagrams' => '1.3.6.1.2.1.7.1',
  205.     'udpNoPorts' => '1.3.6.1.2.1.7.2',
  206.     'udpInErrors' => '1.3.6.1.2.1.7.3',
  207.     'udpOutDatagrams' => '1.3.6.1.2.1.7.4',
  208.     'udpTable' => '1.3.6.1.2.1.7.5',
  209.     'udpEntry' => '1.3.6.1.2.1.7.5.1',
  210.     'udpLocalAddress' => '1.3.6.1.2.1.7.5.1.1',
  211.     'udpLocalPort' => '1.3.6.1.2.1.7.5.1.2',
  212.     'egp' => '1.3.6.1.2.1.8',
  213.     'egpInMsgs' => '1.3.6.1.2.1.8.1',
  214.     'egpInErrors' => '1.3.6.1.2.1.8.2',
  215.     'egpOutMsgs' => '1.3.6.1.2.1.8.3',
  216.     'egpOutErrors' => '1.3.6.1.2.1.8.4',
  217.     'egpNeighTable' => '1.3.6.1.2.1.8.5',
  218.     'egpNeighEntry' => '1.3.6.1.2.1.8.5.1',
  219.     'egpNeighState' => '1.3.6.1.2.1.8.5.1.1',
  220.     'egpNeighStateUps' => '1.3.6.1.2.1.8.5.1.10',
  221.     'egpNeighStateDowns' => '1.3.6.1.2.1.8.5.1.11',
  222.     'egpNeighIntervalHello' => '1.3.6.1.2.1.8.5.1.12',
  223.     'egpNeighIntervalPoll' => '1.3.6.1.2.1.8.5.1.13',
  224.     'egpNeighMode' => '1.3.6.1.2.1.8.5.1.14',
  225.     'egpNeighEventTrigger' => '1.3.6.1.2.1.8.5.1.15',
  226.     'egpNeighAddr' => '1.3.6.1.2.1.8.5.1.2',
  227.     'egpNeighAs' => '1.3.6.1.2.1.8.5.1.3',
  228.     'egpNeighInMsgs' => '1.3.6.1.2.1.8.5.1.4',
  229.     'egpNeighInErrs' => '1.3.6.1.2.1.8.5.1.5',
  230.     'egpNeighOutMsgs' => '1.3.6.1.2.1.8.5.1.6',
  231.     'egpNeighOutErrs' => '1.3.6.1.2.1.8.5.1.7',
  232.     'egpNeighInErrMsgs' => '1.3.6.1.2.1.8.5.1.8',
  233.     'egpNeighOutErrMsgs' => '1.3.6.1.2.1.8.5.1.9',
  234.     'egpAs' => '1.3.6.1.2.1.8.6',
  235.     'transmission' => '1.3.6.1.2.1.10',
  236.     'frame-relay' => '1.3.6.1.2.1.10.32',
  237.     'frDlcmiTable' => '1.3.6.1.2.1.10.32.1',
  238.     'frDlcmiEntry' => '1.3.6.1.2.1.10.32.1.1',
  239.     'frDlcmiIfIndex' => '1.3.6.1.2.1.10.32.1.1.1',
  240.     'frDlcmiState' => '1.3.6.1.2.1.10.32.1.1.2',
  241.     'frDlcmiAddress' => '1.3.6.1.2.1.10.32.1.1.3',
  242.     'frDlcmiAddressLen' => '1.3.6.1.2.1.10.32.1.1.4',
  243.     'frDlcmiPollingInterval' => '1.3.6.1.2.1.10.32.1.1.5',
  244.     'frDlcmiFullEnquiryInterval' => '1.3.6.1.2.1.10.32.1.1.6',
  245.     'frDlcmiErrorThreshold' => '1.3.6.1.2.1.10.32.1.1.7',
  246.     'frDlcmiMonitoredEvents' => '1.3.6.1.2.1.10.32.1.1.8',
  247.     'frDlcmiMaxSupportedVCs' => '1.3.6.1.2.1.10.32.1.1.9',
  248.     'frDlcmiMulticast' => '1.3.6.1.2.1.10.32.1.1.10',
  249.     'frCircuitTable' => '1.3.6.1.2.1.10.32.2',
  250.     'frCircuitEntry' => '1.3.6.1.2.1.10.32.2.1',
  251.     'frCircuitIfIndex' => '1.3.6.1.2.1.10.32.2.1.1',
  252.     'frCircuitDlci' => '1.3.6.1.2.1.10.32.2.1.2',
  253.     'frCircuitState' => '1.3.6.1.2.1.10.32.2.1.3',
  254.     'frCircuitReceivedFECNs' => '1.3.6.1.2.1.10.32.2.1.4',
  255.     'frCircuitReceivedBECNs' => '1.3.6.1.2.1.10.32.2.1.5',
  256.     'frCircuitSentFrames' => '1.3.6.1.2.1.10.32.2.1.6',
  257.     'frCircuitSentOctets' => '1.3.6.1.2.1.10.32.2.1.7',
  258.     'frOutOctets' => '1.3.6.1.2.1.10.32.2.1.7',
  259.     'frCircuitReceivedFrames' => '1.3.6.1.2.1.10.32.2.1.8',
  260.     'frCircuitReceivedOctets' => '1.3.6.1.2.1.10.32.2.1.9',
  261.     'frInOctets' => '1.3.6.1.2.1.10.32.2.1.9',
  262.     'frCircuitCreationTime' => '1.3.6.1.2.1.10.32.2.1.10',
  263.     'frCircuitLastTimeChange' => '1.3.6.1.2.1.10.32.2.1.11',
  264.     'frCircuitCommittedBurst' => '1.3.6.1.2.1.10.32.2.1.12',
  265.     'frCircuitExcessBurst' => '1.3.6.1.2.1.10.32.2.1.13',
  266.     'frCircuitThroughput' => '1.3.6.1.2.1.10.32.2.1.14',
  267.     'frErrTable' => '1.3.6.1.2.1.10.32.3',
  268.     'frErrEntry' => '1.3.6.1.2.1.10.32.3.1',
  269.     'frErrIfIndex' => '1.3.6.1.2.1.10.32.3.1.1',
  270.     'frErrType' => '1.3.6.1.2.1.10.32.3.1.2',
  271.     'frErrData' => '1.3.6.1.2.1.10.32.3.1.3',
  272.     'frErrTime' => '1.3.6.1.2.1.10.32.3.1.4',
  273.     'frame-relay-globals' => '1.3.6.1.2.1.10.32.4',
  274.     'frTrapState' => '1.3.6.1.2.1.10.32.4.1',
  275.     'snmp' => '1.3.6.1.2.1.11',
  276.     'snmpInPkts' => '1.3.6.1.2.1.11.1',
  277.     'snmpInBadValues' => '1.3.6.1.2.1.11.10',
  278.     'snmpInReadOnlys' => '1.3.6.1.2.1.11.11',
  279.     'snmpInGenErrs' => '1.3.6.1.2.1.11.12',
  280.     'snmpInTotalReqVars' => '1.3.6.1.2.1.11.13',
  281.     'snmpInTotalSetVars' => '1.3.6.1.2.1.11.14',
  282.     'snmpInGetRequests' => '1.3.6.1.2.1.11.15',
  283.     'snmpInGetNexts' => '1.3.6.1.2.1.11.16',
  284.     'snmpInSetRequests' => '1.3.6.1.2.1.11.17',
  285.     'snmpInGetResponses' => '1.3.6.1.2.1.11.18',
  286.     'snmpInTraps' => '1.3.6.1.2.1.11.19',
  287.     'snmpOutPkts' => '1.3.6.1.2.1.11.2',
  288.     'snmpOutTooBigs' => '1.3.6.1.2.1.11.20',
  289.     'snmpOutNoSuchNames' => '1.3.6.1.2.1.11.21',
  290.     'snmpOutBadValues' => '1.3.6.1.2.1.11.22',
  291.     'snmpOutGenErrs' => '1.3.6.1.2.1.11.24',
  292.     'snmpOutGetRequests' => '1.3.6.1.2.1.11.25',
  293.     'snmpOutGetNexts' => '1.3.6.1.2.1.11.26',
  294.     'snmpOutSetRequests' => '1.3.6.1.2.1.11.27',
  295.     'snmpOutGetResponses' => '1.3.6.1.2.1.11.28',
  296.     'snmpOutTraps' => '1.3.6.1.2.1.11.29',
  297.     'snmpInBadVersions' => '1.3.6.1.2.1.11.3',
  298.     'snmpEnableAuthenTraps' => '1.3.6.1.2.1.11.30',
  299.     'snmpInBadCommunityNames' => '1.3.6.1.2.1.11.4',
  300.     'snmpInBadCommunityUses' => '1.3.6.1.2.1.11.5',
  301.     'snmpInASNParseErrs' => '1.3.6.1.2.1.11.6',
  302.     'snmpInTooBigs' => '1.3.6.1.2.1.11.8',
  303.     'snmpInNoSuchNames' => '1.3.6.1.2.1.11.9',
  304.     'ifName' => '1.3.6.1.2.1.31.1.1.1.1',
  305.     'ifInMulticastPkts' => '1.3.6.1.2.1.31.1.1.1.2',
  306.     'ifInBroadcastPkts' => '1.3.6.1.2.1.31.1.1.1.3',
  307.     'ifOutMulticastPkts' => '1.3.6.1.2.1.31.1.1.1.4',
  308.     'ifOutBroadcastPkts' => '1.3.6.1.2.1.31.1.1.1.5',
  309.     'ifHCInOctets' => '1.3.6.1.2.1.31.1.1.1.6',
  310.     'ifHCInUcastPkts' => '1.3.6.1.2.1.31.1.1.1.7',
  311.     'ifHCInMulticastPkts' => '1.3.6.1.2.1.31.1.1.1.8',
  312.     'ifHCInBroadcastPkts' => '1.3.6.1.2.1.31.1.1.1.9',
  313.     'ifHCOutOctets' => '1.3.6.1.2.1.31.1.1.1.10',
  314.     'ifHCOutUcastPkts' => '1.3.6.1.2.1.31.1.1.1.11',
  315.     'ifHCOutMulticastPkts' => '1.3.6.1.2.1.31.1.1.1.12',
  316.     'ifHCOutBroadcastPkts' => '1.3.6.1.2.1.31.1.1.1.13',
  317.     'ifLinkUpDownTrapEnable' => '1.3.6.1.2.1.31.1.1.1.14',
  318.     'ifHighSpeed' => '1.3.6.1.2.1.31.1.1.1.15',
  319.     'ifPromiscuousMode' => '1.3.6.1.2.1.31.1.1.1.16',
  320.     'ifConnectorPresent' => '1.3.6.1.2.1.31.1.1.1.17',
  321.     'ifAlias' => '1.3.6.1.2.1.31.1.1.1.18',
  322.     'ifCounterDiscontinuityTime' => '1.3.6.1.2.1.31.1.1.1.19',
  323.     'experimental' => '1.3.6.1.3',
  324.     'private' => '1.3.6.1.4',
  325.     'enterprises' => '1.3.6.1.4.1',
  326.   );
  327. # GIL
  328. my %revOIDS = (); # Reversed %Net_SNMP_util::OIDS hash
  329. my $RevNeeded = 1;
  330. undef $Net_SNMP_util::Host;
  331. undef $Net_SNMP_util::Session;
  332. undef $Net_SNMP_util::Version;
  333. undef $Net_SNMP_util::LHost;
  334. undef $Net_SNMP_util::IPv4only;
  335. undef $Net_SNMP_util::ContextEngineID;
  336. undef $Net_SNMP_util::ContextName;
  337. $Net_SNMP_util::Debug = 0;
  338. $Net_SNMP_util::SuppressWarnings = 0;
  339. $Net_SNMP_util::CacheFile = "OID_cache.txt";
  340. $Net_SNMP_util::CacheLoaded = 0;
  341. $Net_SNMP_util::ReturnArrayRefs = 0;
  342. $Net_SNMP_util::ReturnHashRefs = 0;
  343. $Net_SNMP_util::MaxRepetitions = 12;
  344. ### Prototypes
  345. sub snmpget ($@);
  346. sub snmpgetnext ($@);
  347. sub snmpopen ($$$);
  348. sub snmpwalk ($@);
  349. sub snmpwalk_flg ($$@);
  350. sub snmpset ($@);
  351. sub snmptrap ($$$$$@);
  352. sub snmpgetbulk ($$$@);
  353. sub snmpwalkhash ($$@);
  354. sub toOID (@);
  355. sub snmpmapOID (@);
  356. sub snmpMIB_to_OID ($);
  357. sub Check_OID ($);
  358. sub snmpLoad_OID_Cache ($);
  359. sub snmpQueue_MIB_File (@);
  360. sub ASNtype ($);
  361. sub version () { $VERSION; }
  362. =head1 Option Notes
  363. =over
  364. =item host Parameter
  365. SNMP parameters can be specified as part of the hostname/ip address passed
  366. as the first argument.  The syntax is
  367.     community@host:port:timeout:retries:backoff:version
  368. If the community is left off, it defaults to "public".
  369. If the port is left off, it defaults to 161 for everything but snmptrap().
  370. The snmptrap() routine uses a default port of 162.
  371. Timeout and retries defaults to whatever Net::SNMP uses, currently 5.0 seconds
  372. and 1 retry (2 tries total).
  373. The backoff parameter is currently unimplemented.
  374. The version parameter defaults to SNMP version 1.  Some SNMP values such as
  375. 64-bit counters have to be queried using SNMP version 2.  Specifying "2" or
  376. "2c" as the version parameter will accomplish this.  The snmpgetbulk routine
  377. is only supported in SNMP version 2 and higher.  Additional security features
  378. are available under SNMP version 3.
  379. Some machines have additional security features that only allow SNMP
  380. queries to come from certain IP addresses.  If the host doing the query
  381. has multiple interfaces, it may be necessary to specify the interface
  382. the query should come from.  The port parameter is further broken down into
  383.     remote_port!local_address!local_port
  384. Here are some examples:
  385.     somehost
  386.     somehost:161
  387.     somehost:161!192.168.2.4!4000  use 192.168.2.4 and port 4000 as source
  388.     somehost:!192.168.2.4          use 192.168.2.4 as source
  389.     somehost:!!4000                use port 4000 as source
  390. Most people will only need to use the first form ("somehost").
  391. =item OBJECT IDENTIFIERs
  392. To further simplify SNMP queries, the query routines use a small table that
  393. maps the textual representation of OBJECT IDENTIFIERs to their dotted notation.
  394. The OBJECT IDENTIFIERs from RFC1213 (MIB-II) and RFC1315 (Frame Relay) are
  395. preloaded.  This allows OBJECT IDENTIFIERs like "ifInOctets.4" to be used
  396. instead of the more cumbersome "1.3.6.1.2.1.2.2.1.10.4".
  397. Several functions are provided to manage the mapping table.  Mapping entries
  398. can be added directly, SNMP MIB files can be read, and a cache file with the
  399. text-to-OBJECT-IDENTIFIER mappings are maintained.  By default, the file
  400. "OID_cache.txt" is loaded, but it can by changed by setting the variable
  401. $Net_SNMP_util::CacheFile to the desired file name.  The functions to
  402. manipulate the mappings are:
  403.     snmpmapOID Add a textual OID mapping directly
  404.     snmpMIB_to_OID Read a SNMP MIB file
  405.     snmpLoad_OID_Cache Load an OID-mapping cache file
  406.     snmpQueue_MIB_File Queue a SNMP MIB file for loading on demand
  407. =item Net::SNMP extensions
  408. This module is built on top of Net::SNMP.  Net::SNMP has a different method
  409. of specifying SNMP parameters.  To support this different method, this module
  410. will accept an optional hash reference containing the SNMP parameters. The
  411. hash may contain the following:
  412. [-port => $port,]
  413. [-localaddr => $localaddr,]
  414. [-localport     => $localport,]
  415. [-version       => $version,]
  416. [-domain        => $domain,]
  417. [-timeout       => $seconds,]
  418. [-retries       => $count,]
  419. [-maxmsgsize    => $octets,]
  420. [-debug         => $bitmask,]
  421. [-community     => $community,]   # v1/v2c  
  422. [-username      => $username,]    # v3
  423. [-authkey => $authkey,]     # v3  
  424. [-authpassword  => $authpasswd,]  # v3  
  425. [-authprotocol  => $authproto,]   # v3  
  426. [-privkey       => $privkey,]     # v3  
  427. [-privpassword  => $privpasswd,]  # v3  
  428. [-privprotocol  => $privproto,]   # v3
  429. [-contextengineid => $engine_id,] # v3 
  430. [-contextname     => $name,]      # v3
  431. Please see the documentation for Net::SNMP for a description of these
  432. parameters.
  433. =item SNMPv3 Arguments
  434. A SNMP context is a collection of management information accessible by a SNMP 
  435. entity.  An item of management information may exist in more than one context 
  436. and a SNMP entity potentially has access to many contexts.  The combination of 
  437. a contextEngineID and a contextName unambiguously identifies a context within 
  438. an administrative domain.  In a SNMPv3 message, the contextEngineID and 
  439. contextName are included as part of the scopedPDU.  All methods that generate 
  440. a SNMP message optionally take a B<-contextengineid> and B<-contextname> 
  441. argument to configure these fields.
  442. =over
  443. =item Context Engine ID
  444. The B<-contextengineid> argument expects a hexadecimal string representing
  445. the desired contextEngineID.  The string must be 10 to 64 characters (5 to 
  446. 32 octets) long and can be prefixed with an optional "0x".  Once the 
  447. B<-contextengineid> is specified it stays with the object until it is changed 
  448. again or reset to default by passing in the undefined value.  By default, the 
  449. contextEngineID is set to match the authoritativeEngineID of the authoritative
  450. SNMP engine.
  451. =item Context Name
  452. The contextName is passed as a string which must be 0 to 32 octets in length 
  453. using the B<-contextname> argument.  The contextName stays with the object 
  454. until it is changed.  The contextName defaults to an empty string which 
  455. represents the "default" context.
  456. =back
  457. =back
  458. =cut
  459. # [public methods] ---------------------------------------------------
  460. =head1 Functions
  461. =head2 snmpget() - send a SNMP get-request to the remote agent
  462.     @result = snmpget(
  463. [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
  464. [%param_hash],
  465. @oids
  466.     );
  467. This function performs a SNMP get-request query to gather data from the remote
  468. agent on the host specified.  The message is built using the list of OBJECT
  469. IDENTIFIERs passed as an array.  Each OBJECT IDENTIFIER is placed into a single
  470. SNMP GetRequest-PDU in the same order that it held in the original list.
  471. The requested values are returned in an array in the same order as they were
  472. requested.  In scalar context the first requested value is returned.
  473. =cut
  474. #
  475. # snmpget.
  476. #
  477. sub snmpget ($@) {
  478.   my($host, @vars) = @_;
  479.   my($session, @enoid, %args, $ret, $oid, @retvals);
  480.   $session = &snmpopen($host, 0, @vars);
  481.   if (!defined($session)) {
  482.     carp "SNMPGET Problem for $host"
  483.       unless ($Net_SNMP_util::SuppressWarnings > 1);
  484.     return undef;
  485.   }
  486.   @enoid = &toOID(@vars);
  487.   return undef unless defined $enoid[0];
  488.   $args{'-varbindlist'} = @enoid;
  489.   if ($Net_SNMP_util::Version > 2) {
  490.     $args{'-contextengineid'} = $Net_SNMP_util::ContextEngineID
  491.       if (defined($Net_SNMP_util::ContextEngineID));
  492.     $args{'-contextname'} = $Net_SNMP_util::ContextName
  493.       if (defined($Net_SNMP_util::ContextName));
  494.   }
  495.   $ret = $session->get_request(%args);
  496.   if ($ret) {
  497.       foreach $oid (@enoid) {
  498.       push @retvals, $ret->{$oid} if (exists($ret->{$oid}));
  499.     }
  500.     return wantarray ? @retvals : $retvals[0];
  501.   }
  502.   $ret = join(' ', @vars);
  503.   $oid = $session->error();
  504.   carp "SNMPGET Problem for $ret on $host : $oid"
  505.     unless ($Net_SNMP_util::SuppressWarnings > 1);
  506.   return undef;
  507. }
  508. =head2 snmpgetnext() - send a SNMP get-next-request to the remote agent
  509.     @result = snmpgetnext(
  510. [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
  511. [%param_hash],
  512. @oids
  513.     );
  514. This function performs a SNMP get-next-request query to gather data from the
  515. remote agent on the host specified.  The message is built using the list of
  516. OBJECT IDENTIFIERs passed as an array.  Each OBJECT IDENTIFIER is placed into a
  517. single SNMP GetNextRequest-PDU in the same order that it held in the original
  518. list.
  519. The requested values are returned in an array in the same order as they were
  520. requested.  The OBJECT IDENTIFIER number is added as a prefix to each value
  521. using a colon as a separator, like '1.3.6.1.2.1.2.2.1.2.1:ethernet'.
  522. In scalar context the first requested value is returned.
  523. =cut
  524. #
  525. # snmpgetnext.
  526. #
  527. sub snmpgetnext ($@) {
  528.   my($host, @vars) = @_;
  529.   my($session, @enoid, %args, $ret, $oid, @retvals);
  530.   $session = &snmpopen($host, 0, @vars);
  531.   if (!defined($session)) {
  532.     carp "SNMPGETNEXT Problem for $host"
  533.       unless ($Net_SNMP_util::SuppressWarnings > 1);
  534.     return undef;
  535.   }
  536.   @enoid = &toOID(@vars);
  537.   return undef unless defined $enoid[0];
  538.   $args{'-varbindlist'} = @enoid;
  539.   if ($Net_SNMP_util::Version > 2) {
  540.     $args{'-contextengineid'} = $Net_SNMP_util::ContextEngineID
  541.       if (defined($Net_SNMP_util::ContextEngineID));
  542.     $args{'-contextname'} = $Net_SNMP_util::ContextName
  543.       if (defined($Net_SNMP_util::ContextName));
  544.   }
  545.   $ret = $session->get_next_request(%args);
  546.   if ($ret) {
  547.       foreach $oid (@enoid) {
  548.       push @retvals, $oid . ':' . $ret->{$oid} if (exists($ret->{$oid}));
  549.     }
  550.     return wantarray ? @retvals : $retvals[0];
  551.   }
  552.   $ret = join(' ', @vars);
  553.   $oid = $session->error();
  554.   carp "SNMPGETNEXT Problem for $ret on $host : $oid"
  555.     unless ($Net_SNMP_util::SuppressWarnings > 1);
  556.   return undef;
  557. }
  558. =head2 snmpgetbulk() - send a SNMP get-bulk-request to the remote agent
  559.     @result = snmpgetbulk(
  560. [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
  561. $nonrepeaters,
  562. $maxrepetitions,
  563. [%param_hash],
  564. @oids
  565.     );
  566. This function performs a SNMP get-bulk-request query to gather data from the
  567. remote agent on the host specified.
  568. =over
  569. =item *
  570. The B<$nonrepeaters> value specifies the number of variables in the @oids list
  571. for which a single successor is to be returned.  If it is null or undefined,
  572. a value of 0 is used.
  573. =item *
  574. The B<$maxrepetitions> value specifies the number of successors to be returned
  575. for the remaining variables in the @oids list.  If it is null or undefined,
  576. the default value of 12 is used.
  577. =item *
  578. The message is built using the list of
  579. OBJECT IDENTIFIERs passed as an array.  Each OBJECT IDENTIFIER is placed into a
  580. single SNMP GetNextRequest-PDU in the same order that it held in the original
  581. list.
  582. =back
  583. The requested values are returned in an array in the same order as they were
  584. requested.
  585. B<NOTE:> This function can only be used when the SNMP version is set to
  586. SNMPv2c or SNMPv3.
  587. =cut
  588. #
  589. # snmpgetbulk.
  590. #
  591. sub snmpgetbulk ($$$@) {
  592.   my($host, $nr, $mr, @vars) = @_;
  593.   my($session, %args, @enoid, $ret);
  594.   my($oid, @retvals);
  595.   $session = &snmpopen($host, 0, @vars);
  596.   if (!defined($session)) {
  597.     carp "SNMPGETBULK Problem for $hostn"
  598.       unless ($Net_SNMP_util::SuppressWarnings > 1);
  599.     return undef;
  600.   }
  601.   if ($Net_SNMP_util::Version < 2) {
  602.     carp "SNMPGETBULK Problem for $host : must use SNMP version > 1"
  603.       unless ($Net_SNMP_util::SuppressWarnings > 1);
  604.     return undef;
  605.   }
  606.   $args{'-nonrepeaters'} = $nr if ($nr > 0);
  607.   $mr = $Net_SNMP_util::MaxRepetitions if ($mr <= 0);
  608.   $args{'-maxrepetitions'} = $mr;
  609.   if ($Net_SNMP_util::Version > 2) {
  610.     $args{'-contextengineid'} = $Net_SNMP_util::ContextEngineID
  611.       if (defined($Net_SNMP_util::ContextEngineID));
  612.     $args{'-contextname'} = $Net_SNMP_util::ContextName
  613.       if (defined($Net_SNMP_util::ContextName));
  614.   }
  615.   @enoid = &toOID(@vars);
  616.   return undef unless defined $enoid[0];
  617.   $args{'-varbindlist'} = @enoid;
  618.   $ret = $session->getbulk_request(%args);
  619.   if ($ret) {
  620.     @enoid = &Net::SNMP::oid_lex_sort(keys %$ret);
  621.     foreach $oid (@enoid) {
  622.       push @retvals, $oid . ":" . $ret->{$oid};
  623.     }
  624.     return (@retvals);
  625.   } else {
  626.     $ret = join(' ', @vars);
  627.     $oid = $session->error();
  628.     carp "SNMPGETBULK Problem for $ret on $host : $oidn"
  629.       unless ($Net_SNMP_util::SuppressWarnings > 1);
  630.     return undef;
  631.   }
  632. }
  633. =head2 snmpwalk() - walk OBJECT IDENTIFIER tree(s) on the remote agent
  634.     @result = snmpwalk(
  635. [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
  636. [%param_hash],
  637. @oids
  638.     );
  639. This function performs a sequence of SNMP get-next-request or get-bulk-request
  640. (if the SNMP version is 2 or higher) queries to gather data from the remote
  641. agent on the host specified.  The initial message is built using the list of
  642. OBJECT IDENTIFIERs passed as an array.  Each OBJECT IDENTIFIER is placed into a
  643. single SNMP GetNextRequest-PDU in the same order that it held in the original
  644. list.  Queries continue until all the returned OBJECT IDENTIFIERs are no longer
  645. a child of the base OBJECT IDENTIFIERs.
  646. The requested values are returned in an array in the same order as they were
  647. requested.  The OBJECT IDENTIFIER number is added as a prefix to each value
  648. using a colon as a separator, like '1.3.6.1.2.1.2.2.1.2.1:ethernet'.  If only
  649. one OBJECT IDENTIFIER is requested, just the "instance" part of the OBJECT
  650. IDENTIFIER is added as a prefix, like '1:ethernet', '2:ethernet', '3:fddi'.
  651. =cut
  652. #
  653. # snmpwalk.
  654. #
  655. sub snmpwalk ($@) {
  656.   my($host, @vars) = @_;
  657.   return(&snmpwalk_flg($host, undef, @vars));
  658. }
  659. =head2 snmpset() - send a SNMP set-request to the remote agent
  660.     @result = snmpset(
  661. [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
  662. [%param_hash],
  663. $oid1, $type1, $value1,
  664. [$oid2, $type2, $value2 ...]
  665.     );
  666. This function is used to modify data on the remote agent using a SNMP
  667. set-request.  The message is built using the list of values consisting of groups
  668. of an OBJECT IDENTIFIER, an object type, and the actual value to be set.
  669. The object type can be one of the following strings:
  670.     integer | int
  671.     string | octetstring | octet string
  672.     oid | object id | object identifier
  673.     ipaddr | ip addr4ess
  674.     timeticks
  675.     uint | uinteger | uinteger32 | unsigned int | unsigned integer | unsigned integer32
  676.     counter | counter 32
  677.     counter64
  678.     gauge | gauge32
  679. The object type may also be an octet corresponding to the ASN.1 type.  See
  680. the Net::SNMP documentation for more information.
  681. The requested values are returned in an array in the same order as they were
  682. requested.  In scalar context the first requested value is returned.
  683. =cut
  684. #
  685. # snmpset.
  686. #
  687. sub snmpset($@) {
  688.   my($host, @vars) = @_;
  689.   my($session, @vals, %args, $ret);
  690.   my($oid, $type, $value, @enoid, @retvals);
  691.   $session = &snmpopen($host, 0, @vars);
  692.   if (!defined($session)) {
  693.     carp "SNMPSET Problem for $host"
  694.       unless ($Net_SNMP_util::SuppressWarnings > 1);
  695.     return undef;
  696.   }
  697.   if ($Net_SNMP_util::Version > 2) {
  698.     $args{'-contextengineid'} = $Net_SNMP_util::ContextEngineID
  699.       if (defined($Net_SNMP_util::ContextEngineID));
  700.     $args{'-contextname'} = $Net_SNMP_util::ContextName
  701.       if (defined($Net_SNMP_util::ContextName));
  702.   }
  703.   while(@vars) {
  704.     ($oid) = toOID((shift @vars));
  705.     $ret   = shift @vars;
  706.     $value = shift @vars;
  707.     $type  = ASNtype($ret);
  708.     if (!defined($type)) {
  709.       carp "unknown SNMP type: $typen"
  710. unless ($Net_SNMP_util::SuppressWarnings > 1);
  711.     }
  712.     push @vals, $oid, $type, $value;
  713.     push @enoid, $oid;
  714.   }
  715.   return undef unless defined $vals[0];
  716.   $args{'-varbindlist'} = @vals;
  717.   $ret = $session->set_request(%args);
  718.   if ($ret) {
  719.       foreach $oid (@enoid) {
  720.       push @retvals, $ret->{$oid} if (exists($ret->{$oid}));
  721.     }
  722.     return wantarray ? @retvals : $retvals[0];
  723.   }
  724.   $ret = join(' ', @enoid);
  725.   $oid = $session->error();
  726.   carp "SNMPSET Problem for $ret on $host : $oid"
  727.     unless ($Net_SNMP_util::SuppressWarnings > 1);
  728.   return undef;
  729. }
  730. =head2 snmptrap() - send a SNMP trap to the remote manager
  731.     @result = snmptrap(
  732. [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
  733. $enterprise,
  734. $agentaddr,
  735. $generictrap,
  736. $specifictrap,
  737. [%param_hash],
  738. $oid1, $type1, $value1, 
  739. [$oid2, $type2, $value2 ...]
  740.     );
  741. This function sends a SNMP trap to the remote manager on the host specified.
  742. The message is built using the list of values consisting of groups of an
  743. OBJECT IDENTIFIER, an object type, and the actual value to be set.
  744. The object type can be one of the following strings:
  745.     integer | int
  746.     string | octetstring | octet string
  747.     oid | object id | object identifier
  748.     ipaddr | ip addr4ess
  749.     timeticks
  750.     uint | uinteger | uinteger32 | unsigned int | unsigned integer | unsigned integer32
  751.     counter | counter 32
  752.     counter64
  753.     gauge | gauge32
  754. The object type may also be an octet corresponding to the ASN.1 type.  See
  755. the Net::SNMP documentation for more information.
  756. A true value is returned if sending the trap is successful.  The undefined value
  757. is returned when a failure has occurred.
  758. When the trap is sent as SNMPv2c, the B<$enterprise>, B<$agentaddr>,
  759. B<$generictrap>, and B<$specifictrap> arguments are ignored.  Furthermore,
  760. the first two (oid, type, value) tuples should be:
  761. =over
  762. =item *
  763. sysUpTime.0 - ('1.3.6.1.2.1.1.3.0', 'timeticks', $timeticks)
  764. =item *
  765. snmpTrapOID.0 - ('1.3.6.1.6.3.1.1.4.1.0', 'oid', $oid)
  766. =back
  767. B<NOTE:> This function can only be used when the SNMP version is set to
  768. SNMPv1 or SNMPv2c.
  769. =cut
  770. #
  771. # Send an SNMP trap
  772. #
  773. sub snmptrap($$$$$@) {
  774.   my($host, $ent, $agent, $gen, $spec, @vars) = @_;
  775.   my($oid, $type, $value, $ret, @enoid, @vals);
  776.   my($session, %args);
  777.   $session = &snmpopen($host, 1, @vars);
  778.   if (!defined($session)) {
  779.     carp "SNMPTRAP Problem for $hostn"
  780.       unless ($Net_SNMP_util::SuppressWarnings > 1);
  781.     return undef;
  782.   }
  783.   if ($Net_SNMP_util::Version == 1) {
  784.     $args{'-enterprise'} = $ent if (defined($ent) && (length($ent) > 0));
  785.     $args{'-agentaddr'} = $agent if (defined($agent) && (length($agent) > 0));
  786.     $args{'-generictrap'} = $gen if (defined($gen) && (length($gen) > 0));
  787.     $args{'-specifictrap'} = $spec if (defined($spec) && (length($spec) > 0));
  788.   } elsif ($Net_SNMP_util::Version > 2) {
  789.     carp "SNMPTRAP Problem for $host : must use SNMP version 1 or 2"
  790.       unless ($Net_SNMP_util::SuppressWarnings > 1);
  791.   }
  792.   while(@vars) {
  793.     ($oid) = toOID((shift @vars));
  794.     $ret   = shift @vars;
  795.     $value = shift @vars;
  796.     $type  = ASNtype($ret);
  797.     if (!defined($type)) {
  798.       carp "unknown SNMP type: $typen"
  799. unless ($Net_SNMP_util::SuppressWarnings > 1);
  800.     }
  801.     push @vals, $oid, $type, $value;
  802.     push @enoid, $oid;
  803.   }
  804.   return undef unless defined $vals[0];
  805.   $args{'-varbindlist'} = @vals;
  806.   if ($Net_SNMP_util::Version == 1) {
  807.     $ret = $session->trap_request(%args);
  808.   } else {
  809.     $ret = $session->snmpv2_trap(%args);
  810.   }
  811.   if (!$ret) {
  812.     $ret = join(' ', @enoid);
  813.     $oid = $session->error();
  814.     carp "SNMPTRAP Problem for $ret on $host : $oid"
  815.       unless ($Net_SNMP_util::SuppressWarnings > 1);
  816.   }
  817.   return $ret;
  818. }
  819. =head2 snmpmaptable() - walk OBJECT IDENTIFIER tree(s) on the remote agent
  820.     $result = snmpmaptable(
  821. [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
  822. &function,
  823. [%param_hash],
  824. @oids
  825.     );
  826. This function performs a sequence of SNMP get-next-request or get-bulk-request
  827. (if the SNMP version is 2 or higher) queries to gather data from the remote
  828. agent on the host specified.  The initial message is built using the list of
  829. OBJECT IDENTIFIERs passed as an array.  Each OBJECT IDENTIFIER is placed into a
  830. single SNMP GetNextRequest-PDU in the same order that it held in the original
  831. list.  Queries continue until all the returned OBJECT IDENTIFIERs are no longer
  832. a child of the base OBJECT IDENTIFIERs.  The OBJECT IDENTIFIERs must correspond
  833. to column entries for a conceptual row in a table.  They may however be columns
  834. in different tables as long as each table is indexed the same way.
  835. =over
  836. =item *
  837. The B<&function> argument will be called once per row of the table.  It
  838. will be passed the row index as a partial OBJECT IDENTIFIER in dotted notation,
  839. e.g. "1.3" or "10.0.1.34", and the values of the requested table columns in
  840. that row.
  841. =back
  842. The number of rows in the table is returned on success.  The undefined value
  843. is returned when a failure has occurred.
  844. =cut
  845. #
  846. # walk a table, calling a user-supplied function for each
  847. # column of a table.
  848. #
  849. sub snmpmaptable($$@) {
  850.   my($host, $fun, @vars) = @_;
  851.   return snmpmaptable4($host, $fun, 0, @vars);
  852. }
  853. =head2 snmpmaptable4() - walk OBJECT IDENTIFIER tree(s) on the remote agent
  854.     $result = snmpmaptable4(
  855. [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
  856. &function,
  857. $maxrepetitions,
  858. [%param_hash],
  859. @oids
  860.     );
  861. This function performs a sequence of SNMP get-next-request or get-bulk-request
  862. (if the SNMP version is 2 or higher) queries to gather data from the remote
  863. agent on the host specified.  The initial message is built using the list of
  864. OBJECT IDENTIFIERs passed as an array.  Each OBJECT IDENTIFIER is placed into a
  865. single SNMP GetNextRequest-PDU in the same order that it held in the original
  866. list.  Queries continue until all the returned OBJECT IDENTIFIERs are no longer
  867. a child of the base OBJECT IDENTIFIERs.  The OBJECT IDENTIFIERs must correspond
  868. to column entries for a conceptual row in a table.  They may however be columns
  869. in different tables as long as each table is indexed the same way.
  870. =over
  871. =item *
  872. The B<&function> argument will be called once per row of the table.  It
  873. will be passed the row index as a partial OBJECT IDENTIFIER in dotted notation,
  874. e.g. "1.3" or "10.0.1.34", and the values of the requested table columns in
  875. that row.
  876. =item *
  877. The B<$maxrepetitions> argument specifies the number of rows to be returned
  878. by a single get-bulk-request.  If it is null or undefined, the default value
  879. of 12 is used.
  880. =back
  881. The number of rows in the table is returned on success.  The undefined value
  882. is returned when a failure has occurred.
  883. =cut
  884. sub snmpmaptable4($$$@) {
  885.   my($host, $fun, $max_reps, @vars) = @_;
  886.   my($session, @enoid, %args, $ret);
  887.   my($oid, $soid, $toid, $inst, @row, $nr);
  888.   $session = &snmpopen($host, 0, @vars);
  889.   if (!defined($session)) {
  890.     carp "SNMPMAPTABLE Problem for $hostn"
  891.       unless ($Net_SNMP_util::SuppressWarnings > 1);
  892.     return undef;
  893.   }
  894.   @enoid = toOID(@vars);
  895.   return undef unless defined $enoid[0];
  896.   if ($Net_SNMP_util::Version > 1) {
  897.     $max_reps = $Net_SNMP_util::MaxRepetitions if ($max_reps <= 0);
  898.     $args{'-maxrepetitions'} = $max_reps;
  899.   }
  900.   if ($Net_SNMP_util::Version > 2) {
  901.     $args{'-contextengineid'} = $Net_SNMP_util::ContextEngineID
  902.       if (defined($Net_SNMP_util::ContextEngineID));
  903.     $args{'-contextname'} = $Net_SNMP_util::ContextName
  904.       if (defined($Net_SNMP_util::ContextName));
  905.   }
  906.   $args{'-columns'} = @enoid;
  907.   $ret = $session->get_entries(%args);
  908.   if ($ret) {
  909.     $soid = $enoid[0];
  910.     $nr = 0;
  911.     foreach $oid (&Net::SNMP::oid_lex_sort(keys %$ret)) {
  912.       if (&Net::SNMP::oid_base_match($soid, $oid)) {
  913. $inst = substr($oid, length($soid)+1);
  914. undef @row;
  915. foreach $toid (@enoid) {
  916.   push @row, $ret->{$toid . "." . $inst};
  917. }
  918. &$fun($inst, @row);
  919. $nr++;
  920.       } else {
  921. return($nr) if ($nr > 0);
  922.       }
  923.     }
  924.     return($nr);
  925.   } else {
  926.     $ret = join(' ', @vars);
  927.     $oid = $session->error();
  928.     carp "SNMPMAPTABLE Problem for $ret on $host : $oidn"
  929.       unless ($Net_SNMP_util::SuppressWarnings > 1);
  930.     return undef;
  931.   }
  932. }
  933. =head2 snmpwalkhash() - send a SNMP get-next-request to the remote agent
  934.     @result = snmpwalkhash(
  935. [community@]host[:port[:timeout[:retries[:backoff[:version]]]]],
  936. &function(),
  937. [%param_hash],
  938. @oids,
  939. [%hash]
  940.     );
  941. This function performs a sequence of SNMP get-next-request or get-bulk-request
  942. (if the SNMP version is 2 or higher) queries to gather data from the remote
  943. agent on the host specified.  The message is built using the list of
  944. OBJECT IDENTIFIERs passed as an array.  Each OBJECT IDENTIFIER is placed into a
  945. single SNMP GetNextRequest-PDU in the same order that it held in the original
  946. list.  Queries continue until all the returned OBJECT IDENTIFIERs are outside
  947. of the tree specified by the initial OBJECT IDENTIFIERs.
  948. The B<&function> is called once for every returned value.  It is passed a
  949. reference to a hash, the hostname, the textual OBJECT IDENTIFIER, the
  950. dotted-numberic OBJECT IDENTIFIER, the instance, the value and the requested
  951. textual OBJECT IDENTIFIER.  That function can customize the result so the
  952. values can be extracted later by hosts, by oid_names, by oid_numbers,
  953. by instances... like these:
  954.     $hash{$host}{$name}{$inst} = $value;
  955.     $hash{$host}{$oid}{$inst} = $value;
  956.     $hash{$name}{$inst} = $value;
  957.     $hash{$oid}{$inst} = $value;
  958.     $hash{$oid . '.' . $ints} = $value;
  959.     $hash{$inst} = $value;
  960.     ...
  961. If the last argument to B<snmpwalkhash> is a reference to a hash, that hash
  962. reference is passed to the passed-in function instead of a local hash
  963. reference.  That way the function can look up other objects unrelated
  964. to the current invocation of B<snmpwalkhash>.
  965. The snmpwalkhash routine returns the hash.
  966. =cut
  967. #
  968. # Walk the MIB, putting everything you find into hashes.
  969. #
  970. sub snmpwalkhash($$@) {
  971. #  my($host, $hash_sub, @vars) = @_;
  972.   return(&snmpwalk_flg( @_ ));
  973. }
  974. =head2 snmpmapOID() - add texual OBJECT INDENTIFIER mapping
  975.     snmpmapOID(
  976. $text1, $oid1,
  977. [ $text2, $oid2 ...]
  978.     );
  979. This routine adds entries to the table that maps textual representation of
  980. OBJECT IDENTIFIERs to their dotted notation.  For example, 
  981.     snmpmapOID('ciscoCPU', '1.3.6.1.4.1.9.9.109.1.1.1.1.5.1');
  982. allows the string 'ciscoCPU' to be used as an OBJECT IDENTIFIER in any SNMP
  983. query routine.
  984. This routine doesn't return anything.
  985. =cut
  986. #
  987. #  Add passed-in text, OID pairs to the OID mapping table.
  988. #
  989. sub snmpmapOID(@)
  990. {
  991.   my(@vars) = @_;
  992.   my($oid, $txt, $ind);
  993.   $ind = 0;
  994.   while($ind <= $#vars) {
  995.     $txt = $vars[$ind++];
  996.     next unless($txt =~ /^(([a-zA-Z][a-zA-Zd-]*.)*([a-zA-Z][a-zA-Zd-]*))$/);
  997.     $oid = $vars[$ind++];
  998.     next unless($oid =~ /^((d+.)*d+)$/);
  999.     $Net_SNMP_util::OIDS{$txt} = $oid;
  1000.     $RevNeeded = 1;
  1001.     print "snmpmapOID: $txt => $oidn" if $Net_SNMP_util::Debug;
  1002.   }
  1003.   return undef;
  1004. }
  1005. =head2 snmpLoad_OID_Cache() - Read a file of cached OID mappings
  1006.     $result = snmpLoad_OID_Cache(
  1007. $file
  1008.     );
  1009. This routine opens the file named by the B<$file> argument and reads it.
  1010. The file should contain text, OBJECT IDENTIFIER pairs, one pair
  1011. per line.  It adds the pairs as entries to the table that maps textual
  1012. representation of OBJECT IDENTIFIERs to their dotted notation.
  1013. Blank lines and anything after a '#' or between '--' is ignored.
  1014. This routine returns 0 on success and -1 if the B<$file> could not be opened.
  1015. =cut
  1016. #
  1017. # Open the passed-in file name and read it in to populate
  1018. # the cache of text-to-OID map table.  It expects lines
  1019. # with two fields, the first the textual string like "ifInOctets",
  1020. # and the second the OID value, like "1.3.6.1.2.1.2.2.1.10".
  1021. #
  1022. # blank lines and anything after a '#' or between '--' is ignored.
  1023. #
  1024. sub snmpLoad_OID_Cache ($) {
  1025.   my($arg) = @_;
  1026.   my($txt, $oid);
  1027.   if (!open(CACHE, $arg)) {
  1028.     carp "snmpLoad_OID_Cache: Can't open $arg: $!"
  1029.       unless ($Net_SNMP_util::SuppressWarnings > 1);
  1030.     return -1;
  1031.   }
  1032.   while(<CACHE>) {
  1033.     s/#.*//;
  1034.     s/--.*--//g;
  1035.     s/--.*//;
  1036.     next if (/^$/);
  1037.     next unless (/s/);
  1038.     chop;
  1039.     ($txt, $oid) = split(' ', $_, 2);
  1040.     &snmpmapOID($txt, $oid);
  1041.   }
  1042.   close(CACHE);
  1043.   return 0;
  1044. }
  1045. =head2 snmpMIB_to_OID() - Read a MIB file for textual OID mappings
  1046.     $result = snmpMIB_to_OID(
  1047. $file
  1048.     );
  1049. This routine opens the file named by the B<$file> argument and reads it.
  1050. The file should be an SNMP Management Information Base (MIB) file
  1051. that describes OBJECT IDENTIFIERs supported by an SNMP agent.
  1052. per line.  It adds the textual representation of the OBJECT IDENTIFIERs
  1053. to the text-to-OID mapping table.
  1054. This routine returns the number of entries added to the table or -1 if
  1055. the B<$file> could not be opened.
  1056. =cut
  1057. #
  1058. # Read in the passed MIB file, parsing it
  1059. # for their text-to-OID mappings
  1060. #
  1061. sub snmpMIB_to_OID ($) {
  1062.   my($arg) = @_;
  1063.   my($quote, $buf, $var, $code, $val, $tmp, $tmpv, $strt);
  1064.   my($ret, $pass, $pos, $need2pass, $cnt, %prev);
  1065.   my(%Link) = (
  1066.     'org' => 'iso',
  1067.     'dod' => 'org',
  1068.     'internet' => 'dod',
  1069.     'directory' => 'internet',
  1070.     'mgmt' => 'internet',
  1071.     'mib-2' => 'mgmt',
  1072.     'experimental' => 'internet',
  1073.     'private' => 'internet',
  1074.     'enterprises' => 'private',
  1075.   );
  1076.   if (!open(MIB, $arg)) {
  1077.     carp "snmpMIB_to_OID: Can't open $arg: $!"
  1078.       unless ($Net_SNMP_util::SuppressWarnings > 1);
  1079.     return -1;
  1080.   }
  1081.   print "snmpMIB_to_OID: loading $argn" if $Net_SNMP_util::Debug;
  1082.   $ret = 0;
  1083.   $pass = 0;
  1084.   $need2pass = 1;
  1085.   $cnt = 0;
  1086.   $pos = tell(MIB);
  1087.   while($need2pass) {
  1088.     while(<MIB>) {
  1089.       s/--.*--//g; # throw away comments (-- anything --)
  1090.       s/--.*//; # throw away comments (-- anything EOL)
  1091.       if ($quote) {
  1092. next unless /"/;
  1093. $quote = 0;
  1094.       }
  1095.       chop;
  1096. #
  1097. # $buf = "$buf $_";
  1098. # Previous line removed (and following replacement)
  1099. # suggested by Brian Reichert, reichert@numachi.com
  1100. #
  1101.       $buf .= ' ' . $_;
  1102.       $buf =~ s/s+/ /g;
  1103.       if ($buf =~ / DEFINITIONS ::= BEGIN/) {
  1104. if ($pass == 0 && $need2pass) {
  1105.   seek(MIB, $pos, 0);
  1106.   $buf = "";
  1107.   $pass = 1;
  1108.   $need2pass = 0;
  1109.   $cnt = 0;
  1110.   next;
  1111. }
  1112. $need2pass = 0;
  1113. $pass = 0;
  1114. $pos = tell(MIB);
  1115. undef %Link;
  1116. undef %prev;
  1117. %Link = (
  1118.   'org' => 'iso',
  1119.   'dod' => 'org',
  1120.   'internet' => 'dod',
  1121.   'directory' => 'internet',
  1122.   'mgmt' => 'internet',
  1123.   'mib-2' => 'mgmt',
  1124.   'experimental' => 'internet',
  1125.   'private' => 'internet',
  1126.   'enterprises' => 'private',
  1127. );
  1128. $buf = "";
  1129. next;
  1130.       }
  1131.       $buf =~ s/OBJECT-TYPE/OBJECT IDENTIFIER/;
  1132.       $buf =~ s/OBJECT-IDENTITY/OBJECT IDENTIFIER/;
  1133.       $buf =~ s/OBJECT-GROUP/OBJECT IDENTIFIER/;
  1134.       $buf =~ s/MODULE-IDENTITY/OBJECT IDENTIFIER/;
  1135.       $buf =~ s/ IMPORTS .*;//;
  1136.       $buf =~ s/ SEQUENCE {.*}//;
  1137.       $buf =~ s/ SYNTAX .*//;
  1138.       $buf =~ s/ [w-]+ ::= OBJECT IDENTIFIER//;
  1139.       $buf =~ s/ OBJECT IDENTIFIER .* ::= {/ OBJECT IDENTIFIER ::= {/;
  1140.       $buf =~ s/".*"//;
  1141.       if ($buf =~ /"/) {
  1142. $quote = 1;
  1143.       }
  1144.       if ($buf =~ / ([w-]+) OBJECT IDENTIFIER ::= {([^}]+)}/) {
  1145. $var = $1;
  1146. $buf = $2;
  1147. undef $val;
  1148. $buf =~ s/ +$//;
  1149. ($code, $val) = split(' ', $buf, 2);
  1150. if (!defined($val) || (length($val) <= 0)) {
  1151.   $Net_SNMP_util::OIDS{$var} = $code;
  1152.   $cnt++;
  1153.   print "'$var' => '$code'n" if $Net_SNMP_util::Debug;
  1154. } else {
  1155.   $strt = $code;
  1156.   while($val =~ / /) {
  1157.     ($tmp, $val) = split(' ', $val, 2);
  1158.     if ($tmp =~ /([w-]+)((d+))/) {
  1159.       $tmp = $1;
  1160.       if (exists($Net_SNMP_util::OIDS{$strt})) {
  1161. $tmpv = "$Net_SNMP_util::OIDS{$strt}.$2";
  1162.       } else {
  1163. $tmpv = $2;
  1164.       }
  1165.       $Link{$tmp} = $strt;
  1166.       if (!exists($prev{$tmp}) && exists($Net_SNMP_util::OIDS{$tmp})) {
  1167. if ($tmpv ne $Net_SNMP_util::OIDS{$tmp}) {
  1168.   $strt = "$strt.$tmp";
  1169.   $Net_SNMP_util::OIDS{$strt} = $tmpv;
  1170.   $cnt++;
  1171. }
  1172.       } else {
  1173. $prev{$tmp} = 1;
  1174. $Net_SNMP_util::OIDS{$tmp} = $tmpv;
  1175. $cnt++;
  1176. $strt = $tmp;
  1177.       }
  1178.     }
  1179.   }
  1180.   if (!exists($Net_SNMP_util::OIDS{$strt})) {
  1181.     if ($pass) {
  1182.       carp "snmpMIB_to_OID: $arg: "$strt" prefix unknown, load the parent MIB first.n"
  1183. unless ($Net_SNMP_util::SuppressWarnings > 1);
  1184.     } else {
  1185. $need2pass = 1;
  1186.     }
  1187.   }
  1188.   $Link{$var} = $strt;
  1189.   if (exists($Net_SNMP_util::OIDS{$strt})) {
  1190.     $val = "$Net_SNMP_util::OIDS{$strt}.$val";
  1191.   }
  1192.   if (!exists($prev{$var}) && exists($Net_SNMP_util::OIDS{$var})) {
  1193.     if ($val ne $Net_SNMP_util::OIDS{$var}) {
  1194.       $var = "$strt.$var";
  1195.     }
  1196.   }
  1197.   $Net_SNMP_util::OIDS{$var} = $val;
  1198.   $prev{$var} = 1;
  1199.   $cnt++;
  1200.   print "'$var' => '$val'n" if $Net_SNMP_util::Debug;
  1201. }
  1202. undef $buf;
  1203.       }
  1204.     }
  1205.     if ($pass == 0 && $need2pass) {
  1206.       seek(MIB, $pos, 0);
  1207.       $buf = "";
  1208.       $pass = 1;
  1209.       $cnt = 0;
  1210.     } else {
  1211.       $ret += $cnt;
  1212.       $need2pass = 0;
  1213.     }
  1214.   }
  1215.   close(MIB);
  1216.   $RevNeeded = 1;
  1217.   return $ret;
  1218. }
  1219. =head2 snmpQueue_MIB_File() - queue a MIB file for reading "on demand"
  1220.     snmpQueue_MIB_File(
  1221. $file1,
  1222. [$file2, ...]
  1223.     );
  1224. This routine queues the list of SNMP MIB files for later processing.
  1225. Whenever a text-to-OBJECT IDENTIFIER lookup fails, the list of queued MIB
  1226. files is consulted.  If it isn't empty, the first MIB file in the list is
  1227. removed and passed to B<snmpMIB_to_OID()>.  The lookup is attempted again,
  1228. and if that still fails the next MIB file in the list is removed and passed
  1229. to B<snmpMIB_to_OID()>. This process continues until the lookup succeeds
  1230. or the list is exhausted.
  1231. This routine doesn't return anything.
  1232. =cut
  1233. #
  1234. # Save the passed-in list of MIB files until an OID can't be
  1235. # found in the existing table.  At that time the MIB file will
  1236. # be loaded, and the lookup attempted again.
  1237. #
  1238. sub snmpQueue_MIB_File (@) {
  1239.   my(@files) = @_;
  1240.   my($file);
  1241.   foreach $file (@files) {
  1242.     push(@Net_SNMP_util::MIB_Files, $file);
  1243.   }
  1244. }
  1245. # [private methods] -------------------------------------
  1246. #
  1247. # Start an snmp session
  1248. #
  1249. sub snmpopen ($$$) {
  1250.   my($host, $type, $vars) = @_;
  1251.   my($nhost, $port, $community, $lhost, $lport, $nlhost);
  1252.   my($timeout, $retries, $backoff, $version, $v4onlystr);
  1253.   my($opts, %args, $tmp, $sess);
  1254.   my($debug, $maxmsgsize);
  1255.   $type = 0 if (!defined($type));
  1256.   $community = "public";
  1257.   $nlhost = "";
  1258.   ($community, $host) = ($1, $2) if ($host =~ /^(.*)@([^@]+)$/);
  1259.   # We can't split on the : character because a numeric IPv6
  1260.   # address contains a variable number of :'s
  1261.   if( ($host =~ /^([.*]):(.*)$/) || ($host =~ /^([.*])$/) ) {
  1262.     # Numeric IPv6 address between []
  1263.     ($host, $opts) = ($1, $2);
  1264.   } else {
  1265.     # Hostname or numeric IPv4 address
  1266.     ($host, $opts) = split(':', $host, 2);
  1267.   }
  1268.   ($port, $timeout, $retries, $backoff, $version, $v4onlystr)
  1269.     = split(':', $opts, 6) if(defined($opts) && (length $opts > 0) );
  1270.   undef($timeout) if (defined($timeout) && length($timeout) <= 0);
  1271.   undef($retries) if (defined($retries) && length($retries) <= 0);
  1272.   undef($backoff) if (defined($backoff) && length($backoff) <= 0);
  1273.   undef($version) if (defined($version) && length($version) <= 0);
  1274.   $v4onlystr = "" unless defined $v4onlystr;
  1275.   if (defined($port) && ($port =~ /^([^!]*)!(.*)$/)) {
  1276.     ($port, $lhost) = ($1, $2);
  1277.     $nlhost = $lhost;
  1278.     ($lhost, $lport) = ($1, $2) if ($lhost =~ /^(.*)!(.*)$/);
  1279.     undef($lport) if (defined($lport) && (length($lport) <= 0));
  1280.   }
  1281.   undef($port) if (defined($port) && length($port) <= 0);
  1282.   if (ref $vars->[0] eq 'HASH') {
  1283.     undef($debug);
  1284.     undef($maxmsgsize);
  1285.     $opts = shift @$vars;
  1286.     foreach $type (keys %$opts) {
  1287.       if ($type =~ /^-?return_array_refs$/i) {
  1288. $Net_SNMP_util::ReturnArrayRefs = $opts->{$type};
  1289.       } elsif ($type =~ /^-?return_hash_refs$/i) {
  1290. $Net_SNMP_util::ReturnHashRefs = $opts->{$type};
  1291.       } elsif ($type =~ /^-?contextengineid$/i) {
  1292. $Net_SNMP_util::ContextEngineID = $opts->{$type};
  1293.       } elsif ($type =~ /^-?contextname$/i) {
  1294. $Net_SNMP_util::ContextName = $opts->{$type};
  1295.       } elsif ($type =~ /^-?maxrepetitions$/i) {
  1296. $Net_SNMP_util::MaxRepetitions = $opts->{$type};
  1297.       } elsif ($type =~ /^-?default_max_repetitions$/i) {
  1298. $Net_SNMP_util::MaxRepetitions = $opts->{$type};
  1299.       } elsif ($type =~ /^-?version$/i) {
  1300. $version = $opts->{$type};
  1301.       } elsif ($type =~ /^-?port$/i) {
  1302. $port = $opts->{$type};
  1303.       } elsif ($type =~ /^-?localaddr$/i) {
  1304. $lhost = $opts->{$type};
  1305.       } elsif ($type =~ /^-?community$/i) {
  1306. $community = $opts->{$type};
  1307.       } elsif ($type =~ /^-?timeout$/i) {
  1308. $timeout = $opts->{$type};
  1309.       } elsif ($type =~ /^-?retries$/i) {
  1310. $retries = $opts->{$type};
  1311.       } elsif ($type =~ /^-?maxmsgsize$/i) {
  1312. $maxmsgsize = $opts->{$type};
  1313.       } elsif ($type =~ /^-?debug$/i) {
  1314. $debug = $opts->{$type};
  1315.       } elsif ($type =~ /^-?backoff$/i) {
  1316. next; # XXXX not implemented in Net::SNMP
  1317.       } elsif ($type =~ /^-?avoid_negative_request_ids$/i) {
  1318. next; # XXXX not implemented in Net::SNMP
  1319.       } elsif ($type =~ /^-?lenient_source_/i) {
  1320. next; # XXXX not implemented in Net::SNMP
  1321.       } elsif ($type =~ /^-?use_16bit_request_ids$/i) {
  1322. next; # XXXX not implemented in Net::SNMP
  1323.       } elsif ($type =~ /^-?use_getbulk$/i) {
  1324. next; # XXXX not implemented in Net::SNMP
  1325.       } else {
  1326. $tmp = $type;
  1327. $tmp = '-' . $tmp unless ($tmp =~ /^-/);
  1328. $args{$tmp} = $opts->{$type};
  1329.       }
  1330.     }
  1331.   }
  1332.   $port = 162 if ($type == 1 && !defined($port));
  1333.   $nhost = "$community@$host";
  1334.   $nhost .= ":" . $port if (defined($port));
  1335.   undef($lhost) if (defined($lhost) && (length($lhost) <= 0));
  1336.   $version = '1' unless defined $version;
  1337.   if ($version =~ /1/) {
  1338.     $version = 1;
  1339.   } elsif ($version =~ /2/) {
  1340.     $version = 2;
  1341.   } elsif ($version =~ /3/) {
  1342.     $version = 3;
  1343.   }
  1344.   if ((!defined($Net_SNMP_util::Session))
  1345.     || ($Net_SNMP_util::Host ne $nhost)
  1346.     || ($Net_SNMP_util::Version ne $version)
  1347.     || ($Net_SNMP_util::LHost ne $nlhost)
  1348.     || ($Net_SNMP_util::IPv4only ne $v4onlystr)) {
  1349.     if (defined($Net_SNMP_util::Session)) {
  1350.       $Net_SNMP_util::Session->close();    
  1351.       undef $Net_SNMP_util::Session;
  1352.       undef $Net_SNMP_util::Host;
  1353.       undef $Net_SNMP_util::Version;
  1354.       undef $Net_SNMP_util::LHost;
  1355.       undef $Net_SNMP_util::IPv4only;
  1356.       undef $Net_SNMP_util::ContextEngineID;
  1357.       undef $Net_SNMP_util::ContextName;
  1358.     }
  1359.     $args{'-hostname'} = $host;
  1360.     $args{'-port'} = $port if (defined($port));
  1361.     $args{'-localaddr'} = $lhost if (defined($lhost));
  1362.     $args{'-localport'} = $lport if (defined($lport));
  1363.     $args{'-version'} = $version;
  1364.     $args{'-domain'} = "udp/ipv4" if (length($v4onlystr) > 0);
  1365.     $args{'-timeout'} = $timeout if (defined($timeout));
  1366.     $args{'-retries'} = $retries if (defined($retries));
  1367.     $args{'-maxmsgsize'} = $maxmsgsize if (defined($maxmsgsize));
  1368.     $args{'-debug'} = $debug if (defined($debug));
  1369.     $args{'-community'} = $community unless ($community eq "public");
  1370.     delete $args{'-community'} if ($version == 3);
  1371.     ($sess, $tmp) = Net::SNMP->session(%args);
  1372.     if (defined($sess)) {
  1373.       $Net_SNMP_util::Session = $sess;
  1374.       $Net_SNMP_util::Host = $nhost;
  1375.       $Net_SNMP_util::Version = $version;
  1376.       $Net_SNMP_util::LHost = $nlhost;
  1377.       $Net_SNMP_util::IPv4only = $v4onlystr;
  1378.     } else {
  1379.       carp "SNMPopen failed: $tmp"
  1380. unless ($Net_SNMP_util::SuppressWarnings > 1);
  1381.       return(undef);
  1382.     }
  1383.     return $Net_SNMP_util::Session;
  1384.   } else {
  1385.     $Net_SNMP_util::Session->timeout($timeout)
  1386.       if (defined($timeout) && (length($timeout) > 0));
  1387.     $Net_SNMP_util::Session->retries($retries)
  1388.       if (defined($retries) && (length($retries) > 0));
  1389.     $Net_SNMP_util::Session->maxmsgsize($maxmsgsize)
  1390.       if (defined($maxmsgsize) && (length($maxmsgsize) > 0));
  1391.     $Net_SNMP_util::Session->debug($debug)
  1392.       if (defined($debug) && (length($debug) > 0));
  1393.   }
  1394.   return $Net_SNMP_util::Session;
  1395. }
  1396. #
  1397. #  Given an OID in either ASN.1 or mixed text/ASN.1 notation, return an OID.
  1398. #
  1399. sub toOID(@) {
  1400.   my(@vars) = @_;
  1401.   my($oid, $var, $tmp, $tmpv, @retvar);
  1402.   undef @retvar;
  1403.   foreach $var (@vars) {
  1404.     ($oid, $tmp) = &Check_OID($var);
  1405.     if (!$oid && $Net_SNMP_util::CacheLoaded == 0) {
  1406.       $tmp = $Net_SNMP_util::SuppressWarnings;
  1407.       $Net_SNMP_util::SuppressWarnings = 1000;
  1408.       &snmpLoad_OID_Cache($Net_SNMP_util::CacheFile);
  1409.       $Net_SNMP_util::CacheLoaded = 1;
  1410.       $Net_SNMP_util::SuppressWarnings = $tmp;
  1411.       ($oid, $tmp) = &Check_OID($var);
  1412.     }
  1413.     while (!$oid && $#Net_SNMP_util::MIB_Files >= 0) {
  1414.       $tmp = $Net_SNMP_util::SuppressWarnings;
  1415.       $Net_SNMP_util::SuppressWarnings = 1000;
  1416.       snmpMIB_to_OID(shift(@Net_SNMP_util::MIB_Files));
  1417.       $Net_SNMP_util::SuppressWarnings = $tmp;
  1418.       ($oid, $tmp) = &Check_OID($var);
  1419.       if ($oid) {
  1420. open(CACHE, ">>$Net_SNMP_util::CacheFile");
  1421. print CACHE "$tmpt$oidn";
  1422. close(CACHE);
  1423.       }
  1424.     }
  1425.     if ($oid) {
  1426.       $var =~ s/^$tmp/$oid/;
  1427.     } else {
  1428.       carp "Unknown SNMP var $var"
  1429.       unless ($Net_SNMP_util::SuppressWarnings > 1);
  1430.       next;
  1431.     }
  1432.     while ($var =~ /"([^"]*)"/) {
  1433.       $tmp = sprintf("%d.%s", length($1), join(".", map(ord, split(//, $1))));
  1434.       $var =~ s/"$1"/$tmp/;
  1435.     }
  1436.     print "toOID: $varn" if $Net_SNMP_util::Debug;
  1437.     push(@retvar, $var);
  1438.   }
  1439.   return @retvar;
  1440. }
  1441. #
  1442. # Check to see if an OID is in the text-to-OID cache.
  1443. # Returns the OID and the corresponding text as two separate
  1444. # elements.
  1445. #
  1446. sub Check_OID ($) {
  1447.   my($var) = @_;
  1448.   my($tmp, $tmpv, $oid);
  1449.   if ($var =~ /^(([a-zA-Z][a-zA-Zd-]*.)*([a-zA-Z][a-zA-Zd-]*))/)
  1450.   {
  1451.     $tmp = $&;
  1452.     $tmpv = $tmp;
  1453.     for (;;) {
  1454.       last if exists($Net_SNMP_util::OIDS{$tmpv});
  1455.       last if !($tmpv =~ s/^[^.]*.//);
  1456.     }
  1457.     $oid = $Net_SNMP_util::OIDS{$tmpv};
  1458.     if ($oid) {
  1459.       return ($oid, $tmp);
  1460.     } else {
  1461.       return undef;
  1462.     }
  1463.   }
  1464.   return ($var, $var);
  1465. }
  1466. sub snmpwalk_flg ($$@) {
  1467.   my($host, $hash_sub, @vars) = @_;
  1468.   my($session, %args, @enoid, @poid, $toid, $oid, $got);
  1469.   my($val, $ret, %soid, @retvals, $tmp);
  1470.   my(%rethash, $h_ref, @tmprefs);
  1471.   $session = &snmpopen($host, 0, @vars);
  1472.   if (!defined($session)) {
  1473.     carp "SNMPWALK Problem for $hostn"
  1474.       unless ($Net_SNMP_util::SuppressWarnings > 1);
  1475.     return undef;
  1476.   }
  1477.   $h_ref = (ref $vars[$#vars] eq "HASH") ? pop(@vars) : %rethash;
  1478.   @enoid = toOID(@vars);
  1479.   return undef unless defined $enoid[0];
  1480.   #
  1481.   # Create/Refresh a reversed hash with oid -> name
  1482.   #
  1483.   if (defined($hash_sub) && ($RevNeeded)) {
  1484.       %revOIDS = reverse %Net_SNMP_util::OIDS;
  1485.       $RevNeeded = 0;
  1486.   }
  1487.   #
  1488.   # Create temporary array of refs to return values
  1489.   #
  1490.   foreach $oid (0..$#enoid)  {
  1491.     my $tmparray = [];
  1492.     $tmprefs[$oid] = $tmparray;
  1493.   }
  1494.   $got = 0;
  1495.   @poid = @enoid;
  1496.   if ($Net_SNMP_util::Version > 1) {
  1497.     $args{'-maxrepetitions'} = $Net_SNMP_util::MaxRepetitions;
  1498.   }
  1499.   if ($Net_SNMP_util::Version > 2) {
  1500.     $args{'-contextengineid'} = $Net_SNMP_util::ContextEngineID
  1501.       if (defined($Net_SNMP_util::ContextEngineID));
  1502.     $args{'-contextname'} = $Net_SNMP_util::ContextName
  1503.       if (defined($Net_SNMP_util::ContextName));
  1504.   }
  1505.   do {
  1506.     $args{'-varbindlist'} = @poid;
  1507.     if (($Net_SNMP_util::Version > 1)
  1508.     && ($Net_SNMP_util::MaxRepetitions > 1)) {
  1509.       $ret = $session->get_bulk_request(%args);
  1510.     } else {
  1511.       $ret = $session->get_next_request(%args);
  1512.     }
  1513.     last if (!defined($ret));
  1514.     undef %soid;
  1515.     foreach $oid (&Net::SNMP::oid_lex_sort(keys %$ret)) {
  1516.       $got = 1;
  1517.       $tmp = -1;
  1518.       foreach $toid (@enoid) {
  1519. $tmp++;
  1520. if (&Net::SNMP::oid_base_match($toid, $oid)) {
  1521.   $soid{$toid} = $oid;
  1522.   if (defined($hash_sub)) {
  1523.     #
  1524.     # extract name of the oid, if possible, the rest becomes the
  1525.     # instance
  1526.     #
  1527.     my $inst = "";
  1528.     my $upo = $toid;
  1529.     while (!exists($revOIDS{$upo}) && length($upo)) {
  1530.       $upo =~ s/(.d+?)$//;
  1531.       if (defined($1) && length($1)) {
  1532. $inst = $1 . $inst;
  1533.       } else {
  1534. $upo = "";
  1535. last;
  1536.       }
  1537.     }
  1538.     if (length($upo) && exists($revOIDS{$upo})) {
  1539.       $upo = $revOIDS{$upo} . $inst;
  1540.     } else {
  1541.       $upo = $toid;
  1542.     }
  1543.     my $qoid = $oid;
  1544.     my $tmpo;
  1545.     $inst = "";
  1546.     while (!exists($revOIDS{$qoid}) && length($qoid)) {
  1547.       $qoid =~ s/(.d+?)$//;
  1548.       if (defined($1) && length($1)) {
  1549. $inst = $1 . $inst;
  1550.       } else {
  1551. $qoid = "";
  1552. last;
  1553.       }
  1554.     }
  1555.     if (length($qoid) && exists($revOIDS{$qoid})) {
  1556.       $tmpo = $qoid;
  1557.       $qoid = $revOIDS{$qoid};
  1558.     } else {
  1559.       $qoid = $oid;
  1560.       $tmpo = $toid;
  1561.       $inst = substr($oid, length($tmpo)+1);
  1562.     }
  1563.     #
  1564.     # call hash_sub
  1565.     #
  1566.     &$hash_sub($h_ref, $host, $qoid, $tmpo, $inst, $ret->{$oid}, $upo);
  1567.   } else {
  1568.     my $tmpo;
  1569.     my $tmpv = $ret->{$oid};
  1570.     $tmpo = substr($oid, length($toid)+1);
  1571.     push @{$tmprefs[$tmp]}, "$tmpo:$tmpv";
  1572.   }
  1573. }
  1574.       }
  1575.     }
  1576.     undef @poid;
  1577.     @poid = values %soid;
  1578.   } while($#poid >= 0);
  1579.   if ($got) {
  1580.     if (defined($hash_sub)) {
  1581. return ($h_ref) if ($Net_SNMP_util::ReturnHashRefs);
  1582.      return (%$h_ref);
  1583.     } elsif ($Net_SNMP_util::Return_array_refs)  {
  1584.       return (@tmprefs);
  1585.     } else {
  1586.       do {
  1587. $got = 0;
  1588. foreach $toid (0..$#enoid) {
  1589.   next if (scalar(@{$tmprefs[$toid]}) <= 0);
  1590.   $got = 1;
  1591.   $oid = shift(@{$tmprefs[$toid]});
  1592.   if ($#enoid > 0) {
  1593.     ($oid, $val) = split(':', $oid, 2);
  1594.     $oid = $enoid[$toid] . '.' . $oid;
  1595.     push(@retvals, "$oid:$val");
  1596.   } else {
  1597.     push(@retvals, $oid);
  1598.   }
  1599. }
  1600.       } while($got);
  1601.       return (@retvals);
  1602.     }
  1603.   } else {
  1604.     $ret = join(' ', @vars);
  1605.     $oid = $session->error();
  1606.     carp "SNMPWALK Problem for $ret on $host : $oidn"
  1607.       unless ($Net_SNMP_util::SuppressWarnings > 1);
  1608.     return undef;
  1609.   }
  1610. }
  1611. #
  1612. # When passed a string, return the ASN.1 type that corresponds to the
  1613. # string.
  1614. #
  1615. sub ASNtype($) {
  1616.   my($type) = @_;
  1617.   $type =~ tr/A-Z/a-z/;
  1618.   if ($type eq "int") {
  1619.     $type = 0x02;
  1620.   } elsif ($type eq "integer") {
  1621.     $type = 0x02;
  1622.   } elsif ($type eq "string") {
  1623.     $type = 0x04;
  1624.   } elsif ($type eq "octetstring") {
  1625.     $type = 0x04;
  1626.   } elsif ($type eq "octet string") {
  1627.     $type = 0x04;
  1628.   } elsif ($type eq "oid") {
  1629.     $type = 0x06;
  1630.   } elsif ($type eq "object id") {
  1631.     $type = 0x06;
  1632.   } elsif ($type eq "object identifier") {
  1633.     $type = 0x06;
  1634.   } elsif ($type eq "ipaddr") {
  1635.     $type = 0x40;
  1636.   } elsif ($type eq "ip address") {
  1637.     $type = 0x40;
  1638.   } elsif ($type eq "timeticks") {
  1639.     $type = 0x43;
  1640.   } elsif ($type eq "uint") {
  1641.     $type = 0x47;
  1642.   } elsif ($type eq "uinteger") {
  1643.     $type = 0x47;
  1644.   } elsif ($type eq "uinteger32") {
  1645.     $type = 0x47;
  1646.   } elsif ($type eq "unsigned int") {
  1647.     $type = 0x47;
  1648.   } elsif ($type eq "unsigned integer") {
  1649.     $type = 0x47;
  1650.   } elsif ($type eq "unsigned integer32") {
  1651.     $type = 0x47;
  1652.   } elsif ($type eq "counter") {
  1653.     $type = 0x41;
  1654.   } elsif ($type eq "counter32") {
  1655.     $type = 0x41;
  1656.   } elsif ($type eq "counter64") {
  1657.     $type = 0x46;
  1658.   } elsif ($type eq "gauge") {
  1659.     $type = 0x42;
  1660.   } elsif ($type eq "gauge32") {
  1661.     $type = 0x42;
  1662.   } elsif (($type <= 0) || ($type > 255)) {
  1663.     return undef;
  1664.   }
  1665.   return $type;
  1666. }
  1667. # [documentation] ------------------------------------------------------------
  1668. =head1 EXPORTS
  1669. The Net_SNMP_util module uses the F<Exporter> module to export useful
  1670. constants and subroutines.  These exportable symbols are defined below and
  1671. follow the rules and conventions of the F<Exporter> module (see L<Exporter>).
  1672. =over
  1673. =item Exportable
  1674. &snmpget, &snmpgetnext, &snmpgetbulk, &snmpwalk, &snmpset, &snmptrap,
  1675. &snmpmaptable, &snmpmaptable4, &snmpwalkhash, &snmpmapOID, &snmpMIB_to_OID,
  1676. &snmpLoad_OID_Cache, &snmpQueue_MIB_File
  1677. =back
  1678. =head1 EXAMPLES
  1679. =head2 1. SNMPv1 get-request for sysUpTime
  1680. This example gets the sysUpTime from a remote host.
  1681.     #! /usr/local/bin/perl
  1682.     use strict;
  1683.     use Net_SNMP_util;
  1684.     my ($host, $ret)
  1685.     $host = shift || 'localhost';
  1686.     $ret = snmpget($host, 'sysUpTime');
  1687.     print("sysUpTime for $host is $retn");
  1688.     exit 0;
  1689. =head2 2. SNMPv3 set-request of sysContact
  1690. This example sets the sysContact information on the remote host to 
  1691. "Help Desk x911".  The parameters passed to the snmpset function are for
  1692. the demonstration of syntax only.  These parameters will need to be
  1693. set according to the SNMPv3 parameters of the remote host used by the script. 
  1694.     #! /usr/local/bin/perl
  1695.     use strict;
  1696.     use Net_SNMP_util;
  1697.     my($host, %v3hash, $ret);
  1698.     $host = shift || 'localhost';
  1699.     $v3hash{'-version'} = 'snmpv3';
  1700.     $v3hash{'-username'} = 'myv3Username';
  1701.     $v3hash{'-authkey'} = '0x05c7fbde31916f64da4d5b77156bdfa7';
  1702.     $v3hash{'-authprotocol'} = 'md5';
  1703.     $v3hash{'-privkey'} = '0x93725fd3a02a48ce02df4e065a1c1746';
  1704.     $ret = snmpset($host, %v3hash, 'sysContact', 'string', 'Help Desk x911');
  1705.     print "sysContact on $host is now $retn";
  1706.     exit 0;
  1707. =head2 3. SNMPv2c walk for ifTable
  1708. This example gets the contents of the ifTable by sending get-bulk-requests
  1709. until the responses are no longer part of the ifTable.  The ifTable can also
  1710. be retrieved using C<snmpmaptable>.
  1711.     #! /usr/local/bin/perl
  1712.     use strict;
  1713.     use Net_SNMP_util;
  1714.     my($host, @ret, $oid, $val);
  1715.     $host = shift || 'localhost';
  1716.     @ret = snmpwalk($host . ':::::2', 'ifTable');
  1717.     foreach $val (@ret) {
  1718. ($oid, $val) = split(':', $val, 2);
  1719. print "$oid => $valn";
  1720.     }
  1721.     exit 0;
  1722. =head2 4. SNMPv2c maptable collecting ifDescr, ifInOctets, and ifOutOctets.
  1723. This example collects a table containing the columns ifDescr, ifInOctets, and
  1724. ifOutOctets.  A printing function is called once per row.
  1725.     #! /usr/local/bin/perl
  1726.     use strict;
  1727.     use Net_SNMP_util;
  1728.     sub printfun($$$$) {
  1729. my($inst, $desc, $in, $out) = @_;
  1730. printf "%3d %-52.52s %10d %10dn", $inst, $desc, $in, $out;
  1731.     }
  1732.     my($host, @ret);
  1733.     $host = shift || 'localhost';
  1734.     printf "%-3s %-52s %10s %10sn", "Int", "Description", "In", "Out";
  1735.     @ret = snmpmaptable($host . ':::::2', &printfun,
  1736. 'ifDescr', 'ifInOctets', 'ifOutOctets');
  1737.     exit 0;
  1738. =head1 REQUIREMENTS
  1739. =over
  1740. =item *
  1741. The Net_SNMP_util module uses syntax that is not supported in versions of Perl 
  1742. earlier than v5.6.0. 
  1743. =item *
  1744. The Net_SNMP_util module uses the F<Net::SNMP> module, and as such may depend
  1745. on other modules.  Please see the documentaion on F<Net::SNMP> for more
  1746. information.
  1747. =back
  1748. =head1 AUTHOR
  1749. Mike Mitchell <Mike.Mitchell@sas.com>
  1750. =head1 ACKNOWLEGEMENTS
  1751. The original concept for this module was based on F<SNMP_Session.pm> written
  1752. by Simon Leinen <simon@switch.ch>
  1753. =head1 COPYRIGHT
  1754. Copyright (c) 2005 Mike Mitchell.  All rights reserved.  This program 
  1755. is free software; you may redistribute it and/or modify it under the same
  1756. terms as Perl itself.
  1757. =cut
  1758. # ======================================================================
  1759. 1; # [end Net_SNMP_util]