net-snmp 0.1.7 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,64 @@
1
+ module Net
2
+ module SNMP
3
+ class TrapSession < Session
4
+ # == Represents a session for sending SNMP traps
5
+ def initialize(options = {})
6
+ options[:peername] = "#{options[:peername]}:162"
7
+ super(options)
8
+ end
9
+
10
+ # Send an SNMPv1 trap
11
+ # +options+
12
+ # * :enterprise The Oid of the enterprise
13
+ # * :trap_type The generic trap type.
14
+ # * :specific_type The specific trap type
15
+ def trap(options = {})
16
+ pdu = PDU.new(Constants::SNMP_MSG_TRAP)
17
+ options[:enterprise] ||= '1.3.6.1.4.1.3.1.1' # uh, just send netsnmp enterprise i guess
18
+ pdu.enterprise = OID.new(options[:enterprise])
19
+ pdu.trap_type = options[:trap_type] || 1 # need to check all these defaults
20
+ pdu.specific_type = options[:specific_type] || 0
21
+ pdu.time = 1 # put what here?
22
+ send_pdu(pdu)
23
+ true
24
+ end
25
+
26
+ # Send an SNMPv2 trap
27
+ # +options
28
+ # * :oid The Oid of the trap
29
+ # * :varbinds A list of Varbind objects to send with the trap
30
+ def trap_v2(options = {})
31
+ if options[:oid].kind_of?(String)
32
+ options[:oid] = Net::SNMP::OID.new(options[:oid])
33
+ end
34
+ pdu = PDU.new(Constants::SNMP_MSG_TRAP2)
35
+ build_trap_pdu(pdu, options)
36
+ send_pdu(pdu)
37
+ end
38
+
39
+ # Send an SNMPv2 inform. Can accept a callback to execute on confirmation of the inform
40
+ # +options
41
+ # * :oid The OID of the inform
42
+ # * :varbinds A list of Varbind objects to send with the inform
43
+ def inform(options = {}, &callback)
44
+ if options[:oid].kind_of?(String)
45
+ options[:oid] = Net::SNMP::OID.new(options[:oid])
46
+ end
47
+ pdu = PDU.new(Constants::SNMP_MSG_INFORM)
48
+ build_trap_pdu(pdu, options)
49
+ send_pdu(pdu, &callback)
50
+ end
51
+
52
+ private
53
+ def build_trap_pdu(pdu, options = {})
54
+ pdu.add_varbind(:oid => OID.new('sysUpTime.0'), :type => Constants::ASN_TIMETICKS, :value => 42)
55
+ pdu.add_varbind(:oid => OID.new('snmpTrapOID.0'), :type => Constants::ASN_OBJECT_ID, :value => options[:oid])
56
+ if options[:varbinds]
57
+ options[:varbinds].each do |vb|
58
+ pdu.add_varbind(vb)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,34 +1,56 @@
1
1
  module Net
2
2
  module SNMP
3
3
  class Varbind
4
+ # == Represents an SNMP Variable Binding
5
+
4
6
  attr_accessor :struct
5
7
 
6
- def initialize(ptr)
8
+ def initialize(ptr = nil)
7
9
  @struct = Net::SNMP::Wrapper::VariableList.new(ptr)
8
10
  end
9
11
 
10
12
  def self.from_pointer(ptr)
11
13
  new(ptr)
12
14
  end
13
-
15
+
16
+ # Returns the data type of the varbind
14
17
  def object_type
15
18
  @struct.type
16
19
  end
17
20
 
21
+ # Returns the OID associated with the varbind
18
22
  def oid
19
23
  @oid ||= Net::SNMP::OID.new(@struct.name.read_array_of_long(@struct.name_length).join("."))
20
24
  end
21
-
22
-
23
25
 
26
+ # Returns the value of the varbind
24
27
  def value
25
28
  case object_type
26
- when Constants::ASN_OCTET_STR
29
+ when Constants::ASN_OCTET_STR, Constants::ASN_OPAQUE
27
30
  struct.val[:string].read_string(struct.val_len)
28
- when Constants::ASN_INTEGER, Constants::ASN_COUNTER, Constants::ASN_GAUGE
31
+ when Constants::ASN_INTEGER
29
32
  struct.val[:integer].read_long
33
+ when Constants::ASN_UINTEGER, Constants::ASN_TIMETICKS, Constants::ASN_COUNTER, Constants::ASN_GAUGE
34
+ struct.val[:integer].read_ulong
30
35
  when Constants::ASN_IPADDRESS
31
36
  struct.val[:objid].read_string(struct.val_len).unpack('CCCC').join(".")
