net-snmp2 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +24 -0
- data/TODO.md +6 -0
- data/bin/mib2rb +129 -0
- data/bin/net-snmp2 +64 -0
- data/examples/agent.rb +104 -0
- data/examples/manager.rb +11 -0
- data/examples/trap_handler.rb +46 -0
- data/examples/v1_trap_session.rb +24 -0
- data/examples/v2_trap_session.rb +21 -0
- data/lib/net-snmp2.rb +85 -0
- data/lib/net/snmp.rb +27 -0
- data/lib/net/snmp/agent/agent.rb +48 -0
- data/lib/net/snmp/agent/provider.rb +51 -0
- data/lib/net/snmp/agent/provider_dsl.rb +124 -0
- data/lib/net/snmp/agent/request_dispatcher.rb +38 -0
- data/lib/net/snmp/constants.rb +287 -0
- data/lib/net/snmp/debug.rb +54 -0
- data/lib/net/snmp/dispatcher.rb +108 -0
- data/lib/net/snmp/error.rb +29 -0
- data/lib/net/snmp/listener.rb +76 -0
- data/lib/net/snmp/message.rb +142 -0
- data/lib/net/snmp/mib/mib.rb +67 -0
- data/lib/net/snmp/mib/module.rb +39 -0
- data/lib/net/snmp/mib/node.rb +122 -0
- data/lib/net/snmp/mib/templates.rb +48 -0
- data/lib/net/snmp/oid.rb +134 -0
- data/lib/net/snmp/pdu.rb +235 -0
- data/lib/net/snmp/repl/manager_repl.rb +243 -0
- data/lib/net/snmp/session.rb +560 -0
- data/lib/net/snmp/trap_handler/trap_handler.rb +42 -0
- data/lib/net/snmp/trap_handler/v1_trap_dsl.rb +44 -0
- data/lib/net/snmp/trap_handler/v2_trap_dsl.rb +38 -0
- data/lib/net/snmp/trap_session.rb +92 -0
- data/lib/net/snmp/utility.rb +10 -0
- data/lib/net/snmp/varbind.rb +57 -0
- data/lib/net/snmp/version.rb +5 -0
- data/lib/net/snmp/wrapper.rb +450 -0
- data/net-snmp2.gemspec +30 -0
- data/spec/README.md +105 -0
- data/spec/async_spec.rb +123 -0
- data/spec/em_spec.rb +23 -0
- data/spec/error_spec.rb +34 -0
- data/spec/fiber_spec.rb +41 -0
- data/spec/mib_spec.rb +68 -0
- data/spec/net-snmp_spec.rb +18 -0
- data/spec/oid_spec.rb +21 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/sync_spec.rb +132 -0
- data/spec/thread_spec.rb +19 -0
- data/spec/trap_spec.rb +45 -0
- data/spec/utility_spec.rb +10 -0
- data/spec/wrapper_spec.rb +69 -0
- metadata +166 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
# Ruby api to the Wrapper::Module class (represents netsnmp's `struct module`)
|
2
|
+
|
3
|
+
module Net::SNMP
|
4
|
+
class Module
|
5
|
+
extend Forwardable
|
6
|
+
def_delegators :struct, :modid, :no_imports
|
7
|
+
|
8
|
+
# Gets a module node by its id
|
9
|
+
def self.find(module_id)
|
10
|
+
if module_id < 0
|
11
|
+
nil
|
12
|
+
else
|
13
|
+
new(Wrapper.find_module(module_id))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(struct)
|
18
|
+
raise "Tried to initialize null module" if struct.null?
|
19
|
+
@struct = struct
|
20
|
+
end
|
21
|
+
|
22
|
+
def name
|
23
|
+
@struct.name.read_string
|
24
|
+
end
|
25
|
+
|
26
|
+
def file
|
27
|
+
@struct.file.read_string
|
28
|
+
end
|
29
|
+
|
30
|
+
def next
|
31
|
+
if @struct.next.null?
|
32
|
+
nil
|
33
|
+
else
|
34
|
+
self.class.new(@struct.next)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# Ruby api to the Wrapper::Tree class (represents netsnmp's `struct tree`)
|
2
|
+
|
3
|
+
module Net::SNMP
|
4
|
+
module MIB
|
5
|
+
class Node
|
6
|
+
include Debug
|
7
|
+
extend Forwardable
|
8
|
+
attr_accessor :struct, :is_in_mib
|
9
|
+
def_delegators :struct, :label, :type, :access, :status, :modid, :subid
|
10
|
+
|
11
|
+
class << self
|
12
|
+
include Debug
|
13
|
+
def get_node(oid)
|
14
|
+
if oid.kind_of?(String)
|
15
|
+
oid = OID.new(oid)
|
16
|
+
end
|
17
|
+
struct = Wrapper.get_tree(oid.pointer, oid.length_pointer.read_int, Wrapper.get_tree_head().pointer)
|
18
|
+
node = new(struct.pointer)
|
19
|
+
warn "OID #{oid.to_s} not found in MIB" unless node.in_mib?
|
20
|
+
node
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(arg)
|
25
|
+
@oid = nil
|
26
|
+
@module = nil
|
27
|
+
case arg
|
28
|
+
when Wrapper::Tree
|
29
|
+
@struct = arg
|
30
|
+
when FFI::Pointer
|
31
|
+
@struct = Wrapper::Tree.new(arg)
|
32
|
+
else
|
33
|
+
raise "invalid type"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def exists_in_mib?
|
38
|
+
# The structure can be created without the oid actually
|
39
|
+
# existing in the mib, but the parent will be null.
|
40
|
+
# Of course, the parent is null for the root node as well,
|
41
|
+
# so ignore that case.
|
42
|
+
(!@struct.parent.null?) || oid.to_s == '1'
|
43
|
+
end
|
44
|
+
alias in_mib? exists_in_mib?
|
45
|
+
|
46
|
+
def module
|
47
|
+
unless @module
|
48
|
+
@module = Module.find(modid)
|
49
|
+
end
|
50
|
+
@module
|
51
|
+
end
|
52
|
+
|
53
|
+
def description
|
54
|
+
if @struct.description.null?
|
55
|
+
nil
|
56
|
+
else
|
57
|
+
@struct.description.read_string
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def oid
|
62
|
+
return @oid if @oid
|
63
|
+
@oid = OID.new(label)
|
64
|
+
end
|
65
|
+
|
66
|
+
# actually seems like list is linked backward, so this will retrieve the previous oid numerically
|
67
|
+
def next
|
68
|
+
return nil if @struct.next.null?
|
69
|
+
self.class.new(@struct.next)
|
70
|
+
end
|
71
|
+
|
72
|
+
def next_peer
|
73
|
+
return nil if @struct.next_peer.null?
|
74
|
+
self.class.new(@struct.next_peer)
|
75
|
+
end
|
76
|
+
|
77
|
+
def parent
|
78
|
+
return nil if @struct.parent.null?
|
79
|
+
self.class.new(@struct.parent)
|
80
|
+
end
|
81
|
+
|
82
|
+
def children
|
83
|
+
return to_enum __method__ unless block_given?
|
84
|
+
return if @struct.child_list.null?
|
85
|
+
child = self.class.new(@struct.child_list)
|
86
|
+
yield child
|
87
|
+
while child = child.next_peer
|
88
|
+
yield child
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Depth-first traversal of all descendants
|
93
|
+
def descendants(&block)
|
94
|
+
return to_enum __method__ unless block_given?
|
95
|
+
return if @struct.child_list.null?
|
96
|
+
child = self.class.new(@struct.child_list)
|
97
|
+
block[child]
|
98
|
+
child.descendants(&block)
|
99
|
+
while child = child.next_peer
|
100
|
+
block[child]
|
101
|
+
child.descendants(&block)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def peers
|
106
|
+
return [] if oid.to_s == '1'
|
107
|
+
parent.children.reject { |n| n.oid.to_s == oid.to_s }
|
108
|
+
end
|
109
|
+
alias siblings peers
|
110
|
+
|
111
|
+
def enums
|
112
|
+
return to_enum __method__ unless block_given?
|
113
|
+
enum = struct.enums
|
114
|
+
while !enum.null?
|
115
|
+
yield({value: enum.value, label: enum.label.read_string})
|
116
|
+
enum = enum.next
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Net::SNMP::MIB
|
2
|
+
module Templates
|
3
|
+
DESCRIBE = '
|
4
|
+
<% nodes.each do |node| -%>
|
5
|
+
<%= node.module.nil? ? "" : "#{node.module.name}::" %><%= node.label %>
|
6
|
+
- oid: <%= node.oid %>
|
7
|
+
- type: <%= node.type %>
|
8
|
+
- file: <%= node.module.file unless node.module.nil? %>
|
9
|
+
- descr: <%= "\"#{node.description}\"" %>
|
10
|
+
- enums: <%=
|
11
|
+
if !(node.enums.count == 0)
|
12
|
+
node.enums.map { |e| "#{e[:label]}(#{e[:value]})" }.join(", ")
|
13
|
+
else
|
14
|
+
"NONE"
|
15
|
+
end
|
16
|
+
%>
|
17
|
+
- parent: <%= "#{node.parent.label}(#{node.parent.oid})" unless node.parent.nil? %>
|
18
|
+
- peers: <%= node.peers.map { |n| "#{n.label}(#{n.subid})"}.join(", ") %>
|
19
|
+
- next: <%= node.next.oid unless node.next.nil? %>
|
20
|
+
- next_peer: <%= node.next_peer.oid unless node.next_peer.nil? %>
|
21
|
+
- children: <%=
|
22
|
+
if node.children.count > 0
|
23
|
+
node.children.map { |n| "#{n.label}(#{n.subid})"}.join(", ")
|
24
|
+
else
|
25
|
+
"NONE"
|
26
|
+
end
|
27
|
+
%>
|
28
|
+
<% end -%>
|
29
|
+
'.sub!("\n", "") # Remove leading newline
|
30
|
+
|
31
|
+
JSON = json_template = '
|
32
|
+
[
|
33
|
+
<% nodes.each_with_index { |node, index| -%>
|
34
|
+
<%= ",\n" if index > 0 -%>
|
35
|
+
{
|
36
|
+
"name": "<%= node.module.nil? ? "" : "#{node.module.name}::" %><%= node.label %>",
|
37
|
+
"oid": "<%= node.oid %>",
|
38
|
+
"type": <%= node.type %>,
|
39
|
+
<% if node.enums && node.enums.count > 0 -%>
|
40
|
+
"enums": { <%= node.enums.map { |enum| "\"#{enum[:label]}\": #{enum[:value]}" }.join(", ") %> },
|
41
|
+
<% end -%>
|
42
|
+
"parent": <%= node.parent ? %Q["#{node.parent.oid}"] : "undefined" %>
|
43
|
+
}<% } -%>
|
44
|
+
|
45
|
+
]
|
46
|
+
'.sub!("\n", "")
|
47
|
+
end
|
48
|
+
end
|
data/lib/net/snmp/oid.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
module Net
|
2
|
+
module SNMP
|
3
|
+
class OID
|
4
|
+
extend Debug
|
5
|
+
include Debug
|
6
|
+
|
7
|
+
attr_reader :oid, :pointer, :length_pointer
|
8
|
+
@oid_size = nil
|
9
|
+
@sub_id_bit_width = nil
|
10
|
+
|
11
|
+
def self.from_pointer(ptr, sub_id_count)
|
12
|
+
OID.new(OID.read_pointer(ptr, sub_id_count))
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.oid_size
|
16
|
+
unless @oid_size
|
17
|
+
determine_oid_size
|
18
|
+
end
|
19
|
+
@oid_size
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.determine_oid_size
|
23
|
+
if Net::SNMP.initialized?
|
24
|
+
oid_ptr = FFI::MemoryPointer.new(:ulong, 8)
|
25
|
+
length_ptr = FFI::MemoryPointer.new(:size_t, 1)
|
26
|
+
length_ptr.write_int(oid_ptr.total)
|
27
|
+
|
28
|
+
Wrapper.read_objid('1.1', oid_ptr, length_ptr)
|
29
|
+
oid_str = oid_ptr.read_array_of_uint8(oid_ptr.total).map{|byte| byte.to_s(2).rjust(8, '0') }.join('')
|
30
|
+
|
31
|
+
@oid_size = (oid_str[/10*1/].length - 1) / 8
|
32
|
+
else
|
33
|
+
@oid_size = FFI::MemoryPointer.new(:ulong).total
|
34
|
+
warn "SNMP not initialized\n" + <<-WARNING
|
35
|
+
Cannot determine OID sub-id size, assuming common case of sizeof(ulong)
|
36
|
+
On this platform, sizeof(ulong) = #{@oid_size} bytes
|
37
|
+
To avoid this warning, call `Net::SNMP.init`
|
38
|
+
WARNING
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.read_pointer(pointer, sub_id_count)
|
43
|
+
unless @sub_id_bit_width
|
44
|
+
@sub_id_bit_width = OID.oid_size * 8
|
45
|
+
end
|
46
|
+
pointer.send("read_array_of_uint#{@sub_id_bit_width}", sub_id_count).join('.')
|
47
|
+
end
|
48
|
+
|
49
|
+
def write_to_buffer(buffer)
|
50
|
+
unless @sub_id_bit_width
|
51
|
+
@sub_id_bit_width = OID.oid_size * 8
|
52
|
+
end
|
53
|
+
buffer.send("write_array_of_uint#{@sub_id_bit_width}", self.to_s.split('.').map{ |subid| subid.to_i })
|
54
|
+
end
|
55
|
+
|
56
|
+
def initialize(oid)
|
57
|
+
@oid = oid
|
58
|
+
@pointer = FFI::MemoryPointer.new(Net::SNMP::OID.oid_size * Constants::MAX_OID_LEN)
|
59
|
+
@length_pointer = FFI::MemoryPointer.new(:size_t)
|
60
|
+
@length_pointer.write_int(Constants::MAX_OID_LEN)
|
61
|
+
if @oid =~ /^[\d\.]*$/
|
62
|
+
if Wrapper.read_objid(@oid, @pointer, @length_pointer) == 0
|
63
|
+
Wrapper.snmp_perror(@oid)
|
64
|
+
end
|
65
|
+
else
|
66
|
+
if Wrapper.get_node(@oid, @pointer, @length_pointer) == 0
|
67
|
+
raise "No such node: #{oid}"
|
68
|
+
end
|
69
|
+
@oid = to_s
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def size
|
74
|
+
@length_pointer.read_int * Net::SNMP::OID.oid_size
|
75
|
+
end
|
76
|
+
|
77
|
+
def length
|
78
|
+
@length_pointer.read_int
|
79
|
+
end
|
80
|
+
|
81
|
+
def oid
|
82
|
+
@oid
|
83
|
+
end
|
84
|
+
|
85
|
+
def name
|
86
|
+
@oid
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_s
|
90
|
+
OID.read_pointer(@pointer, length)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Gets the MIB node corresponding to this OID.
|
94
|
+
# Note that if this OID represents a MIB node, like '1.3',
|
95
|
+
# then `oid.to_s == oid.node.oid.to_s`. However, if there
|
96
|
+
# are indices on this oid, then `oid.to_s.start_with?(oid.node.oid.to_s)`
|
97
|
+
def node
|
98
|
+
MIB::Node.get_node(oid)
|
99
|
+
end
|
100
|
+
|
101
|
+
# The instance index string
|
102
|
+
# Note that some MIB nodes specify the instance implicitly,
|
103
|
+
# like sysUpTimeInstance. So, this may be an empty string.
|
104
|
+
def index
|
105
|
+
# Strip the name
|
106
|
+
index = oid.sub(node.oid.name, '')
|
107
|
+
# Strip any leading dot
|
108
|
+
index.sub(/^\./, '')
|
109
|
+
end
|
110
|
+
|
111
|
+
# The label for the this OID. Includes any instance indexes.
|
112
|
+
def label
|
113
|
+
"#{node.label}#{index.length > 0 ? "." + index : ""}"
|
114
|
+
end
|
115
|
+
|
116
|
+
def <=>(o)
|
117
|
+
a = self._packed
|
118
|
+
b = o._packed
|
119
|
+
a <=> b
|
120
|
+
end
|
121
|
+
|
122
|
+
def _packed
|
123
|
+
i = self.to_s.dup
|
124
|
+
i.sub!(/^\./,'')
|
125
|
+
i.gsub!(/ /, '.0')
|
126
|
+
i.replace(i.split('.').map(&:to_i).pack('N*'))
|
127
|
+
end
|
128
|
+
|
129
|
+
def parent_of?(o)
|
130
|
+
o.to_s =~ /^#{self.to_s}\./
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
data/lib/net/snmp/pdu.rb
ADDED
@@ -0,0 +1,235 @@
|
|
1
|
+
module Net
|
2
|
+
module SNMP
|
3
|
+
# Wrapper around netsnmp_pdu.
|
4
|
+
class PDU
|
5
|
+
extend Forwardable
|
6
|
+
include Net::SNMP::Debug
|
7
|
+
attr_accessor :struct, :varbinds, :callback, :command
|
8
|
+
def_delegators :struct, :pointer
|
9
|
+
|
10
|
+
# Create a new PDU object.
|
11
|
+
# +pdu_type+ The type of the PDU. For example, Net::SNMP::SNMP_MSG_GET. See constants.rb
|
12
|
+
def initialize(pdu_type)
|
13
|
+
@varbinds = []
|
14
|
+
case pdu_type
|
15
|
+
when FFI::Pointer
|
16
|
+
@struct = Wrapper::SnmpPdu.new(pdu_type)
|
17
|
+
@command = @struct.command
|
18
|
+
v = @struct.variables
|
19
|
+
unless v.null?
|
20
|
+
@varbinds << Varbind.from_pointer(v)
|
21
|
+
while( !(v = v.next_variable).null? )
|
22
|
+
@varbinds << Varbind.from_pointer(v)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
when Fixnum
|
26
|
+
@struct = Wrapper.snmp_pdu_create(pdu_type)
|
27
|
+
@command = pdu_type
|
28
|
+
else
|
29
|
+
raise Error.new, "invalid pdu type"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Specifies the number of non-repeating, regular objects at the start of
|
34
|
+
# the variable list in the request.
|
35
|
+
# (For getbulk requests only, non-repeaters is stored in errstat location)
|
36
|
+
def non_repeaters
|
37
|
+
@struct.errstat
|
38
|
+
end
|
39
|
+
|
40
|
+
def non_repeaters=(nr)
|
41
|
+
@struct.errstat = nr
|
42
|
+
end
|
43
|
+
|
44
|
+
# The number of iterations in the table to be read for the repeating
|
45
|
+
# objects that follow the non-repeating objects.
|
46
|
+
# (For getbulk requests only, max-repititions are stored in errindex location)
|
47
|
+
def max_repetitions=(mr)
|
48
|
+
@struct.errindex = mr
|
49
|
+
end
|
50
|
+
|
51
|
+
def max_repetitions
|
52
|
+
@struct.errindex
|
53
|
+
end
|
54
|
+
|
55
|
+
# Sets the enterprise OID of this PDU
|
56
|
+
# (Valid for SNMPv1 traps only)
|
57
|
+
def enterprise=(oid)
|
58
|
+
@i_own_enterprise = true
|
59
|
+
oid = OID.new(oid) if oid.kind_of?(String)
|
60
|
+
@struct.enterprise = FFI::LibC.calloc(oid.length, OID.oid_size)
|
61
|
+
oid.write_to_buffer(@struct.enterprise)
|
62
|
+
@struct.enterprise_length = oid.length
|
63
|
+
end
|
64
|
+
|
65
|
+
# The enterprise OID of this PDU
|
66
|
+
# (Valid for SNMPv1 traps only)
|
67
|
+
def enterprise
|
68
|
+
OID.from_pointer(@struct.enterprise, @struct.enterprise_length)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Sets the address of the agent that sent this PDU
|
72
|
+
# (Valid for SNMPv1 traps only)
|
73
|
+
def agent_addr=(addr)
|
74
|
+
# @struct.agent_addr is a binary array of 4 characters,
|
75
|
+
# so pack the provided string into four bytes and we can assign it
|
76
|
+
@struct.agent_addr = addr.split('.').map{ |octet| octet.to_i }.pack("CCCC")
|
77
|
+
end
|
78
|
+
|
79
|
+
# The address of the agent that sent this PDU
|
80
|
+
# (Valid for SNMPv1 traps only)
|
81
|
+
def agent_addr
|
82
|
+
# @struct.agent_addr is a binary array of 4 characters,
|
83
|
+
# to_a converts this to a ruby array of Integers, then join get's us
|
84
|
+
# back to the string form
|
85
|
+
@struct.agent_addr.to_a.join('.')
|
86
|
+
end
|
87
|
+
|
88
|
+
# The uptime for the PDU
|
89
|
+
# (Only valid for SNMPv1 traps)
|
90
|
+
def uptime
|
91
|
+
@struct.time
|
92
|
+
end
|
93
|
+
|
94
|
+
# The uptime for the PDU
|
95
|
+
# (Only valid for SNMPv1 traps)
|
96
|
+
def uptime=(value)
|
97
|
+
@struct.time = value.to_i
|
98
|
+
end
|
99
|
+
|
100
|
+
# Returns true if pdu is in error
|
101
|
+
def error?
|
102
|
+
self.errstat != 0
|
103
|
+
end
|
104
|
+
|
105
|
+
# Sets the pdu errstat
|
106
|
+
def error=(value)
|
107
|
+
@struct.errstat = value
|
108
|
+
end
|
109
|
+
alias errstat= error=
|
110
|
+
alias error_status= error=
|
111
|
+
|
112
|
+
# Sets the error index
|
113
|
+
def error_index=(index)
|
114
|
+
@struct.errindex = index
|
115
|
+
end
|
116
|
+
alias errindex= error_index=
|
117
|
+
|
118
|
+
# A descriptive error message
|
119
|
+
def error_message
|
120
|
+
Wrapper::snmp_errstring(self.errstat)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Tries to delegate missing methods to the underlying Wrapper::SnmpPdu object.
|
124
|
+
# If it does not respond to the method, calls super.
|
125
|
+
def method_missing(m, *args)
|
126
|
+
if @struct.respond_to?(m)
|
127
|
+
@struct.send(m, *args)
|
128
|
+
else
|
129
|
+
super
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Adds a variable binding to the pdu.
|
134
|
+
# Options:
|
135
|
+
# * +oid+ The SNMP OID
|
136
|
+
# * +type+ The data type. Possible values include Net::SNMP::ASN_OCTET_STR, Net::SNMP::ASN_COUNTER, etc. See constants.rb
|
137
|
+
# * +value+ The value of the varbind. default is nil.
|
138
|
+
def add_varbind(options)
|
139
|
+
options[:type] ||= case options[:value]
|
140
|
+
when String
|
141
|
+
Constants::ASN_OCTET_STR
|
142
|
+
when Fixnum
|
143
|
+
Constants::ASN_INTEGER
|
144
|
+
when Net::SNMP::OID
|
145
|
+
Constants::ASN_OBJECT_ID
|
146
|
+
when nil
|
147
|
+
Constants::ASN_NULL
|
148
|
+
else
|
149
|
+
raise "Unknown value type"
|
150
|
+
end
|
151
|
+
|
152
|
+
value = options[:value]
|
153
|
+
value_len = case options[:type]
|
154
|
+
when Constants::ASN_NULL,
|
155
|
+
Constants::SNMP_NOSUCHOBJECT,
|
156
|
+
Constants::SNMP_NOSUCHINSTANCE,
|
157
|
+
Constants::SNMP_ENDOFMIBVIEW
|
158
|
+
0
|
159
|
+
else
|
160
|
+
options[:value].size
|
161
|
+
end
|
162
|
+
|
163
|
+
value = case options[:type]
|
164
|
+
when Constants::ASN_INTEGER,
|
165
|
+
Constants::ASN_GAUGE,
|
166
|
+
Constants::ASN_COUNTER,
|
167
|
+
Constants::ASN_TIMETICKS,
|
168
|
+
Constants::ASN_UNSIGNED
|
169
|
+
new_val = FFI::MemoryPointer.new(:long)
|
170
|
+
new_val.write_long(value)
|
171
|
+
new_val
|
172
|
+
when Constants::ASN_OCTET_STR,
|
173
|
+
Constants::ASN_BIT_STR,
|
174
|
+
Constants::ASN_OPAQUE
|
175
|
+
value
|
176
|
+
when Constants::ASN_IPADDRESS
|
177
|
+
# TODO
|
178
|
+
when Constants::ASN_OBJECT_ID
|
179
|
+
value.pointer
|
180
|
+
when Constants::ASN_NULL,
|
181
|
+
Constants::SNMP_NOSUCHOBJECT,
|
182
|
+
Constants::SNMP_NOSUCHINSTANCE,
|
183
|
+
Constants::SNMP_ENDOFMIBVIEW
|
184
|
+
nil
|
185
|
+
else
|
186
|
+
if value.respond_to?(:pointer)
|
187
|
+
value.pointer
|
188
|
+
else
|
189
|
+
raise Net::SNMP::Error.new, "Unknown variable type #{options[:type]}"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
oid = options[:oid].kind_of?(OID) ? options[:oid] : OID.new(options[:oid])
|
194
|
+
var_ptr = Wrapper.snmp_pdu_add_variable(@struct.pointer, oid.pointer, oid.length_pointer.read_int, options[:type], value, value_len)
|
195
|
+
varbind = Varbind.new(var_ptr)
|
196
|
+
varbinds << varbind
|
197
|
+
end
|
198
|
+
|
199
|
+
def print_errors
|
200
|
+
puts "errstat = #{self.errstat}, index = #{self.errindex}, message = #{self.error_message}"
|
201
|
+
end
|
202
|
+
|
203
|
+
# Free the pdu
|
204
|
+
# Segfaults at the moment - most of the time, anyway.
|
205
|
+
# This is troublesome...
|
206
|
+
def free
|
207
|
+
# HACK
|
208
|
+
# snmp_free_pdu segfaults intermittently when freeing the enterprise
|
209
|
+
# oid if we've allocated it. Can't figure out why. For now, freeing it manually
|
210
|
+
# before calling snmp_free_pdu does the trick
|
211
|
+
if @i_own_enterprise
|
212
|
+
FFI::LibC.free(@struct.enterprise) unless @struct.enterprise.null?
|
213
|
+
@struct.enterprise = FFI::Pointer::NULL
|
214
|
+
end
|
215
|
+
Wrapper.snmp_free_pdu(@struct.pointer)
|
216
|
+
end
|
217
|
+
|
218
|
+
def print
|
219
|
+
puts "PDU"
|
220
|
+
if command == Constants::SNMP_MSG_TRAP
|
221
|
+
puts " - Enterprise: #{enterprise}"
|
222
|
+
puts " - Trap Type: #{trap_type}"
|
223
|
+
puts " - Specific Type: #{specific_type}"
|
224
|
+
puts " - Agent Addr: #{agent_addr}"
|
225
|
+
end
|
226
|
+
|
227
|
+
puts " - Varbinds:"
|
228
|
+
varbinds.each do |v|
|
229
|
+
puts " + #{MIB.translate(v.oid.to_s)}(#{v.oid}) = #{v.value}"
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|