snmp 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +193 -0
- data/Rakefile +52 -0
- data/data/ruby/snmp/mibs/ACCOUNTING-CONTROL-MIB.yaml +44 -0
- data/data/ruby/snmp/mibs/ADSL-LINE-EXT-MIB.yaml +66 -0
- data/data/ruby/snmp/mibs/ADSL-LINE-MIB.yaml +238 -0
- data/data/ruby/snmp/mibs/ADSL-TC-MIB.yaml +2 -0
- data/data/ruby/snmp/mibs/AGENTX-MIB.yaml +40 -0
- data/data/ruby/snmp/mibs/APM-MIB.yaml +98 -0
- data/data/ruby/snmp/mibs/APPC-MIB.yaml +295 -0
- data/data/ruby/snmp/mibs/APPLETALK-MIB.yaml +284 -0
- data/data/ruby/snmp/mibs/APPLICATION-MIB.yaml +161 -0
- data/data/ruby/snmp/mibs/APPN-DLUR-MIB.yaml +41 -0
- data/data/ruby/snmp/mibs/APPN-MIB.yaml +356 -0
- data/data/ruby/snmp/mibs/APPN-TRAP-MIB.yaml +8 -0
- data/data/ruby/snmp/mibs/APS-MIB.yaml +62 -0
- data/data/ruby/snmp/mibs/ATM-ACCOUNTING-INFORMATION-MIB.yaml +37 -0
- data/data/ruby/snmp/mibs/ATM-MIB.yaml +112 -0
- data/data/ruby/snmp/mibs/ATM-TC-MIB.yaml +19 -0
- data/data/ruby/snmp/mibs/ATM2-MIB.yaml +182 -0
- data/data/ruby/snmp/mibs/BGP4-MIB.yaml +56 -0
- data/data/ruby/snmp/mibs/BLDG-HVAC-MIB.yaml +35 -0
- data/data/ruby/snmp/mibs/BRIDGE-MIB.yaml +63 -0
- data/data/ruby/snmp/mibs/CHARACTER-MIB.yaml +48 -0
- data/data/ruby/snmp/mibs/CIRCUIT-IF-MIB.yaml +21 -0
- data/data/ruby/snmp/mibs/CLNS-MIB.yaml +116 -0
- data/data/ruby/snmp/mibs/COFFEE-POT-MIB.yaml +13 -0
- data/data/ruby/snmp/mibs/COPS-CLIENT-MIB.yaml +54 -0
- data/data/ruby/snmp/mibs/DECNET-PHIV-MIB.yaml +237 -0
- data/data/ruby/snmp/mibs/DIAL-CONTROL-MIB.yaml +84 -0
- data/data/ruby/snmp/mibs/DIFFSERV-CONFIG-MIB.yaml +15 -0
- data/data/ruby/snmp/mibs/DIFFSERV-DSCP-TC.yaml +2 -0
- data/data/ruby/snmp/mibs/DIFFSERV-MIB.yaml +171 -0
- data/data/ruby/snmp/mibs/DIRECTORY-SERVER-MIB.yaml +52 -0
- data/data/ruby/snmp/mibs/DISMAN-EVENT-MIB.yaml +110 -0
- data/data/ruby/snmp/mibs/DISMAN-EXPRESSION-MIB.yaml +55 -0
- data/data/ruby/snmp/mibs/DISMAN-NSLOOKUP-MIB.yaml +23 -0
- data/data/ruby/snmp/mibs/DISMAN-PING-MIB.yaml +57 -0
- data/data/ruby/snmp/mibs/DISMAN-SCHEDULE-MIB.yaml +32 -0
- data/data/ruby/snmp/mibs/DISMAN-SCRIPT-MIB.yaml +80 -0
- data/data/ruby/snmp/mibs/DISMAN-TRACEROUTE-MIB.yaml +72 -0
- data/data/ruby/snmp/mibs/DLSW-MIB.yaml +193 -0
- data/data/ruby/snmp/mibs/DNS-RESOLVER-MIB.yaml +87 -0
- data/data/ruby/snmp/mibs/DNS-SERVER-MIB.yaml +73 -0
- data/data/ruby/snmp/mibs/DOCS-BPI-MIB.yaml +101 -0
- data/data/ruby/snmp/mibs/DOCS-CABLE-DEVICE-MIB.yaml +107 -0
- data/data/ruby/snmp/mibs/DOCS-IF-MIB.yaml +143 -0
- data/data/ruby/snmp/mibs/DOT12-IF-MIB.yaml +33 -0
- data/data/ruby/snmp/mibs/DS0-MIB.yaml +18 -0
- data/data/ruby/snmp/mibs/DS0BUNDLE-MIB.yaml +17 -0
- data/data/ruby/snmp/mibs/DS1-MIB.yaml +118 -0
- data/data/ruby/snmp/mibs/DS3-MIB.yaml +106 -0
- data/data/ruby/snmp/mibs/DSA-MIB.yaml +44 -0
- data/data/ruby/snmp/mibs/DSMON-MIB.yaml +219 -0
- data/data/ruby/snmp/mibs/EBN-MIB.yaml +47 -0
- data/data/ruby/snmp/mibs/ENTITY-MIB.yaml +51 -0
- data/data/ruby/snmp/mibs/ENTITY-SENSOR-MIB.yaml +16 -0
- data/data/ruby/snmp/mibs/ETHER-CHIPSET-MIB.yaml +79 -0
- data/data/ruby/snmp/mibs/ETHER-WIS.yaml +28 -0
- data/data/ruby/snmp/mibs/EtherLike-MIB.yaml +58 -0
- data/data/ruby/snmp/mibs/FDDI-SMT73-MIB.yaml +128 -0
- data/data/ruby/snmp/mibs/FIBRE-CHANNEL-FE-MIB.yaml +122 -0
- data/data/ruby/snmp/mibs/FLOW-METER-MIB.yaml +112 -0
- data/data/ruby/snmp/mibs/FR-ATM-PVC-SERVICE-IWF-MIB.yaml +45 -0
- data/data/ruby/snmp/mibs/FR-MFR-MIB.yaml +52 -0
- data/data/ruby/snmp/mibs/FRAME-RELAY-DTE-MIB.yaml +54 -0
- data/data/ruby/snmp/mibs/FRNETSERV-MIB.yaml +109 -0
- data/data/ruby/snmp/mibs/FRSLD-MIB.yaml +82 -0
- data/data/ruby/snmp/mibs/Finisher-MIB.yaml +53 -0
- data/data/ruby/snmp/mibs/GSMP-MIB.yaml +82 -0
- data/data/ruby/snmp/mibs/HC-ALARM-MIB.yaml +32 -0
- data/data/ruby/snmp/mibs/HC-PerfHist-TC-MIB.yaml +2 -0
- data/data/ruby/snmp/mibs/HC-RMON-MIB.yaml +193 -0
- data/data/ruby/snmp/mibs/HCNUM-TC.yaml +2 -0
- data/data/ruby/snmp/mibs/HDSL2-SHDSL-LINE-MIB.yaml +115 -0
- data/data/ruby/snmp/mibs/HOST-RESOURCES-MIB.yaml +98 -0
- data/data/ruby/snmp/mibs/HOST-RESOURCES-TYPES.yaml +56 -0
- data/data/ruby/snmp/mibs/HPR-IP-MIB.yaml +24 -0
- data/data/ruby/snmp/mibs/HPR-MIB.yaml +81 -0
- data/data/ruby/snmp/mibs/IF-INVERTED-STACK-MIB.yaml +9 -0
- data/data/ruby/snmp/mibs/IF-MIB.yaml +73 -0
- data/data/ruby/snmp/mibs/IGMP-STD-MIB.yaml +33 -0
- data/data/ruby/snmp/mibs/INET-ADDRESS-MIB.yaml +2 -0
- data/data/ruby/snmp/mibs/INTEGRATED-SERVICES-GUARANTEED-MIB.yaml +13 -0
- data/data/ruby/snmp/mibs/INTEGRATED-SERVICES-MIB.yaml +44 -0
- data/data/ruby/snmp/mibs/INTERFACETOPN-MIB.yaml +29 -0
- data/data/ruby/snmp/mibs/IP-FORWARD-MIB.yaml +42 -0
- data/data/ruby/snmp/mibs/IP-MIB.yaml +66 -0
- data/data/ruby/snmp/mibs/IPATM-IPMC-MIB.yaml +203 -0
- data/data/ruby/snmp/mibs/IPMROUTE-STD-MIB.yaml +64 -0
- data/data/ruby/snmp/mibs/IPOA-MIB.yaml +85 -0
- data/data/ruby/snmp/mibs/IPV6-FLOW-LABEL-MIB.yaml +2 -0
- data/data/ruby/snmp/mibs/IPV6-ICMP-MIB.yaml +42 -0
- data/data/ruby/snmp/mibs/IPV6-MIB.yaml +88 -0
- data/data/ruby/snmp/mibs/IPV6-MLD-MIB.yaml +30 -0
- data/data/ruby/snmp/mibs/IPV6-TCP-MIB.yaml +14 -0
- data/data/ruby/snmp/mibs/IPV6-UDP-MIB.yaml +11 -0
- data/data/ruby/snmp/mibs/ISDN-MIB.yaml +71 -0
- data/data/ruby/snmp/mibs/Job-Monitoring-MIB.yaml +43 -0
- data/data/ruby/snmp/mibs/L2TP-MIB.yaml +156 -0
- data/data/ruby/snmp/mibs/MALLOC-MIB.yaml +83 -0
- data/data/ruby/snmp/mibs/MAU-MIB.yaml +110 -0
- data/data/ruby/snmp/mibs/MIOX25-MIB.yaml +38 -0
- data/data/ruby/snmp/mibs/MIP-MIB.yaml +180 -0
- data/data/ruby/snmp/mibs/MPLS-FTN-STD-MIB.yaml +44 -0
- data/data/ruby/snmp/mibs/MPLS-LDP-ATM-STD-MIB.yaml +35 -0
- data/data/ruby/snmp/mibs/MPLS-LDP-FRAME-RELAY-STD-MIB.yaml +28 -0
- data/data/ruby/snmp/mibs/MPLS-LDP-GENERIC-STD-MIB.yaml +15 -0
- data/data/ruby/snmp/mibs/MPLS-LDP-STD-MIB.yaml +118 -0
- data/data/ruby/snmp/mibs/MPLS-LSR-STD-MIB.yaml +98 -0
- data/data/ruby/snmp/mibs/MPLS-TC-STD-MIB.yaml +3 -0
- data/data/ruby/snmp/mibs/MPLS-TE-STD-MIB.yaml +120 -0
- data/data/ruby/snmp/mibs/MTA-MIB.yaml +64 -0
- data/data/ruby/snmp/mibs/Modem-MIB.yaml +106 -0
- data/data/ruby/snmp/mibs/NETWORK-SERVICES-MIB.yaml +33 -0
- data/data/ruby/snmp/mibs/NHRP-MIB.yaml +163 -0
- data/data/ruby/snmp/mibs/NOTIFICATION-LOG-MIB.yaml +51 -0
- data/data/ruby/snmp/mibs/OPT-IF-MIB.yaml +431 -0
- data/data/ruby/snmp/mibs/OSPF-MIB.yaml +150 -0
- data/data/ruby/snmp/mibs/OSPF-TRAP-MIB.yaml +11 -0
- data/data/ruby/snmp/mibs/P-BRIDGE-MIB.yaml +51 -0
- data/data/ruby/snmp/mibs/PARALLEL-MIB.yaml +24 -0
- data/data/ruby/snmp/mibs/PIM-MIB.yaml +66 -0
- data/data/ruby/snmp/mibs/PINT-MIB.yaml +51 -0
- data/data/ruby/snmp/mibs/POWER-ETHERNET-MIB.yaml +36 -0
- data/data/ruby/snmp/mibs/PPP-BRIDGE-NCP-MIB.yaml +25 -0
- data/data/ruby/snmp/mibs/PPP-IP-NCP-MIB.yaml +13 -0
- data/data/ruby/snmp/mibs/PPP-LCP-MIB.yaml +47 -0
- data/data/ruby/snmp/mibs/PPP-SEC-MIB.yaml +20 -0
- data/data/ruby/snmp/mibs/PTOPO-MIB.yaml +39 -0
- data/data/ruby/snmp/mibs/PerfHist-TC-MIB.yaml +2 -0
- data/data/ruby/snmp/mibs/Printer-MIB.yaml +209 -0
- data/data/ruby/snmp/mibs/Q-BRIDGE-MIB.yaml +99 -0
- data/data/ruby/snmp/mibs/RADIUS-ACC-CLIENT-MIB.yaml +26 -0
- data/data/ruby/snmp/mibs/RADIUS-ACC-SERVER-MIB.yaml +35 -0
- data/data/ruby/snmp/mibs/RADIUS-AUTH-CLIENT-MIB.yaml +28 -0
- data/data/ruby/snmp/mibs/RADIUS-AUTH-SERVER-MIB.yaml +37 -0
- data/data/ruby/snmp/mibs/RDBMS-MIB.yaml +82 -0
- data/data/ruby/snmp/mibs/RFC1065-SMI.yaml +9 -0
- data/data/ruby/snmp/mibs/RFC1155-SMI.yaml +9 -0
- data/data/ruby/snmp/mibs/RFC1158-MIB.yaml +202 -0
- data/data/ruby/snmp/mibs/RFC1213-MIB.yaml +202 -0
- data/data/ruby/snmp/mibs/RFC1269-MIB.yaml +29 -0
- data/data/ruby/snmp/mibs/RFC1271-MIB.yaml +214 -0
- data/data/ruby/snmp/mibs/RFC1285-MIB.yaml +104 -0
- data/data/ruby/snmp/mibs/RFC1316-MIB.yaml +42 -0
- data/data/ruby/snmp/mibs/RFC1381-MIB.yaml +60 -0
- data/data/ruby/snmp/mibs/RFC1382-MIB.yaml +169 -0
- data/data/ruby/snmp/mibs/RFC1414-MIB.yaml +10 -0
- data/data/ruby/snmp/mibs/RIPv2-MIB.yaml +34 -0
- data/data/ruby/snmp/mibs/RMON-MIB.yaml +219 -0
- data/data/ruby/snmp/mibs/RMON2-MIB.yaml +282 -0
- data/data/ruby/snmp/mibs/ROHC-MIB.yaml +64 -0
- data/data/ruby/snmp/mibs/ROHC-RTP-MIB.yaml +29 -0
- data/data/ruby/snmp/mibs/ROHC-UNCOMPRESSED-MIB.yaml +11 -0
- data/data/ruby/snmp/mibs/RS-232-MIB.yaml +54 -0
- data/data/ruby/snmp/mibs/RSVP-MIB.yaml +156 -0
- data/data/ruby/snmp/mibs/RTP-MIB.yaml +57 -0
- data/data/ruby/snmp/mibs/SFLOW-MIB.yaml +22 -0
- data/data/ruby/snmp/mibs/SIP-MIB.yaml +70 -0
- data/data/ruby/snmp/mibs/SLAPM-MIB.yaml +144 -0
- data/data/ruby/snmp/mibs/SMON-MIB.yaml +63 -0
- data/data/ruby/snmp/mibs/SNA-NAU-MIB.yaml +137 -0
- data/data/ruby/snmp/mibs/SNA-SDLC-MIB.yaml +147 -0
- data/data/ruby/snmp/mibs/SNMP-COMMUNITY-MIB.yaml +22 -0
- data/data/ruby/snmp/mibs/SNMP-FRAMEWORK-MIB.yaml +14 -0
- data/data/ruby/snmp/mibs/SNMP-MPD-MIB.yaml +11 -0
- data/data/ruby/snmp/mibs/SNMP-NOTIFICATION-MIB.yaml +25 -0
- data/data/ruby/snmp/mibs/SNMP-PROXY-MIB.yaml +17 -0
- data/data/ruby/snmp/mibs/SNMP-REPEATER-MIB.yaml +135 -0
- data/data/ruby/snmp/mibs/SNMP-TARGET-MIB.yaml +29 -0
- data/data/ruby/snmp/mibs/SNMP-USER-BASED-SM-MIB.yaml +35 -0
- data/data/ruby/snmp/mibs/SNMP-USM-DH-OBJECTS-MIB.yaml +21 -0
- data/data/ruby/snmp/mibs/SNMP-VIEW-BASED-ACM-MIB.yaml +37 -0
- data/data/ruby/snmp/mibs/SNMPv2-MIB.yaml +58 -0
- data/data/ruby/snmp/mibs/SNMPv2-SMI.yaml +17 -0
- data/data/ruby/snmp/mibs/SNMPv2-TM.yaml +9 -0
- data/data/ruby/snmp/mibs/SNMPv2-USEC-MIB.yaml +19 -0
- data/data/ruby/snmp/mibs/SONET-MIB.yaml +131 -0
- data/data/ruby/snmp/mibs/SOURCE-ROUTING-MIB.yaml +30 -0
- data/data/ruby/snmp/mibs/SYSAPPL-MIB.yaml +81 -0
- data/data/ruby/snmp/mibs/TCP-MIB.yaml +27 -0
- data/data/ruby/snmp/mibs/TCPIPX-MIB.yaml +24 -0
- data/data/ruby/snmp/mibs/TN3270E-MIB.yaml +105 -0
- data/data/ruby/snmp/mibs/TN3270E-RT-MIB.yaml +43 -0
- data/data/ruby/snmp/mibs/TOKEN-RING-RMON-MIB.yaml +183 -0
- data/data/ruby/snmp/mibs/TOKENRING-MIB.yaml +58 -0
- data/data/ruby/snmp/mibs/TOKENRING-STATION-SR-MIB.yaml +12 -0
- data/data/ruby/snmp/mibs/TRANSPORT-ADDRESS-MIB.yaml +19 -0
- data/data/ruby/snmp/mibs/TUNNEL-MIB.yaml +23 -0
- data/data/ruby/snmp/mibs/UDP-MIB.yaml +14 -0
- data/data/ruby/snmp/mibs/UPS-MIB.yaml +117 -0
- data/data/ruby/snmp/mibs/VDSL-LINE-MIB.yaml +173 -0
- data/data/ruby/snmp/mibs/VRRP-MIB.yaml +50 -0
- data/data/ruby/snmp/mibs/WWW-MIB.yaml +91 -0
- data/examples/dump.rb +15 -0
- data/examples/get.rb +7 -0
- data/examples/iftable.rb +14 -0
- data/examples/log_traps.rb +23 -0
- data/examples/set.rb +8 -0
- data/examples/walk.rb +9 -0
- data/lib/snmp.rb +10 -0
- data/lib/snmp/agent.rb +74 -0
- data/lib/snmp/ber.rb +332 -0
- data/lib/snmp/manager.rb +502 -0
- data/lib/snmp/mib.rb +259 -0
- data/lib/snmp/pdu.rb +363 -0
- data/lib/snmp/varbind.rb +520 -0
- data/setup.rb +1360 -0
- data/test/test_ber.rb +236 -0
- data/test/test_manager.rb +192 -0
- data/test/test_mib.rb +66 -0
- data/test/test_pdu.rb +184 -0
- data/test/test_varbind.rb +270 -0
- metadata +251 -0
data/lib/snmp/manager.rb
ADDED
@@ -0,0 +1,502 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2004 David R. Halliday
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# This SNMP library is free software. Redistribution is permitted under the
|
6
|
+
# same terms and conditions as the standard Ruby distribution. See the
|
7
|
+
# COPYING file in the Ruby distribution for details.
|
8
|
+
#
|
9
|
+
|
10
|
+
require 'snmp/pdu'
|
11
|
+
require 'snmp/mib'
|
12
|
+
require 'socket'
|
13
|
+
require 'timeout'
|
14
|
+
require 'thread'
|
15
|
+
|
16
|
+
module SNMP
|
17
|
+
|
18
|
+
class RequestTimeout < RuntimeError; end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Wrap socket so that it can be easily substituted for testing or for
|
22
|
+
# using other transport types (e.g. TCP)
|
23
|
+
#
|
24
|
+
class UDPTransport
|
25
|
+
def initialize(host, port)
|
26
|
+
@socket = UDPSocket.open
|
27
|
+
@socket.connect(host, port)
|
28
|
+
end
|
29
|
+
|
30
|
+
def close
|
31
|
+
@socket.close
|
32
|
+
end
|
33
|
+
|
34
|
+
def send(data)
|
35
|
+
@socket.send(data, 0)
|
36
|
+
end
|
37
|
+
|
38
|
+
def recv(max_bytes)
|
39
|
+
@socket.recv(max_bytes)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Manage a request-id in the range 1..2**31-1
|
45
|
+
#
|
46
|
+
class RequestId
|
47
|
+
MAX_REQUEST_ID = 2**31
|
48
|
+
|
49
|
+
def initialize
|
50
|
+
@lock = Mutex.new
|
51
|
+
@request_id = rand(MAX_REQUEST_ID)
|
52
|
+
end
|
53
|
+
|
54
|
+
def next
|
55
|
+
@lock.synchronize do
|
56
|
+
@request_id += 1
|
57
|
+
@request_id = 1 if @request_id == MAX_REQUEST_ID
|
58
|
+
return @request_id
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def force_next(next_id)
|
63
|
+
new_request_id = next_id.to_i
|
64
|
+
if new_request_id < 1 || new_request_id >= MAX_REQUEST_ID
|
65
|
+
raise "Invalid request id: #{new_request_id}"
|
66
|
+
end
|
67
|
+
new_request_id = MAX_REQUEST_ID if new_request_id == 1
|
68
|
+
@lock.synchronize do
|
69
|
+
@request_id = new_request_id - 1
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# == SNMP Manager
|
76
|
+
#
|
77
|
+
# This class provides a manager for interacting with a single SNMP agent.
|
78
|
+
#
|
79
|
+
# = Example
|
80
|
+
#
|
81
|
+
# require 'snmp'
|
82
|
+
#
|
83
|
+
# manager = SNMP::Manager.new(:Host => 'localhost', :Port => 1061)
|
84
|
+
# response = manager.get(["1.3.6.1.2.1.1.1.0", "1.3.6.1.2.1.1.2.0"])
|
85
|
+
# response.each_varbind {|vb| puts vb.inspect}
|
86
|
+
# manager.close
|
87
|
+
#
|
88
|
+
# == Symbolic Object Names
|
89
|
+
#
|
90
|
+
# Symbolic names for SNMP object IDs can be used as parameters to the
|
91
|
+
# APIs in this class if the MIB modules are imported and the names of the
|
92
|
+
# MIBs are included in the MibModules configuration parameter.
|
93
|
+
#
|
94
|
+
# See MIB.varbind_list for a description of valid parameter formats.
|
95
|
+
#
|
96
|
+
# The following modules are loaded by default: "SNMPv2-MIB", "IF-MIB",
|
97
|
+
# "IP-MIB", "TCP-MIB", "UDP-MIB". All of the current IETF MIBs have been
|
98
|
+
# imported and are available for loading.
|
99
|
+
#
|
100
|
+
# Additional modules may be imported using the MIB class. The
|
101
|
+
# current implementation of the importing code requires that the
|
102
|
+
# external 'smidump' tool is available in your PATH. This tool can be
|
103
|
+
# obtained from the libsmi website at
|
104
|
+
# http://http://www.ibr.cs.tu-bs.de/projects/libsmi/ .
|
105
|
+
#
|
106
|
+
# = Example
|
107
|
+
#
|
108
|
+
# Do this once:
|
109
|
+
#
|
110
|
+
# SNMP::MIB.import_module(MY_MODULE_FILENAME, MIB_OUTPUT_DIR)
|
111
|
+
#
|
112
|
+
# Include your module in MibModules each time you create a Manager:
|
113
|
+
#
|
114
|
+
# SNMP::Manager.new(:Host => 'localhost', :MibDir => MIB_OUTPUT_DIR,
|
115
|
+
# :MibModules => ["MY-MODULE-MIB", "SNMPv2-MIB", ...])
|
116
|
+
#
|
117
|
+
|
118
|
+
class Manager
|
119
|
+
|
120
|
+
##
|
121
|
+
# Default configuration. Individual options may be overridden when
|
122
|
+
# the Manager is created.
|
123
|
+
#
|
124
|
+
DefaultConfig = {
|
125
|
+
:Host => 'localhost',
|
126
|
+
:Port => 161,
|
127
|
+
:Community => 'public',
|
128
|
+
:WriteCommunity => nil,
|
129
|
+
:Version => :SNMPv2c,
|
130
|
+
:Timeout => 1,
|
131
|
+
:Retries => 5,
|
132
|
+
:Transport => UDPTransport,
|
133
|
+
:MaxReceiveBytes => 8000,
|
134
|
+
:MibDir => MIB::DEFAULT_MIB_PATH,
|
135
|
+
:MibModules => ["SNMPv2-MIB", "IF-MIB", "IP-MIB", "TCP-MIB", "UDP-MIB"]}
|
136
|
+
|
137
|
+
@@request_id = RequestId.new
|
138
|
+
|
139
|
+
##
|
140
|
+
# Retrieves the current configuration of this Manager.
|
141
|
+
#
|
142
|
+
attr_reader :config
|
143
|
+
|
144
|
+
##
|
145
|
+
# Retrieves the MIB for this Manager.
|
146
|
+
#
|
147
|
+
attr_reader :mib
|
148
|
+
|
149
|
+
def initialize(config = {})
|
150
|
+
if block_given?
|
151
|
+
warn "SNMP::Manager::new() does not take block; use SNMP::Manager::open() instead"
|
152
|
+
end
|
153
|
+
@config = DefaultConfig.merge(config)
|
154
|
+
@config[:WriteCommunity] = @config[:WriteCommunity] || @config[:Community]
|
155
|
+
@community = @config[:Community]
|
156
|
+
@write_community = @config[:WriteCommunity]
|
157
|
+
@snmp_version = @config[:Version]
|
158
|
+
@max_bytes = @config[:MaxReceiveBytes]
|
159
|
+
@timeout = @config[:Timeout]
|
160
|
+
@retries = @config[:Retries]
|
161
|
+
@transport = @config[:Transport].new(@config[:Host], @config[:Port])
|
162
|
+
@mib = MIB.new
|
163
|
+
load_modules(@config[:MibModules], @config[:MibDir])
|
164
|
+
end
|
165
|
+
|
166
|
+
##
|
167
|
+
# Creates a Manager but also takes an optional block and automatically
|
168
|
+
# closes the transport connection used by this manager after the block
|
169
|
+
# completes.
|
170
|
+
#
|
171
|
+
def self.open(config = {})
|
172
|
+
manager = Manager.new(config)
|
173
|
+
if block_given?
|
174
|
+
begin
|
175
|
+
yield manager
|
176
|
+
ensure
|
177
|
+
manager.close
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
##
|
183
|
+
# Close the transport connection for this manager.
|
184
|
+
#
|
185
|
+
def close
|
186
|
+
@transport.close
|
187
|
+
end
|
188
|
+
|
189
|
+
def load_module(name)
|
190
|
+
@mib.load_module(name)
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# Sends a get request for the supplied list of ObjectId or VarBind
|
195
|
+
# objects.
|
196
|
+
#
|
197
|
+
# Returns a Response PDU with the results of the request.
|
198
|
+
#
|
199
|
+
def get(object_list)
|
200
|
+
varbind_list = @mib.varbind_list(object_list, :NullValue)
|
201
|
+
request = GetRequest.new(@@request_id.next, varbind_list)
|
202
|
+
try_request(request)
|
203
|
+
end
|
204
|
+
|
205
|
+
##
|
206
|
+
# Sends a get-next request for the supplied list of ObjectId or VarBind
|
207
|
+
# objects.
|
208
|
+
#
|
209
|
+
# Returns a Response PDU with the results of the request.
|
210
|
+
#
|
211
|
+
def get_next(object_list)
|
212
|
+
varbind_list = @mib.varbind_list(object_list, :NullValue)
|
213
|
+
request = GetNextRequest.new(@@request_id.next, varbind_list)
|
214
|
+
try_request(request)
|
215
|
+
end
|
216
|
+
|
217
|
+
##
|
218
|
+
# Sends a get-bulk request. The non_repeaters parameter specifies
|
219
|
+
# the number of objects in the object_list to be retrieved once. The
|
220
|
+
# remaining objects in the list will be retrieved up to the number of
|
221
|
+
# times specified by max_repetitions.
|
222
|
+
#
|
223
|
+
def get_bulk(non_repeaters, max_repetitions, object_list)
|
224
|
+
varbind_list = @mib.varbind_list(object_list, :NullValue)
|
225
|
+
request = GetBulkRequest.new(
|
226
|
+
@@request_id.next,
|
227
|
+
varbind_list,
|
228
|
+
non_repeaters,
|
229
|
+
max_repetitions)
|
230
|
+
try_request(request)
|
231
|
+
end
|
232
|
+
|
233
|
+
##
|
234
|
+
# Sends a set request using the supplied list of VarBind objects.
|
235
|
+
#
|
236
|
+
# Returns a Response PDU with the results of the request.
|
237
|
+
#
|
238
|
+
def set(object_list)
|
239
|
+
varbind_list = @mib.varbind_list(object_list, :KeepValue)
|
240
|
+
request = SetRequest.new(@@request_id.next, varbind_list)
|
241
|
+
try_request(request, @write_community)
|
242
|
+
end
|
243
|
+
|
244
|
+
##
|
245
|
+
# Walks a list of ObjectId or VarBind objects using get_next until
|
246
|
+
# the response to the first OID in the list reaches the end of its
|
247
|
+
# MIB subtree.
|
248
|
+
#
|
249
|
+
# The results of each get_next are yielded to the given block as
|
250
|
+
# they are retrieved.
|
251
|
+
#
|
252
|
+
# Normally this method is used for walking tables by providing an
|
253
|
+
# ObjectId for each column of the table.
|
254
|
+
#
|
255
|
+
# For example:
|
256
|
+
#
|
257
|
+
# SNMP::Manager.open(:Host => "localhost") do |manager|
|
258
|
+
# manager.walk(["ifIndex", "ifDescr"]) do |index, descr|
|
259
|
+
# puts "#{index.value} #{descr.value}"
|
260
|
+
# end
|
261
|
+
# end
|
262
|
+
#
|
263
|
+
def walk(object_list)
|
264
|
+
raise ArgumentError, "expected a block to be given" unless block_given?
|
265
|
+
varbind_list = @mib.varbind_list(object_list, :NullValue)
|
266
|
+
start_oid = varbind_list.first.name
|
267
|
+
loop do
|
268
|
+
varbind_list = get_next(varbind_list).varbind_list
|
269
|
+
first_vb = varbind_list.first
|
270
|
+
break unless first_vb.name.subtree_of?(start_oid)
|
271
|
+
break if first_vb.value == EndOfMibView
|
272
|
+
yield varbind_list
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
##
|
277
|
+
# Set the next request-id instead of letting it be generated
|
278
|
+
# automatically. This method is useful for testing and debugging.
|
279
|
+
#
|
280
|
+
def next_request_id=(request_id)
|
281
|
+
@@request_id.force_next(request_id)
|
282
|
+
end
|
283
|
+
|
284
|
+
private
|
285
|
+
|
286
|
+
def warn(message)
|
287
|
+
trace = caller(2)
|
288
|
+
location = trace[0].sub(/:in.*/,'')
|
289
|
+
Kernel::warn "#{location}: warning: #{message}"
|
290
|
+
end
|
291
|
+
|
292
|
+
def load_modules(module_list, mib_dir)
|
293
|
+
module_list.each { |m| @mib.load_module(m, mib_dir) }
|
294
|
+
end
|
295
|
+
|
296
|
+
def try_request(request, community=@community)
|
297
|
+
@retries.times do |n|
|
298
|
+
begin
|
299
|
+
send_request(request, community)
|
300
|
+
timeout(@timeout) do
|
301
|
+
return get_response(request)
|
302
|
+
end
|
303
|
+
rescue Timeout::Error
|
304
|
+
# no action - try again
|
305
|
+
end
|
306
|
+
end
|
307
|
+
raise RequestTimeout, "host #{@config[:Host]} not responding", caller
|
308
|
+
end
|
309
|
+
|
310
|
+
def send_request(request, community)
|
311
|
+
message = Message.new(@snmp_version, community, request)
|
312
|
+
@transport.send(message.encode)
|
313
|
+
end
|
314
|
+
|
315
|
+
def get_response(request)
|
316
|
+
data = @transport.recv(@max_bytes)
|
317
|
+
message = Message.decode(data)
|
318
|
+
response = message.pdu
|
319
|
+
if (request.request_id != response.request_id)
|
320
|
+
raise "Request ID mismatch: expected #{request.request_id}, got #{pdu.request_id}", caller
|
321
|
+
end
|
322
|
+
response
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
class UDPServerTransport
|
327
|
+
def initialize(port)
|
328
|
+
@socket = UDPSocket.open
|
329
|
+
@socket.bind('localhost', port)
|
330
|
+
end
|
331
|
+
|
332
|
+
def close
|
333
|
+
@socket.close
|
334
|
+
end
|
335
|
+
|
336
|
+
def recvfrom(max_bytes)
|
337
|
+
data, host_info = @socket.recvfrom(max_bytes)
|
338
|
+
flags, host_socket, host_name, host_ip = host_info
|
339
|
+
return data, host_ip
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
##
|
344
|
+
# == SNMP Trap Listener
|
345
|
+
#
|
346
|
+
# Listens to a socket and processes received traps in a separate thread.
|
347
|
+
#
|
348
|
+
# === Example
|
349
|
+
#
|
350
|
+
# require 'snmp'
|
351
|
+
#
|
352
|
+
# m = SNMP::TrapListener.new(:Port => 1062, :Community => 'public') do |manager|
|
353
|
+
# manager.on_trap_default { |trap| p trap }
|
354
|
+
# end
|
355
|
+
# m.join
|
356
|
+
#
|
357
|
+
class TrapListener
|
358
|
+
DefaultConfig = {
|
359
|
+
:Port => 162,
|
360
|
+
:Community => 'public',
|
361
|
+
:ServerTransport => UDPServerTransport,
|
362
|
+
:MaxReceiveBytes => 8000}
|
363
|
+
|
364
|
+
NULL_HANDLER = Proc.new {}
|
365
|
+
|
366
|
+
##
|
367
|
+
# Start a trap handler thread. If a block is provided then the block
|
368
|
+
# is executed before trap handling begins. This block is typically used
|
369
|
+
# to define the trap handler blocks.
|
370
|
+
#
|
371
|
+
# The trap handler blocks execute in the context of the trap handler thread.
|
372
|
+
#
|
373
|
+
# The most specific trap handler is executed when a trap arrives. Only one
|
374
|
+
# handler is executed. The handlers are checked in the following order:
|
375
|
+
#
|
376
|
+
# 1. handler for a specific OID
|
377
|
+
# 2. handler for a specific SNMP version
|
378
|
+
# 3. default handler
|
379
|
+
#
|
380
|
+
def initialize(config={}, &block)
|
381
|
+
@config = DefaultConfig.dup.update(config)
|
382
|
+
@transport = @config[:ServerTransport].new(@config[:Port])
|
383
|
+
@max_bytes = @config[:MaxReceiveBytes]
|
384
|
+
@handler_init = block
|
385
|
+
@oid_handler = {}
|
386
|
+
@v1_handler = nil
|
387
|
+
@v2c_handler = nil
|
388
|
+
@default_handler = nil
|
389
|
+
@lock = Mutex.new
|
390
|
+
@handler_thread = Thread.new(self) { |m| process_traps(m) }
|
391
|
+
end
|
392
|
+
|
393
|
+
##
|
394
|
+
# Define the default trap handler. The default trap handler block is
|
395
|
+
# executed only if no other block is applicable. This handler should
|
396
|
+
# expect to receive both SNMPv1_Trap and SNMPv2_Trap objects.
|
397
|
+
#
|
398
|
+
def on_trap_default(&block)
|
399
|
+
raise ArgumentError, "a block must be provided" unless block
|
400
|
+
@lock.synchronize { @default_handler = block }
|
401
|
+
end
|
402
|
+
|
403
|
+
##
|
404
|
+
# Define a trap handler block for a specific trap ObjectId. This handler
|
405
|
+
# only applies to SNMPv2 traps.
|
406
|
+
#
|
407
|
+
def on_trap(object_id, &block)
|
408
|
+
raise ArgumentError, "a block must be provided" unless block
|
409
|
+
@lock.synchronize { @oid_handler[ObjectId.new(object_id)] = block }
|
410
|
+
end
|
411
|
+
|
412
|
+
##
|
413
|
+
# Define a trap handler block for all SNMPv1 traps. The trap yielded
|
414
|
+
# to the block will always be an SNMPv1_Trap.
|
415
|
+
#
|
416
|
+
def on_trap_v1(&block)
|
417
|
+
raise ArgumentError, "a block must be provided" unless block
|
418
|
+
@lock.synchronize { @v1_handler = block }
|
419
|
+
end
|
420
|
+
|
421
|
+
##
|
422
|
+
# Define a trap handler block for all SNMPv2c traps. The trap yielded
|
423
|
+
# to the block will always be an SNMPv2_Trap.
|
424
|
+
#
|
425
|
+
def on_trap_v2c(&block)
|
426
|
+
raise ArgumentError, "a block must be provided" unless block
|
427
|
+
@lock.synchronize { @v2c_handler = block }
|
428
|
+
end
|
429
|
+
|
430
|
+
##
|
431
|
+
# Joins the current thread to the trap handler thread.
|
432
|
+
#
|
433
|
+
# See also Thread#join.
|
434
|
+
#
|
435
|
+
def join
|
436
|
+
@handler_thread.join
|
437
|
+
end
|
438
|
+
|
439
|
+
##
|
440
|
+
# Stops the trap handler thread and releases the socket.
|
441
|
+
#
|
442
|
+
# See also Thread#exit.
|
443
|
+
#
|
444
|
+
def exit
|
445
|
+
@handler_thread.exit
|
446
|
+
@transport.close
|
447
|
+
end
|
448
|
+
|
449
|
+
alias kill exit
|
450
|
+
alias terminate exit
|
451
|
+
|
452
|
+
private
|
453
|
+
|
454
|
+
def process_traps(trap_listener)
|
455
|
+
@handler_init.call(trap_listener) if @handler_init
|
456
|
+
loop do
|
457
|
+
data, source_ip = @transport.recvfrom(@max_bytes)
|
458
|
+
begin
|
459
|
+
message = Message.decode(data)
|
460
|
+
if @config[:Community] == message.community
|
461
|
+
trap = message.pdu
|
462
|
+
trap.source_ip = source_ip
|
463
|
+
select_handler(trap).call(trap)
|
464
|
+
end
|
465
|
+
rescue => e
|
466
|
+
puts "Error handling trap: #{e}"
|
467
|
+
puts e.backtrace.join("\n")
|
468
|
+
puts "Received data:"
|
469
|
+
p data
|
470
|
+
end
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
def select_handler(trap)
|
475
|
+
@lock.synchronize do
|
476
|
+
if trap.kind_of?(SNMPv2_Trap)
|
477
|
+
oid = trap.trap_oid
|
478
|
+
if @oid_handler[oid]
|
479
|
+
return @oid_handler[oid]
|
480
|
+
elsif @v2c_handler
|
481
|
+
return @v2c_handler
|
482
|
+
elsif @default_handler
|
483
|
+
return @default_handler
|
484
|
+
else
|
485
|
+
return NULL_HANDLER
|
486
|
+
end
|
487
|
+
elsif trap.kind_of?(SNMPv1_Trap)
|
488
|
+
if @v1_handler
|
489
|
+
return @v1_handler
|
490
|
+
elsif @default_handler
|
491
|
+
return @default_handler
|
492
|
+
else
|
493
|
+
return NULL_HANDLER
|
494
|
+
end
|
495
|
+
else
|
496
|
+
return NULL_HANDLER
|
497
|
+
end
|
498
|
+
end
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
end
|