37
+ when Constants::ASN_NULL
38
+ nil
39
+ when Constants::ASN_OBJECT_ID
40
+ Net::SNMP::OID.new(struct.val[:objid].read_array_of_long(struct.val_len).join("."))
41
+ when Constants::ASN_COUNTER64
42
+ counter = Wrapper::Counter64.new(struct.val[:counter64])
43
+ counter.high * 2^32 + counter.low
44
+ when Constants::ASN_BIT_STR
45
+ # XXX not sure what to do here. Is this obsolete?
46
+ when Constants::SNMP_ENDOFMIBVIEW
47
+ :endofmibview
48
+ when Constants::SNMP_NOSUCHOBJECT
49
+ :nosuchobject
50
+ when Constants::SNMP_NOSUCHINSTANCE
51
+ :nosuchinstance
52
+ else
53
+ raise Net::SNMP::Error.new, "Unknown value type #{object_type}"
32
54
  end
33
55
  end
34
56
  end
@@ -1,5 +1,5 @@
1
1
  module Net
2
2
  module SNMP
3
- VERSION = "0.1.7"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
@@ -12,7 +12,7 @@ module Wrapper
12
12
  :low, :u_long
13
13
  )
14
14
  end
15
-
15
+
16
16
  class TimeVal < NiceFFI::Struct
17
17
  layout(:tv_sec, :long, :tv_usec, :long)
18
18
  end
@@ -20,7 +20,7 @@ module Wrapper
20
20
  puts "tv_sec = #{tv.tv_sec}, tv_usec = #{tv.tv_usec} "
21
21
  end
22
22
 
23
-
23
+
24
24
  class NetsnmpVardata < FFI::Union
