Class: SNMP::MIB

Inherits:
Object
  • Object
show all
Defined in:
lib/snmp/mib.rb

Defined Under Namespace

Classes: ModuleNotLoadedError

Constant Summary collapse

DEFAULT_MIB_PATH =
if (File.exist?(data_path))
  data_path
else
  warn "Could not find default MIB directory, tried:\n  #{data_path}"
  nil
end
MODULE_EXT =

:startdoc:

'yaml'

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeMIB

class methods



150
151
152
153
154
# File 'lib/snmp/mib.rb', line 150

def initialize
  @by_name = {}
  @by_module_by_name = {}
  @by_oid = {}
end

Class Method Details

.import_module(module_file, mib_dir = DEFAULT_MIB_PATH) ⇒ Object

Import an SMIv2 MIB file for later loading. A module only needs to be installed once.

module_file - the filename of the module to be imported
mib_dir - the output directory for the serialized MIB data

NOTE: This implementation requires that the ‘smidump’ tool is available in the PATH. This tool can be obtained from the libsmi website at http://www.ibr.cs.tu-bs.de/projects/libsmi/ .

ALSO NOTE: The file format in future releases is subject to change. For now, it is a simple YAML hash with the MIB symbol as the key and the OID as the value. These files could be generated manually if ‘smidump’ is not available.

Here is an example of the contents of an output file:

---
ipDefaultTTL: 1.3.6.1.2.1.4.2
ipForwDatagrams: 1.3.6.1.2.1.4.6
ipOutRequests: 1.3.6.1.2.1.4.10
ipOutNoRoutes: 1.3.6.1.2.1.4.12
ipReasmTimeout: 1.3.6.1.2.1.4.13
icmpInDestUnreachs: 1.3.6.1.2.1.5.3


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/snmp/mib.rb', line 73

def import_module(module_file, mib_dir=DEFAULT_MIB_PATH)
  raise "smidump tool must be installed" unless import_supported?
  FileUtils.makedirs mib_dir
  mib_hash = `smidump -k -f python #{module_file}`
  mib = eval_mib_data(mib_hash)
  if mib
    module_name = mib["moduleName"]
    raise "#{module_file}: invalid file format; no module name" unless module_name
    if mib["nodes"]
      oid_hash = {}
      mib["nodes"].each { |key, value| oid_hash[key] = value["oid"] }
      if mib["notifications"]
        mib["notifications"].each { |key, value| oid_hash[key] = value["oid"] }
      end
      File.open(module_file_name(module_name, mib_dir), 'w') do |file|
        YAML.dump(oid_hash, file)
        file.puts
      end
      module_name
    else
      warn "*** No nodes defined in: #{module_file} ***"
      nil
    end
  else
    warn "*** Import failed for: #{module_file} ***"
    nil
  end
end

.import_supported?Boolean

The MIB.import_module method is only supported if the external ‘smidump’ tool is available. This method returns true if a known version of the tool is available.

Returns:

  • (Boolean)


115
116
117
# File 'lib/snmp/mib.rb', line 115

def import_supported?
  `smidump --version` =~ /^smidump 0.[45]/  && $? == 0
end

