ikkeniet has asked for the wisdom of the Perl Monks concerning the following question:

It is my first time that I post something as I tend to try solving a problem without bothering other people. However I have spent 2 days Googling on this issue and I just can't fix it. I hope that a Perl GOD out there can do justice and help me out :-)

I have a simple script that receives SNMP trap messages on port 162 (UDP).

It works fine except for one thing: decoding the varbinds of the SNMP trap message. The message are sent from a CISCO firewall and commercial packages are able to decode the trap without any problems. SNMP packages are SNMPv1

The part of the trap that includes the varbinds has following HEX value:
3014060e2b06010401090929010203010200040232303013060e2b0601040109092901 +0203010300020105301d060e2b06010401090929010203010400040b5379736c6f672 +05472 617030818c060e2b06010401090929010203010500047a3130363032333a2044656e79 +2069636d7020737263206f7574736964653a3231362e3139362e36342e31323420647 +37420696e73 6964653a3230382e3130392e39302e323120287479706520382c20636f646520302920 +6279206163636573732d67726f757020226f7574736964655f6163636573735f696e2 +23016060e2b 06010401090929010203010600430473c36bf8


The code works fine for a simple trap message generated by trapgen but it seems that when there are multiple oid's then it just no longer does the job.

Here is the code
use BER; use SNMP_session; my $session = SNMPv1_Session->open_trap_session (); while (my ($trap, $sender, $sender_port) = $session->receive_trap ()) { &print_trap($session,$trap,$sender,$sender_port,$counter); } sub print_trap { my ($this, $trap, $sender, $sender_port, $counter) = @_; my $error=0; my ($community, $ent, $agent, $gen, $spec, $dt, $error, @bindings +) = $this->decode_trap_request ($trap); foreach my $encoded_pair (@bindings) { my ($oid, $value) = decode_by_template ($encoded_pair, "%O%@") +; print "returned pair: $oid -> $value\n"; } }

Replies are listed 'Best First'.
Re: SNMP Trap Decoding issue
by shmem (Chancellor) on May 04, 2007 at 12:11 UTC

    What are those BER and SNMP_session modules? I Don't have them and can't seem to find them on CPAN, either.

    The problem seems to be that this payload has multiple BER encoded data chunks concatenated together. You could decode the payload, encode back the chunk you've decoded, and strip that off the payload, lather, rinse, repeat:

    #!/usr/bin/perl use Encoding::BER::SNMP; while(<DATA>) { chop; $data .= chr hex $1 while s/(..)//; } my $enc = Encoding::BER::SNMP->new(); while ($data) { my $result = $enc->decode($data); my $oid = $result->{'value'}->[0]->{'value'}; my $value = $result->{'value'}->[1]->{'value'}; print "returned pair: $oid -> $value\n"; my $back = $enc->encode($result); $data =~ s/\Q$back\E// or last; } __DATA__ 3014060e2b06010401090929010203010200040232303013060e2b060104 01090929010203010300020105301d060e2b060104010909290102030104 00040b5379736c6f67205472617030818c060e2b06010401090929010203 010500047a3130363032333a2044656e792069636d7020737263206f7574 736964653a3231362e3139362e36342e3132342064737420696e73696465 3a3230382e3130392e39302e323120287479706520382c20636f64652030 29206279206163636573732d67726f757020226f7574736964655f616363 6573735f696e223016060e2b06010401090929010203010600430473c36bf8

    Output:

    returned pair: 1.3.6.1.4.1.9.9.41.1.2.3.1.2.0 -> 20 returned pair: 1.3.6.1.4.1.9.9.41.1.2.3.1.3.0 -> 5 returned pair: 1.3.6.1.4.1.9.9.41.1.2.3.1.4.0 -> Syslog Trap returned pair: 1.3.6.1.4.1.9.9.41.1.2.3.1.5.0 -> 106023: Deny icmp src + outside:216.196.64.124 dst inside:208.109.90.21 (type 8, code 0) by +access-group "outside_access_in" returned pair: 1.3.6.1.4.1.9.9.41.1.2.3.1.6.0 -> 1942187000

    update: removed superfluous data dump
    update: changed Encoding::BER to Encoding::BER::SNMP

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      shmem,

      thank you for your wisdom.

      The modules I have installed did come with ActiveState's Perl (yes on Windows :-( and from Net-SNMP)

      Small problem though. The hex is stored in a variable called $encoded_pair

      How do I modify your code so that it applies to $encoded_pair?
      while(<DATA>) { chop; $data .= chr hex $1 while s/(..)//; }


      Pretty sure it is a dump question but reading your post has improved my day and spirit a lot already.
        Easy:
        $data .= chr hex $1 while $encoded_pair =~ s/(..)//;

        :-)

        If you need your $encoded_pair for any other purpose after that, make a copy first, since the s/// is destructive. Or, better, do

        $data = join '', map { chr hex $_ } $encoded_pair =~ /(..)/g;

        BTW, could you please reformat your OP and wrap your HEX string in <code> tags? Thank you.

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}