Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/snmp/mib.rb
Views: 11766
#1# Copyright (c) 2004 David R. Halliday2# All rights reserved.3#4# This SNMP library is free software. Redistribution is permitted under the5# same terms and conditions as the standard Ruby distribution. See the6# COPYING file in the Ruby distribution for details.7#89require 'snmp/varbind'10require 'fileutils'11require 'yaml'1213module SNMP1415class MIB1617DEFAULT_MIB_PATH = File.expand_path(18File.join(File.dirname(__FILE__), "..", "..", "data", "snmp", "mibs")19)2021#:startdoc:2223MODULE_EXT = 'yaml'2425class ModuleNotLoadedError < RuntimeError; end2627class << self28##29# Import an SMIv2 MIB file for later loading. A module only needs to30# be installed once.31#32# module_file - the filename of the module to be imported33# mib_dir - the output directory for the serialized MIB data34#35# NOTE: This implementation requires that the 'smidump' tool is available36# in the PATH. This tool can be obtained from the libsmi website at37# http://http://www.ibr.cs.tu-bs.de/projects/libsmi/ .38#39# ALSO NOTE: The file format in future releases is subject to40# change. For now, it is a simple YAML hash with the MIB symbol41# as the key and the OID as the value. These files could be42# generated manually if 'smidump' is not available.43#44# Here is an example of the contents of an output file:45#46# ---47# ipDefaultTTL: 1.3.6.1.2.1.4.248# ipForwDatagrams: 1.3.6.1.2.1.4.649# ipOutRequests: 1.3.6.1.2.1.4.1050# ipOutNoRoutes: 1.3.6.1.2.1.4.1251# ipReasmTimeout: 1.3.6.1.2.1.4.1352# icmpInDestUnreachs: 1.3.6.1.2.1.5.353#54def import_module(module_file, mib_dir=DEFAULT_MIB_PATH)55raise "smidump tool must be installed" unless import_supported?56FileUtils.makedirs mib_dir57mib_hash = `smidump -f python #{module_file}`58mib = eval_mib_data(mib_hash)59if mib60module_name = mib["moduleName"]61raise "#{module_file}: invalid file format; no module name" unless module_name62if mib["nodes"]63oid_hash = {}64mib["nodes"].each { |key, value| oid_hash[key] = value["oid"] }65if mib["notifications"]66mib["notifications"].each { |key, value| oid_hash[key] = value["oid"] }67end68File.open(module_file_name(module_name, mib_dir), 'w') do |file|69YAML.dump(oid_hash, file)70file.puts71end72module_name73else74warn "*** No nodes defined in: #{module_file} ***"75nil76end77else78warn "*** Import failed for: #{module_file} ***"79nil80end81end8283##84# Returns the full filename of the imported MIB file for the given85# module name.86#87def module_file_name(module_name, mib_dir=DEFAULT_MIB_PATH)88File.join(mib_dir, module_name + "." + MODULE_EXT)89end9091##92# The MIB.import_module method is only supported if the external93# 'smidump' tool is available. This method returns true if a94# known version of the tool is available.95#96def import_supported?97`smidump --version` =~ /^smidump 0.4/ && $? == 098end99100##101# Returns a list of MIB modules that have been imported. All of102# the current IETF MIBs should be available from the default103# MIB directory.104#105# If a regex is provided, then the module names are matched106# against that pattern.107#108def list_imported(regex=//, mib_dir=DEFAULT_MIB_PATH)109list = []110Dir["#{mib_dir}/*.#{MODULE_EXT}"].each do |name|111module_name = File.basename(name, ".*")112list << module_name if module_name =~ regex113end114list115end116117private118119def eval_mib_data(mib_hash)120ruby_hash = mib_hash.121gsub(':', '=>'). # fix hash syntax122gsub('(', '[').gsub(')', ']'). # fix tuple syntax123sub('FILENAME =', 'filename ='). # get rid of constants124sub('MIB =', 'mib =')125mib = nil126eval(ruby_hash)127mib128end129end # class methods130131def initialize132@by_name = {}133@by_module_by_name = {}134end135136##137# Loads a module into this MIB. The module must be imported before it138# can be loaded. See MIB.import_module .139#140def load_module(module_name, mib_dir=DEFAULT_MIB_PATH)141oid_hash = nil142File.open(MIB.module_file_name(module_name, mib_dir)) do |file|143oid_hash = YAML.load(file.read)144end145@by_name.merge!(oid_hash) do |key, old, value|146warn "warning: overwriting old MIB name '#{key}'"147end148@by_module_by_name[module_name] = {}149@by_module_by_name[module_name].merge!(oid_hash)150end151152##153# Returns a VarBindList for the provided list of objects. If a154# string is provided it is interpreted as a symbolic OID.155#156# This method accepts many different kinds of objects:157# - single string object IDs e.g. "1.3.6.1" or "IF-MIB::ifTable.1.1"158# - single ObjectId159# - list of string object IDs160# - list of ObjectIds161# - list of VarBinds162#163def varbind_list(object_list, option=:KeepValue)164vb_list = VarBindList.new165if object_list.respond_to? :to_str166vb_list << oid(object_list).to_varbind167elsif object_list.respond_to? :to_varbind168vb_list << apply_option(object_list.to_varbind, option)169else170object_list.each do |item|171if item.respond_to? :to_str172varbind = oid(item).to_varbind173else174varbind = item.to_varbind175end176vb_list << apply_option(varbind, option)177end178end179vb_list180end181182def apply_option(varbind, option)183if option == :NullValue184varbind.value = Null185elsif option != :KeepValue186raise ArgumentError, "invalid option: #{option.to_s}", caller187end188varbind189end190private :apply_option191192##193# Returns a VarBind object for the given name and value. The name194# can be a String, ObjectId, or anything that responds to :to_varbind.195#196# String names are in the format <ModuleName>::<NodeName>.<Index> with197# ModuleName and Index being optional.198#199def varbind(name, value=Null)200if name.respond_to? :to_str201vb = VarBind.new(oid(name), value)202else203vb = name.to_varbind204vb.value = value205end206vb207end208209##210# Returns an ObjectId for the given name. Names are in the format211# <ModuleName>::<NodeName>.<Index> with ModuleName and Index being212# optional.213#214def oid(name)215module_parts = name.to_str.split("::")216if module_parts.length == 1217parse_oid(@by_name, name.to_str)218elsif module_parts.length == 2219module_name = module_parts[0]220oid = module_parts[1]221module_hash = @by_module_by_name[module_name]222if module_hash223parse_oid(module_hash, oid)224else225raise ModuleNotLoadedError, "module '#{module_name}' not loaded"226end227else228raise ArgumentError, "invalid format: #{name.to_str}"229end230end231232def parse_oid(node_hash, name)233oid_parts = name.split(".")234first_part = oid_parts.shift235oid_string = node_hash[first_part]236if oid_string237oid_array = oid_string.split(".")238else239oid_array = [first_part]240end241oid_array.concat(oid_parts)242ObjectId.new(oid_array)243end244private :parse_oid245246end247248end # module SNMP249250251