net-snmp 0.1.7 → 0.2.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.
@@ -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