25
25
  layout(
26
26
  :integer, :pointer,
@@ -288,7 +288,7 @@ module Wrapper
288
288
  attach_function :snmp_add, [ :pointer, :pointer, callback([ :pointer, :pointer, :pointer, :int ], :int), callback([ :pointer, :pointer, :int ], :int) ], :pointer
289
289
  attach_function :snmp_add_full, [ :pointer, :pointer, callback([ :pointer, :pointer, :pointer, :int ], :int), callback([ :pointer, :pointer, :pointer, :uint ], :int), callback([ :pointer, :pointer, :int ], :int), callback([ :pointer, :pointer, :pointer, :pointer ], :int), callback([ :pointer, :pointer, :pointer, :pointer, :pointer ], :int), callback([ :pointer, :uint ], :int), callback([ :pointer, :pointer, :uint ], :pointer) ], :pointer
290
290
  attach_function :snmp_sess_send, [ :pointer, :pointer ], :int
291
- attach_function :snmp_sess_async_send, [ :pointer, :pointer, :netsnmp_callback, :pointer ], :int
291
+ attach_function :snmp_sess_async_send, [ :pointer, :pointer, :snmp_callback, :pointer ], :int
292
292
  attach_function :snmp_sess_select_info, [ :pointer, :pointer, :pointer, :pointer, :pointer ], :int
293
293
  attach_function :snmp_sess_read, [ :pointer, :pointer ], :int
294
294
  attach_function :snmp_sess_timeout, [ :pointer ], :void
@@ -344,8 +344,7 @@ module Wrapper
344
344
  attach_function :generate_Ku, [:pointer, :int, :string, :int, :pointer, :pointer], :int
345
345
 
346
346
 
347
- # Standard IO functions
348
- attach_function :select, [:int, :pointer, :pointer, :pointer, :pointer], :int
347
+
349
348
  # MIB functions
350
349
  attach_function :init_mib, [], :void
351
350
  attach_function :read_all_mibs, [], :void
@@ -369,9 +368,35 @@ end
369
368
  end
370
369
  end
371
370
 
371
+
372
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"
373
+ # extend FFI::Library
374
+ # ffi_lib FFI::CURRENT_PROCESS
376
375
  # attach_function :rb_thread_select, [:int, :pointer, :pointer, :pointer, :pointer], :int
377
376
  #end
377
+
378
+
379
+
380
+ module FFI
381
+ module LibC
382
+ extend FFI::Library
383
+ ffi_lib [FFI::CURRENT_PROCESS, 'c']
384
+
385
+ typedef :pointer, :FILE
386
+ typedef :uint32, :in_addr_t
387
+ typedef :uint16, :in_port_t
388
+
389
+ class Timeval < FFI::Struct
390
+ layout :tv_sec, :time_t,
391
+ :tv_usec, :suseconds_t
392
+ end
393
+
394
+ # Standard IO functions
395
+ #@blocking = true # some undocumented voodoo that tells the next attach_function to release the GIL
396
+ attach_function :select, [:int, :pointer, :pointer, :pointer, :pointer], :int
397
+ attach_variable :errno, :int
398
+ attach_function :malloc, [:size_t], :pointer
399
+ attach_function :free, [:pointer], :void
400
+ end
401
+ end
402
+
data/spec/async_spec.rb CHANGED
@@ -3,106 +3,154 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
3
  describe "async" do
4
4
  context "version 1" do
5
5
  it "get should work" do
6
+ #pending
6
7
  did_callback = false
7
- Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |s|
8
- s.get(["sysDescr.0", "sysContact.0"]) do |result|
8
+ puts "started test #{Time.now}"
9
+ sess = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |s|
10
+ s.get(["sysDescr.0", "sysContact.0"]) do |op, pdu|
9
11
  did_callback = true
10
- result.varbinds[0].value.should eql("test.net-snmp.org")
11
- result.varbinds[1].value.should match(/Coders/)
12
+ pdu.varbinds[0].value.should eql("test.net-snmp.org")
13
+ pdu.varbinds[1].value.should match(/Coders/)
12
14
  end
13
15
  end
14
- Net::SNMP::Dispatcher.poll(false)
16
+ Net::SNMP::Dispatcher.select(false)
15
17
  did_callback.should be(true)
18
+ puts "ended test #{Time.now}"
19
+ end
20
+
21
+ it "get should return an error" do
22
+ Net::SNMP.thread_safe = true
23
+ puts "started test #{Time.now}"
24
+
25
+ did_callback = false
26
+ sess = Net::SNMP::Session.open(:peername => 'www.yahoo.com', :timeout => 5, :retries => 0) do |sess|
27
+ sess.get("sysDescr.0") do |op, pdu|
28
+ puts "IN GET CALLBACK"
29
+ puts pdu.inspect
30
+ did_callback = true
31
+ op.should eql(:timeout)
32
+ end
33
+ end
34
+ puts"selecting #{Time.now}"
35
+ sleep 2
36
+ pdu = sess.select(10)
37
+ puts "and now #{Time.now}"
38
+ puts "sess err = #{sess.s_snmp_errno}"
39
+
40
+ pdu.should eql(0)
41
+ did_callback.should be(true)
42
+ puts "ended test #{Time.now}"
43
+ Net::SNMP.thread_safe = false
16
44
  end
17
45
 
18
46
  it "getnext should work" do
47
+ puts "started test #{Time.now}"
48
+
49
+ #pending
19
50
  puts "testing getnext"
20
51
  did_callback = false
21
52
  Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |s|
22
- s.get_next(["sysDescr", "sysContact"]) do |result|
53
+ s.get_next(["sysDescr", "sysContact"]) do |op, pdu|
23
54
  did_callback = true
24
- #result.varbinds[0].value.should eql("test.net-snmp.org")
25
- #result.varbinds[1].value.should match(/Coders/)
55
+ pdu.varbinds[0].value.should eql("test.net-snmp.org")
56
+ pdu.varbinds[1].value.should match(/Coders/)
26
57
  end
27
58
  end
28
- Net::SNMP::Dispatcher.poll(false)
59
+ Net::SNMP::Dispatcher.select(false)
29
60
  puts "done getnext"
30
61
  did_callback.should be(true)
62
+ puts "ended test #{Time.now}"
63
+
31
64
  end
32
65
 
33
66
  end
34
67
 
35
68
  context "version 2" do
36
69
  it "get should work" do
70
+ puts "started test #{Time.now}"
71
+
72
+ #pending
37
73
  did_callback = false
38
74
  Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic', :version => '2c') do |s|
39
- s.get(["sysDescr.0", "sysContact.0"]) do |result|
75
+ s.get(["sysDescr.0", "sysContact.0"]) do |op, pdu|
40
76
  did_callback = true
41
- result.varbinds[0].value.should eql("test.net-snmp.org")
42
- result.varbinds[1].value.should match(/Coders/)
77
+ pdu.varbinds[0].value.should eql("test.net-snmp.org")
78
+ pdu.varbinds[1].value.should match(/Coders/)
43
79
  end
44
80
  end
45
- Net::SNMP::Dispatcher.poll(false)
81
+ Net::SNMP::Dispatcher.select(false)
46
82
  did_callback.should be(true)
83
+ puts "ended test #{Time.now}"
84
+
47
85
  end
48
86
 
49
87
  it "getnext should work" do
88
+ #pending
89
+ puts "started test #{Time.now}"
90
+
50
91
  did_callback = false
51
92
  Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic', :version => '2c') do |s|
52
- s.get_next(["sysDescr", "sysContact"]) do |result|
93
+ s.get_next(["sysDescr", "sysContact"]) do |op, pdu|
53
94
  did_callback = true
54
- result.varbinds[0].value.should eql("test.net-snmp.org")
55
- result.varbinds[1].value.should match(/Coders/)
95
+ pdu.varbinds[0].value.should eql("test.net-snmp.org")
96
+ pdu.varbinds[1].value.should match(/Coders/)
56
97
  end
57
98
  end
58
- Net::SNMP::Dispatcher.poll(false)
99
+ Net::SNMP::Dispatcher.select(false)
59
100
  did_callback.should be(true)
101
+ puts "ended test #{Time.now}"
102
+
60
103
  end
104
+
61
105
  end
62
106
 
63
107
  context "version 3" do
64
108
  #failing intermittently
65
109
  it "should get async using snmpv3" do
110
+ #pending
66
111
  did_callback = false
67
112
  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|
68
- sess.get(["sysDescr.0"]) do |result|
113
+ sess.get(["sysDescr.0"]) do |op, pdu|
69
114
  did_callback = true
70
- result.varbinds[0].value.should eql('test.net-snmp.org')
115
+ pdu.varbinds[0].value.should eql('test.net-snmp.org')
71
116
  end
72
117
  sleep(0.5)
73
- Net::SNMP::Dispatcher.poll(false)
74
- #Net::SNMP::Dispatcher.poll(false)
75
- puts "done poll"
118
+ Net::SNMP::Dispatcher.select(false)
119
+ #Net::SNMP::Dispatcher.select(false)
120
+ puts "done select"
76
121
  did_callback.should be(true)
77
122
  end
78
123
  end
79
124
  #
80
125
  #
81
126
  it "get should work" do
127
+ #pending
82
128
  did_callback = false
83
129
  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|
84
- sess.get(["sysDescr.0", "sysContact.0"]) do |result|
130
+ sess.get(["sysDescr.0", "sysContact.0"]) do |op,pdu|
85
131
  did_callback = true
86
- result.varbinds[0].value.should eql("test.net-snmp.org")
87
- result.varbinds[1].value.should match(/Coders/)
132
+ pdu.varbinds[0].value.should eql("test.net-snmp.org")
133
+ pdu.varbinds[1].value.should match(/Coders/)
88
134
  end
89
135
  end
90
- Net::SNMP::Dispatcher.poll(false)
136
+ Net::SNMP::Dispatcher.select(false)
91
137
  sess.close
92
138
  did_callback.should be(true)
93
139
  end
94
140
 
141
+ # XXX occasionally segfaulting
95
142
  it "getnext should work" do
143
+ #pending
96
144
  did_callback = false
97
145
 
98
146
  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|
99
- sess.get_next(["sysDescr", "sysContact"]) do |result|
147
+ sess.get_next(["sysDescr", "sysContact"]) do |op, pdu|
100
148
  did_callback = true
101
- result.varbinds[0].value.should eql("test.net-snmp.org")
102
- result.varbinds[1].value.should match(/Coders/)
149
+ pdu.varbinds[0].value.should eql("test.net-snmp.org")
150
+ pdu.varbinds[1].value.should match(/Coders/)
103
151
  end
104
152
  end
105
- Net::SNMP::Dispatcher.poll(false)
153
+ Net::SNMP::Dispatcher.select(false)
106
154
  sess.close
107
155
  did_callback.should be(true)
108
156
  end
data/spec/em_spec.rb CHANGED
@@ -9,7 +9,7 @@ describe "em" do
9
9
  Net::SNMP::Dispatcher.em_loop
10
10
 
11
11
  session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |s|
12
- s.get("sysDescr.0") do |result|
12
+ s.get("sysDescr.0") do |op, result|
13
13
  did_callback = true
14
14
  result.varbinds[0].value.should eql("test.net-snmp.org")
15
15
  end
@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'eventmachine'
3
+
4
+ describe "snmp errors" do
5
+ it "should rescue a timeout error" do
6
+ Net::SNMP::Session.open(:peername => 'www.yahoo.com') do |sess|
7
+ begin
8
+ sess.get("sysDescr.0")
9
+ rescue Net::SNMP::Error => e
10
+ e.print
11
+ e.status.should eql(Net::SNMP::Constants::STAT_TIMEOUT)
12
+ end
13
+ end
14
+ end
15
+
16
+ it "should rescue timeout error in a fiber" do
17
+ got_error = false
18
+ EM.run {
19
+ Fiber.new {
20
+ Net::SNMP::Dispatcher.fiber_loop
21
+ Net::SNMP::Session.open(:peername => 'www.yahoo.com') do |sess|
22
+ begin
23
+ puts "sending get pdu"
24
+ sess.get("sysDescr.0")
25
+ puts "done sess.get"
26
+ rescue Net::SNMP::TimeoutError => e
27
+ got_error = true
28
+ end
29
+ end
30
+ EM.stop
31
+ }.resume(nil)
32
+ }
33
+ got_error.should be_true
34
+ end
35
+
36
+ end
data/spec/spec_helper.rb CHANGED
@@ -4,6 +4,7 @@ require 'net-snmp'
4
4
  require 'rspec'
5
5
  require 'rspec/autorun'
6
6
 
7
+ Net::SNMP::Debug.debug = true
7
8
  #Spec::Runner.configure do |config|
8
9
 
9
10
  #end