snmp 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (214) hide show
  1. data/README +193 -0
  2. data/Rakefile +52 -0
  3. data/data/ruby/snmp/mibs/ACCOUNTING-CONTROL-MIB.yaml +44 -0
  4. data/data/ruby/snmp/mibs/ADSL-LINE-EXT-MIB.yaml +66 -0
  5. data/data/ruby/snmp/mibs/ADSL-LINE-MIB.yaml +238 -0
  6. data/data/ruby/snmp/mibs/ADSL-TC-MIB.yaml +2 -0
  7. data/data/ruby/snmp/mibs/AGENTX-MIB.yaml +40 -0
  8. data/data/ruby/snmp/mibs/APM-MIB.yaml +98 -0
  9. data/data/ruby/snmp/mibs/APPC-MIB.yaml +295 -0
  10. data/data/ruby/snmp/mibs/APPLETALK-MIB.yaml +284 -0
  11. data/data/ruby/snmp/mibs/APPLICATION-MIB.yaml +161 -0
  12. data/data/ruby/snmp/mibs/APPN-DLUR-MIB.yaml +41 -0
  13. data/data/ruby/snmp/mibs/APPN-MIB.yaml +356 -0
  14. data/data/ruby/snmp/mibs/APPN-TRAP-MIB.yaml +8 -0
  15. data/data/ruby/snmp/mibs/APS-MIB.yaml +62 -0
  16. data/data/ruby/snmp/mibs/ATM-ACCOUNTING-INFORMATION-MIB.yaml +37 -0
  17. data/data/ruby/snmp/mibs/ATM-MIB.yaml +112 -0
  18. data/data/ruby/snmp/mibs/ATM-TC-MIB.yaml +19 -0
  19. data/data/ruby/snmp/mibs/ATM2-MIB.yaml +182 -0
  20. data/data/ruby/snmp/mibs/BGP4-MIB.yaml +56 -0
  21. data/data/ruby/snmp/mibs/BLDG-HVAC-MIB.yaml +35 -0
  22. data/data/ruby/snmp/mibs/BRIDGE-MIB.yaml +63 -0
  23. data/data/ruby/snmp/mibs/CHARACTER-MIB.yaml +48 -0
  24. data/data/ruby/snmp/mibs/CIRCUIT-IF-MIB.yaml +21 -0
  25. data/data/ruby/snmp/mibs/CLNS-MIB.yaml +116 -0
  26. data/data/ruby/snmp/mibs/COFFEE-POT-MIB.yaml +13 -0
  27. data/data/ruby/snmp/mibs/COPS-CLIENT-MIB.yaml +54 -0
  28. data/data/ruby/snmp/mibs/DECNET-PHIV-MIB.yaml +237 -0
  29. data/data/ruby/snmp/mibs/DIAL-CONTROL-MIB.yaml +84 -0
  30. data/data/ruby/snmp/mibs/DIFFSERV-CONFIG-MIB.yaml +15 -0
  31. data/data/ruby/snmp/mibs/DIFFSERV-DSCP-TC.yaml +2 -0
  32. data/data/ruby/snmp/mibs/DIFFSERV-MIB.yaml +171 -0
  33. data/data/ruby/snmp/mibs/DIRECTORY-SERVER-MIB.yaml +52 -0
  34. data/data/ruby/snmp/mibs/DISMAN-EVENT-MIB.yaml +110 -0
  35. data/data/ruby/snmp/mibs/DISMAN-EXPRESSION-MIB.yaml +55 -0
  36. data/data/ruby/snmp/mibs/DISMAN-NSLOOKUP-MIB.yaml +23 -0
  37. data/data/ruby/snmp/mibs/DISMAN-PING-MIB.yaml +57 -0
  38. data/data/ruby/snmp/mibs/DISMAN-SCHEDULE-MIB.yaml +32 -0
  39. data/data/ruby/snmp/mibs/DISMAN-SCRIPT-MIB.yaml +80 -0
  40. data/data/ruby/snmp/mibs/DISMAN-TRACEROUTE-MIB.yaml +72 -0
  41. data/data/ruby/snmp/mibs/DLSW-MIB.yaml +193 -0
  42. data/data/ruby/snmp/mibs/DNS-RESOLVER-MIB.yaml +87 -0
  43. data/data/ruby/snmp/mibs/DNS-SERVER-MIB.yaml +73 -0
  44. data/data/ruby/snmp/mibs/DOCS-BPI-MIB.yaml +101 -0
  45. data/data/ruby/snmp/mibs/DOCS-CABLE-DEVICE-MIB.yaml +107 -0
  46. data/data/ruby/snmp/mibs/DOCS-IF-MIB.yaml +143 -0
  47. data/data/ruby/snmp/mibs/DOT12-IF-MIB.yaml +33 -0
  48. data/data/ruby/snmp/mibs/DS0-MIB.yaml +18 -0
  49. data/data/ruby/snmp/mibs/DS0BUNDLE-MIB.yaml +17 -0
  50. data/data/ruby/snmp/mibs/DS1-MIB.yaml +118 -0
  51. data/data/ruby/snmp/mibs/DS3-MIB.yaml +106 -0
  52. data/data/ruby/snmp/mibs/DSA-MIB.yaml +44 -0
  53. data/data/ruby/snmp/mibs/DSMON-MIB.yaml +219 -0
  54. data/data/ruby/snmp/mibs/EBN-MIB.yaml +47 -0
  55. data/data/ruby/snmp/mibs/ENTITY-MIB.yaml +51 -0
  56. data/data/ruby/snmp/mibs/ENTITY-SENSOR-MIB.yaml +16 -0
  57. data/data/ruby/snmp/mibs/ETHER-CHIPSET-MIB.yaml +79 -0
  58. data/data/ruby/snmp/mibs/ETHER-WIS.yaml +28 -0
  59. data/data/ruby/snmp/mibs/EtherLike-MIB.yaml +58 -0
  60. data/data/ruby/snmp/mibs/FDDI-SMT73-MIB.yaml +128 -0
  61. data/data/ruby/snmp/mibs/FIBRE-CHANNEL-FE-MIB.yaml +122 -0
  62. data/data/ruby/snmp/mibs/FLOW-METER-MIB.yaml +112 -0
  63. data/data/ruby/snmp/mibs/FR-ATM-PVC-SERVICE-IWF-MIB.yaml +45 -0
  64. data/data/ruby/snmp/mibs/FR-MFR-MIB.yaml +52 -0
  65. data/data/ruby/snmp/mibs/FRAME-RELAY-DTE-MIB.yaml +54 -0
  66. data/data/ruby/snmp/mibs/FRNETSERV-MIB.yaml +109 -0
  67. data/data/ruby/snmp/mibs/FRSLD-MIB.yaml +82 -0
  68. data/data/ruby/snmp/mibs/Finisher-MIB.yaml +53 -0
  69. data/data/ruby/snmp/mibs/GSMP-MIB.yaml +82 -0
  70. data/data/ruby/snmp/mibs/HC-ALARM-MIB.yaml +32 -0
  71. data/data/ruby/snmp/mibs/HC-PerfHist-TC-MIB.yaml +2 -0
  72. data/data/ruby/snmp/mibs/HC-RMON-MIB.yaml +193 -0
  73. data/data/ruby/snmp/mibs/HCNUM-TC.yaml +2 -0
  74. data/data/ruby/snmp/mibs/HDSL2-SHDSL-LINE-MIB.yaml +115 -0
  75. data/data/ruby/snmp/mibs/HOST-RESOURCES-MIB.yaml +98 -0
  76. data/data/ruby/snmp/mibs/HOST-RESOURCES-TYPES.yaml +56 -0
  77. data/data/ruby/snmp/mibs/HPR-IP-MIB.yaml +24 -0
  78. data/data/ruby/snmp/mibs/HPR-MIB.yaml +81 -0
  79. data/data/ruby/snmp/mibs/IF-INVERTED-STACK-MIB.yaml +9 -0
  80. data/data/ruby/snmp/mibs/IF-MIB.yaml +73 -0
  81. data/data/ruby/snmp/mibs/IGMP-STD-MIB.yaml +33 -0
  82. data/data/ruby/snmp/mibs/INET-ADDRESS-MIB.yaml +2 -0
  83. data/data/ruby/snmp/mibs/INTEGRATED-SERVICES-GUARANTEED-MIB.yaml +13 -0
  84. data/data/ruby/snmp/mibs/INTEGRATED-SERVICES-MIB.yaml +44 -0
  85. data/data/ruby/snmp/mibs/INTERFACETOPN-MIB.yaml +29 -0
  86. data/data/ruby/snmp/mibs/IP-FORWARD-MIB.yaml +42 -0
  87. data/data/ruby/snmp/mibs/IP-MIB.yaml +66 -0
  88. data/data/ruby/snmp/mibs/IPATM-IPMC-MIB.yaml +203 -0
  89. data/data/ruby/snmp/mibs/IPMROUTE-STD-MIB.yaml +64 -0
  90. data/data/ruby/snmp/mibs/IPOA-MIB.yaml +85 -0
  91. data/data/ruby/snmp/mibs/IPV6-FLOW-LABEL-MIB.yaml +2 -0
  92. data/data/ruby/snmp/mibs/IPV6-ICMP-MIB.yaml +42 -0
  93. data/data/ruby/snmp/mibs/IPV6-MIB.yaml +88 -0
  94. data/data/ruby/snmp/mibs/IPV6-MLD-MIB.yaml +30 -0
  95. data/data/ruby/snmp/mibs/IPV6-TCP-MIB.yaml +14 -0
  96. data/data/ruby/snmp/mibs/IPV6-UDP-MIB.yaml +11 -0
  97. data/data/ruby/snmp/mibs/ISDN-MIB.yaml +71 -0
  98. data/data/ruby/snmp/mibs/Job-Monitoring-MIB.yaml +43 -0
  99. data/data/ruby/snmp/mibs/L2TP-MIB.yaml +156 -0
  100. data/data/ruby/snmp/mibs/MALLOC-MIB.yaml +83 -0
  101. data/data/ruby/snmp/mibs/MAU-MIB.yaml +110 -0
  102. data/data/ruby/snmp/mibs/MIOX25-MIB.yaml +38 -0
  103. data/data/ruby/snmp/mibs/MIP-MIB.yaml +180 -0
  104. data/data/ruby/snmp/mibs/MPLS-FTN-STD-MIB.yaml +44 -0
  105. data/data/ruby/snmp/mibs/MPLS-LDP-ATM-STD-MIB.yaml +35 -0
  106. data/data/ruby/snmp/mibs/MPLS-LDP-FRAME-RELAY-STD-MIB.yaml +28 -0
  107. data/data/ruby/snmp/mibs/MPLS-LDP-GENERIC-STD-MIB.yaml +15 -0
  108. data/data/ruby/snmp/mibs/MPLS-LDP-STD-MIB.yaml +118 -0
  109. data/data/ruby/snmp/mibs/MPLS-LSR-STD-MIB.yaml +98 -0
  110. data/data/ruby/snmp/mibs/MPLS-TC-STD-MIB.yaml +3 -0
  111. data/data/ruby/snmp/mibs/MPLS-TE-STD-MIB.yaml +120 -0
  112. data/data/ruby/snmp/mibs/MTA-MIB.yaml +64 -0
  113. data/data/ruby/snmp/mibs/Modem-MIB.yaml +106 -0
  114. data/data/ruby/snmp/mibs/NETWORK-SERVICES-MIB.yaml +33 -0
  115. data/data/ruby/snmp/mibs/NHRP-MIB.yaml +163 -0
  116. data/data/ruby/snmp/mibs/NOTIFICATION-LOG-MIB.yaml +51 -0
  117. data/data/ruby/snmp/mibs/OPT-IF-MIB.yaml +431 -0
  118. data/data/ruby/snmp/mibs/OSPF-MIB.yaml +150 -0
  119. data/data/ruby/snmp/mibs/OSPF-TRAP-MIB.yaml +11 -0
  120. data/data/ruby/snmp/mibs/P-BRIDGE-MIB.yaml +51 -0
  121. data/data/ruby/snmp/mibs/PARALLEL-MIB.yaml +24 -0
  122. data/data/ruby/snmp/mibs/PIM-MIB.yaml +66 -0
  123. data/data/ruby/snmp/mibs/PINT-MIB.yaml +51 -0
  124. data/data/ruby/snmp/mibs/POWER-ETHERNET-MIB.yaml +36 -0
  125. data/data/ruby/snmp/mibs/PPP-BRIDGE-NCP-MIB.yaml +25 -0
  126. data/data/ruby/snmp/mibs/PPP-IP-NCP-MIB.yaml +13 -0
  127. data/data/ruby/snmp/mibs/PPP-LCP-MIB.yaml +47 -0
  128. data/data/ruby/snmp/mibs/PPP-SEC-MIB.yaml +20 -0
  129. data/data/ruby/snmp/mibs/PTOPO-MIB.yaml +39 -0
  130. data/data/ruby/snmp/mibs/PerfHist-TC-MIB.yaml +2 -0
  131. data/data/ruby/snmp/mibs/Printer-MIB.yaml +209 -0
  132. data/data/ruby/snmp/mibs/Q-BRIDGE-MIB.yaml +99 -0
  133. data/data/ruby/snmp/mibs/RADIUS-ACC-CLIENT-MIB.yaml +26 -0
  134. data/data/ruby/snmp/mibs/RADIUS-ACC-SERVER-MIB.yaml +35 -0
  135. data/data/ruby/snmp/mibs/RADIUS-AUTH-CLIENT-MIB.yaml +28 -0
  136. data/data/ruby/snmp/mibs/RADIUS-AUTH-SERVER-MIB.yaml +37 -0
  137. data/data/ruby/snmp/mibs/RDBMS-MIB.yaml +82 -0
  138. data/data/ruby/snmp/mibs/RFC1065-SMI.yaml +9 -0
  139. data/data/ruby/snmp/mibs/RFC1155-SMI.yaml +9 -0
  140. data/data/ruby/snmp/mibs/RFC1158-MIB.yaml +202 -0
  141. data/data/ruby/snmp/mibs/RFC1213-MIB.yaml +202 -0
  142. data/data/ruby/snmp/mibs/RFC1269-MIB.yaml +29 -0
  143. data/data/ruby/snmp/mibs/RFC1271-MIB.yaml +214 -0
  144. data/data/ruby/snmp/mibs/RFC1285-MIB.yaml +104 -0
  145. data/data/ruby/snmp/mibs/RFC1316-MIB.yaml +42 -0
  146. data/data/ruby/snmp/mibs/RFC1381-MIB.yaml +60 -0
  147. data/data/ruby/snmp/mibs/RFC1382-MIB.yaml +169 -0
  148. data/data/ruby/snmp/mibs/RFC1414-MIB.yaml +10 -0
  149. data/data/ruby/snmp/mibs/RIPv2-MIB.yaml +34 -0
  150. data/data/ruby/snmp/mibs/RMON-MIB.yaml +219 -0
  151. data/data/ruby/snmp/mibs/RMON2-MIB.yaml +282 -0
  152. data/data/ruby/snmp/mibs/ROHC-MIB.yaml +64 -0
  153. data/data/ruby/snmp/mibs/ROHC-RTP-MIB.yaml +29 -0
  154. data/data/ruby/snmp/mibs/ROHC-UNCOMPRESSED-MIB.yaml +11 -0
  155. data/data/ruby/snmp/mibs/RS-232-MIB.yaml +54 -0
  156. data/data/ruby/snmp/mibs/RSVP-MIB.yaml +156 -0
  157. data/data/ruby/snmp/mibs/RTP-MIB.yaml +57 -0
  158. data/data/ruby/snmp/mibs/SFLOW-MIB.yaml +22 -0
  159. data/data/ruby/snmp/mibs/SIP-MIB.yaml +70 -0
  160. data/data/ruby/snmp/mibs/SLAPM-MIB.yaml +144 -0
  161. data/data/ruby/snmp/mibs/SMON-MIB.yaml +63 -0
  162. data/data/ruby/snmp/mibs/SNA-NAU-MIB.yaml +137 -0
  163. data/data/ruby/snmp/mibs/SNA-SDLC-MIB.yaml +147 -0
  164. data/data/ruby/snmp/mibs/SNMP-COMMUNITY-MIB.yaml +22 -0
  165. data/data/ruby/snmp/mibs/SNMP-FRAMEWORK-MIB.yaml +14 -0
  166. data/data/ruby/snmp/mibs/SNMP-MPD-MIB.yaml +11 -0
  167. data/data/ruby/snmp/mibs/SNMP-NOTIFICATION-MIB.yaml +25 -0
  168. data/data/ruby/snmp/mibs/SNMP-PROXY-MIB.yaml +17 -0
  169. data/data/ruby/snmp/mibs/SNMP-REPEATER-MIB.yaml +135 -0
  170. data/data/ruby/snmp/mibs/SNMP-TARGET-MIB.yaml +29 -0
  171. data/data/ruby/snmp/mibs/SNMP-USER-BASED-SM-MIB.yaml +35 -0
  172. data/data/ruby/snmp/mibs/SNMP-USM-DH-OBJECTS-MIB.yaml +21 -0
  173. data/data/ruby/snmp/mibs/SNMP-VIEW-BASED-ACM-MIB.yaml +37 -0
  174. data/data/ruby/snmp/mibs/SNMPv2-MIB.yaml +58 -0
  175. data/data/ruby/snmp/mibs/SNMPv2-SMI.yaml +17 -0
  176. data/data/ruby/snmp/mibs/SNMPv2-TM.yaml +9 -0
  177. data/data/ruby/snmp/mibs/SNMPv2-USEC-MIB.yaml +19 -0
  178. data/data/ruby/snmp/mibs/SONET-MIB.yaml +131 -0
  179. data/data/ruby/snmp/mibs/SOURCE-ROUTING-MIB.yaml +30 -0
  180. data/data/ruby/snmp/mibs/SYSAPPL-MIB.yaml +81 -0
  181. data/data/ruby/snmp/mibs/TCP-MIB.yaml +27 -0
  182. data/data/ruby/snmp/mibs/TCPIPX-MIB.yaml +24 -0
  183. data/data/ruby/snmp/mibs/TN3270E-MIB.yaml +105 -0
  184. data/data/ruby/snmp/mibs/TN3270E-RT-MIB.yaml +43 -0
  185. data/data/ruby/snmp/mibs/TOKEN-RING-RMON-MIB.yaml +183 -0
  186. data/data/ruby/snmp/mibs/TOKENRING-MIB.yaml +58 -0
  187. data/data/ruby/snmp/mibs/TOKENRING-STATION-SR-MIB.yaml +12 -0
  188. data/data/ruby/snmp/mibs/TRANSPORT-ADDRESS-MIB.yaml +19 -0
  189. data/data/ruby/snmp/mibs/TUNNEL-MIB.yaml +23 -0
  190. data/data/ruby/snmp/mibs/UDP-MIB.yaml +14 -0
  191. data/data/ruby/snmp/mibs/UPS-MIB.yaml +117 -0
  192. data/data/ruby/snmp/mibs/VDSL-LINE-MIB.yaml +173 -0
  193. data/data/ruby/snmp/mibs/VRRP-MIB.yaml +50 -0
  194. data/data/ruby/snmp/mibs/WWW-MIB.yaml +91 -0
  195. data/examples/dump.rb +15 -0
  196. data/examples/get.rb +7 -0
  197. data/examples/iftable.rb +14 -0
  198. data/examples/log_traps.rb +23 -0
  199. data/examples/set.rb +8 -0
  200. data/examples/walk.rb +9 -0
  201. data/lib/snmp.rb +10 -0
  202. data/lib/snmp/agent.rb +74 -0
  203. data/lib/snmp/ber.rb +332 -0
  204. data/lib/snmp/manager.rb +502 -0
  205. data/lib/snmp/mib.rb +259 -0
  206. data/lib/snmp/pdu.rb +363 -0
  207. data/lib/snmp/varbind.rb +520 -0
  208. data/setup.rb +1360 -0
  209. data/test/test_ber.rb +236 -0
  210. data/test/test_manager.rb +192 -0
  211. data/test/test_mib.rb +66 -0
  212. data/test/test_pdu.rb +184 -0
  213. data/test/test_varbind.rb +270 -0
  214. metadata +251 -0
@@ -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