net-snmp 0.1.5 → 0.1.6
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.
- 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
|