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

Hi I am using the following script to initiate an SAA session with a cisco router, I am using the snmp module from http://www.switch.ch/misc/leinen/snmp/perl/ I get the same problem with the standard SNMP module.

The problem is the format of the string value '9A 20 FF 09' is being reported as being invalid by the router.

If I do an snmpget and set using the HPOV tools and the values above it works fine.

Any help is greatly appreciated.

(my head now hurts from banging it against the wall)

#!/usr/bin/perl BEGIN { push @INC, '/opt/home/uknops/saa/SNMP_Session-0.94/lib'; } require 5.002; use strict; use SNMP_Session; use BER; my $host = "154.32.255.25"; my $community = "PSI-EU-RW"; my %OIDS; my @varbind = ('1.3.6.1.4.1.9.9.42.1.2.1.1.9.1', 'int', 4, '1.3.6.1.4.1.9.9.42.1.2.1.1.4.1', 'int', 1, '1.3.6.1.4.1.9.9.42.1.2.2.1.1.1', 'int', 2, '1.3.6.1.4.1.9.9.42.1.2.2.1.2.1', 'string', '9A 20 FF 09', '1.3.6.1.4.1.9.9.42.1.2.2.1.6.1', 'string', '9A 20 FF 19', '1.3.6.1.4.1.9.9.42.1.2.5.1.2.1', 'int', 1, '1.3.6.1.4.1.9.9.42.1.2.5.1.1.1', 'int', 2147483647); my ($response) = &snmpset($host, $community, @varbind); if ($response) { print "Response: $response\n"; } else { print "$host did not respond to SNMP query\n"; } exit 0; sub snmpset { my($host,$community,@varList) = @_; my(@enoid, $response, $bindings, $binding, $inoid,$outoid, $upoid,$oid,@retvals); my ($type,$value); while (@varList) { $oid = toOID(shift @varList); $type = shift @varList; $value = shift @varList; ($type eq 'string') && do { $value = encode_string($value); push @enoid, [$oid,$value]; next; }; ($type eq 'int') && do { $value = encode_int($value); push @enoid, [$oid,$value]; next; }; die "Unknown SNMP type: $type"; } srand(); my $session = SNMP_Session->open ($host , $community, 161); if ($session->set_request_response(@enoid)) { $response = $session->pdu_buffer; ($bindings) = $session->decode_get_response ($response +); $session->close (); while ($bindings) { ($binding,$bindings) = decode_sequence ($bindi +ngs); ($oid,$value) = decode_by_template ($binding, +"%O%@"); my $tempo = pretty_print($value); $tempo=~s/\t/ /g; $tempo=~s/\n/ /g; $tempo=~s/^\s+//; $tempo=~s/\s+$//; push @retvals, $tempo; } return (@retvals); } else { return (-1,-1); } } sub toOID { my $var = shift; if ($var =~ /^([a-z]+[^\.]*)/i) { my $oid = $OIDS{$1}; if ($oid) { $var =~ s/$1/$oid/; } else { die "Unknown SNMP var $var\n" } } encode_oid((split /\./, $var)); }

update (broquaint): reformatted code + added <readmore>

Replies are listed 'Best First'.
Re: SNMP String format
by grinder (Bishop) on Mar 11, 2003 at 13:41 UTC

    In this part:

    ($type eq 'string') && do { $value = encode_string($value); push @enoid, [$oid,$value]; next; };

    You process the oids of type string (e.g. $value = '9A 20 FF 19'). One must assume that encode_string is not encoding as it should.

    If you have root access somewhere on the path between the host performing the SNMP gets and the router, run tcpdump with something like:

    tcdump -nvv port 161

    And do a get with HPOV, and likewise with your perl script. Hopefully it will be obvious what needs to be done. Either you're calling encode_String incorrectly, or you can do the same much more efficiently with pack.

    This latter approach was one I adopted when playing around with MRTG. It comes with a module for dealing with the nitty-gritty of speaking SNMP. The perl code for assembling and disassembling SNMP packets is some of the most unnecessarily convoluted and poorly structured code it has been my misfortune to lay my eyes upon.

    I just checked: SNMP_Session, the one and same. The code is just abysmal. MRTG is nice, though :)


    print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u'
Re: SNMP String format
by traveler (Parson) on Mar 11, 2003 at 15:42 UTC
    I am not a very good MIB compiler and do not have a real one handy, but a quick glance at the MIB makes me wonder: are those values really "string" or should they be some other type? IP addresses and octet strings get encoded differently, for example. I'd check to ensure that you have the right types for those OIDs.

    HTH, --traveler

Re: SNMP String format
by zengargoyle (Deacon) on Mar 11, 2003 at 19:30 UTC

    does your encode_string look like this?

    sub encode_string { pack 'C*', map {hex} split /\s/, shift }

    it probably should (i've never used SNMP_Session, prefering Net::SNMP or plain old SNMP modules).

      This would not encode the string. If it is to be an OCTET STRING (sorry, the name is always in caps), it would be encoded as 04 04 9A 20 FF 09 (for the first example). You need the type (04 == OCTET STRING), the length (4) and then the value. This is the TLV (Type, Length, Value) encoding used by SNMP. Other data types are also encoded with TLV, but the type (T) is different. (IIRC, as an IP address this would be 40 04 9A 20 FF 09 for 154.32.255.9).

      --traveler

        the SNMP (or Net::SNMP) module will take care of that for you. at least it does for me.

        $res = $sess->set_request(-varbindlist => [ '1.3.6.1.4.1.5624.1.2.9.1.2.1.1.4.34603010', OCTET_STRING, "b +lahfoo", ]);