net-snmp2 0.3.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.
- 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,54 @@
|
|
1
|
+
module Net
|
2
|
+
module SNMP
|
3
|
+
module Debug
|
4
|
+
class << self
|
5
|
+
attr_accessor :logger
|
6
|
+
end
|
7
|
+
|
8
|
+
def debug(msg)
|
9
|
+
Debug.logger.debug msg if Debug.logger
|
10
|
+
end
|
11
|
+
|
12
|
+
def info(msg)
|
13
|
+
Debug.logger.info msg if Debug.logger
|
14
|
+
end
|
15
|
+
|
16
|
+
def warn(msg)
|
17
|
+
Debug.logger.warn msg if Debug.logger
|
18
|
+
end
|
19
|
+
|
20
|
+
def error(msg)
|
21
|
+
Debug.logger.error msg if Debug.logger
|
22
|
+
end
|
23
|
+
|
24
|
+
def fatal(msg)
|
25
|
+
Debug.logger.fatal msg if Debug.logger
|
26
|
+
end
|
27
|
+
|
28
|
+
def time(label, &block)
|
29
|
+
t_start = Time.now
|
30
|
+
block[]
|
31
|
+
t_end = Time.now
|
32
|
+
info "#{label}: #{(t_end - t_start)*1000}ms"
|
33
|
+
end
|
34
|
+
|
35
|
+
def print_packet(packet)
|
36
|
+
byte_string = (packet.kind_of?(Array) ? packet[0] : packet)
|
37
|
+
|
38
|
+
byte_array = byte_string.unpack("C*")
|
39
|
+
binary = byte_array.map{|n| n.to_s(2).rjust(8, '0')}
|
40
|
+
|
41
|
+
puts " # | Decimal | Hex | Binary | Character"
|
42
|
+
puts "-------------------------------------------"
|
43
|
+
|
44
|
+
i = 0
|
45
|
+
prev = 0
|
46
|
+
byte_array.zip(binary).each do |byte, binary_string|
|
47
|
+
puts "#{i.to_s.ljust(5)}#{byte.to_s.ljust(10)}0x#{byte.to_s(16).ljust(6)}#{binary_string.ljust(11)}#{byte.chr} #{'Sequence Length' if byte == 130 && prev == 48}"
|
48
|
+
prev = byte
|
49
|
+
i += 1
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
class Net::SNMP::Dispatcher
|
2
|
+
# A class with convenience methods for polling multiple open sessions
|
3
|
+
class << self
|
4
|
+
# Loop through all sessions, calling select on each.
|
5
|
+
def select(timeout = nil)
|
6
|
+
total = 0
|
7
|
+
t = timeout
|
8
|
+
t = nil if t == false
|
9
|
+
catch :got_data do
|
10
|
+
loop do
|
11
|
+
if Net::SNMP.thread_safe
|
12
|
+
Net::SNMP::Session.lock.synchronize {
|
13
|
+
Net::SNMP::Session.sessions.each do |k, sess|
|
14
|
+
total += sess.select(t)
|
15
|
+
end
|
16
|
+
}
|
17
|
+
else
|
18
|
+
Net::SNMP::Session.sessions.each do |k, sess|
|
19
|
+
total += sess.select(t)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
throw :got_data if total > 0
|
24
|
+
throw :got_data unless timeout == false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
total
|
28
|
+
end
|
29
|
+
alias :poll :select
|
30
|
+
|
31
|
+
# Start a poller loop. Behavior depends upon whether
|
32
|
+
# you are running under eventmachine and whether fibers
|
33
|
+
# are available.
|
34
|
+
# +options+
|
35
|
+
# * :timeout Number of seconds to block on select. nil effects a poll. false blocks forever (probably not what you want).
|
36
|
+
# * :sleep Number of seconds to sleep if no data is available. Gives other fibers/threads a chance to run.
|
37
|
+
def run_loop(options = {})
|
38
|
+
if defined?(EM) && EM.reactor_running?
|
39
|
+
if defined?(Fiber)
|
40
|
+
fiber_loop(options)
|
41
|
+
else
|
42
|
+
em_loop(options)
|
43
|
+
end
|
44
|
+
else
|
45
|
+
thread_loop(options)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Start a poller loop in a seperate thread. You
|
50
|
+
# should first call Net::SNMP.thread_safe = true.
|
51
|
+
# +options+
|
52
|
+
# * :timeout Number of seconds to block on select. Will not block other threads.
|
53
|
+
# * :sleep Number of seconds to sleep if no data is available. Allows other threads to run. Default 0.2
|
54
|
+
def thread_loop(options = {})
|
55
|
+
timeout = options[:timeout] || 0.2
|
56
|
+
sleep_time = options[:sleep] || 0.2
|
57
|
+
Thread.new do
|
58
|
+
loop do
|
59
|
+
num_ready = select(timeout)
|
60
|
+
if num_ready == 0
|
61
|
+
sleep(sleep_time) if sleep_time
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Start a loop in eventmachine (no fibers)
|
68
|
+
# +options+
|
69
|
+
# * :sleep Number of seconds to sleep if no data available. So we don't peg the reactor. Default 0.2
|
70
|
+
def em_loop(options = {})
|
71
|
+
timeout = options[:timeout]
|
72
|
+
sleep_time = options[:sleep] || 0.2
|
73
|
+
myproc = Proc.new do
|
74
|
+
EM.next_tick do
|
75
|
+
while(true) do
|
76
|
+
num_ready = select(timeout)
|
77
|
+
break if num_ready == 0
|
78
|
+
end
|
79
|
+
EM.add_timer(sleep_time) do
|
80
|
+
myproc.call
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
myproc.call
|
85
|
+
end
|
86
|
+
|
87
|
+
# Start a loop using eventmachine and fibers
|
88
|
+
# +options+
|
89
|
+
# * :sleep Number of seconds to sleep if no data available, so we don't peg the reactor. Default 0.2
|
90
|
+
def fiber_loop(options = {})
|
91
|
+
timeout = options[:timeout]
|
92
|
+
sleep_time = options[:sleep] || 0.2
|
93
|
+
fib = Fiber.new {
|
94
|
+
loop do
|
95
|
+
num_handled = poll(timeout)
|
96
|
+
if num_handled == 0
|
97
|
+
f = Fiber.current
|
98
|
+
EM.add_timer(sleep_time) do
|
99
|
+
f.resume
|
100
|
+
end
|
101
|
+
Fiber.yield
|
102
|
+
end
|
103
|
+
end
|
104
|
+
}
|
105
|
+
fib.resume
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Net
|
2
|
+
module SNMP
|
3
|
+
class Error < RuntimeError
|
4
|
+
attr_accessor :status, :errno, :snmp_err, :snmp_msg
|
5
|
+
def initialize(opts = {})
|
6
|
+
@status = opts[:status]
|
7
|
+
@fiber = opts[:fiber]
|
8
|
+
if opts[:session]
|
9
|
+
@errno = opts[:session].errno
|
10
|
+
@snmp_err = opts[:session].snmp_err
|
11
|
+
@snmp_msg = opts[:session].error_message
|
12
|
+
end
|
13
|
+
print
|
14
|
+
end
|
15
|
+
|
16
|
+
def print
|
17
|
+
puts "SNMP Error: #{self.class.to_s}"
|
18
|
+
puts "message = #{message}"
|
19
|
+
puts "status = #{@status}"
|
20
|
+
puts "errno = #{@errno}"
|
21
|
+
puts "snmp_err = #{@snmp_err}"
|
22
|
+
puts "snmp_msg = #{@snmp_msg}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class TimeoutError < Error
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
|
3
|
+
module Net::SNMP
|
4
|
+
|
5
|
+
# Implements a generic listener for incoming SNMP packets
|
6
|
+
|
7
|
+
class Listener
|
8
|
+
include Debug
|
9
|
+
|
10
|
+
attr_accessor :port, :socket, :packet, :callback
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
# Set by `stop` (probably in an INT signal handler) to
|
14
|
+
# indicate that the agent should stop
|
15
|
+
@killed = false
|
16
|
+
end
|
17
|
+
|
18
|
+
# Starts the listener's run loop
|
19
|
+
def start(port = 161, interval = 2, max_packet_size = 65_000)
|
20
|
+
@interval = interval
|
21
|
+
@socket = UDPSocket.new
|
22
|
+
@socket.bind("127.0.0.1", port)
|
23
|
+
@max_packet_size = max_packet_size
|
24
|
+
info "Listening on port #{port}"
|
25
|
+
run_loop
|
26
|
+
end
|
27
|
+
alias listen start
|
28
|
+
alias run start
|
29
|
+
|
30
|
+
# Stops the listener's run loop
|
31
|
+
def stop
|
32
|
+
@killed = true
|
33
|
+
end
|
34
|
+
alias kill stop
|
35
|
+
|
36
|
+
# Sets the handler for all incoming messages.
|
37
|
+
#
|
38
|
+
# The block provided will be called back for each message as follows:
|
39
|
+
#
|
40
|
+
# block[message, from_address, from_port]
|
41
|
+
#
|
42
|
+
# Where
|
43
|
+
#
|
44
|
+
# - `message` is the parsed Net::SNMP::Message object
|
45
|
+
# - `from_address` is a string representing the address of the host sending the request
|
46
|
+
# - `from_port` is the port the host sent the request from
|
47
|
+
def on_message(&block)
|
48
|
+
@callback = block
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def run_loop
|
54
|
+
packet = nil
|
55
|
+
loop {
|
56
|
+
begin
|
57
|
+
return if @killed
|
58
|
+
# TODO: Not exactly the most efficient solution...
|
59
|
+
timeout(@interval) do
|
60
|
+
@packet = @socket.recvfrom(@max_packet_size)
|
61
|
+
end
|
62
|
+
return if @killed
|
63
|
+
time "Message Processing" do
|
64
|
+
message = Message.parse(@packet)
|
65
|
+
@callback[message, @packet[1][3], @packet[1][1]] if @callback
|
66
|
+
end
|
67
|
+
rescue Timeout::Error => timeout
|
68
|
+
next
|
69
|
+
rescue StandardError => ex
|
70
|
+
error "Error in listener.\n#{ex}\n #{ex.backtrace.join("\n ")}"
|
71
|
+
end
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module Net
|
2
|
+
module SNMP
|
3
|
+
class Message
|
4
|
+
include SNMP::Debug
|
5
|
+
|
6
|
+
def self.parse(packet)
|
7
|
+
Message.new(packet)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Could have been an instance method, but a response pdu
|
11
|
+
# isn't really an intrinsic property of all messages. So,
|
12
|
+
# going with class method instead.
|
13
|
+
def self.response_pdu_for(message)
|
14
|
+
response_pdu = PDU.new(Constants::SNMP_MSG_RESPONSE)
|
15
|
+
response_pdu.reqid = message.pdu.reqid
|
16
|
+
response_pdu.version = message.version
|
17
|
+
response_pdu.community = message.pdu.community
|
18
|
+
response_pdu
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_accessor :version, :community, :pdu, :version_ptr, :community_ptr
|
22
|
+
|
23
|
+
def version_name
|
24
|
+
case @version
|
25
|
+
when Constants::SNMP_VERSION_1
|
26
|
+
'1'
|
27
|
+
when Constants::SNMP_VERSION_2c
|
28
|
+
'2c'
|
29
|
+
when Constants::SNMP_VERSION_3
|
30
|
+
'3'
|
31
|
+
else
|
32
|
+
raise "Invalid SNMP version: #{@version}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
attr_accessor :type,
|
39
|
+
:length,
|
40
|
+
:data,
|
41
|
+
:cursor,
|
42
|
+
:bytes_remaining
|
43
|
+
|
44
|
+
def initialize(packet)
|
45
|
+
@version = nil
|
46
|
+
@version_ptr = FFI::MemoryPointer.new(:long, 1)
|
47
|
+
@community_ptr = FFI::MemoryPointer.new(:uchar, 100)
|
48
|
+
@packet = packet
|
49
|
+
@packet_length = packet[0].length
|
50
|
+
@type_ptr = FFI::MemoryPointer.new(:int, 1)
|
51
|
+
@data_ptr = FFI::MemoryPointer.new(:char, @packet_length)
|
52
|
+
@data_ptr.write_bytes(packet[0])
|
53
|
+
@cursor_ptr = @data_ptr
|
54
|
+
@bytes_remaining_ptr = FFI::MemoryPointer.new(:int, 1)
|
55
|
+
@bytes_remaining_ptr.write_bytes([@packet_length].pack("L"))
|
56
|
+
debug "MESSAGE INITIALIZED\n#{self}"
|
57
|
+
parse
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse
|
61
|
+
parse_length
|
62
|
+
parse_version
|
63
|
+
parse_community
|
64
|
+
parse_pdu
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def parse_length
|
69
|
+
@cursor_ptr = Net::SNMP::Wrapper.asn_parse_header(@data_ptr, @bytes_remaining_ptr, @type_ptr)
|
70
|
+
unless @type_ptr.read_int == 48
|
71
|
+
raise "Invalid SNMP packet. Message should start with a sequence declaration"
|
72
|
+
end
|
73
|
+
debug "MESSAGE SEQUENCE HEADER PARSED\n#{self}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def parse_version
|
77
|
+
@cursor_ptr = Net::SNMP::Wrapper.asn_parse_int(
|
78
|
+
@cursor_ptr,
|
79
|
+
@bytes_remaining_ptr,
|
80
|
+
@type_ptr,
|
81
|
+
@version_ptr,
|
82
|
+
@version_ptr.total)
|
83
|
+
|
84
|
+
@version = @version_ptr.read_long
|
85
|
+
debug "VERSION NUMBER PARSED\n#{self}"
|
86
|
+
end
|
87
|
+
|
88
|
+
def parse_community
|
89
|
+
community_length_ptr = FFI::MemoryPointer.new(:size_t, 1)
|
90
|
+
community_length_ptr.write_int(@community_ptr.total)
|
91
|
+
@cursor_ptr = Net::SNMP::Wrapper.asn_parse_string(
|
92
|
+
@cursor_ptr,
|
93
|
+
@bytes_remaining_ptr,
|
94
|
+
@type_ptr,
|
95
|
+
@community_ptr,
|
96
|
+
community_length_ptr)
|
97
|
+
|
98
|
+
@community = @community_ptr.read_string
|
99
|
+
debug "COMMUNITY PARSED\n#{self}"
|
100
|
+
end
|
101
|
+
|
102
|
+
def parse_pdu
|
103
|
+
###########################################
|
104
|
+
# Don't do this...
|
105
|
+
#
|
106
|
+
# pdu_struct_ptr = Wrapper::SnmpPdu.new
|
107
|
+
#
|
108
|
+
# We do not want to own this pointer, or we can't call `snmp_free_pdu` on it,
|
109
|
+
# which happens in PDU#free. Instead, let the native library allocate it.
|
110
|
+
# Note that if we allocate any members for this pdu (like the enterprise oid string),
|
111
|
+
# We will have to free those ourselves before calling `snmp_free_pdu`.
|
112
|
+
#
|
113
|
+
# If the above is not done, segfaults start happening when one side tries
|
114
|
+
# to free memory malloc'ed by the other side. Possibly because the netsnmp.dll
|
115
|
+
# links to a different C Runtime library, which may have differences in malloc/free.
|
116
|
+
pdu_struct_ptr = Wrapper.snmp_pdu_create(0)
|
117
|
+
###########################################
|
118
|
+
|
119
|
+
Net::SNMP::Wrapper.snmp_pdu_parse(pdu_struct_ptr, @cursor_ptr, @bytes_remaining_ptr)
|
120
|
+
@pdu = Net::SNMP::PDU.new(pdu_struct_ptr.pointer)
|
121
|
+
debug "PDU PARSED\n#{self}"
|
122
|
+
end
|
123
|
+
|
124
|
+
def to_s
|
125
|
+
<<-EOF
|
126
|
+
version(#{@version})
|
127
|
+
community(#{@community})
|
128
|
+
pdu
|
129
|
+
command(#{@pdu.command if @pdu})
|
130
|
+
varbinds (#{@pdu.varbinds.map{|v| "\n #{v.oid.to_s} => #{v.value}" }.join('') if @pdu})
|
131
|
+
type(#{@type_ptr.read_int})
|
132
|
+
bytes_remaining(#{@bytes_remaining_ptr.read_int})
|
133
|
+
cursor @ #{@cursor_ptr.address}
|
134
|
+
Byte: #{indices = []; (@bytes_remaining_ptr.read_int.times {|i| indices.push((i+1).to_s.rjust(2))}; indices.join ' ')}
|
135
|
+
Value: #{@cursor_ptr.get_bytes(0, @bytes_remaining_ptr.read_int).each_byte.map {|b| b.to_s(16).rjust(2, '0') }.join(' ')}
|
136
|
+
data @ #{@data_ptr.address}
|
137
|
+
#{@data_ptr.get_bytes(0, @packet_length).each_byte.map {|b| b.to_s(16).rjust(2, '0') }.join(' ')}
|
138
|
+
EOF
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Net
|
2
|
+
module SNMP
|
3
|
+
module MIB
|
4
|
+
|
5
|
+
# Configures the MIB directory search path (using add_mibdir ), sets up the internal
|
6
|
+
# MIB framework, and then loads the appropriate MIB modules (using netsnmp_read_module
|
7
|
+
# and read_mib). It should be called before any other routine that manipulates
|
8
|
+
# or accesses the MIB tree (but after any additional add_mibdir calls).
|
9
|
+
def self.init
|
10
|
+
Wrapper.netsnmp_init_mib
|
11
|
+
end
|
12
|
+
|
13
|
+
# Read in all the MIB modules found on the MIB directory search list
|
14
|
+
def self.read_all_mibs
|
15
|
+
Wrapper.read_all_mibs
|
16
|
+
end
|
17
|
+
|
18
|
+
# Get an OID object representing the MIB node containing `oid`
|
19
|
+
# - `oid` argument may be a numerical oid, or the MIB name
|
20
|
+
def self.get_node(oid)
|
21
|
+
Node.get_node(oid)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Get an OID object representing the MIB node containing `oid`
|
25
|
+
# - `oid` argument may be a numerical oid, or the MIB name
|
26
|
+
def self.[](oid)
|
27
|
+
Node.get_node(oid)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Translates a numerical oid to it's MIB name, or a name to numerical oid
|
31
|
+
def self.translate(oid)
|
32
|
+
node = Node.get_node(oid)
|
33
|
+
if oid =~ /^[0-9.]*$/
|
34
|
+
# Node label + instance indexes from argument
|
35
|
+
"#{node.label}#{oid.sub(node.oid.to_s, "")}"
|
36
|
+
else
|
37
|
+
# Node OID + instance indexes from argument
|
38
|
+
"#{node.oid.to_s}#{oid.sub(node.label.to_s, "")}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Add the specified directory to the path of locations which are searched
|
43
|
+
# for files containing MIB modules. Note that this does not actually load
|
44
|
+
# the MIB modules located in that directory
|
45
|
+
def self.add_mibdir(dirname)
|
46
|
+
Wrapper.add_mibdir(dirname)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Takes the name of a MIB module (which need not be the same as the name
|
50
|
+
# of the file that contains the module), locates this within the configured
|
51
|
+
# list of MIB directories, and loads the definitions from the module into
|
52
|
+
# the active MIB tree. It also loads any MIB modules listed in the IMPORTS
|
53
|
+
# clause of this module.
|
54
|
+
def self.read_module(name)
|
55
|
+
Wrapper.netsnmp_read_module(name)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Similar to read_module, but takes the name of the file containing the MIB
|
59
|
+
# module. Note that this file need not be located within the MIB directory
|
60
|
+
# search list (although any modules listed in the IMPORTS clause do).
|
61
|
+
def self.read_mib(filename)
|
62
|
+
Wrapper.read_mib(filename)
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|