Version 5 of SNMP parser

Updated 2006-08-30 16:19:04

MJ - Because SNMP uses ASN.1 to encode packets, one can use tcllib's asn package to decode the SNMP packets. The code below implements the ::asn::decodeBer command that will create a nested list of the parsed SNMP packet.


 package require asn

 namespace eval asn {

   namespace eval util {

     proc string2hex {string} {
       binary scan $string H* t
       set res [regexp -inline -all {..} $t] 
       return [join $res " "]
     }
   }

   array set dispatch {
     02    decodeInteger
     04    decodeOctetString
     06    decodeOID
     30    decodeSequence
     40    decodeNetworkAddress
     43    decodeTimeTicks
     A4    decodeTrap-PDU
     A6    decodeInformRequest-PDU
     A7    decodeSNMPv2-Trap-PDU
   }


   proc decodeBer {raw} {
     variable dispatch

     asnGetHexTag raw hex_tag

     if {[info exists dispatch($hex_tag)] } {
        set res [$dispatch($hex_tag) $raw]
        return $res
     } else {
       dputs "Don't know how to handle: $hex_tag"
       asnGetByte raw tag
       asnGetLength raw length
       asnGetBytes raw $length value
       return [list $hex_tag [util::string2hex $value] ]
     } 
   }

   proc asnGetHexTag { data_var tag_var} {
     # no destructively get the tag
     upvar $data_var data $tag_var hex_tag
     set orig $data
     asnGetByte data tag
     set hex_tag [format %2.2X $tag]
     dputs "Part has tag $hex_tag"
     set data $orig
   }

   proc asnMorphTag { data_var tag } {
     upvar $data_var data 
     asnGetByte data dummy
     set data $tag$data
   }

   proc asnGetElement { data_var element_var } {

     upvar $data_var data $element_var element
     dputs "Getting the first element from: [util::string2hex $data]"
     set orig $data
     asnGetByte data tag
     asnGetLength data length
     asnGetBytes  data $length temp

     set remaining_length [string length $data]
     set element [string range $orig 0 end-$remaining_length] 
     dputs "Element is: [util::string2hex $element]"
     return
   } 

   proc decodeSequence {raw {type SEQUENCE}} {
     set data $raw
     asnGetSequence data sequence
     while {[string length $sequence] > 0 } {
       asnGetElement sequence element
       lappend result [decodeBer $element]
     }
     if {![info exists result] } { set result {}}
     return [list $type $result]
   }

   proc decodeTrap-PDU { raw } {
     # a trap PDU is an implicit sequence so morph it to that
     asnMorphTag raw "\x30"
     return [decodeSequence $raw Trap-PDU]
   }
   proc decodeSNMPv2-Trap-PDU { raw } {
     # an SNMPv2 trap PDU is an implicit sequence so morph it to that
     asnMorphTag raw "\x30"
     return [decodeSequence $raw SNMPv2-Trap-PDU]
   }
   proc decodeInformRequest-PDU { raw } {
     # an InformRequest PDU is an implicit sequence so morph it to that
     asnMorphTag raw "\x30"
     return [decodeSequence $raw InformRequest-PDU]
   }

   proc decodeTimeTicks { raw } {
     # a TimeTick is an implicit integer so morph it to that
     asnMorphTag raw "\x02"
     return [decodeInteger $raw TimeTicks]
   }

   proc decodeInteger {raw {type INTEGER}} {
     return [handleWithAsnLib $type asnGetInteger $raw]
   }
   proc decodeOID {raw} {
     return [handleWithAsnLib {OBJECT IDENTIFIER} asnGetObjectIdentifier $raw]
   }

   proc decodeOctetString {raw} {
     return [handleWithAsnLib OCTETSTRING asnGetOctetString $raw]
   }

   proc decodeNetworkAddress {raw} {
     asnGetByte raw dummy
     asnGetByte raw length
     asnGetBytes raw $length address
     foreach number [split $address ""] {
       lappend result [scan $number %c]
     }
     return [list IpAddress $result]
   }

   proc handleWithAsnLib {type libfunction raw} {
     dputs "Decoding $type: [util::string2hex $raw]"
     $libfunction raw result
     return [list $type $result]
   }      

 }
 proc dputs {text} {}

 package provide ber 0.1

Sample output for a SNMPv1 trap PDU

 SEQUENCE {{INTEGER 0} {OCTETSTRING OS} {Trap-PDU {{{OBJECT IDENTIFIER} {1 3 6 1 4 1 8072 3 2 3}}\ 
 {IpAddress {192 168 0 5}} {INTEGER 0} {INTEGER 0} {TimeTicks 7} {SEQUENCE {}}}}}

Category Example | Category Networking | Category Package