net-snmp 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +10 -7
- data/lib/net-snmp.rb +1 -1
- data/lib/net/snmp.rb +0 -27
- data/lib/net/snmp/dispatcher.rb +68 -42
- data/lib/net/snmp/oid.rb +2 -2
- data/lib/net/snmp/session.rb +126 -47
- data/lib/net/snmp/utility.rb +10 -0
- data/lib/net/snmp/varbind.rb +1 -1
- data/lib/net/snmp/version.rb +1 -1
- data/lib/net/snmp/wrapper.rb +11 -4
- data/net-snmp.gemspec +2 -2
- data/spec/async_spec.rb +12 -8
- data/spec/em_spec.rb +1 -1
- data/spec/fiber_spec.rb +3 -0
- data/spec/net-snmp_spec.rb +1 -39
- data/spec/oid_spec.rb +15 -0
- data/spec/sync_spec.rb +17 -7
- data/spec/thread_spec.rb +24 -0
- data/spec/utility_spec.rb +10 -0
- metadata +10 -3
data/README.rdoc
CHANGED
@@ -42,10 +42,7 @@ functions are defined in Net::SNMP::Wrapper. You can call them like so:
|
|
42
42
|
Net::SNMP::Wrapper.snmp_perror("some_error")
|
43
43
|
|
44
44
|
== NOTES
|
45
|
-
|
46
|
-
It's not necessary in async calls because the library automatically frees the pdu after the callback fires.
|
47
|
-
This is where destructors would be handy.
|
48
|
-
|
45
|
+
You must call Session.close when you're done with a session to avoid leaking memory
|
49
46
|
|
50
47
|
== EXAMPLES
|
51
48
|
|
@@ -55,24 +52,29 @@ A simple synchronous SNMP-GET
|
|
55
52
|
session = Net::SNMP::Session.open(:peername => "test.net-snmp.org", :community => "demopublic" )
|
56
53
|
result = session.get("sysDescr.0")
|
57
54
|
puts result.varbinds.first.value
|
58
|
-
|
55
|
+
session.close
|
59
56
|
|
60
57
|
An asynchronous SNMP-GET
|
61
|
-
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |session|
|
58
|
+
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |session|
|
62
59
|
session.get(["sysDescr.0", "sysContact.0"]) do |result|
|
63
60
|
puts result.varbinds[0].value
|
64
61
|
end
|
65
62
|
end
|
66
63
|
Net::SNMP::Dispatcher.poll(false) #Setting timeout to false causes dispatcher to block until data is ready
|
64
|
+
session.close
|
67
65
|
|
68
66
|
Running the dispatcher from eventmachine
|
69
67
|
EM.run do
|
70
68
|
Net::SNMP::Dispatcher.em_loop
|
71
|
-
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |session|
|
69
|
+
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |session|
|
72
70
|
session.get("sysDescr.0") do |result|
|
73
71
|
puts result.varbinds[0].value
|
74
72
|
end
|
75
73
|
end
|
74
|
+
EM.add_timer(2) do
|
75
|
+
session.close
|
76
|
+
EM.stop
|
77
|
+
end
|
76
78
|
end
|
77
79
|
|
78
80
|
Using synchronous style with eventmachine in ruby 1.9
|
@@ -82,6 +84,7 @@ Using synchronous style with eventmachine in ruby 1.9
|
|
82
84
|
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic')
|
83
85
|
result = session.get("sysDescr.0")
|
84
86
|
puts result.varbinds[0].value
|
87
|
+
session.close
|
85
88
|
EM.stop
|
86
89
|
}.resume
|
87
90
|
end
|
data/lib/net-snmp.rb
CHANGED
@@ -2,7 +2,7 @@ require 'forwardable'
|
|
2
2
|
require 'nice-ffi'
|
3
3
|
require 'fiber'
|
4
4
|
|
5
|
-
%w(snmp snmp/version snmp/constants snmp/oid snmp/error snmp/pdu snmp/wrapper snmp/session snmp/varbind snmp/mib snmp/mib/node snmp/dispatcher).each do |f|
|
5
|
+
%w(snmp snmp/version snmp/constants snmp/utility snmp/oid snmp/error snmp/pdu snmp/wrapper snmp/session snmp/varbind snmp/mib snmp/mib/node snmp/dispatcher).each do |f|
|
6
6
|
require "#{File.dirname(__FILE__)}/net/#{f}"
|
7
7
|
end
|
8
8
|
Net::SNMP::MIB.init
|
data/lib/net/snmp.rb
CHANGED
@@ -11,33 +11,6 @@ module Net
|
|
11
11
|
|
12
12
|
|
13
13
|
|
14
|
-
# Some utility methods
|
15
|
-
|
16
|
-
def self._get_oid(name)
|
17
|
-
oid_ptr = FFI::MemoryPointer.new(:ulong, Constants::MAX_OID_LEN)
|
18
|
-
oid_len_ptr = FFI::MemoryPointer.new(:size_t)
|
19
|
-
oid_len_ptr.write_int(Constants::MAX_OID_LEN)
|
20
|
-
|
21
|
-
if !Wrapper.snmp_parse_oid(name, oid_ptr, oid_len_ptr)
|
22
|
-
Wrapper.snmp_perror(name)
|
23
|
-
end
|
24
|
-
[oid_ptr, oid_len_ptr]
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.get_oid(name)
|
28
|
-
oid_ptr, oid_len_ptr = _get_oid(name)
|
29
|
-
oid_ptr.read_array_of_long(oid_len_ptr.read_int).join(".")
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.oid_lex_cmp(a,b)
|
33
|
-
[a,b].each do |i|
|
34
|
-
i.sub!(/^\./,'')
|
35
|
-
i.gsub!(/ /, '.0')
|
36
|
-
i.replace(i.split('.').map(&:to_i).pack('N*'))
|
37
|
-
end
|
38
|
-
a <=> b
|
39
|
-
end
|
40
|
-
|
41
14
|
|
42
15
|
end
|
43
16
|
end
|
data/lib/net/snmp/dispatcher.rb
CHANGED
@@ -2,48 +2,70 @@ class Net::SNMP::Dispatcher
|
|
2
2
|
class << self
|
3
3
|
|
4
4
|
# timeout = nil no block(poll), timeout = false block forever, timeout = int, block int seconds
|
5
|
-
def poll(timeout = nil)
|
6
|
-
fdset = Net::SNMP::Wrapper.get_fd_set
|
7
|
-
num_fds = FFI::MemoryPointer.new(:int)
|
8
|
-
tv_sec = timeout ? timeout.round : 0
|
9
|
-
tv_usec = timeout ? (timeout - timeout.round) * 1000000 : 0
|
10
|
-
tval = Net::SNMP::Wrapper::TimeVal.new(:tv_sec => tv_sec, :tv_usec => tv_usec)
|
11
|
-
block = FFI::MemoryPointer.new(:int)
|
5
|
+
# def poll(timeout = nil)
|
6
|
+
# fdset = Net::SNMP::Wrapper.get_fd_set
|
7
|
+
# num_fds = FFI::MemoryPointer.new(:int)
|
8
|
+
# tv_sec = timeout ? timeout.round : 0
|
9
|
+
# tv_usec = timeout ? (timeout - timeout.round) * 1000000 : 0
|
10
|
+
# tval = Net::SNMP::Wrapper::TimeVal.new(:tv_sec => tv_sec, :tv_usec => tv_usec)
|
11
|
+
# block = FFI::MemoryPointer.new(:int)
|
12
|
+
#
|
13
|
+
# if timeout.nil?
|
14
|
+
# block.write_int(0)
|
15
|
+
# else
|
16
|
+
# block.write_int(1)
|
17
|
+
# end
|
18
|
+
# #puts "calling snmp_select_info"
|
19
|
+
# Net::SNMP::Wrapper.snmp_select_info(num_fds, fdset, tval.pointer, block )
|
20
|
+
# #puts "done snmp_select_info."
|
21
|
+
# num_ready = 0
|
22
|
+
# #puts "block = #{block.read_int}"
|
23
|
+
#
|
24
|
+
# #puts "numready = #{num_fds.read_int}"
|
25
|
+
# #puts "tv = #{tval[:tv_sec]} #{tval[:tv_usec]}"
|
26
|
+
# #puts "timeout = #{timeout}"
|
27
|
+
# tv = (timeout == false ? nil : tval)
|
28
|
+
# #puts "calling select"
|
29
|
+
# #puts "tv = #{tv.inspect}"
|
30
|
+
# #puts "calling select with #{num_fds.read_int}"
|
31
|
+
# #num_ready = RubyWrapper.rb_thread_select(num_fds.read_int, fdset, nil, nil, tv)
|
32
|
+
# num_ready = Net::SNMP::Wrapper.select(num_fds.read_int, fdset, nil, nil, tv)
|
33
|
+
# #puts "done select. num_ready = #{num_ready}"
|
34
|
+
# if num_ready > 0
|
35
|
+
# Net::SNMP::Wrapper.snmp_read(fdset)
|
36
|
+
# elsif num_ready == 0
|
37
|
+
# # timeout. do something here? or just return 0?
|
38
|
+
# elsif num_ready == -1
|
39
|
+
# # error. check snmp_error?
|
40
|
+
# else
|
41
|
+
# # uhhh
|
42
|
+
# end
|
43
|
+
# #puts "done snmp_read"
|
44
|
+
# num_ready
|
45
|
+
# end
|
12
46
|
|
13
|
-
if timeout.nil?
|
14
|
-
block.write_int(0)
|
15
|
-
else
|
16
|
-
block.write_int(1)
|
17
|
-
end
|
18
|
-
#puts "calling snmp_select_info"
|
19
|
-
Net::SNMP::Wrapper.snmp_select_info(num_fds, fdset, tval.pointer, block )
|
20
|
-
#puts "done snmp_select_info."
|
21
|
-
num_ready = 0
|
22
|
-
#puts "block = #{block.read_int}"
|
23
47
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
else
|
40
|
-
# uhhh
|
48
|
+
def poll(timeout = nil)
|
49
|
+
puts "Dispatcher.poll #{Net::SNMP::Session.sessions.size}"
|
50
|
+
total = 0
|
51
|
+
t = timeout
|
52
|
+
t = nil if t == false
|
53
|
+
catch :got_data do
|
54
|
+
loop do
|
55
|
+
Net::SNMP::Session.lock.synchronize {
|
56
|
+
Net::SNMP::Session.sessions.each do |k, sess|
|
57
|
+
puts "polling session"
|
58
|
+
total += sess.poll(t)
|
59
|
+
end
|
60
|
+
}
|
61
|
+
throw :got_data if total > 0
|
62
|
+
throw :got_data unless timeout == false
|
41
63
|
end
|
42
|
-
|
43
|
-
|
64
|
+
end
|
65
|
+
puts "Done Dispatcher.poll"
|
66
|
+
total
|
44
67
|
end
|
45
68
|
|
46
|
-
|
47
69
|
def run_loop(options = {})
|
48
70
|
if defined?(EM) && EM.reactor_running?
|
49
71
|
fiber_loop(options)
|
@@ -55,12 +77,16 @@ class Net::SNMP::Dispatcher
|
|
55
77
|
# You should not pass nil to this as it will peg your cpu
|
56
78
|
def thread_loop(options = {})
|
57
79
|
|
58
|
-
timeout = options[:timeout] ||
|
59
|
-
sleep_time = options[:sleep]
|
80
|
+
timeout = options[:timeout] || 0.1
|
81
|
+
sleep_time = options[:sleep] || 0.1
|
60
82
|
Thread.new do
|
61
83
|
loop do
|
62
|
-
|
63
|
-
|
84
|
+
puts "polling"
|
85
|
+
num_ready = poll(timeout)
|
86
|
+
puts "num_ready = #{num_ready}"
|
87
|
+
if num_ready == 0
|
88
|
+
sleep(sleep_time) if sleep_time
|
89
|
+
end
|
64
90
|
end
|
65
91
|
end
|
66
92
|
end
|
@@ -85,7 +111,7 @@ class Net::SNMP::Dispatcher
|
|
85
111
|
|
86
112
|
def fiber_loop(options = {})
|
87
113
|
timeout = options[:timeout]
|
88
|
-
sleep_time = options[:sleep] || 0.
|
114
|
+
sleep_time = options[:sleep] || 0.1
|
89
115
|
Fiber.new {
|
90
116
|
loop do
|
91
117
|
num_handled = poll(timeout)
|
data/lib/net/snmp/oid.rb
CHANGED
@@ -16,7 +16,7 @@ module Net
|
|
16
16
|
if Wrapper.get_node(@oid, @pointer, @length_pointer) == 0
|
17
17
|
Wrapper.snmp_perror(@oid)
|
18
18
|
end
|
19
|
-
@oid =
|
19
|
+
@oid = to_s
|
20
20
|
end
|
21
21
|
|
22
22
|
end
|
@@ -32,7 +32,7 @@ module Net
|
|
32
32
|
@oid
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
35
|
+
def to_s
|
36
36
|
@pointer.read_array_of_long(length_pointer.read_int).join(".")
|
37
37
|
end
|
38
38
|
|
data/lib/net/snmp/session.rb
CHANGED
@@ -1,29 +1,42 @@
|
|
1
|
+
require 'thread'
|
1
2
|
require 'forwardable'
|
2
3
|
require 'pp'
|
3
4
|
module Net
|
4
5
|
module SNMP
|
5
6
|
class Session
|
6
7
|
extend Forwardable
|
7
|
-
attr_accessor :struct, :callback
|
8
|
+
attr_accessor :struct, :callback, :requests, :peername, :community
|
8
9
|
attr_reader :version
|
9
10
|
def_delegator :@struct, :pointer
|
10
11
|
#@sessions = []
|
11
|
-
@
|
12
|
+
@lock = Mutex.new
|
13
|
+
@sessions = {}
|
14
|
+
|
12
15
|
class << self
|
13
|
-
attr_accessor :
|
16
|
+
attr_accessor :sessions, :lock
|
14
17
|
def open(options = {})
|
18
|
+
puts "building session"
|
15
19
|
session = new(options)
|
20
|
+
@lock.synchronize {
|
21
|
+
@sessions[session.sessid] = session
|
22
|
+
}
|
23
|
+
puts "done building"
|
16
24
|
if block_given?
|
25
|
+
puts "calling block"
|
17
26
|
yield session
|
27
|
+
|
18
28
|
end
|
19
29
|
session
|
20
30
|
end
|
21
31
|
end
|
22
32
|
|
23
33
|
def initialize(options = {})
|
24
|
-
|
25
|
-
|
26
|
-
|
34
|
+
puts "in initialize"
|
35
|
+
@requests = {}
|
36
|
+
@peername = options[:peername] || 'localhost'
|
37
|
+
@community = options[:community] || "public"
|
38
|
+
options[:community_len] = @community.length
|
39
|
+
@version = options[:version] || 1
|
27
40
|
options[:version] ||= Constants::SNMP_VERSION_1
|
28
41
|
@callback = options[:callback]
|
29
42
|
@version = options[:version] || 1
|
@@ -31,9 +44,9 @@ module Net
|
|
31
44
|
@sess = Wrapper::SnmpSession.new(nil)
|
32
45
|
Wrapper.snmp_sess_init(@sess.pointer)
|
33
46
|
#options.each_pair {|k,v| ptr.send("#{k}=", v)}
|
34
|
-
@sess.community = FFI::MemoryPointer.from_string(
|
35
|
-
@sess.community_len =
|
36
|
-
@sess.peername = FFI::MemoryPointer.from_string(
|
47
|
+
@sess.community = FFI::MemoryPointer.from_string(@community)
|
48
|
+
@sess.community_len = @community.length
|
49
|
+
@sess.peername = FFI::MemoryPointer.from_string(@peername)
|
37
50
|
@sess.version = case options[:version].to_s
|
38
51
|
when '1'
|
39
52
|
Constants::SNMP_VERSION_1
|
@@ -51,7 +64,7 @@ module Net
|
|
51
64
|
if options[:retries]
|
52
65
|
@sess.retries = options[:retries]
|
53
66
|
end
|
54
|
-
|
67
|
+
puts "1"
|
55
68
|
if @sess.version == Constants::SNMP_VERSION_3
|
56
69
|
@sess.securityLevel = options[:security_level] || Constants::SNMP_SEC_LEVEL_NOAUTH
|
57
70
|
|
@@ -84,27 +97,35 @@ module Net
|
|
84
97
|
Wrapper.snmp_perror("netsnmp")
|
85
98
|
end
|
86
99
|
end
|
87
|
-
|
100
|
+
puts "2"
|
88
101
|
# General callback just takes the pdu, calls the session callback if any, then the request specific callback.
|
89
102
|
@sess.callback = lambda do |operation, session, reqid, pdu_ptr, magic|
|
90
|
-
callback
|
103
|
+
#puts "callback is #{callback.inspect}"
|
104
|
+
#callback.call(operation, reqid, pdu, magic) if callback
|
91
105
|
|
92
106
|
puts "in main callback"
|
93
|
-
if
|
107
|
+
if @requests[reqid]
|
94
108
|
puts "got request"
|
95
109
|
pdu = Net::SNMP::PDU.new(pdu_ptr)
|
96
|
-
|
97
|
-
|
110
|
+
@requests[reqid].call(pdu)
|
111
|
+
@requests.delete(reqid)
|
98
112
|
end
|
99
113
|
0
|
100
114
|
end
|
101
|
-
|
102
|
-
@struct = Wrapper.
|
115
|
+
puts "3"
|
116
|
+
@struct = Wrapper.snmp_sess_open(@sess.pointer)
|
117
|
+
puts "4"
|
103
118
|
#@handle = Wrapper.snmp_sess_open(@sess.pointer)
|
104
119
|
#@struct = Wrapper.snmp_sess_session(@handle)
|
105
120
|
end
|
106
121
|
|
107
122
|
|
123
|
+
def close
|
124
|
+
Net::SNMP::Session.lock.synchronize {
|
125
|
+
Wrapper.snmp_sess_close(@struct)
|
126
|
+
Net::SNMP::Session.sessions.delete(self.sessid)
|
127
|
+
}
|
128
|
+
end
|
108
129
|
|
109
130
|
def get(oidlist, options = {}, &block)
|
110
131
|
pdu = Net::SNMP::PDU.new(Constants::SNMP_MSG_GET)
|
@@ -146,6 +167,14 @@ module Net
|
|
146
167
|
send_pdu(pdu, &block)
|
147
168
|
end
|
148
169
|
|
170
|
+
def method_missing(m, *args)
|
171
|
+
if @struct.respond_to?(m)
|
172
|
+
@struct.send(m, *args)
|
173
|
+
else
|
174
|
+
super
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
149
178
|
|
150
179
|
# XXX This needs work. Need to use getbulk for speed, guess maxrepeaters, etc..
|
151
180
|
# Also need to figure out how we can tell column names from something like ifTable
|
@@ -157,6 +186,7 @@ module Net
|
|
157
186
|
results = []
|
158
187
|
|
159
188
|
first_result = get_next(column_names)
|
189
|
+
puts "got first result #{first_result.inspect}"
|
160
190
|
oidlist = []
|
161
191
|
good_column_names = []
|
162
192
|
row = {}
|
@@ -173,7 +203,7 @@ module Net
|
|
173
203
|
|
174
204
|
catch :break_main_loop do
|
175
205
|
while(result = get_next(oidlist))
|
176
|
-
|
206
|
+
puts "got result #{result.inspect}"
|
177
207
|
oidlist = []
|
178
208
|
row = {}
|
179
209
|
result.varbinds.each_with_index do |vb, idx|
|
@@ -212,13 +242,83 @@ module Net
|
|
212
242
|
end
|
213
243
|
|
214
244
|
def error(msg)
|
215
|
-
Wrapper.snmp_perror(
|
216
|
-
Wrapper.snmp_sess_perror(
|
245
|
+
Wrapper.snmp_perror(msg)
|
246
|
+
Wrapper.snmp_sess_perror(msg, @sess.pointer)
|
247
|
+
|
217
248
|
#Wrapper.print_session(self.struct)
|
218
249
|
raise Net::SNMP::Error.new({:session => self}), msg
|
219
250
|
end
|
220
251
|
|
221
252
|
|
253
|
+
def trap(options = {})
|
254
|
+
pdu = PDU.new(Constants::SNMP_MSG_TRAP)
|
255
|
+
options[:enterprise] ||= '1.3.6.1.4.1.3.1.1' # uh, just send netsnmp enterprise i guess
|
256
|
+
pdu.enterprise = OID.new(options[:enterprise])
|
257
|
+
pdu.trap_type = options[:trap_type] || 1 # need to check all these defaults
|
258
|
+
pdu.specific_type = options[:specific_type] || 0
|
259
|
+
pdu.time = 1 # put what here?
|
260
|
+
send_pdu(pdu)
|
261
|
+
end
|
262
|
+
|
263
|
+
|
264
|
+
def trap_v2(options = {})
|
265
|
+
pdu = PDU.new(Constants::SNMP_MSG_TRAP2)
|
266
|
+
build_trap_pdu(options)
|
267
|
+
send_pdu(pdu)
|
268
|
+
end
|
269
|
+
|
270
|
+
def inform(options = {}, &block)
|
271
|
+
pdu = PDU.new(Constants::SNMP_MSG_INFORM)
|
272
|
+
build_trap_pdu(options)
|
273
|
+
send_pdu(pdu, &block)
|
274
|
+
end
|
275
|
+
|
276
|
+
def poll(timeout = nil)
|
277
|
+
|
278
|
+
puts "IN POLL"
|
279
|
+
fdset = Net::SNMP::Wrapper.get_fd_set
|
280
|
+
num_fds = FFI::MemoryPointer.new(:int)
|
281
|
+
tv_sec = timeout ? timeout.round : 0
|
282
|
+
tv_usec = timeout ? (timeout - timeout.round) * 1000000 : 0
|
283
|
+
tval = Net::SNMP::Wrapper::TimeVal.new(:tv_sec => tv_sec, :tv_usec => tv_usec)
|
284
|
+
block = FFI::MemoryPointer.new(:int)
|
285
|
+
|
286
|
+
if timeout.nil?
|
287
|
+
block.write_int(0)
|
288
|
+
else
|
289
|
+
block.write_int(1)
|
290
|
+
end
|
291
|
+
#puts "calling snmp_select_info"
|
292
|
+
num = Net::SNMP::Wrapper.snmp_sess_select_info(@struct, num_fds, fdset, tval.pointer, block )
|
293
|
+
puts "done snmp_select_info. #{num}"
|
294
|
+
num_ready = 0
|
295
|
+
#puts "block = #{block.read_int}"
|
296
|
+
|
297
|
+
#puts "numready = #{num_fds.read_int}"
|
298
|
+
#puts "tv = #{tval[:tv_sec]} #{tval[:tv_usec]}"
|
299
|
+
#puts "timeout = #{timeout}"
|
300
|
+
tv = (timeout == false ? nil : tval)
|
301
|
+
#puts "calling select"
|
302
|
+
#puts "tv = #{tv.inspect}"
|
303
|
+
#puts "calling select with #{num_fds.read_int}"
|
304
|
+
#num_ready = RubyWrapper.rb_thread_select(num_fds.read_int, fdset, nil, nil, tv)
|
305
|
+
puts "calling select"
|
306
|
+
num_ready = Net::SNMP::Wrapper.select(num_fds.read_int, fdset, nil, nil, tv)
|
307
|
+
puts "done select"
|
308
|
+
#puts "done select. num_ready = #{num_ready}"
|
309
|
+
if num_ready > 0
|
310
|
+
Net::SNMP::Wrapper.snmp_sess_read(@struct, fdset)
|
311
|
+
elsif num_ready == 0
|
312
|
+
# timeout. do something here? or just return 0?
|
313
|
+
elsif num_ready == -1
|
314
|
+
# error. check snmp_error?
|
315
|
+
else
|
316
|
+
# uhhh
|
317
|
+
end
|
318
|
+
#puts "done snmp_read"
|
319
|
+
num_ready
|
320
|
+
end
|
321
|
+
|
222
322
|
private
|
223
323
|
def send_pdu(pdu, &block)
|
224
324
|
#puts "send_pdu #{Fiber.current.inspect}"
|
@@ -232,18 +332,19 @@ module Net
|
|
232
332
|
Fiber.yield
|
233
333
|
else
|
234
334
|
if block
|
235
|
-
|
236
|
-
if (status = Net::SNMP::Wrapper.
|
335
|
+
@requests[pdu.reqid] = block
|
336
|
+
if (status = Net::SNMP::Wrapper.snmp_sess_send(@struct, pdu.pointer)) == 0
|
237
337
|
error("snmp_get async failed")
|
238
338
|
end
|
239
|
-
pdu.free
|
339
|
+
#pdu.free
|
240
340
|
nil
|
241
341
|
else
|
242
342
|
response_ptr = FFI::MemoryPointer.new(:pointer)
|
243
343
|
#Net::SNMP::Wrapper.print_session(@struct)
|
244
344
|
#Net::SNMP::Wrapper.print_pdu(pdu.struct)
|
245
|
-
status = Wrapper.
|
246
|
-
|
345
|
+
status = Net::SNMP::Wrapper.snmp_sess_synch_response(@struct, pdu.pointer, response_ptr)
|
346
|
+
puts "called snmp_sync_response"
|
347
|
+
#pdu.free #causing segfaults
|
247
348
|
if status != 0
|
248
349
|
error("snmp_get failed #{status}")
|
249
350
|
else
|
@@ -279,28 +380,6 @@ module Net
|
|
279
380
|
|
280
381
|
|
281
382
|
|
282
|
-
def trap(options = {})
|
283
|
-
pdu = PDU.new(Constants::SNMP_MSG_TRAP)
|
284
|
-
options[:enterprise] ||= '1.3.6.1.4.1.3.1.1' # uh, just send netsnmp enterprise i guess
|
285
|
-
pdu.enterprise = OID.new(options[:enterprise])
|
286
|
-
pdu.trap_type = options[:trap_type] || 1 # need to check all these defaults
|
287
|
-
pdu.specific_type = options[:specific_type] || 0
|
288
|
-
pdu.time = 1 # put what here?
|
289
|
-
send_pdu(pdu)
|
290
|
-
end
|
291
|
-
|
292
|
-
|
293
|
-
def trap_v2(options = {})
|
294
|
-
pdu = PDU.new(Constants::SNMP_MSG_TRAP2)
|
295
|
-
build_trap_pdu(options)
|
296
|
-
send_pdu(pdu)
|
297
|
-
end
|
298
|
-
|
299
|
-
def inform(options = {}, &block)
|
300
|
-
pdu = PDU.new(Constants::SNMP_MSG_INFORM)
|
301
|
-
build_trap_pdu(options)
|
302
|
-
send_pdu(pdu, &block)
|
303
|
-
end
|
304
383
|
|
305
384
|
def build_trap_pdu(pdu, options = {})
|
306
385
|
pdu.add_varbind(:oid => OID.new('sysUpTime'), :type => Constants::ASN_TIMETICKS, :value => 0)
|
data/lib/net/snmp/varbind.rb
CHANGED
@@ -26,7 +26,7 @@ module Net
|
|
26
26
|
when Constants::ASN_OCTET_STR
|
27
27
|
struct.val[:string].read_string(struct.val_len)
|
28
28
|
when Constants::ASN_INTEGER, Constants::ASN_COUNTER, Constants::ASN_GAUGE
|
29
|
-
struct.val[:integer].
|
29
|
+
struct.val[:integer].read_long
|
30
30
|
when Constants::ASN_IPADDRESS
|
31
31
|
struct.val[:objid].read_string(struct.val_len).unpack('CCCC').join(".")
|
32
32
|
end
|
data/lib/net/snmp/version.rb
CHANGED
data/lib/net/snmp/wrapper.rb
CHANGED
@@ -278,7 +278,7 @@ module Wrapper
|
|
278
278
|
attach_function :snmp_get_do_debugging, [ ], :int
|
279
279
|
attach_function :snmp_error, [ :pointer, :pointer, :pointer, :pointer ], :void
|
280
280
|
attach_function :snmp_sess_init, [ :pointer ], :void
|
281
|
-
attach_function :snmp_sess_open, [ :pointer ],
|
281
|
+
attach_function :snmp_sess_open, [ :pointer ], SnmpSession.typed_pointer
|
282
282
|
attach_function :snmp_sess_pointer, [ :pointer ], :pointer
|
283
283
|
attach_function :snmp_sess_session, [ :pointer ], SnmpSession.typed_pointer
|
284
284
|
attach_function :snmp_sess_transport, [ :pointer ], :pointer
|
@@ -340,11 +340,12 @@ module Wrapper
|
|
340
340
|
attach_function :snmp_set_detail, [ :string ], :void
|
341
341
|
|
342
342
|
attach_function :snmp_select_info, [:pointer, :pointer, :pointer, :pointer], :int
|
343
|
-
attach_function :select, [:int, :pointer, :pointer, :pointer, :pointer], :int
|
344
343
|
attach_function :snmp_read, [:pointer], :void
|
345
344
|
attach_function :generate_Ku, [:pointer, :int, :string, :int, :pointer, :pointer], :int
|
346
345
|
|
347
|
-
|
346
|
+
|
347
|
+
# Standard IO functions
|
348
|
+
attach_function :select, [:int, :pointer, :pointer, :pointer, :pointer], :int
|
348
349
|
# MIB functions
|
349
350
|
attach_function :init_mib, [], :void
|
350
351
|
attach_function :read_all_mibs, [], :void
|
@@ -355,7 +356,6 @@ module Wrapper
|
|
355
356
|
|
356
357
|
attach_function :get_tree_head, [], Tree.typed_pointer
|
357
358
|
attach_function :get_tree, [:pointer, :int, :pointer], Tree.typed_pointer
|
358
|
-
|
359
359
|
#attach_function :send_easy_trap, [:int, :int], :void
|
360
360
|
#attach_function :send_trap_vars, [:int, :int, :pointer], :void
|
361
361
|
#attach_function :send_v2trap, [:pointer], :void
|
@@ -368,3 +368,10 @@ module Wrapper
|
|
368
368
|
end
|
369
369
|
end
|
370
370
|
end
|
371
|
+
|
372
|
+
#module RubyWrapper
|
373
|
+
# extend NiceFFI::Library
|
374
|
+
# #ffi_lib "libruby"
|
375
|
+
# ffi_lib "/Users/rmcclain/.rvm/rubies/ruby-1.9.2-preview3/lib/libruby.dylib"
|
376
|
+
# attach_function :rb_thread_select, [:int, :pointer, :pointer, :pointer, :pointer], :int
|
377
|
+
#end
|
data/net-snmp.gemspec
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
lib = File.expand_path("../lib", __FILE__)
|
3
3
|
$:.unshift lib
|
4
|
-
|
4
|
+
require 'net/snmp/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "net-snmp"
|
8
|
-
s.version =
|
8
|
+
s.version = Net::SNMP::VERSION
|
9
9
|
s.platform = Gem::Platform::RUBY
|
10
10
|
s.authors = ["Ron McClain"]
|
11
11
|
s.email = ["mixtli@github.com"]
|
data/spec/async_spec.rb
CHANGED
@@ -16,15 +16,17 @@ describe "async" do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
it "getnext should work" do
|
19
|
-
|
19
|
+
puts "testing getnext"
|
20
|
+
did_callback = false
|
20
21
|
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |s|
|
21
22
|
s.get_next(["sysDescr", "sysContact"]) do |result|
|
22
23
|
did_callback = true
|
23
|
-
result.varbinds[0].value.should eql("test.net-snmp.org")
|
24
|
-
result.varbinds[1].value.should match(/Coders/)
|
24
|
+
#result.varbinds[0].value.should eql("test.net-snmp.org")
|
25
|
+
#result.varbinds[1].value.should match(/Coders/)
|
25
26
|
end
|
26
27
|
end
|
27
28
|
Net::SNMP::Dispatcher.poll(false)
|
29
|
+
puts "done getnext"
|
28
30
|
did_callback.should be(true)
|
29
31
|
end
|
30
32
|
|
@@ -45,7 +47,7 @@ describe "async" do
|
|
45
47
|
end
|
46
48
|
|
47
49
|
it "getnext should work" do
|
48
|
-
|
50
|
+
did_callback = false
|
49
51
|
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic', :version => '2c') do |s|
|
50
52
|
s.get_next(["sysDescr", "sysContact"]) do |result|
|
51
53
|
did_callback = true
|
@@ -74,11 +76,11 @@ describe "async" do
|
|
74
76
|
did_callback.should be(true)
|
75
77
|
end
|
76
78
|
end
|
77
|
-
|
78
|
-
|
79
|
+
#
|
80
|
+
#
|
79
81
|
it "get should work" do
|
80
82
|
did_callback = false
|
81
|
-
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :version => 3, :username => 'MD5User',:security_level => Net::SNMP::Constants::SNMP_SEC_LEVEL_AUTHNOPRIV, :auth_protocol => :md5, :password => 'The Net-SNMP Demo Password') do |sess|
|
83
|
+
sess = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :version => 3, :username => 'MD5User',:security_level => Net::SNMP::Constants::SNMP_SEC_LEVEL_AUTHNOPRIV, :auth_protocol => :md5, :password => 'The Net-SNMP Demo Password') do |sess|
|
82
84
|
sess.get(["sysDescr.0", "sysContact.0"]) do |result|
|
83
85
|
did_callback = true
|
84
86
|
result.varbinds[0].value.should eql("test.net-snmp.org")
|
@@ -86,13 +88,14 @@ describe "async" do
|
|
86
88
|
end
|
87
89
|
end
|
88
90
|
Net::SNMP::Dispatcher.poll(false)
|
91
|
+
sess.close
|
89
92
|
did_callback.should be(true)
|
90
93
|
end
|
91
94
|
|
92
95
|
it "getnext should work" do
|
93
96
|
did_callback = false
|
94
97
|
|
95
|
-
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :version => 3, :username => 'MD5User',:security_level => Net::SNMP::Constants::SNMP_SEC_LEVEL_AUTHNOPRIV, :auth_protocol => :md5, :password => 'The Net-SNMP Demo Password') do |sess|
|
98
|
+
sess = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :version => 3, :username => 'MD5User',:security_level => Net::SNMP::Constants::SNMP_SEC_LEVEL_AUTHNOPRIV, :auth_protocol => :md5, :password => 'The Net-SNMP Demo Password') do |sess|
|
96
99
|
sess.get_next(["sysDescr", "sysContact"]) do |result|
|
97
100
|
did_callback = true
|
98
101
|
result.varbinds[0].value.should eql("test.net-snmp.org")
|
@@ -100,6 +103,7 @@ describe "async" do
|
|
100
103
|
end
|
101
104
|
end
|
102
105
|
Net::SNMP::Dispatcher.poll(false)
|
106
|
+
sess.close
|
103
107
|
did_callback.should be(true)
|
104
108
|
end
|
105
109
|
end
|
data/spec/em_spec.rb
CHANGED
data/spec/fiber_spec.rb
CHANGED
@@ -13,6 +13,7 @@ describe "in fiber" do
|
|
13
13
|
|
14
14
|
|
15
15
|
it "get should work in a fiber with synchronous calling style" do
|
16
|
+
#pending
|
16
17
|
wrap_fiber do
|
17
18
|
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic')
|
18
19
|
result = session.get("sysDescr.0")
|
@@ -22,6 +23,7 @@ describe "in fiber" do
|
|
22
23
|
end
|
23
24
|
|
24
25
|
it "getnext" do
|
26
|
+
#pending
|
25
27
|
wrap_fiber do
|
26
28
|
Net::SNMP::Session.open(:peername => "test.net-snmp.org", :community => "demopublic" ) do |sess|
|
27
29
|
result = sess.get_next(["sysUpTimeInstance.0"])
|
@@ -32,6 +34,7 @@ describe "in fiber" do
|
|
32
34
|
end
|
33
35
|
|
34
36
|
it "should get using snmpv3" do
|
37
|
+
#pending
|
35
38
|
wrap_fiber do
|
36
39
|
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :version => 3, :username => 'MD5User', :security_level => Net::SNMP::Constants::SNMP_SEC_LEVEL_AUTHNOPRIV, :auth_protocol => :md5, :password => 'The Net-SNMP Demo Password') do |sess|
|
37
40
|
result = sess.get(["sysDescr.0"])
|
data/spec/net-snmp_spec.rb
CHANGED
@@ -1,22 +1,7 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
3
|
describe "NetSnmp" do
|
4
|
-
|
5
|
-
did_callback = false
|
6
|
-
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |s|
|
7
|
-
s.get(["sysDescr.0", "sysContact.0"]) do |result|
|
8
|
-
did_callback = true
|
9
|
-
result.varbinds[0].value.should eql("test.net-snmp.org")
|
10
|
-
result.varbinds[1].value.should match(/Coders/)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
Thread.new do
|
14
|
-
while Net::SNMP::Dispatcher.poll == 0
|
15
|
-
sleep 1
|
16
|
-
end
|
17
|
-
end.join
|
18
|
-
did_callback.should be(true)
|
19
|
-
end
|
4
|
+
|
20
5
|
|
21
6
|
|
22
7
|
# it "should get columns" do
|
@@ -29,28 +14,5 @@ describe "NetSnmp" do
|
|
29
14
|
# end
|
30
15
|
|
31
16
|
|
32
|
-
it "should compare oids" do
|
33
|
-
Net::SNMP.oid_lex_cmp('1.3.5', '1.3.7').should eql(-1)
|
34
|
-
Net::SNMP.oid_lex_cmp('1.3.7', '1.3.5').should eql(1)
|
35
|
-
Net::SNMP.oid_lex_cmp('1.3.7', '1.3.7.1').should eql(-1)
|
36
|
-
Net::SNMP.oid_lex_cmp('1.3.5', '1.3.5').should eql(0)
|
37
|
-
end
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
it "should translate an oid" do
|
42
|
-
|
43
|
-
oid = Net::SNMP::OID.new("ifDescr.1")
|
44
|
-
oid.node.label.should eql("ifDescr")
|
45
|
-
oid.label.should eql("ifDescr.1")
|
46
|
-
oid.index.should eql("1")
|
47
|
-
end
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
17
|
|
56
18
|
end
|
data/spec/oid_spec.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Net::SNMP::OID do
|
4
|
+
it "should instantiate valid oid with numeric" do
|
5
|
+
oid = Net::SNMP::OID.new("1.3.6.1.2.1.2.1.0")
|
6
|
+
oid.to_s.should eql("1.3.6.1.2.1.2.1.0")
|
7
|
+
oid.label.should eql("ifNumber.0")
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should instantiate valid oid with string" do
|
11
|
+
oid = Net::SNMP::OID.new("ifNumber.0")
|
12
|
+
oid.to_s.should eql("1.3.6.1.2.1.2.1.0")
|
13
|
+
oid.label.should eql("ifNumber.0")
|
14
|
+
end
|
15
|
+
end
|
data/spec/sync_spec.rb
CHANGED
@@ -10,6 +10,14 @@ describe "synchronous calls" do
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
+
it "multiple calls within session should succeed" do
|
14
|
+
Net::SNMP::Session.open(:peername => "test.net-snmp.org", :community => "demopublic" ) do |sess|
|
15
|
+
result = sess.get("sysDescr.0")
|
16
|
+
result.varbinds.first.value.should eql("test.net-snmp.org")
|
17
|
+
second = sess.get("sysName.0")
|
18
|
+
second.varbinds.first.value.should eql("test.net-snmp.org")
|
19
|
+
end
|
20
|
+
end
|
13
21
|
it "get should succeed with multiple oids" do
|
14
22
|
Net::SNMP::Session.open(:peername => "test.net-snmp.org", :community => 'demopublic' ) do |sess|
|
15
23
|
result = sess.get(["sysDescr.0", "sysName.0"])
|
@@ -58,6 +66,7 @@ describe "synchronous calls" do
|
|
58
66
|
end
|
59
67
|
|
60
68
|
it "get_table should work with multiple columns" do
|
69
|
+
#pending
|
61
70
|
session = Net::SNMP::Session.open(:peername => "localhost", :version => '1')
|
62
71
|
table = session.get_table("ifTable", :columns => ["ifIndex", "ifDescr", "ifName"])
|
63
72
|
table[0]['ifName'].should eql("lo0")
|
@@ -79,17 +88,18 @@ describe "synchronous calls" do
|
|
79
88
|
|
80
89
|
context "version 3" do
|
81
90
|
it "should get using snmpv3" do
|
91
|
+
#pending
|
82
92
|
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :version => 3, :username => 'MD5User', :security_level => Net::SNMP::Constants::SNMP_SEC_LEVEL_AUTHNOPRIV, :auth_protocol => :md5, :password => 'The Net-SNMP Demo Password') do |sess|
|
83
93
|
result = sess.get("sysDescr.0")
|
84
94
|
result.varbinds.first.value.should eql('test.net-snmp.org')
|
85
95
|
end
|
86
96
|
end
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
97
|
+
it "should set using snmpv3" do
|
98
|
+
pending
|
99
|
+
Net::SNMP::Session.open(:peername => '127.0.0.1', :version => 3, :username => 'myuser', :auth_protocol => :sha1, :password => '0x1234') do |sess|
|
100
|
+
result = sess.set([["sysDescr.0", Net::SNMP::Constants::ASN_OCTET_STR, 'yomama']])
|
101
|
+
result.varbinds.first.value.should match(/Darwin/)
|
102
|
+
end
|
103
|
+
end
|
94
104
|
end
|
95
105
|
end
|
data/spec/thread_spec.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "in a thread" do
|
4
|
+
it "should get an oid asynchronously in a thread" do
|
5
|
+
did_callback = false
|
6
|
+
puts "calling thread"
|
7
|
+
dispatch_thread = Net::SNMP::Dispatcher.thread_loop
|
8
|
+
puts "still here"
|
9
|
+
Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |s|
|
10
|
+
puts "sending get"
|
11
|
+
s.get(["sysDescr.0", "sysContact.0"]) do |result|
|
12
|
+
puts "got callback"
|
13
|
+
did_callback = true
|
14
|
+
result.varbinds[0].value.should eql("test.net-snmp.org")
|
15
|
+
result.varbinds[1].value.should match(/Coders/)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
sleep 3
|
19
|
+
puts "joining thread"
|
20
|
+
did_callback.should be(true)
|
21
|
+
|
22
|
+
Thread.kill(dispatch_thread)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Net::SNMP::Utility do
|
4
|
+
it "should compare oids" do
|
5
|
+
Net::SNMP::Utility.oid_lex_cmp('1.3.5', '1.3.7').should eql(-1)
|
6
|
+
Net::SNMP::Utility.oid_lex_cmp('1.3.7', '1.3.5').should eql(1)
|
7
|
+
Net::SNMP::Utility.oid_lex_cmp('1.3.7', '1.3.7.1').should eql(-1)
|
8
|
+
Net::SNMP::Utility.oid_lex_cmp('1.3.5', '1.3.5').should eql(0)
|
9
|
+
end
|
10
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 6
|
9
|
+
version: 0.1.6
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ron McClain
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-04-
|
17
|
+
date: 2011-04-28 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -77,6 +77,7 @@ files:
|
|
77
77
|
- lib/net/snmp/oid.rb
|
78
78
|
- lib/net/snmp/pdu.rb
|
79
79
|
- lib/net/snmp/session.rb
|
80
|
+
- lib/net/snmp/utility.rb
|
80
81
|
- lib/net/snmp/varbind.rb
|
81
82
|
- lib/net/snmp/version.rb
|
82
83
|
- lib/net/snmp/wrapper.rb
|
@@ -86,8 +87,11 @@ files:
|
|
86
87
|
- spec/fiber_spec.rb
|
87
88
|
- spec/mib_spec.rb
|
88
89
|
- spec/net-snmp_spec.rb
|
90
|
+
- spec/oid_spec.rb
|
89
91
|
- spec/spec_helper.rb
|
90
92
|
- spec/sync_spec.rb
|
93
|
+
- spec/thread_spec.rb
|
94
|
+
- spec/utility_spec.rb
|
91
95
|
- spec/wrapper_spec.rb
|
92
96
|
has_rdoc: true
|
93
97
|
homepage: ""
|
@@ -127,6 +131,9 @@ test_files:
|
|
127
131
|
- spec/fiber_spec.rb
|
128
132
|
- spec/mib_spec.rb
|
129
133
|
- spec/net-snmp_spec.rb
|
134
|
+
- spec/oid_spec.rb
|
130
135
|
- spec/spec_helper.rb
|
131
136
|
- spec/sync_spec.rb
|
137
|
+
- spec/thread_spec.rb
|
138
|
+
- spec/utility_spec.rb
|
132
139
|
- spec/wrapper_spec.rb
|