development on snmp

This commit is contained in:
blackhedd 2006-12-15 13:55:13 +00:00
parent cf82f83ddf
commit 19452a6206

View file

@ -4,7 +4,7 @@
# #
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# #
# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved. # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
# #
# Gmail: garbagecat10 # Gmail: garbagecat10
# #
@ -54,53 +54,161 @@ module Net
class SnmpPdu class SnmpPdu
class Error < Exception; end class Error < Exception; end
attr_reader :version, :community, :pdu_type, :request_id, :variables PduTypes = [
:get_request,
:get_next_request,
:get_response,
:set_request,
:trap
]
ErrorStatusCodes = { # Per RFC1157, pgh 4.1.1
0 => "noError",
1 => "tooBig",
2 => "noSuchName",
3 => "badValue",
4 => "readOnly",
5 => "genErr"
}
class << self
def parse ber_object
n = new
n.send :parse, ber_object
n
end
end
attr_reader :version, :community, :pdu_type, :variables, :error_status
attr_accessor :request_id, :error_index
def initialize args={}
@version = args[:version] || 0
@community = args[:community] || "public"
@pdu_type = args[:pdu_type] # leave nil unless specified; there's no reasonable default value.
@error_status = args[:error_status] || 0
@error_index = args[:error_index] || 0
end
#-- #--
# TODO, improve the error-trapping. def parse ber_object
# We want to wrap up Ruby errors like array-ranges, which can appear if we get bad data.
# We should probably do the whole parse under a catch-all block.
def initialize ber_object
begin begin
parse_ber_object ber_object parse_ber_object ber_object
rescue RuntimeError rescue Error
# Pass through any SnmpPdu::Error instances
raise $!
rescue
# Wrap any basic parsing error so it becomes a PDU-format error # Wrap any basic parsing error so it becomes a PDU-format error
raise Error.new( "snmp-pdu format error" ) raise Error.new( "snmp-pdu format error" )
end end
end end
private :parse
def parse_ber_object ber_object def parse_ber_object ber_object
@version = ber_object[0].to_i version= ber_object[0].to_i
unless [0,2].include?(@version)
raise Error.new("unknown snmp-version: #{@version}")
end
@community = ber_object[1].to_s community= ber_object[1].to_s
data = ber_object[2] data = ber_object[2]
app_tag = data.ber_identifier & 31 case (app_tag = data.ber_identifier & 31)
case app_tag
when 0 when 0
@pdu_type = :get_request send :pdu_type=, :get_request
parse_get_request data parse_get_request data
else else
raise Error.new( "unknown snmp-pdu type: #{app_tag}" ) raise Error.new( "unknown snmp-pdu type: #{app_tag}" )
end end
end end
private :parse_ber_object
#-- #--
# Defined in RFC1157, pgh 4.1.2. # Defined in RFC1157, pgh 4.1.2.
def parse_get_request data def parse_get_request data
@request_id = data[0].to_i send :request_id=, data[0].to_i
# data[1] is error-status, always 0. # data[1] is error-status, always 0.
# data[2] is error-index, always 0. # data[2] is error-index, always 0.
@variables = data[3].map {|v| data[3].each {|n,v|
# A variable-binding, of which there may be several, # A variable-binding, of which there may be several,
# consists of an OID and a BER null. # consists of an OID and a BER null.
# We're ignoring the null, we might want to verify it instead. # We're ignoring the null, we might want to verify it instead.
v[0] unless v.is_a?(Net::BER::BerIdentifiedNull)
raise Error.new(" invalid variable-binding in get-request" )
end
add_variable_binding n, nil
} }
end end
private :parse_get_request
def version= ver
unless [0,2].include?(ver)
raise Error.new("unknown snmp-version: #{ver}")
end
@version = ver
end
def pdu_type= t
unless PduTypes.include?(t)
raise Error.new("unknown pdu-type: #{t}")
end
@pdu_type = t
end
def error_status= es
unless ErrorStatusCodes.has_key?(es)
raise Error.new("unknown error-status: #{es}")
end
end
def community= c
@community = c.to_s
end
#--
# Syntactic sugar
def add_variable_binding name, value
@variables ||= []
@variables << [name, value]
end
def to_ber_string
[
version.to_ber,
community.to_ber,
pdu_to_ber_string
].to_ber_sequence
end
#--
# Helper method that returns a PDU payload in BER form,
# depending on the PDU type.
def pdu_to_ber_string
case pdu_type
when :get_request
[
request_id.to_ber,
error_status.to_ber,
error_index.to_ber,
[
@variables.map {|n,v|
[n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence
}
].to_ber_sequence
].to_ber_contextspecific(0)
when :get_response
[
request_id.to_ber,
error_status.to_ber,
error_index.to_ber,
[
@variables.map {|n,v|
[n.to_ber_oid, v.to_ber].to_ber_sequence
}
].to_ber_sequence
].to_ber_contextspecific(2)
else
raise Error.new( "unknown pdu-type: #{pdu_type}" )
end
end
private :pdu_to_ber_string
end end
end end