snmp 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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