.list_imported(regex = //, mib_dir = DEFAULT_MIB_PATH) ⇒ Object

Returns a list of MIB modules that have been imported. All of the current IETF MIBs should be available from the default MIB directory.

If a regex is provided, then the module names are matched against that pattern.



127
128
129
130
131
132
133
134
# File 'lib/snmp/mib.rb', line 127

def list_imported(regex=//, mib_dir=DEFAULT_MIB_PATH)
  list = []
  Dir["#{mib_dir}/*.#{MODULE_EXT}"].each do |name|
    module_name = File.basename(name, ".*")
    list << module_name if module_name =~ regex
  end
  list
end

.module_file_name(module_name, mib_dir = DEFAULT_MIB_PATH) ⇒ Object

Returns the full filename of the imported MIB file for the given module name.



106
107
108
# File 'lib/snmp/mib.rb', line 106

def module_file_name(module_name, mib_dir=DEFAULT_MIB_PATH)
  File.join(mib_dir, module_name + "." + MODULE_EXT)
end

Instance Method Details

#load_module(module_name, mib_dir = DEFAULT_MIB_PATH) ⇒ Object

Loads a module into this MIB. The module must be imported before it can be loaded. See MIB.import_module .



160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/snmp/mib.rb', line 160

def load_module(module_name, mib_dir=DEFAULT_MIB_PATH)
  oid_hash = nil
  File.open(MIB.module_file_name(module_name, mib_dir)) do |file|
    oid_hash = YAML.load(file.read)
  end
  @by_name.merge!(oid_hash) do |key, old, value|
    warn "warning: overwriting old MIB name '#{key}'"
  end
  @by_module_by_name[module_name] = {}
  @by_module_by_name[module_name].merge!(oid_hash)

  name_hash = Hash[ oid_hash.invert.to_a.collect { |oid, name| [oid, "#{module_name}::#{name}"] } ]
  @by_oid.merge!(name_hash)
end

#name(oid) ⇒ Object

Returns the symbolic name of the given OID.

e.g. OID “1.3.6.1.2.1.1.0” returns symbol “SNMPv2-MIB::system.0”



261
262
263
264
265
266
267
268
269
270
271
272
# File 'lib/snmp/mib.rb', line 261

def name(oid)
  current_oid = ObjectId.new(oid)
  index = []
  while current_oid.size > 1
    name = @by_oid[current_oid.to_s]
    if name
      return index.empty? ? name : "#{name}.#{index.join('.')}"
    end
    index.unshift current_oid.slice!(-1)
  end
  ObjectId.new(oid).to_s
end

#oid(name) ⇒ Object

Returns an ObjectId for the given name. Names are in the format <ModuleName>::<NodeName>.<Index> with ModuleName and Index being optional.



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/snmp/mib.rb', line 238

def oid(name)
  module_parts = name.to_str.split("::")
  if module_parts.length == 1
    parse_oid(@by_name, name.to_str)
  elsif module_parts.length == 2
    module_name = module_parts[0]
    oid = module_parts[1]
    module_hash = @by_module_by_name[module_name]
    if module_hash
      parse_oid(module_hash, oid)
    else
      raise ModuleNotLoadedError, "module '#{module_name}' not loaded"
    end
  else
    raise ArgumentError, "invalid format: #{name.to_str}"
  end
end

#varbind(name, value = Null) ⇒ Object

Returns a VarBind object for the given name and value. The name can be a String, ObjectId, or anything that responds to :to_varbind.

String names are in the format <ModuleName>::<NodeName>.<Index> with ModuleName and Index being optional.



223
224
225
226
227
228
229
230
231
# File 'lib/snmp/mib.rb', line 223

def varbind(name, value=Null)
  if name.respond_to? :to_str
    vb = VarBind.new(oid(name), value)
  else
    vb = name.to_varbind
    vb.value = value
  end
  vb
end

#varbind_list(object_list, option = :KeepValue) ⇒ Object

Returns a VarBindList for the provided list of objects. If a string is provided it is interpretted as a symbolic OID.

This method accepts many different kinds of objects:

  • single string object IDs e.g. “1.3.6.1” or “IF-MIB::ifTable.1.1”

  • single ObjectId

  • list of string object IDs

  • list of ObjectIds

  • list of VarBinds

Raises:

  • (ArgumentError)


186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/snmp/mib.rb', line 186

def varbind_list(object_list, option=:KeepValue)
  raise ArgumentError, "A list of ObjectId or VarBind objects is NilClass" if object_list.nil?
  vb_list = VarBindList.new
  if object_list.respond_to? :to_str
    vb_list << oid(object_list).to_varbind
  elsif object_list.respond_to? :to_varbind
    vb_list << apply_option(object_list.to_varbind, option)
  else
    object_list.each do |item|
      if item.respond_to? :to_str
        varbind = oid(item).to_varbind
      else
        varbind = item.to_varbind
      end
      vb_list << apply_option(varbind, option)
    end
  end
  vb_list
end