netsnmp 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.travis.yml +42 -0
- data/AUTHORS +1 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +201 -0
- data/README.md +162 -0
- data/Rakefile +26 -0
- data/lib/netsnmp.rb +16 -0
- data/lib/netsnmp/client.rb +131 -0
- data/lib/netsnmp/core.rb +12 -0
- data/lib/netsnmp/core/client.rb +15 -0
- data/lib/netsnmp/core/constants.rb +153 -0
- data/lib/netsnmp/core/inline.rb +20 -0
- data/lib/netsnmp/core/libc.rb +48 -0
- data/lib/netsnmp/core/libsnmp.rb +44 -0
- data/lib/netsnmp/core/structures.rb +167 -0
- data/lib/netsnmp/core/utilities.rb +13 -0
- data/lib/netsnmp/errors.rb +8 -0
- data/lib/netsnmp/handlers/celluloid.rb +27 -0
- data/lib/netsnmp/handlers/em.rb +56 -0
- data/lib/netsnmp/oid.rb +94 -0
- data/lib/netsnmp/pdu.rb +105 -0
- data/lib/netsnmp/session.rb +306 -0
- data/lib/netsnmp/varbind.rb +181 -0
- data/lib/netsnmp/version.rb +3 -0
- data/netsnmp.gemspec +36 -0
- data/spec/client_spec.rb +90 -0
- data/spec/core/libc_spec.rb +2 -0
- data/spec/core/libsnmp_spec.rb +32 -0
- data/spec/core/structures_spec.rb +54 -0
- data/spec/handlers/celluloid_spec.rb +29 -0
- data/spec/handlers/em_client_spec.rb +34 -0
- data/spec/oid_spec.rb +9 -0
- data/spec/pdu_spec.rb +29 -0
- data/spec/session_spec.rb +34 -0
- data/spec/spec_helper.rb +114 -0
- data/spec/support/Dockerfile +14 -0
- data/spec/support/celluloid.rb +22 -0
- data/spec/support/start_docker.sh +4 -0
- data/spec/support/stop_docker.sh +5 -0
- data/spec/varbind_spec.rb +54 -0
- metadata +187 -0
@@ -0,0 +1,306 @@
|
|
1
|
+
module NETSNMP
|
2
|
+
# The Entity abstracts the C net-snmp session, and the lifecycle steps.
|
3
|
+
#
|
4
|
+
# For example, a session must be initialized (memory allocated) and opened
|
5
|
+
# (authentication, encryption, signature)
|
6
|
+
#
|
7
|
+
# The session uses the signature to send and receive PDUs. They are built somewhere else.
|
8
|
+
#
|
9
|
+
# After the session is established, a socket handle is read from the structure. This will
|
10
|
+
# be later used for non-blocking behaviour. It's important to notice, there is no
|
11
|
+
# usage of the C net-snmp sync API, we always do async send/response, even if the
|
12
|
+
# ruby API "feels" blocking. This was done so that the GIL can be released between
|
13
|
+
# sends and receives, and the load can be shared through different threads possibly.
|
14
|
+
# As we use the session abstraction, this means we ONLY use the thread-safe API.
|
15
|
+
#
|
16
|
+
class Session
|
17
|
+
|
18
|
+
attr_reader :host, :signature
|
19
|
+
|
20
|
+
# @param [String] host the host IP/hostname
|
21
|
+
# @param [Hash] opts the options set
|
22
|
+
#
|
23
|
+
def initialize(host, opts)
|
24
|
+
@host = host
|
25
|
+
@options = opts
|
26
|
+
@request = nil
|
27
|
+
# For now, let's eager load the signature
|
28
|
+
@signature = build_signature(@options)
|
29
|
+
if @signature.null?
|
30
|
+
raise ConnectionFailed, "could not connect to #{host}"
|
31
|
+
end
|
32
|
+
@requests ||= {}
|
33
|
+
end
|
34
|
+
|
35
|
+
# TODO: do we need this?
|
36
|
+
def reachable?
|
37
|
+
!!transport
|
38
|
+
end
|
39
|
+
|
40
|
+
# Closes the session
|
41
|
+
def close
|
42
|
+
return unless @signature
|
43
|
+
if @transport
|
44
|
+
transport.close rescue nil
|
45
|
+
end
|
46
|
+
if Core::LibSNMP.snmp_sess_close(@signature) == 0
|
47
|
+
raise Error, "#@host: Couldn't clean up session properly"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# sends a request PDU and waits for the response
|
52
|
+
#
|
53
|
+
# @param [RequestPDU] pdu a request pdu
|
54
|
+
# @param [Hash] opts additional options
|
55
|
+
# @option opts [true, false] :async if true, it doesn't wait for response (defaults to false)
|
56
|
+
def send(pdu, **opts)
|
57
|
+
write(pdu)
|
58
|
+
read
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def transport
|
64
|
+
@transport ||= fetch_transport
|
65
|
+
end
|
66
|
+
|
67
|
+
def write(pdu)
|
68
|
+
wait_writable
|
69
|
+
async_send(pdu)
|
70
|
+
end
|
71
|
+
|
72
|
+
def async_send(pdu)
|
73
|
+
if ( @reqid = Core::LibSNMP.snmp_sess_async_send(@signature, pdu.pointer, session_callback, nil) ) == 0
|
74
|
+
# it's interesting, pdu's are only fred if the async send is successful... netsnmp 1 - me 0
|
75
|
+
Core::LibSNMP.snmp_free_pdu(pdu.pointer)
|
76
|
+
raise SendError, "#@host: Failed to send pdu"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def read
|
81
|
+
receive # trigger callback ahead of time and wait for it
|
82
|
+
handle_response
|
83
|
+
end
|
84
|
+
|
85
|
+
def handle_response
|
86
|
+
operation, response_pdu = @requests.delete(@reqid)
|
87
|
+
case operation
|
88
|
+
when :send_failed
|
89
|
+
raise ReceiveError, "#@host: Failed to receive pdu"
|
90
|
+
when :timeout
|
91
|
+
raise Timeout::Error, "#@host: timed out while waiting for pdu response"
|
92
|
+
when :success
|
93
|
+
response_pdu
|
94
|
+
else
|
95
|
+
raise Error, "#@host: unrecognized operation for request #{@reqid}: #{operation} for #{response_pdu}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def receive
|
100
|
+
readers, _ = wait_readable
|
101
|
+
case readers.size
|
102
|
+
when 1..Float::INFINITY
|
103
|
+
# triggers callback
|
104
|
+
async_read
|
105
|
+
when 0
|
106
|
+
Core::LibSNMP.snmp_sess_timeout(@signature)
|
107
|
+
else
|
108
|
+
raise ReceiveError, "#@host: error receiving data"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def async_read
|
113
|
+
if Core::LibSNMP.snmp_sess_read(@signature, get_selectable_sockets.pointer) != 0
|
114
|
+
raise ReceiveError, "#@host: Failed to receive pdu response"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def timeout
|
119
|
+
Core::LibSNMP.snmp_sess_timeout(@signature)
|
120
|
+
end
|
121
|
+
|
122
|
+
def wait_writable
|
123
|
+
IO.select([],[transport])
|
124
|
+
end
|
125
|
+
|
126
|
+
def wait_readable
|
127
|
+
IO.select([transport])
|
128
|
+
end
|
129
|
+
|
130
|
+
def get_selectable_sockets
|
131
|
+
fdset = Core::C::FDSet.new
|
132
|
+
fdset.clear
|
133
|
+
num_fds = FFI::MemoryPointer.new(:int)
|
134
|
+
tv_sec = 0
|
135
|
+
tv_usec = 0
|
136
|
+
tval = Core::C::Timeval.new
|
137
|
+
tval[:tv_sec] = tv_sec
|
138
|
+
tval[:tv_usec] = tv_usec
|
139
|
+
block = FFI::MemoryPointer.new(:int)
|
140
|
+
block.write_int(0)
|
141
|
+
Core::LibSNMP.snmp_sess_select_info(@signature, num_fds, fdset.pointer, tval.pointer, block )
|
142
|
+
fdset
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
# @param [Core::Structures::Session] session the snmp session structure
|
147
|
+
# @param [Hash] options session options with authorization parameters
|
148
|
+
# @option options [String] :version the snmp protocol version (if < 3, forget the rest)
|
149
|
+
# @option options [Integer, nil] :security_level the SNMP security level (defaults to authPriv)
|
150
|
+
# @option options [Symbol, nil] :auth_protocol the authorization protocol (ex: :md5, :sha1)
|
151
|
+
# @option options [Symbol, nil] :priv_protocol the privacy protocol (ex: :aes, :des)
|
152
|
+
# @option options [String, nil] :context the authoritative context
|
153
|
+
# @option options [String] :version the snmp protocol version (defaults to 3, if not 3, you actually don't need the rest)
|
154
|
+
# @option options [String] :username the username to login with
|
155
|
+
# @option options [String] :auth_password the authorization password
|
156
|
+
# @option options [String] :priv_password the privacy password
|
157
|
+
def session_authorization(session, options)
|
158
|
+
# we support version 3 by default
|
159
|
+
session[:version] = case options[:version]
|
160
|
+
when /v?1/ then Core::Constants::SNMP_VERSION_1
|
161
|
+
when /v?2c?/ then Core::Constants::SNMP_VERSION_2c
|
162
|
+
when /v?3/, nil then Core::Constants::SNMP_VERSION_3
|
163
|
+
end
|
164
|
+
return unless session[:version] == Core::Constants::SNMP_VERSION_3
|
165
|
+
|
166
|
+
|
167
|
+
# Security Authorization
|
168
|
+
session[:securityLevel] = options[:security_level] || Core::Constants::SNMP_SEC_LEVEL_AUTHPRIV
|
169
|
+
auth_protocol_oid = case options[:auth_protocol]
|
170
|
+
when :md5 then MD5OID.new
|
171
|
+
when :sha1 then SHA1OID.new
|
172
|
+
when nil then NoAuthOID.new
|
173
|
+
else raise Error, "#@host: #{options[:auth_protocol]} is an unsupported authorization protocol"
|
174
|
+
end
|
175
|
+
|
176
|
+
session[:securityAuthProto] = auth_protocol_oid.pointer
|
177
|
+
|
178
|
+
# Priv Protocol
|
179
|
+
priv_protocol_oid = case options[:priv_protocol]
|
180
|
+
when :aes then AESOID.new
|
181
|
+
when :des then DESOID.new
|
182
|
+
when nil then NoPrivOID.new
|
183
|
+
else raise Error, "#@host: #{options[:priv_protocol]} is an unsupported privacy protocol"
|
184
|
+
end
|
185
|
+
session[:securityPrivProto] = priv_protocol_oid.pointer
|
186
|
+
|
187
|
+
# other necessary lengths
|
188
|
+
session[:securityAuthProtoLen] = 10
|
189
|
+
session[:securityAuthKeyLen] = Core::Constants::USM_AUTH_KU_LEN
|
190
|
+
session[:securityPrivProtoLen] = 10
|
191
|
+
session[:securityPrivKeyLen] = Core::Constants::USM_PRIV_KU_LEN
|
192
|
+
|
193
|
+
|
194
|
+
if options[:context]
|
195
|
+
session[:contextName] = FFI::MemoryPointer.from_string(options[:context])
|
196
|
+
session[:contextNameLen] = options[:context].length
|
197
|
+
end
|
198
|
+
|
199
|
+
# Authentication
|
200
|
+
# Do not generate_Ku, unless we're Auth or AuthPriv
|
201
|
+
auth_user, auth_pass = options.values_at(:username, :auth_password)
|
202
|
+
raise Error, "#@host: no given Authorization User" unless auth_user
|
203
|
+
session[:securityName] = FFI::MemoryPointer.from_string(auth_user)
|
204
|
+
session[:securityNameLen] = auth_user.length
|
205
|
+
|
206
|
+
auth_len_ptr = FFI::MemoryPointer.new(:size_t)
|
207
|
+
auth_len_ptr.write_int(Core::Constants::USM_AUTH_KU_LEN)
|
208
|
+
auth_key_result = Core::LibSNMP.generate_Ku(session[:securityAuthProto],
|
209
|
+
session[:securityAuthProtoLen],
|
210
|
+
auth_pass,
|
211
|
+
auth_pass.length,
|
212
|
+
session[:securityAuthKey],
|
213
|
+
auth_len_ptr)
|
214
|
+
session[:securityAuthKeyLen] = auth_len_ptr.read_int
|
215
|
+
|
216
|
+
priv_len_ptr = FFI::MemoryPointer.new(:size_t)
|
217
|
+
priv_len_ptr.write_int(Core::Constants::USM_PRIV_KU_LEN)
|
218
|
+
|
219
|
+
priv_pass = options[:priv_password]
|
220
|
+
# NOTE I know this is handing off the AuthProto, but generates a proper
|
221
|
+
# key for encryption, and using PrivProto does not.
|
222
|
+
priv_key_result = Core::LibSNMP.generate_Ku(session[:securityAuthProto],
|
223
|
+
session[:securityAuthProtoLen],
|
224
|
+
priv_pass,
|
225
|
+
priv_pass.length,
|
226
|
+
session[:securityPrivKey],
|
227
|
+
priv_len_ptr)
|
228
|
+
session[:securityPrivKeyLen] = priv_len_ptr.read_int
|
229
|
+
|
230
|
+
unless auth_key_result == Core::Constants::SNMPERR_SUCCESS and
|
231
|
+
priv_key_result == Core::Constants::SNMPERR_SUCCESS
|
232
|
+
raise AuthenticationFailed, "failed to authenticate #{auth_user} in #{@host}"
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
|
237
|
+
# @param [Hash] options options to open the net-snmp session
|
238
|
+
# @option options [String] :community the snmp community string (defaults to public)
|
239
|
+
# @option options [Integer] :timeout number of millisecs until first timeout
|
240
|
+
# @option options [Integer] :retries number of retries before timeout
|
241
|
+
# @return [FFI::Pointer] a pointer to the validated session signature, which will therefore be used in all _sess_ methods from libnetsnmp
|
242
|
+
def build_signature(options)
|
243
|
+
# allocate new session
|
244
|
+
session = Core::Structures::Session.new(nil)
|
245
|
+
Core::LibSNMP.snmp_sess_init(session.pointer)
|
246
|
+
|
247
|
+
# initialize session
|
248
|
+
if options[:community]
|
249
|
+
community = options[:community]
|
250
|
+
session[:community] = FFI::MemoryPointer.from_string(community)
|
251
|
+
session[:community_len] = community.length
|
252
|
+
end
|
253
|
+
|
254
|
+
peername = host
|
255
|
+
unless peername[':']
|
256
|
+
port = options[:port] || '161'.freeze
|
257
|
+
peername = "#{peername}:#{port}"
|
258
|
+
end
|
259
|
+
|
260
|
+
session[:peername] = FFI::MemoryPointer.from_string(peername)
|
261
|
+
|
262
|
+
session[:timeout] = options[:timeout] if options.has_key?(:timeout)
|
263
|
+
session[:retries] = options[:retries] if options.has_key?(:retries)
|
264
|
+
|
265
|
+
session_authorization(session, options)
|
266
|
+
Core::LibSNMP.snmp_sess_open(session.pointer)
|
267
|
+
end
|
268
|
+
|
269
|
+
def fetch_transport
|
270
|
+
return unless @signature
|
271
|
+
list = Core::Structures::SessionList.new @signature
|
272
|
+
return if not list or list.pointer.null?
|
273
|
+
t = Core::Structures::Transport.new list[:transport]
|
274
|
+
IO.new(t[:sock])
|
275
|
+
end
|
276
|
+
|
277
|
+
# @param [Core::Structures::Session] session the snmp session structure
|
278
|
+
def session_callback
|
279
|
+
@callback ||= FFI::Function.new(:int, [:int, :pointer, :int, :pointer, :pointer]) do |operation, session, reqid, pdu_ptr, magic|
|
280
|
+
op = case operation
|
281
|
+
when Core::Constants::NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE then :success
|
282
|
+
when Core::Constants::NETSNMP_CALLBACK_OP_TIMED_OUT then :timeout
|
283
|
+
when Core::Constants::NETSNMP_CALLBACK_OP_SEND_FAILED then :send_failed
|
284
|
+
when Core::Constants::NETSNMP_CALLBACK_OP_CONNECT then :connect
|
285
|
+
when Core::Constants::NETSNMP_CALLBACK_OP_DISCONNECT then :disconnect
|
286
|
+
else :unrecognized_operation
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
# TODO: pass exception in case of failure
|
291
|
+
|
292
|
+
if reqid == @reqid
|
293
|
+
response_pdu = ResponsePDU.new(pdu_ptr)
|
294
|
+
# probably pass the result as a yield from a fiber
|
295
|
+
@requests[@reqid] = [op, response_pdu]
|
296
|
+
|
297
|
+
op.eql?(:unrecognized_operation) ? 0 : 1
|
298
|
+
else
|
299
|
+
puts "wow, unexpected #{op}.... #{reqid} different than #{@reqid}"
|
300
|
+
0
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
module NETSNMP
|
2
|
+
# Abstracts the PDU variable structure into a ruby object
|
3
|
+
#
|
4
|
+
class Varbind
|
5
|
+
Error = Class.new(Error)
|
6
|
+
|
7
|
+
attr_reader :struct
|
8
|
+
|
9
|
+
# @param [FFI::Pointer] pointer to the variable list
|
10
|
+
def initialize(pointer)
|
11
|
+
@struct = Core::Structures::VariableList.new(pointer)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
# Abstracts the Varbind used for the PDU Request
|
17
|
+
class RequestVarbind < Varbind
|
18
|
+
|
19
|
+
# @param [RequestPDU] pdu the request pdu for this varbind
|
20
|
+
# @param [OID] oid the oid for this varbind
|
21
|
+
# @param [Object] value the value for the oid
|
22
|
+
# @param [Hash] options additional options
|
23
|
+
# @option options [Symbol, Integer, nil] :type C net-snmp type flag,
|
24
|
+
# type-label for value (see #convert_type), if not set it's inferred from the value
|
25
|
+
#
|
26
|
+
def initialize(pdu, oid, value, options={})
|
27
|
+
type = case options[:type]
|
28
|
+
when Integer then options[:type] # assume that the code is properly passed
|
29
|
+
when Symbol then convert_type(options[:type]) # DSL-specific API
|
30
|
+
when nil then infer_from_value(value)
|
31
|
+
else
|
32
|
+
raise Error, "#{options[:type]} is an unsupported type"
|
33
|
+
end
|
34
|
+
|
35
|
+
value_length = case type
|
36
|
+
when Core::Constants::ASN_NULL,
|
37
|
+
Core::Constants::SNMP_NOSUCHOBJECT,
|
38
|
+
Core::Constants::SNMP_NOSUCHINSTANCE,
|
39
|
+
Core::Constants::SNMP_ENDOFMIBVIEW
|
40
|
+
0
|
41
|
+
else value ? value.size : 0
|
42
|
+
end
|
43
|
+
value = convert_value(value, type)
|
44
|
+
|
45
|
+
pointer = Core::LibSNMP.snmp_pdu_add_variable(pdu.pointer, oid.pointer, oid.length, type, value, value_length)
|
46
|
+
super(pointer)
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# @param [Object] value value to infer the type from
|
53
|
+
# @return [Integer] the C net-snmp flag indicating the type
|
54
|
+
# @raise [Error] when the value is from an unexpected type
|
55
|
+
#
|
56
|
+
def infer_from_value(value)
|
57
|
+
case value
|
58
|
+
when String then Core::Constants::ASN_OCTET_STR
|
59
|
+
when Fixnum then Core::Constants::ASN_INTEGER
|
60
|
+
when OID then Core::Constants::ASN_OBJECT_ID
|
61
|
+
when nil then Core::Constants::ASN_NULL
|
62
|
+
else raise Error, "#{value} is from an unsupported type"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# @param [Symbol] symbol_type symbol representing the type
|
67
|
+
# @return [Integer] the C net-snmp flag indicating the type
|
68
|
+
# @raise [Error] when the symbol is unsupported
|
69
|
+
#
|
70
|
+
def convert_type(symbol_type)
|
71
|
+
case symbol_type
|
72
|
+
when :integer then Core::Constants::ASN_INTEGER
|
73
|
+
when :gauge then Core::Constants::ASN_GAUGE
|
74
|
+
when :counter then Core::Constants::ASN_COUNTER
|
75
|
+
when :timeticks then Core::Constants::ASN_TIMETICKS
|
76
|
+
when :unsigned then Core::Constants::ASN_UNSIGNED
|
77
|
+
when :boolean then Core::Constants::ASN_BOOLEAN
|
78
|
+
when :string then Core::Constants::ASN_OCTET_STR
|
79
|
+
when :binary then Core::Constants::ASN_BIT_STR
|
80
|
+
when :ip_address then Core::Constants::ASN_IPADDRESS
|
81
|
+
else
|
82
|
+
raise Error, "#{symbol_type} cannot be converted"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# @param [Object] value the value to convert
|
87
|
+
# @param [Integer] type the C net-snmp level object type flakg
|
88
|
+
#
|
89
|
+
# @return [FFI::Pointer] pointer to the memory location where the value is stored
|
90
|
+
#
|
91
|
+
def convert_value(value, type)
|
92
|
+
case type
|
93
|
+
when Core::Constants::ASN_INTEGER,
|
94
|
+
Core::Constants::ASN_GAUGE,
|
95
|
+
Core::Constants::ASN_COUNTER,
|
96
|
+
Core::Constants::ASN_TIMETICKS,
|
97
|
+
Core::Constants::ASN_UNSIGNED
|
98
|
+
new_val = FFI::MemoryPointer.new(:long)
|
99
|
+
new_val.write_long(value)
|
100
|
+
new_val
|
101
|
+
when Core::Constants::ASN_OCTET_STR,
|
102
|
+
Core::Constants::ASN_BIT_STR,
|
103
|
+
Core::Constants::ASN_OPAQUE
|
104
|
+
value
|
105
|
+
when Core::Constants::ASN_IPADDRESS
|
106
|
+
# TODO
|
107
|
+
when Core::Constants::ASN_OBJECT_ID
|
108
|
+
value.pointer
|
109
|
+
when Core::Constants::ASN_NULL,
|
110
|
+
Core::Constants::SNMP_NOSUCHOBJECT,
|
111
|
+
Core::Constants::SNMP_NOSUCHINSTANCE,
|
112
|
+
Core::Constants::SNMP_ENDOFMIBVIEW
|
113
|
+
nil
|
114
|
+
else
|
115
|
+
raise Error, "Unknown variable type: #{type}"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Abstracts the Varbind used for the PDU Response
|
121
|
+
#
|
122
|
+
class ResponseVarbind < Varbind
|
123
|
+
|
124
|
+
attr_reader :value, :oid_code
|
125
|
+
|
126
|
+
# @param [FFI::Pointer] pointer pointer to the response varbind structure
|
127
|
+
#
|
128
|
+
# @note it loads the value and oid code on initialization
|
129
|
+
#
|
130
|
+
def initialize(pointer)
|
131
|
+
super
|
132
|
+
@value = load_varbind_value
|
133
|
+
@oid_code = load_oid_code
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
|
138
|
+
# @return [String] the oid code from the varbind
|
139
|
+
def load_oid_code
|
140
|
+
OID.read_pointer(@struct[:name], @struct[:name_length])
|
141
|
+
end
|
142
|
+
|
143
|
+
# @return [Object] the value for the varbind (a ruby type, a string, an integer, a symbol etc...)
|
144
|
+
#
|
145
|
+
def load_varbind_value
|
146
|
+
object_type = @struct[:type]
|
147
|
+
case object_type
|
148
|
+
when Core::Constants::ASN_OCTET_STR,
|
149
|
+
Core::Constants::ASN_OPAQUE
|
150
|
+
@struct[:val][:string].read_string(@struct[:val_len])
|
151
|
+
when Core::Constants::ASN_INTEGER
|
152
|
+
@struct[:val][:integer].read_long
|
153
|
+
when Core::Constants::ASN_UINTEGER,
|
154
|
+
Core::Constants::ASN_TIMETICKS,
|
155
|
+
Core::Constants::ASN_COUNTER,
|
156
|
+
Core::Constants::ASN_GAUGE
|
157
|
+
@struct[:val][:integer].read_ulong
|
158
|
+
when Core::Constants::ASN_IPADDRESS
|
159
|
+
@struct[:val][:objid].read_string(@struct[:val_len]).unpack('CCCC').join(".")
|
160
|
+
when Core::Constants::ASN_NULL
|
161
|
+
nil
|
162
|
+
when Core::Constants::ASN_OBJECT_ID
|
163
|
+
OID.from_pointer(@struct[:val][:objid], @struct[:val_len] / OID.default_size)
|
164
|
+
when Core::Constants::ASN_COUNTER64
|
165
|
+
counter = Core::Structures::Counter64.new(@struct[:val][:counter64])
|
166
|
+
counter[:high] * 2^32 + counter[:low]
|
167
|
+
when Core::Constants::ASN_BIT_STR
|
168
|
+
# XXX not sure what to do here. Is this obsolete?
|
169
|
+
when Core::Constants::SNMP_ENDOFMIBVIEW
|
170
|
+
:endofmibview
|
171
|
+
when Core::Constants::SNMP_NOSUCHOBJECT
|
172
|
+
:nosuchobject
|
173
|
+
when Core::Constants::SNMP_NOSUCHINSTANCE
|
174
|
+
:nosuchinstance
|
175
|
+
else
|
176
|
+
raise Error, "#{object_type} is an invalid type"
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
end
|