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

SNMP编程

开发平台:

C/C++

  1. ### - *- mode: Perl -*-
  2. ######################################################################
  3. ### SNMP_util -- SNMP utilities using SNMP_Session.pm and BER.pm
  4. ######################################################################
  5. ### Copyright (c) 1998-2002, 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. ### Tobias Oetiker <oetiker@ee.ethz.ch>:  Basic layout
  15. ### Simon Leinen <simon@switch.ch>: SNMP_session.pm/BER.pm
  16. ### Jeff Allen <jeff.allen@acm.org>: length() of undefined value
  17. ### Johannes Demel <demel@zid.tuwien.ac.at>: MIB file parse problem
  18. ### Simon Leinen <simon@switch.ch>: more OIDs from Interface MIB
  19. ### Jacques Supcik <supcik@ip-plus.net>: Specify local IP, port
  20. ### Tobias Oetiker <oetiker@ee.ethz.ch>: HASH as first OID to set SNMP options
  21. ### Simon Leinen <simon@switch.ch>: 'undefined port' bug
  22. ### Daniel McDonald <dmcdonald@digicontech.com>: request for getbulk support
  23. ### Laurent Girod <girod.laurent@pmintl.ch>: code for snmpwalkhash
  24. ### Ian Duplisse <i.duplisse@cablelabs.com>: MIB parsing suggestions
  25. ### Jakob Ilves <jakob.ilves@oracle.com>: return_array_refs for snmpwalk()
  26. ### Valerio Bontempi <v.bontempi@inwind.it>: IPv6 support
  27. ### Lorenzo Colitti <lorenzo@colitti.com>: IPv6 support
  28. ### Joerg Kummer <JOERG.KUMMER@Roche.COM>: TimeTicks support in snmpset()
  29. ### Christopher J. Tengi <tengi@CS.Princeton.EDU>: Gauge32 support in snmpset()
  30. ### Nicolai Petri <nicolai@catpipe.net>: hashref passing for snmpwalkhash()
  31. ######################################################################
  32. package SNMP_util;
  33. require 5.004;
  34. use strict;
  35. use vars qw(@ISA @EXPORT $VERSION);
  36. use Exporter;
  37. use Carp;
  38. use BER "1.05";
  39. use SNMP_Session "1.05";
  40. use Socket;
  41. $VERSION = '1.04';
  42. @ISA = qw(Exporter);
  43. @EXPORT = qw(snmpget snmpgetnext snmpwalk snmpset snmptrap snmpgetbulk snmpmaptable snmpmaptable4 snmpwalkhash snmpmapOID snmpMIB_to_OID snmpLoad_OID_Cache snmpQueue_MIB_File);
  44. # The OID numbers from RFC1213 (MIB-II) and RFC1315 (Frame Relay)
  45. # are pre-loaded below.
  46. %SNMP_util::OIDS = 
  47.   (
  48.     'iso' => '1',
  49.     'org' => '1.3',
  50.     'dod' => '1.3.6',
  51.     'internet' => '1.3.6.1',
  52.     'directory' => '1.3.6.1.1',
  53.     'mgmt' => '1.3.6.1.2',
  54.     'mib-2' => '1.3.6.1.2.1',
  55.     'system' => '1.3.6.1.2.1.1',
  56.     'sysDescr' => '1.3.6.1.2.1.1.1.0',
  57.     'sysObjectID' => '1.3.6.1.2.1.1.2.0',
  58.     'sysUpTime' => '1.3.6.1.2.1.1.3.0',
  59.     'sysUptime' => '1.3.6.1.2.1.1.3.0',
  60.     'sysContact' => '1.3.6.1.2.1.1.4.0',
  61.     'sysName' => '1.3.6.1.2.1.1.5.0',
  62.     'sysLocation' => '1.3.6.1.2.1.1.6.0',
  63.     'sysServices' => '1.3.6.1.2.1.1.7.0',
  64.     'interfaces' => '1.3.6.1.2.1.2',
  65.     'ifNumber' => '1.3.6.1.2.1.2.1.0',
  66.     'ifTable' => '1.3.6.1.2.1.2.2',
  67.     'ifEntry' => '1.3.6.1.2.1.2.2.1',
  68.     'ifIndex' => '1.3.6.1.2.1.2.2.1.1',
  69.     'ifInOctets' => '1.3.6.1.2.1.2.2.1.10',
  70.     'ifInUcastPkts' => '1.3.6.1.2.1.2.2.1.11',
  71.     'ifInNUcastPkts' => '1.3.6.1.2.1.2.2.1.12',
  72.     'ifInDiscards' => '1.3.6.1.2.1.2.2.1.13',
  73.     'ifInErrors' => '1.3.6.1.2.1.2.2.1.14',
  74.     'ifInUnknownProtos' => '1.3.6.1.2.1.2.2.1.15',
  75.     'ifOutOctets' => '1.3.6.1.2.1.2.2.1.16',
  76.     'ifOutUcastPkts' => '1.3.6.1.2.1.2.2.1.17',
  77.     'ifOutNUcastPkts' => '1.3.6.1.2.1.2.2.1.18',
  78.     'ifOutDiscards' => '1.3.6.1.2.1.2.2.1.19',
  79.     'ifDescr' => '1.3.6.1.2.1.2.2.1.2',
  80.     'ifOutErrors' => '1.3.6.1.2.1.2.2.1.20',
  81.     'ifOutQLen' => '1.3.6.1.2.1.2.2.1.21',
  82.     'ifSpecific' => '1.3.6.1.2.1.2.2.1.22',
  83.     'ifType' => '1.3.6.1.2.1.2.2.1.3',
  84.     'ifMtu' => '1.3.6.1.2.1.2.2.1.4',
  85.     'ifSpeed' => '1.3.6.1.2.1.2.2.1.5',
  86.     'ifPhysAddress' => '1.3.6.1.2.1.2.2.1.6',
  87.     'ifAdminHack' => '1.3.6.1.2.1.2.2.1.7',  
  88.     'ifAdminStatus' => '1.3.6.1.2.1.2.2.1.7',
  89.     'ifOperHack' => '1.3.6.1.2.1.2.2.1.8',             
  90.     'ifOperStatus' => '1.3.6.1.2.1.2.2.1.8',
  91.     'ifLastChange' => '1.3.6.1.2.1.2.2.1.9',
  92.     'at' => '1.3.6.1.2.1.3',
  93.     'atTable' => '1.3.6.1.2.1.3.1',
  94.     'atEntry' => '1.3.6.1.2.1.3.1.1',
  95.     'atIfIndex' => '1.3.6.1.2.1.3.1.1.1',
  96.     'atPhysAddress' => '1.3.6.1.2.1.3.1.1.2',
  97.     'atNetAddress' => '1.3.6.1.2.1.3.1.1.3',
  98.     'ip' => '1.3.6.1.2.1.4',
  99.     'ipForwarding' => '1.3.6.1.2.1.4.1',
  100.     'ipOutRequests' => '1.3.6.1.2.1.4.10',
  101.     'ipOutDiscards' => '1.3.6.1.2.1.4.11',
  102.     'ipOutNoRoutes' => '1.3.6.1.2.1.4.12',
  103.     'ipReasmTimeout' => '1.3.6.1.2.1.4.13',
  104.     'ipReasmReqds' => '1.3.6.1.2.1.4.14',
  105.     'ipReasmOKs' => '1.3.6.1.2.1.4.15',
  106.     'ipReasmFails' => '1.3.6.1.2.1.4.16',
  107.     'ipFragOKs' => '1.3.6.1.2.1.4.17',
  108.     'ipFragFails' => '1.3.6.1.2.1.4.18',
  109.     'ipFragCreates' => '1.3.6.1.2.1.4.19',
  110.     'ipDefaultTTL' => '1.3.6.1.2.1.4.2',
  111.     'ipAddrTable' => '1.3.6.1.2.1.4.20',
  112.     'ipAddrEntry' => '1.3.6.1.2.1.4.20.1',
  113.     'ipAdEntAddr' => '1.3.6.1.2.1.4.20.1.1',
  114.     'ipAdEntIfIndex' => '1.3.6.1.2.1.4.20.1.2',
  115.     'ipAdEntNetMask' => '1.3.6.1.2.1.4.20.1.3',
  116.     'ipAdEntBcastAddr' => '1.3.6.1.2.1.4.20.1.4',
  117.     'ipAdEntReasmMaxSize' => '1.3.6.1.2.1.4.20.1.5',
  118.     'ipRouteTable' => '1.3.6.1.2.1.4.21',
  119.     'ipRouteEntry' => '1.3.6.1.2.1.4.21.1',
  120.     'ipRouteDest' => '1.3.6.1.2.1.4.21.1.1',
  121.     'ipRouteAge' => '1.3.6.1.2.1.4.21.1.10',
  122.     'ipRouteMask' => '1.3.6.1.2.1.4.21.1.11',
  123.     'ipRouteMetric5' => '1.3.6.1.2.1.4.21.1.12',
  124.     'ipRouteInfo' => '1.3.6.1.2.1.4.21.1.13',
  125.     'ipRouteIfIndex' => '1.3.6.1.2.1.4.21.1.2',
  126.     'ipRouteMetric1' => '1.3.6.1.2.1.4.21.1.3',
  127.     'ipRouteMetric2' => '1.3.6.1.2.1.4.21.1.4',
  128.     'ipRouteMetric3' => '1.3.6.1.2.1.4.21.1.5',
  129.     'ipRouteMetric4' => '1.3.6.1.2.1.4.21.1.6',
  130.     'ipRouteNextHop' => '1.3.6.1.2.1.4.21.1.7',
  131.     'ipRouteType' => '1.3.6.1.2.1.4.21.1.8',
  132.     'ipRouteProto' => '1.3.6.1.2.1.4.21.1.9',
  133.     'ipNetToMediaTable' => '1.3.6.1.2.1.4.22',
  134.     'ipNetToMediaEntry' => '1.3.6.1.2.1.4.22.1',
  135.     'ipNetToMediaIfIndex' => '1.3.6.1.2.1.4.22.1.1',
  136.     'ipNetToMediaPhysAddress' => '1.3.6.1.2.1.4.22.1.2',
  137.     'ipNetToMediaNetAddress' => '1.3.6.1.2.1.4.22.1.3',
  138.     'ipNetToMediaType' => '1.3.6.1.2.1.4.22.1.4',
  139.     'ipRoutingDiscards' => '1.3.6.1.2.1.4.23',
  140.     'ipInReceives' => '1.3.6.1.2.1.4.3',
  141.     'ipInHdrErrors' => '1.3.6.1.2.1.4.4',
  142.     'ipInAddrErrors' => '1.3.6.1.2.1.4.5',
  143.     'ipForwDatagrams' => '1.3.6.1.2.1.4.6',
  144.     'ipInUnknownProtos' => '1.3.6.1.2.1.4.7',
  145.     'ipInDiscards' => '1.3.6.1.2.1.4.8',
  146.     'ipInDelivers' => '1.3.6.1.2.1.4.9',
  147.     'icmp' => '1.3.6.1.2.1.5',
  148.     'icmpInMsgs' => '1.3.6.1.2.1.5.1',
  149.     'icmpInTimestamps' => '1.3.6.1.2.1.5.10',
  150.     'icmpInTimestampReps' => '1.3.6.1.2.1.5.11',
  151.     'icmpInAddrMasks' => '1.3.6.1.2.1.5.12',
  152.     'icmpInAddrMaskReps' => '1.3.6.1.2.1.5.13',
  153.     'icmpOutMsgs' => '1.3.6.1.2.1.5.14',
  154.     'icmpOutErrors' => '1.3.6.1.2.1.5.15',
  155.     'icmpOutDestUnreachs' => '1.3.6.1.2.1.5.16',
  156.     'icmpOutTimeExcds' => '1.3.6.1.2.1.5.17',
  157.     'icmpOutParmProbs' => '1.3.6.1.2.1.5.18',
  158.     'icmpOutSrcQuenchs' => '1.3.6.1.2.1.5.19',
  159.     'icmpInErrors' => '1.3.6.1.2.1.5.2',
  160.     'icmpOutRedirects' => '1.3.6.1.2.1.5.20',
  161.     'icmpOutEchos' => '1.3.6.1.2.1.5.21',
  162.     'icmpOutEchoReps' => '1.3.6.1.2.1.5.22',
  163.     'icmpOutTimestamps' => '1.3.6.1.2.1.5.23',
  164.     'icmpOutTimestampReps' => '1.3.6.1.2.1.5.24',
  165.     'icmpOutAddrMasks' => '1.3.6.1.2.1.5.25',
  166.     'icmpOutAddrMaskReps' => '1.3.6.1.2.1.5.26',
  167.     'icmpInDestUnreachs' => '1.3.6.1.2.1.5.3',
  168.     'icmpInTimeExcds' => '1.3.6.1.2.1.5.4',
  169.     'icmpInParmProbs' => '1.3.6.1.2.1.5.5',
  170.     'icmpInSrcQuenchs' => '1.3.6.1.2.1.5.6',
  171.     'icmpInRedirects' => '1.3.6.1.2.1.5.7',
  172.     'icmpInEchos' => '1.3.6.1.2.1.5.8',
  173.     'icmpInEchoReps' => '1.3.6.1.2.1.5.9',
  174.     'tcp' => '1.3.6.1.2.1.6',
  175.     'tcpRtoAlgorithm' => '1.3.6.1.2.1.6.1',
  176.     'tcpInSegs' => '1.3.6.1.2.1.6.10',
  177.     'tcpOutSegs' => '1.3.6.1.2.1.6.11',
  178.     'tcpRetransSegs' => '1.3.6.1.2.1.6.12',
  179.     'tcpConnTable' => '1.3.6.1.2.1.6.13',
  180.     'tcpConnEntry' => '1.3.6.1.2.1.6.13.1',
  181.     'tcpConnState' => '1.3.6.1.2.1.6.13.1.1',
  182.     'tcpConnLocalAddress' => '1.3.6.1.2.1.6.13.1.2',
  183.     'tcpConnLocalPort' => '1.3.6.1.2.1.6.13.1.3',
  184.     'tcpConnRemAddress' => '1.3.6.1.2.1.6.13.1.4',
  185.     'tcpConnRemPort' => '1.3.6.1.2.1.6.13.1.5',
  186.     'tcpInErrs' => '1.3.6.1.2.1.6.14',
  187.     'tcpOutRsts' => '1.3.6.1.2.1.6.15',
  188.     'tcpRtoMin' => '1.3.6.1.2.1.6.2',
  189.     'tcpRtoMax' => '1.3.6.1.2.1.6.3',
  190.     'tcpMaxConn' => '1.3.6.1.2.1.6.4',
  191.     'tcpActiveOpens' => '1.3.6.1.2.1.6.5',
  192.     'tcpPassiveOpens' => '1.3.6.1.2.1.6.6',
  193.     'tcpAttemptFails' => '1.3.6.1.2.1.6.7',
  194.     'tcpEstabResets' => '1.3.6.1.2.1.6.8',
  195.     'tcpCurrEstab' => '1.3.6.1.2.1.6.9',
  196.     'udp' => '1.3.6.1.2.1.7',
  197.     'udpInDatagrams' => '1.3.6.1.2.1.7.1',
  198.     'udpNoPorts' => '1.3.6.1.2.1.7.2',
  199.     'udpInErrors' => '1.3.6.1.2.1.7.3',
  200.     'udpOutDatagrams' => '1.3.6.1.2.1.7.4',
  201.     'udpTable' => '1.3.6.1.2.1.7.5',
  202.     'udpEntry' => '1.3.6.1.2.1.7.5.1',
  203.     'udpLocalAddress' => '1.3.6.1.2.1.7.5.1.1',
  204.     'udpLocalPort' => '1.3.6.1.2.1.7.5.1.2',
  205.     'egp' => '1.3.6.1.2.1.8',
  206.     'egpInMsgs' => '1.3.6.1.2.1.8.1',
  207.     'egpInErrors' => '1.3.6.1.2.1.8.2',
  208.     'egpOutMsgs' => '1.3.6.1.2.1.8.3',
  209.     'egpOutErrors' => '1.3.6.1.2.1.8.4',
  210.     'egpNeighTable' => '1.3.6.1.2.1.8.5',
  211.     'egpNeighEntry' => '1.3.6.1.2.1.8.5.1',
  212.     'egpNeighState' => '1.3.6.1.2.1.8.5.1.1',
  213.     'egpNeighStateUps' => '1.3.6.1.2.1.8.5.1.10',
  214.     'egpNeighStateDowns' => '1.3.6.1.2.1.8.5.1.11',
  215.     'egpNeighIntervalHello' => '1.3.6.1.2.1.8.5.1.12',
  216.     'egpNeighIntervalPoll' => '1.3.6.1.2.1.8.5.1.13',
  217.     'egpNeighMode' => '1.3.6.1.2.1.8.5.1.14',
  218.     'egpNeighEventTrigger' => '1.3.6.1.2.1.8.5.1.15',
  219.     'egpNeighAddr' => '1.3.6.1.2.1.8.5.1.2',
  220.     'egpNeighAs' => '1.3.6.1.2.1.8.5.1.3',
  221.     'egpNeighInMsgs' => '1.3.6.1.2.1.8.5.1.4',
  222.     'egpNeighInErrs' => '1.3.6.1.2.1.8.5.1.5',
  223.     'egpNeighOutMsgs' => '1.3.6.1.2.1.8.5.1.6',
  224.     'egpNeighOutErrs' => '1.3.6.1.2.1.8.5.1.7',
  225.     'egpNeighInErrMsgs' => '1.3.6.1.2.1.8.5.1.8',
  226.     'egpNeighOutErrMsgs' => '1.3.6.1.2.1.8.5.1.9',
  227.     'egpAs' => '1.3.6.1.2.1.8.6',
  228.     'transmission' => '1.3.6.1.2.1.10',
  229.     'frame-relay' => '1.3.6.1.2.1.10.32',
  230.     'frDlcmiTable' => '1.3.6.1.2.1.10.32.1',
  231.     'frDlcmiEntry' => '1.3.6.1.2.1.10.32.1.1',
  232.     'frDlcmiIfIndex' => '1.3.6.1.2.1.10.32.1.1.1',
  233.     'frDlcmiState' => '1.3.6.1.2.1.10.32.1.1.2',
  234.     'frDlcmiAddress' => '1.3.6.1.2.1.10.32.1.1.3',
  235.     'frDlcmiAddressLen' => '1.3.6.1.2.1.10.32.1.1.4',
  236.     'frDlcmiPollingInterval' => '1.3.6.1.2.1.10.32.1.1.5',
  237.     'frDlcmiFullEnquiryInterval' => '1.3.6.1.2.1.10.32.1.1.6',
  238.     'frDlcmiErrorThreshold' => '1.3.6.1.2.1.10.32.1.1.7',
  239.     'frDlcmiMonitoredEvents' => '1.3.6.1.2.1.10.32.1.1.8',
  240.     'frDlcmiMaxSupportedVCs' => '1.3.6.1.2.1.10.32.1.1.9',
  241.     'frDlcmiMulticast' => '1.3.6.1.2.1.10.32.1.1.10',
  242.     'frCircuitTable' => '1.3.6.1.2.1.10.32.2',
  243.     'frCircuitEntry' => '1.3.6.1.2.1.10.32.2.1',
  244.     'frCircuitIfIndex' => '1.3.6.1.2.1.10.32.2.1.1',
  245.     'frCircuitDlci' => '1.3.6.1.2.1.10.32.2.1.2',
  246.     'frCircuitState' => '1.3.6.1.2.1.10.32.2.1.3',
  247.     'frCircuitReceivedFECNs' => '1.3.6.1.2.1.10.32.2.1.4',
  248.     'frCircuitReceivedBECNs' => '1.3.6.1.2.1.10.32.2.1.5',
  249.     'frCircuitSentFrames' => '1.3.6.1.2.1.10.32.2.1.6',
  250.     'frCircuitSentOctets' => '1.3.6.1.2.1.10.32.2.1.7',
  251.     'frOutOctets' => '1.3.6.1.2.1.10.32.2.1.7',
  252.     'frCircuitReceivedFrames' => '1.3.6.1.2.1.10.32.2.1.8',
  253.     'frCircuitReceivedOctets' => '1.3.6.1.2.1.10.32.2.1.9',
  254.     'frInOctets' => '1.3.6.1.2.1.10.32.2.1.9',
  255.     'frCircuitCreationTime' => '1.3.6.1.2.1.10.32.2.1.10',
  256.     'frCircuitLastTimeChange' => '1.3.6.1.2.1.10.32.2.1.11',
  257.     'frCircuitCommittedBurst' => '1.3.6.1.2.1.10.32.2.1.12',
  258.     'frCircuitExcessBurst' => '1.3.6.1.2.1.10.32.2.1.13',
  259.     'frCircuitThroughput' => '1.3.6.1.2.1.10.32.2.1.14',
  260.     'frErrTable' => '1.3.6.1.2.1.10.32.3',
  261.     'frErrEntry' => '1.3.6.1.2.1.10.32.3.1',
  262.     'frErrIfIndex' => '1.3.6.1.2.1.10.32.3.1.1',
  263.     'frErrType' => '1.3.6.1.2.1.10.32.3.1.2',
  264.     'frErrData' => '1.3.6.1.2.1.10.32.3.1.3',
  265.     'frErrTime' => '1.3.6.1.2.1.10.32.3.1.4',
  266.     'frame-relay-globals' => '1.3.6.1.2.1.10.32.4',
  267.     'frTrapState' => '1.3.6.1.2.1.10.32.4.1',
  268.     'snmp' => '1.3.6.1.2.1.11',
  269.     'snmpInPkts' => '1.3.6.1.2.1.11.1',
  270.     'snmpInBadValues' => '1.3.6.1.2.1.11.10',
  271.     'snmpInReadOnlys' => '1.3.6.1.2.1.11.11',
  272.     'snmpInGenErrs' => '1.3.6.1.2.1.11.12',
  273.     'snmpInTotalReqVars' => '1.3.6.1.2.1.11.13',
  274.     'snmpInTotalSetVars' => '1.3.6.1.2.1.11.14',
  275.     'snmpInGetRequests' => '1.3.6.1.2.1.11.15',
  276.     'snmpInGetNexts' => '1.3.6.1.2.1.11.16',
  277.     'snmpInSetRequests' => '1.3.6.1.2.1.11.17',
  278.     'snmpInGetResponses' => '1.3.6.1.2.1.11.18',
  279.     'snmpInTraps' => '1.3.6.1.2.1.11.19',
  280.     'snmpOutPkts' => '1.3.6.1.2.1.11.2',
  281.     'snmpOutTooBigs' => '1.3.6.1.2.1.11.20',
  282.     'snmpOutNoSuchNames' => '1.3.6.1.2.1.11.21',
  283.     'snmpOutBadValues' => '1.3.6.1.2.1.11.22',
  284.     'snmpOutGenErrs' => '1.3.6.1.2.1.11.24',
  285.     'snmpOutGetRequests' => '1.3.6.1.2.1.11.25',
  286.     'snmpOutGetNexts' => '1.3.6.1.2.1.11.26',
  287.     'snmpOutSetRequests' => '1.3.6.1.2.1.11.27',
  288.     'snmpOutGetResponses' => '1.3.6.1.2.1.11.28',
  289.     'snmpOutTraps' => '1.3.6.1.2.1.11.29',
  290.     'snmpInBadVersions' => '1.3.6.1.2.1.11.3',
  291.     'snmpEnableAuthenTraps' => '1.3.6.1.2.1.11.30',
  292.     'snmpInBadCommunityNames' => '1.3.6.1.2.1.11.4',
  293.     'snmpInBadCommunityUses' => '1.3.6.1.2.1.11.5',
  294.     'snmpInASNParseErrs' => '1.3.6.1.2.1.11.6',
  295.     'snmpInTooBigs' => '1.3.6.1.2.1.11.8',
  296.     'snmpInNoSuchNames' => '1.3.6.1.2.1.11.9',
  297.     'ifName' => '1.3.6.1.2.1.31.1.1.1.1',
  298.     'ifInMulticastPkts' => '1.3.6.1.2.1.31.1.1.1.2',
  299.     'ifInBroadcastPkts' => '1.3.6.1.2.1.31.1.1.1.3',
  300.     'ifOutMulticastPkts' => '1.3.6.1.2.1.31.1.1.1.4',
  301.     'ifOutBroadcastPkts' => '1.3.6.1.2.1.31.1.1.1.5',
  302.     'ifHCInOctets' => '1.3.6.1.2.1.31.1.1.1.6',
  303.     'ifHCInUcastPkts' => '1.3.6.1.2.1.31.1.1.1.7',
  304.     'ifHCInMulticastPkts' => '1.3.6.1.2.1.31.1.1.1.8',
  305.     'ifHCInBroadcastPkts' => '1.3.6.1.2.1.31.1.1.1.9',
  306.     'ifHCOutOctets' => '1.3.6.1.2.1.31.1.1.1.10',
  307.     'ifHCOutUcastPkts' => '1.3.6.1.2.1.31.1.1.1.11',
  308.     'ifHCOutMulticastPkts' => '1.3.6.1.2.1.31.1.1.1.12',
  309.     'ifHCOutBroadcastPkts' => '1.3.6.1.2.1.31.1.1.1.13',
  310.     'ifLinkUpDownTrapEnable' => '1.3.6.1.2.1.31.1.1.1.14',
  311.     'ifHighSpeed' => '1.3.6.1.2.1.31.1.1.1.15',
  312.     'ifPromiscuousMode' => '1.3.6.1.2.1.31.1.1.1.16',
  313.     'ifConnectorPresent' => '1.3.6.1.2.1.31.1.1.1.17',
  314.     'ifAlias' => '1.3.6.1.2.1.31.1.1.1.18',
  315.     'ifCounterDiscontinuityTime' => '1.3.6.1.2.1.31.1.1.1.19',
  316.     'experimental' => '1.3.6.1.3',
  317.     'private' => '1.3.6.1.4',
  318.     'enterprises' => '1.3.6.1.4.1',
  319.   );
  320. # GIL
  321. my %revOIDS = (); # Reversed %SNMP_util::OIDS hash
  322. my $RevNeeded = 1;
  323. my $agent_start_time = time;
  324. undef $SNMP_util::Host;
  325. undef $SNMP_util::Session;
  326. undef $SNMP_util::Version;
  327. undef $SNMP_util::LHost;
  328. undef $SNMP_util::IPv4only;
  329. $SNMP_util::Debug = 0;
  330. $SNMP_util::CacheFile = "OID_cache.txt";
  331. $SNMP_util::CacheLoaded = 0;
  332. $SNMP_util::Return_array_refs = 0;
  333. $SNMP_util::Return_hash_refs = 0;
  334. srand(time + $$);
  335. ### Prototypes
  336. sub snmpget ($@);
  337. sub snmpgetnext ($@);
  338. sub snmpopen ($$$);
  339. sub snmpwalk ($@);
  340. sub snmpwalk_flg ($$@);
  341. sub snmpset ($@);
  342. sub snmptrap ($$$$$@);
  343. sub snmpgetbulk ($$$@);
  344. sub snmpmaptable ($$@);
  345. sub snmpmaptable4 ($$$@);
  346. sub snmpwalkhash ($$@);
  347. sub toOID (@);
  348. sub snmpmapOID (@);
  349. sub snmpMIB_to_OID ($);
  350. sub encode_oid_with_errmsg ($);
  351. sub Check_OID ($);
  352. sub snmpLoad_OID_Cache ($);
  353. sub snmpQueue_MIB_File (@);
  354. sub version () { $VERSION; }
  355. #
  356. # Start an snmp session
  357. #
  358. sub snmpopen ($$$) {
  359.   my($host, $type, $vars) = @_;
  360.   my($nhost, $port, $community, $lhost, $lport, $nlhost);
  361.   my($timeout, $retries, $backoff, $version);
  362.   my $v4onlystr;
  363.   $type = 0 if (!defined($type));
  364.   $community = "public";
  365.   $nlhost = "";
  366.   ($community, $host) = ($1, $2) if ($host =~ /^(.*)@([^@]+)$/);
  367.   # We can't split on the : character because a numeric IPv6
  368.   # address contains a variable number of :'s
  369.   my $opts;
  370.  if( ($host =~ /^([.*]):(.*)$/) || ($host =~ /^([.*])$/) ) {
  371.     # Numeric IPv6 address between []
  372.     ($host, $opts) = ($1, $2);
  373.   } else {
  374.     # Hostname or numeric IPv4 address
  375.     ($host, $opts) = split(':', $host, 2);
  376.   }
  377.   ($port, $timeout, $retries, $backoff, $version, $v4onlystr) = split(':', $opts, 6)
  378.     if(defined($opts) && (length $opts > 0) );
  379.   undef($version) if (defined($version) && length($version) <= 0);
  380.   $v4onlystr = "" unless defined $v4onlystr;
  381.   $version = '1' unless defined $version;
  382.   if (defined($port) && ($port =~ /^([^!]*)!(.*)$/)) {
  383.     ($port, $lhost) = ($1, $2);
  384.     $nlhost = $lhost;
  385.     ($lhost, $lport) = ($1, $2) if ($lhost =~ /^(.*)!(.*)$/);
  386.     undef($lhost) if (defined($lhost) && (length($lhost) <= 0));
  387.     undef($lport) if (defined($lport) && (length($lport) <= 0));
  388.   }
  389.   undef($port) if (defined($port) && length($port) <= 0);
  390.   $port = 162 if ($type == 1 && !defined($port));
  391.   $nhost = "$community@$host";
  392.   $nhost .= ":" . $port if (defined($port));
  393.   if ((!defined($SNMP_util::Session))
  394.     || ($SNMP_util::Host ne $nhost)
  395.     || ($SNMP_util::Version ne $version)
  396.     || ($SNMP_util::LHost ne $nlhost)
  397.     || ($SNMP_util::IPv4only ne $v4onlystr)) {
  398.     if (defined($SNMP_util::Session)) {
  399.       $SNMP_util::Session->close();    
  400.       undef $SNMP_util::Session;
  401.       undef $SNMP_util::Host;
  402.       undef $SNMP_util::Version;
  403.       undef $SNMP_util::LHost;
  404.       undef $SNMP_util::IPv4only;
  405.     }
  406.     $SNMP_util::Session = ($version =~ /^2c?$/i)
  407.       ? SNMPv2c_Session->open($host, $community, $port, undef,
  408. $lport, undef, $lhost, ($v4onlystr eq 'v4only') ? 1:0 )
  409.       : SNMP_Session->open($host, $community, $port, undef,
  410. $lport, undef, $lhost, ($v4onlystr eq 'v4only') ? 1:0 );
  411.     ($SNMP_util::Host = $nhost, $SNMP_util::Version = $version,
  412.       $SNMP_util::LHost = $nlhost, $SNMP_util::IPv4only = $v4onlystr) if defined($SNMP_util::Session);
  413.   }
  414.   if (defined($SNMP_util::Session)) {
  415.     if (ref $vars->[0] eq 'HASH') {
  416.       my $opts = shift @$vars;
  417.       foreach $type (keys %$opts) {
  418. if ($type eq 'return_array_refs') {
  419.   $SNMP_util::Return_array_refs = $opts->{$type};
  420. } elsif ($type eq 'return_hash_refs') {
  421.   $SNMP_util::Return_hash_refs = $opts->{$type};
  422. } else {
  423.   if (exists $SNMP_util::Session->{$type}) {
  424.     if ($type eq 'timeout') {
  425.       $SNMP_util::Session->set_timeout($opts->{$type});
  426.     } elsif ($type eq 'retries') {
  427.       $SNMP_util::Session->set_retries($opts->{$type});
  428.     } elsif ($type eq 'backoff') {
  429.       $SNMP_util::Session->set_backoff($opts->{$type});
  430.     } else {
  431.       $SNMP_util::Session->{$type} = $opts->{$type};
  432.     }
  433.   } else {
  434.     carp "SNMPopen Unknown SNMP Option Key '$type'n"
  435.       unless ($SNMP_Session::suppress_warnings > 1);
  436.   }
  437. }
  438.       }
  439.     }
  440.     $SNMP_util::Session->set_timeout($timeout)
  441.       if (defined($timeout) && (length($timeout) > 0));
  442.     $SNMP_util::Session->set_retries($retries)
  443.       if (defined($retries) && (length($retries) > 0));
  444.     $SNMP_util::Session->set_backoff($backoff)
  445.       if (defined($backoff) && (length($backoff) > 0));
  446.   }
  447.   return $SNMP_util::Session;
  448. }
  449. #
  450. # A restricted snmpget.
  451. #
  452. sub snmpget ($@) {
  453.   my($host, @vars) = @_;
  454.   my(@enoid, $var, $response, $bindings, $binding, $value, $oid, @retvals);
  455.   my $session;
  456.   $session = &snmpopen($host, 0, @vars);
  457.   if (!defined($session)) {
  458.     carp "SNMPGET Problem for $hostn"
  459.       unless ($SNMP_Session::suppress_warnings > 1);
  460.     return undef;
  461.   }
  462.   @enoid = &toOID(@vars);
  463.   return undef unless defined $enoid[0];
  464.   if ($session->get_request_response(@enoid)) {
  465.     $response = $session->pdu_buffer;
  466.     ($bindings) = $session->decode_get_response($response);
  467.     while ($bindings) {
  468.       ($binding, $bindings) = decode_sequence($bindings);
  469.       ($oid, $value) = decode_by_template($binding, "%O%@");
  470.       my $tempo = pretty_print($value);
  471.       push @retvals, $tempo;
  472.     }
  473.     return wantarray ? @retvals : $retvals[0];
  474.   }
  475.   $var = join(' ', @vars);
  476.   carp "SNMPGET Problem for $var on $hostn"
  477.     unless ($SNMP_Session::suppress_warnings > 1);
  478.   return undef;
  479. }
  480. #
  481. # A restricted snmpgetnext.
  482. #
  483. sub snmpgetnext ($@) {
  484.   my($host, @vars) = @_;
  485.   my(@enoid, $var, $response, $bindings, $binding);
  486.   my($value, $upoid, $oid, @retvals);
  487.   my($noid);
  488.   my $session;
  489.   $session = &snmpopen($host, 0, @vars);
  490.   if (!defined($session)) {
  491.     carp "SNMPGETNEXT Problem for $hostn"
  492.       unless ($SNMP_Session::suppress_warnings > 1);
  493.     return undef;
  494.   }
  495.   @enoid = &toOID(@vars);
  496.   return undef unless defined $enoid[0];
  497.   undef @vars;
  498.   undef @retvals;
  499.   foreach $noid (@enoid) {
  500.     $upoid = pretty_print($noid);
  501.     push(@vars, $upoid);
  502.   }
  503.   if ($session->getnext_request_response(@enoid)) {
  504.     $response = $session->pdu_buffer;
  505.     ($bindings) = $session->decode_get_response($response);
  506.     while ($bindings) {
  507.       ($binding, $bindings) = decode_sequence($bindings);
  508.       ($oid, $value) = decode_by_template($binding, "%O%@");
  509.       my $tempo = pretty_print($oid);
  510.       my $tempv = pretty_print($value);
  511.       push @retvals, "$tempo:$tempv";
  512.     }
  513.     return wantarray ? @retvals : $retvals[0];
  514.   } else {
  515.     $var = join(' ', @vars);
  516.     carp "SNMPGETNEXT Problem for $var on $hostn"
  517.       unless ($SNMP_Session::suppress_warnings > 1);
  518.     return undef;
  519.   }
  520. }
  521. #
  522. # A restricted snmpwalk.
  523. #
  524. sub snmpwalk ($@) {
  525.   my($host, @vars) = @_;
  526.   return(&snmpwalk_flg($host, undef, @vars));
  527. }
  528. #
  529. # Walk the MIB, putting everything you find into hashes.
  530. #
  531. sub snmpwalkhash($$@) {
  532. #  my($host, $hash_sub, @vars) = @_;
  533.   return(&snmpwalk_flg( @_ ));
  534. }
  535. sub snmpwalk_flg ($$@) {
  536.   my($host, $hash_sub, @vars) = @_;
  537.   my(@enoid, $var, $response, $bindings, $binding);
  538.   my($value, $upoid, $oid, @retvals, @retvaltmprefs);
  539.   my($got, @nnoid, $noid, $ok, $ix, @avars);
  540.   my $session;
  541.   my(%soid);
  542.   my(%done, %rethash, $h_ref);
  543.   $session = &snmpopen($host, 0, @vars);
  544.   if (!defined($session)) {
  545.     carp "SNMPWALK Problem for $hostn"
  546.       unless ($SNMP_Session::suppress_warnings > 1);
  547.     return undef;
  548.   }
  549.   $h_ref = (ref $vars[$#vars] eq "HASH") ? pop(@vars) : %rethash;
  550.   @enoid = toOID(@vars);
  551.   return undef unless defined $enoid[0];
  552.   # GIL
  553.   #
  554.   # Create/Refresh a reversed hash with oid -> name
  555.   #
  556.   if (defined($hash_sub) && ($RevNeeded)) {
  557.       %revOIDS = reverse %SNMP_util::OIDS;
  558.       $RevNeeded = 0;
  559.   }
  560.   $got = 0;
  561.   @nnoid = @enoid;
  562.   undef @vars;
  563.   foreach $noid (@enoid) {
  564.     $upoid = pretty_print($noid);
  565.     push(@vars, $upoid);
  566.   }
  567.   # @vars is the original set of walked variables.
  568.   # @avars is the current set of walked variables as the
  569.   # walk goes on.
  570.   # @vars stays static while @avars may shrink as we reach end
  571.   # of walk for individual variables during PDU exchange.
  572.    
  573.   @avars = @vars;
  574.   # IlvJa
  575.   #
  576.   # Create temporary array of refs to return vals.
  577.   if ($SNMP_util::Return_array_refs) {
  578.     for($ix = 0;$ix < scalar @vars; $ix++) {
  579.       my $tmparray = [];
  580.       $retvaltmprefs[$ix] = $tmparray;
  581.       $retvals[$ix] = $tmparray;
  582.     }
  583.   }
  584.   while(($SNMP_util::Version ne '1' && $session->{'use_getbulk'})
  585.     ? $session->getbulk_request_response(0,
  586.   $session->default_max_repetitions(),
  587.   @nnoid)
  588.     : $session->getnext_request_response(@nnoid))
  589.   {
  590.     $got = 1;
  591.     $response = $session->pdu_buffer;
  592.     ($bindings) = $session->decode_get_response($response);
  593.     $ix = 0;
  594.     while ($bindings) {
  595.       ($binding, $bindings) = decode_sequence($bindings);
  596.       unless ($nnoid[$ix]) { # IlvJa
  597. $ix = ++$ix % (scalar @avars);
  598. next;
  599.       }
  600.       ($oid, $value) = decode_by_template($binding, "%O%@");
  601.       $ok = 0;
  602.       my $tempo = pretty_print($oid);
  603.       $noid = $avars[$ix];  # IlvJa
  604.       if ($tempo =~ /^$noid./ || $tempo eq $noid ) {
  605. $ok = 1;
  606. $upoid = $noid;
  607.       } else {
  608. # IlvJa
  609. #
  610. # The walk for variable $var[$ix] has been finished as
  611. # $nnoid[$ix] no longer is in the $avar[$ix] OID tree.
  612. # So we exclude this variable from further requests.
  613. $avars[$ix] = "";
  614. $nnoid[$ix] = "";
  615. $retvaltmprefs[$ix] = undef if $SNMP_util::Return_array_refs;
  616.       }
  617.       if ($ok) {
  618. my $tmp = encode_oid_with_errmsg ($tempo);
  619. return undef unless defined $tmp;
  620. next if (exists($done{$tmp})); # GIL
  621. $nnoid[$ix] = $tmp;   # Keep on walking. (IlvJa)
  622. my $tempv = pretty_print($value);
  623. if (defined($hash_sub)) {
  624.   #
  625.   # extract name of the oid, if possible, the rest becomes the instance
  626.   #
  627.   my $inst = "";
  628.   my $upo = $upoid;
  629.   while (!exists($revOIDS{$upo}) && length($upo)) {
  630.     $upo =~ s/(.d+?)$//;
  631.     if (defined($1) && length($1)) {
  632.       $inst = $1 . $inst;
  633.     } else {
  634.       $upo = "";
  635.       last;
  636.     }
  637.   }
  638.   if (length($upo) && exists($revOIDS{$upo})) {
  639.     $upo = $revOIDS{$upo} . $inst;
  640.   } else {
  641.     $upo = $upoid;
  642.   }
  643.   $inst = "";
  644.   while (!exists($revOIDS{$tempo}) && length($tempo)) {
  645.     $tempo =~ s/(.d+?)$//;
  646.     if (defined($1) && length($1)) {
  647.       $inst = $1 . $inst;
  648.     } else {
  649.       $tempo = "";
  650.       last;
  651.     }
  652.   }
  653.   if (length($tempo) && exists($revOIDS{$tempo})) {
  654.     $tempo = $revOIDS{$tempo} . $inst;
  655.   } else {
  656.     $tempo = pretty_print($oid);
  657.   }
  658.   #
  659.   # call hash_sub
  660.   #
  661.   &$hash_sub($h_ref, $host, $revOIDS{$tempo}, $tempo, $inst,
  662. $tempv, $upo);
  663. } else {
  664.   if ($SNMP_util::Return_array_refs) {
  665.     $tempo=~s/^$upoid.//;
  666.     push @{$retvaltmprefs[$ix]}, "$tempo:$tempv";
  667.   } else {
  668.     $tempo=~s/^$upoid.// if ($#enoid <= 0);
  669.     push @retvals, "$tempo:$tempv";
  670.   }
  671. }
  672. $done{$tmp} = 1; # GIL
  673.       }
  674.       $ix = ++$ix % (scalar @avars);
  675.     }
  676.     # Ok, @nnoid should contain the remaining variables for the
  677.     # next request.  Some or all entries in @nnoid might be the empty
  678.     # string.  If the nth element in @nnoid is "" that means that
  679.     # the walk related to the nth variable in the last request has been
  680.     # completed and we should not include that var in subsequent reqs.
  681.     # Clean up both @nnoid and @avars so "" elements are removed.
  682.     @nnoid = grep (($_), @nnoid);
  683.     @avars = grep (($_), @avars);
  684.     @retvaltmprefs = grep (($_), @retvaltmprefs);
  685.     last if ($#nnoid < 0);   # @nnoid empty means we are done walking.
  686.   }
  687.   if ($got) {
  688.     if (defined($hash_sub)) {
  689. return ($h_ref) if ($SNMP_util::Return_hash_refs);
  690.      return (%$h_ref);
  691.     } else {
  692.      return (@retvals);
  693.     }
  694.   } else {
  695.     $var = join(' ', @vars);
  696.     carp "SNMPWALK Problem for $var on $hostn"
  697.       unless ($SNMP_Session::suppress_warnings > 1);
  698.     return undef;
  699.   }
  700. }
  701. #
  702. # A restricted snmpset.
  703. #
  704. sub snmpset($@) {
  705.   my($host, @vars) = @_;
  706.   my(@enoid, $response, $bindings, $binding);
  707.   my($oid, @retvals, $type, $value, $val);
  708.   my $session;
  709.   $session = &snmpopen($host, 0, @vars);
  710.   if (!defined($session)) {
  711.     carp "SNMPSET Problem for $hostn"
  712.       unless ($SNMP_Session::suppress_warnings > 1);
  713.     return undef;
  714.   }
  715.   while(@vars) {
  716.     ($oid) = toOID((shift @vars));
  717.     $type  = shift @vars;
  718.     $value = shift @vars;
  719.     $type =~ tr/A-Z/a-z/;
  720.     if ($type eq "int") {
  721.       $val = encode_int($value);
  722.     } elsif ($type eq "integer") {
  723.       $val = encode_int($value);
  724.     } elsif ($type eq "string") {
  725.       $val = encode_string($value);
  726.     } elsif ($type eq "octetstring") {
  727.       $val = encode_string($value);
  728.     } elsif ($type eq "octet string") {
  729.       $val = encode_string($value);
  730.     } elsif ($type eq "oid") {
  731.       $val = encode_oid_with_errmsg($value);
  732.     } elsif ($type eq "object id") {
  733.       $val = encode_oid_with_errmsg($value);
  734.     } elsif ($type eq "object identifier") {
  735.       $val = encode_oid_with_errmsg($value);
  736.     } elsif ($type eq "ipaddr") {
  737.       $val = encode_ip_address($value);
  738.     } elsif ($type eq "ip address") {
  739.       $val = encode_ip_address($value);
  740.     } elsif ($type eq "timeticks") {
  741.       $val = encode_timeticks($value);
  742.     } elsif ($type eq "uint") {
  743.       $val = encode_uinteger32($value);
  744.     } elsif ($type eq "uinteger") {
  745.       $val = encode_uinteger32($value);
  746.     } elsif ($type eq "uinteger32") {
  747.       $val = encode_uinteger32($value);
  748.     } elsif ($type eq "unsigned int") {
  749.       $val = encode_uinteger32($value);
  750.     } elsif ($type eq "unsigned integer") {
  751.       $val = encode_uinteger32($value);
  752.     } elsif ($type eq "unsigned integer32") {
  753.       $val = encode_uinteger32($value);
  754.     } elsif ($type eq "counter") {
  755.       $val = encode_counter32($value);
  756.     } elsif ($type eq "counter32") {
  757.       $val = encode_counter32($value);
  758.     } elsif ($type eq "counter64") {
  759.       $val = encode_counter64($value);
  760.     } elsif ($type eq "gauge") {
  761.       $val = encode_gauge32($value);
  762.     } elsif ($type eq "gauge32") {
  763.       $val = encode_gauge32($value);
  764.     } else {
  765.       carp "unknown SNMP type: $typen"
  766. unless ($SNMP_Session::suppress_warnings > 1);
  767.       return undef;
  768.     }
  769.     if (!defined($val)) {
  770.       carp "SNMP type $type value $value didn't encode properlyn"
  771. unless ($SNMP_Session::suppress_warnings > 1);
  772.       return undef;
  773.     }
  774.     push @enoid, [$oid,$val];
  775.   }
  776.   return undef unless defined $enoid[0];
  777.   if ($session->set_request_response(@enoid)) {
  778.     $response = $session->pdu_buffer;
  779.     ($bindings) = $session->decode_get_response($response);
  780.     while ($bindings) {
  781.       ($binding, $bindings) = decode_sequence($bindings);
  782.       ($oid, $value) = decode_by_template($binding, "%O%@");
  783.       my $tempo = pretty_print($value);
  784.       push @retvals, $tempo;
  785.     }
  786.     return wantarray ? @retvals : $retvals[0];
  787.   }
  788.   return undef;
  789. }
  790. #
  791. # Send an SNMP trap
  792. #
  793. sub snmptrap($$$$$@) {
  794.   my($host, $ent, $agent, $gen, $spec, @vars) = @_;
  795.   my($oid, @retvals, $type, $value);
  796.   my(@enoid);
  797.   my $session;
  798.   $session = &snmpopen($host, 1, @vars);
  799.   if (!defined($session)) {
  800.     carp "SNMPTRAP Problem for $hostn"
  801.       unless ($SNMP_Session::suppress_warnings > 1);
  802.     return undef;
  803.   }
  804.   if ($agent =~ /^d+.d+.d+.d+(.*)/ ) {
  805.     $agent = pack("C*", split /./, $agent);
  806.   } else {
  807.     $agent = inet_aton($agent);
  808.   }
  809.   push @enoid, toOID(($ent));
  810.   push @enoid, encode_ip_address($agent);
  811.   push @enoid, encode_int($gen);
  812.   push @enoid, encode_int($spec);
  813.   push @enoid, encode_timeticks((time-$agent_start_time) * 100);
  814.   while(@vars) {
  815.     ($oid) = toOID((shift @vars));
  816.     $type  = shift @vars;
  817.     $value = shift @vars;
  818.     if ($type =~ /string/i) {
  819.       $value = encode_string($value);
  820.       push @enoid, [$oid,$value];
  821.     } elsif ($type =~ /ipaddr/i) {
  822.       $value = encode_ip_address($value);
  823.       push @enoid, [$oid,$value];
  824.     } elsif ($type =~ /int/i) {
  825.       $value = encode_int($value);
  826.       push @enoid, [$oid,$value];
  827.     } elsif ($type =~ /oid/i) {
  828.       my $tmp = encode_oid_with_errmsg($value);
  829.       return undef unless defined $tmp;
  830.       push @enoid, [$oid,$tmp];
  831.     } else {
  832.       carp "unknown SNMP type: $typen"
  833. unless ($SNMP_Session::suppress_warnings > 1);
  834.       return undef;
  835.     }
  836.   }
  837.   return($session->trap_request_send(@enoid));
  838. }
  839. #
  840. # A restricted snmpgetbulk.
  841. #
  842. sub snmpgetbulk ($$$@) {
  843.   my($host, $nr, $mr, @vars) = @_;
  844.   my(@enoid, $var, $response, $bindings, $binding);
  845.   my($value, $upoid, $oid, @retvals);
  846.   my($noid);
  847.   my $session;
  848.   $session = &snmpopen($host, 0, @vars);
  849.   if (!defined($session)) {
  850.     carp "SNMPGETBULK Problem for $hostn"
  851.       unless ($SNMP_Session::suppress_warnings > 1);
  852.     return undef;
  853.   }
  854.   @enoid = &toOID(@vars);
  855.   return undef unless defined $enoid[0];
  856.   undef @vars;
  857.   undef @retvals;
  858.   foreach $noid (@enoid) {
  859.     $upoid = pretty_print($noid);
  860.     push(@vars, $upoid);
  861.   }
  862.   if ($session->getbulk_request_response($nr, $mr, @enoid)) {
  863.     $response = $session->pdu_buffer;
  864.     ($bindings) = $session->decode_get_response($response);
  865.     while ($bindings) {
  866.       ($binding, $bindings) = decode_sequence($bindings);
  867.       ($oid, $value) = decode_by_template($binding, "%O%@");
  868.       my $tempo = pretty_print($oid);
  869.       my $tempv = pretty_print($value);
  870.       push @retvals, "$tempo:$tempv";
  871.     }
  872.     return (@retvals);
  873.   } else {
  874.     $var = join(' ', @vars);
  875.     carp "SNMPGETBULK Problem for $var on $hostn"
  876.       unless ($SNMP_Session::suppress_warnings > 1);
  877.     return undef;
  878.   }
  879. }
  880. #
  881. # walk a table, calling a user-supplied function for each
  882. # column of a table.
  883. #
  884. sub snmpmaptable($$@) {
  885.   my($host, $fun, @vars) = @_;
  886.   return snmpmaptable4($host, $fun, 0, @vars);
  887. }
  888. sub snmpmaptable4($$$@) {
  889.   my($host, $fun, $max_reps, @vars) = @_;
  890.   my(@enoid, $var, $session);
  891.   $session = &snmpopen($host, 0, @vars);
  892.   if (!defined($session)) {
  893.     carp "SNMPMAPTABLE Problem for $hostn"
  894.       unless ($SNMP_Session::suppress_warnings > 1);
  895.     return undef;
  896.   }
  897.   foreach $var (toOID(@vars)) {
  898.     push(@enoid, [split('.', pretty_print($var))]);
  899.   }
  900.   $max_reps = $session->default_max_repetitions() if ($max_reps <= 0);
  901.   return $session->map_table_start_end( [@enoid],
  902. sub() {
  903.   my ($ind, @vals) = @_;
  904.   my (@pvals, $val);
  905.   foreach $val (@vals) {
  906.     push(@pvals, pretty_print($val));
  907.   }
  908.   &$fun($ind, @pvals);
  909. },
  910. "", undef, $max_reps);
  911. }
  912. #
  913. #  Given an OID in either ASN.1 or mixed text/ASN.1 notation, return an
  914. #  encoded OID.
  915. #
  916. sub toOID(@) {
  917.   my(@vars) = @_;
  918.   my($oid, $var, $tmp, $tmpv, @retvar);
  919.   undef @retvar;
  920.   foreach $var (@vars) {
  921.     ($oid, $tmp) = &Check_OID($var);
  922.     if (!$oid && $SNMP_util::CacheLoaded == 0) {
  923.       $tmp = $SNMP_Session::suppress_warnings;
  924.       $SNMP_Session::suppress_warnings = 1000;
  925.       &snmpLoad_OID_Cache($SNMP_util::CacheFile);
  926.       $SNMP_util::CacheLoaded = 1;
  927.       $SNMP_Session::suppress_warnings = $tmp;
  928.       ($oid, $tmp) = &Check_OID($var);
  929.     }
  930.     while (!$oid && $#SNMP_util::MIB_Files >= 0) {
  931.       $tmp = $SNMP_Session::suppress_warnings;
  932.       $SNMP_Session::suppress_warnings = 1000;
  933.       snmpMIB_to_OID(shift(@SNMP_util::MIB_Files));
  934.       $SNMP_Session::suppress_warnings = $tmp;
  935.       ($oid, $tmp) = &Check_OID($var);
  936.       if ($oid) {
  937. open(CACHE, ">>$SNMP_util::CacheFile");
  938. print CACHE "$tmpt$oidn";
  939. close(CACHE);
  940.       }
  941.     }
  942.     if ($oid) {
  943.       $var =~ s/^$tmp/$oid/;
  944.     } else {
  945.       carp "Unknown SNMP var $varn"
  946.       unless ($SNMP_Session::suppress_warnings > 1);
  947.       next;
  948.     }
  949.     while ($var =~ /"([^"]*)"/) {
  950.       $tmp = sprintf("%d.%s", length($1), join(".", map(ord, split(//, $1))));
  951.       $var =~ s/"$1"/$tmp/;
  952.     }
  953.     print "toOID: $varn" if $SNMP_util::Debug;
  954.     $tmp = encode_oid_with_errmsg($var);
  955.     return undef unless defined $tmp;
  956.     push(@retvar, $tmp);
  957.   }
  958.   return @retvar;
  959. }
  960. #
  961. #  Add passed-in text, OID pairs to the OID mapping table.
  962. #
  963. sub snmpmapOID(@)
  964. {
  965.   my(@vars) = @_;
  966.   my($oid, $txt, $ind);
  967.   $ind = 0;
  968.   while($ind <= $#vars) {
  969.     $txt = $vars[$ind++];
  970.     next unless($txt =~ /^(([a-zA-Z][a-zA-Zd-]*.)*([a-zA-Z][a-zA-Zd-]*))$/);
  971.     $oid = $vars[$ind++];
  972.     next unless($oid =~ /^((d+.)*d+)$/);
  973.     $SNMP_util::OIDS{$txt} = $oid;
  974.     $RevNeeded = 1;
  975.     print "snmpmapOID: $txt => $oidn" if $SNMP_util::Debug;
  976.   }
  977.   
  978.   return undef;
  979. }
  980. #
  981. # Open the passed-in file name and read it in to populate
  982. # the cache of text-to-OID map table.  It expects lines
  983. # with two fields, the first the textual string like "ifInOctets",
  984. # and the second the OID value, like "1.3.6.1.2.1.2.2.1.10".
  985. #
  986. # blank lines and anything after a '#' or between '--' is ignored.
  987. #
  988. sub snmpLoad_OID_Cache ($) {
  989.   my($arg) = @_;
  990.   my($txt, $oid);
  991.   if (!open(CACHE, $arg)) {
  992.     carp "snmpLoad_OID_Cache: Can't open $arg: $!"
  993.       unless ($SNMP_Session::suppress_warnings > 1);
  994.     return -1;
  995.   }
  996.   while(<CACHE>) {
  997.     s/#.*//;
  998.     s/--.*--//g;
  999.     s/--.*//;
  1000.     next if (/^$/);
  1001.     next unless (/s/);
  1002.     chop;
  1003.     ($txt, $oid) = split(' ', $_, 2);
  1004.     &snmpmapOID($txt, $oid);
  1005.   }
  1006.   close(CACHE);
  1007.   return 0;
  1008. }
  1009. #
  1010. # Check to see if an OID is in the text-to-OID cache.
  1011. # Returns the OID and the corresponding text as two separate
  1012. # elements.
  1013. #
  1014. sub Check_OID ($) {
  1015.   my($var) = @_;
  1016.   my($tmp, $tmpv, $oid);
  1017.   if ($var =~ /^(([a-zA-Z][a-zA-Zd-]*.)*([a-zA-Z][a-zA-Zd-]*))/)
  1018.   {
  1019.     $tmp = $&;
  1020.     $tmpv = $tmp;
  1021.     for (;;) {
  1022.       last if defined($SNMP_util::OIDS{$tmpv});
  1023.       last if !($tmpv =~ s/^[^.]*.//);
  1024.     }
  1025.     $oid = $SNMP_util::OIDS{$tmpv};
  1026.     if ($oid) {
  1027.       return ($oid, $tmp);
  1028.     } else {
  1029.       return undef;
  1030.     }
  1031.   }
  1032.   return ($var, $var);
  1033. }
  1034. #
  1035. # Save the passed-in list of MIB files until an OID can't be
  1036. # found in the existing table.  At that time the MIB file will
  1037. # be loaded, and the lookup attempted again.
  1038. #
  1039. sub snmpQueue_MIB_File (@) {
  1040.   my(@files) = @_;
  1041.   my($file);
  1042.   foreach $file (@files) {
  1043.     push(@SNMP_util::MIB_Files, $file);
  1044.   }
  1045. }
  1046. #
  1047. # Read in the passed MIB file, parsing it
  1048. # for their text-to-OID mappings
  1049. #
  1050. sub snmpMIB_to_OID ($) {
  1051.   my($arg) = @_;
  1052.   my($quote, $buf, $var, $code, $val, $tmp, $tmpv, $strt);
  1053.   my($ret, $pass, $pos, $need2pass, $cnt, %prev);
  1054.   my(%Link) = (
  1055.     'org' => 'iso',
  1056.     'dod' => 'org',
  1057.     'internet' => 'dod',
  1058.     'directory' => 'internet',
  1059.     'mgmt' => 'internet',
  1060.     'mib-2' => 'mgmt',
  1061.     'experimental' => 'internet',
  1062.     'private' => 'internet',
  1063.     'enterprises' => 'private',
  1064.   );
  1065.   if (!open(MIB, $arg)) {
  1066.     carp "snmpMIB_to_OID: Can't open $arg: $!"
  1067.       unless ($SNMP_Session::suppress_warnings > 1);
  1068.     return -1;
  1069.   }
  1070.   print "snmpMIB_to_OID: loading $argn" if $SNMP_util::Debug;
  1071.   $ret = 0;
  1072.   $pass = 0;
  1073.   $need2pass = 1;
  1074.   $cnt = 0;
  1075.   $pos = tell(MIB);
  1076.   while($need2pass) {
  1077.     while(<MIB>) {
  1078.       s/--.*--//g; # throw away comments (-- anything --)
  1079.       s/--.*//; # throw away comments (-- anything EOL)
  1080.       if ($quote) {
  1081. next unless /"/;
  1082. $quote = 0;
  1083.       }
  1084.       chop;
  1085. #
  1086. # $buf = "$buf $_";
  1087. # Previous line removed (and following replacement)
  1088. # suggested by Brian Reichert, reichert@numachi.com
  1089. #
  1090.       $buf .= ' ' . $_;
  1091.       $buf =~ s/s+/ /g;
  1092.       if ($buf =~ / DEFINITIONS ::= BEGIN/) {
  1093. if ($pass == 0 && $need2pass) {
  1094.   seek(MIB, $pos, 0);
  1095.   $buf = "";
  1096.   $pass = 1;
  1097.   $need2pass = 0;
  1098.   $cnt = 0;
  1099.   next;
  1100. }
  1101. $need2pass = 0;
  1102. $pass = 0;
  1103. $pos = tell(MIB);
  1104. undef %Link;
  1105. undef %prev;
  1106. %Link = (
  1107.   'org' => 'iso',
  1108.   'dod' => 'org',
  1109.   'internet' => 'dod',
  1110.   'directory' => 'internet',
  1111.   'mgmt' => 'internet',
  1112.   'mib-2' => 'mgmt',
  1113.   'experimental' => 'internet',
  1114.   'private' => 'internet',
  1115.   'enterprises' => 'private',
  1116. );
  1117. $buf = "";
  1118. next;
  1119.       }
  1120.       $buf =~ s/OBJECT-TYPE/OBJECT IDENTIFIER/;
  1121.       $buf =~ s/OBJECT-IDENTITY/OBJECT IDENTIFIER/;
  1122.       $buf =~ s/OBJECT-GROUP/OBJECT IDENTIFIER/;
  1123.       $buf =~ s/MODULE-IDENTITY/OBJECT IDENTIFIER/;
  1124.       $buf =~ s/ IMPORTS .*;//;
  1125.       $buf =~ s/ SEQUENCE {.*}//;
  1126.       $buf =~ s/ SYNTAX .*//;
  1127.       $buf =~ s/ [w-]+ ::= OBJECT IDENTIFIER//;
  1128.       $buf =~ s/ OBJECT IDENTIFIER .* ::= {/ OBJECT IDENTIFIER ::= {/;
  1129.       $buf =~ s/".*"//;
  1130.       if ($buf =~ /"/) {
  1131. $quote = 1;
  1132.       }
  1133.       if ($buf =~ / ([w-]+) OBJECT IDENTIFIER ::= {([^}]+)}/) {
  1134. $var = $1;
  1135. $buf = $2;
  1136. undef $val;
  1137. $buf =~ s/ +$//;
  1138. ($code, $val) = split(' ', $buf, 2);
  1139. if (!defined($val) || (length($val) <= 0)) {
  1140.   $SNMP_util::OIDS{$var} = $code;
  1141.   $cnt++;
  1142.   print "'$var' => '$code'n" if $SNMP_util::Debug;
  1143. } else {
  1144.   $strt = $code;
  1145.   while($val =~ / /) {
  1146.     ($tmp, $val) = split(' ', $val, 2);
  1147.     if ($tmp =~ /([w-]+)((d+))/) {
  1148.       $tmp = $1;
  1149.       $tmpv = "$SNMP_util::OIDS{$strt}.$2";
  1150.       $Link{$tmp} = $strt;
  1151.       if (!defined($prev{$tmp}) && defined($SNMP_util::OIDS{$tmp})) {
  1152. if ($tmpv ne $SNMP_util::OIDS{$tmp}) {
  1153.   $strt = "$strt.$tmp";
  1154.   $SNMP_util::OIDS{$strt} = $tmpv;
  1155.   $cnt++;
  1156. }
  1157.       } else {
  1158. $prev{$tmp} = 1;
  1159. $SNMP_util::OIDS{$tmp} = $tmpv;
  1160. $cnt++;
  1161. $strt = $tmp;
  1162.       }
  1163.     }
  1164.   }
  1165.   if (!defined($SNMP_util::OIDS{$strt})) {
  1166.     if ($pass) {
  1167.       carp "snmpMIB_to_OID: $arg: "$strt" prefix unknown, load the parent MIB first.n"
  1168. unless ($SNMP_Session::suppress_warnings > 1);
  1169.     } else {
  1170. $need2pass = 1;
  1171.     }
  1172.   }
  1173.   $Link{$var} = $strt;
  1174.   $val = "$SNMP_util::OIDS{$strt}.$val";
  1175.   if (!defined($prev{$var}) && defined($SNMP_util::OIDS{$var})) {
  1176.     if ($val ne $SNMP_util::OIDS{$var}) {
  1177.       $var = "$strt.$var";
  1178.     }
  1179.   }
  1180.   $SNMP_util::OIDS{$var} = $val;
  1181.   $prev{$var} = 1;
  1182.   $cnt++;
  1183.   print "'$var' => '$val'n" if $SNMP_util::Debug;
  1184. }
  1185. undef $buf;
  1186.       }
  1187.     }
  1188.     if ($pass == 0 && $need2pass) {
  1189.       seek(MIB, $pos, 0);
  1190.       $buf = "";
  1191.       $pass = 1;
  1192.       $cnt = 0;
  1193.     } else {
  1194.       $ret += $cnt;
  1195.       $need2pass = 0;
  1196.     }
  1197.   }
  1198.   close(MIB);
  1199.   $RevNeeded = 1;
  1200.   return $ret;
  1201. }
  1202. sub encode_oid_with_errmsg ($) {
  1203.   my ($oid) = @_;
  1204.   my $tmp = encode_oid(split(/./, $oid));
  1205.   if (! defined $tmp) {
  1206.     carp "cannot encode Object ID $oid: $BER::errmsg"
  1207.       unless ($SNMP_Session::suppress_warnings > 1);
  1208.     return undef;
  1209.   }
  1210.   return $tmp;
  1211. }
  1212. 1;