3
votes

I have been asked to install an HP OpenView agent onto a remote Unix platform to capture SNMP traps forwarded by a client application.

I have since discovered that the client application can only forward SNMPv3 traps, and the agents we use can only accept SNMPv2 traps.

I have discovered that I may be able to resolve this issue through the use of the Perl module NetSNMP::TrapReceiver but I am unclear how this is setup or how/if you can convert a v3 trap to a v2 trap.

My goal is to capture the v3 trap and, hopefully via a script or tool, convert this to a v2 trap and send it back out on an alternative port.

1
Sorry, this is too broad to meaningfully answer. It should be possible to catch an SNMPv3 trap and create a new SNMPv2 trap with approximately similar information.Sobrique
@Sobrique I disagree that it's too broad. Perhaps rephrasing would help: "How can I use NetSNMP::TrapReceiver to catch SNMP v3 traps and forward them as v2 traps?" Since snmptrapd can run arbitrary Perl code, I expect the solution wouldn't be very long.ThisSuitIsBlackNot
I'm confused about your structure: you don't mention a network manager anywhere. Does your "client application" mean your new HP OpenView agent? In which case, what are "the agents we use"? This is one case where it would be useful to post an image.Borodin
I'm not voting to close, but I do feel this would be a better question if you showed some indication of what you've tried so far with the Perl module. The page you've linked to appears to have lots of good info including example code, what is missing from it that you can't get started on this?miken32
Sorry guy's I realise that I did perhaps jump the gun on this and I have now identified an SNMP trap interceptor that caters for v3 traps. I will close this question - sorry for wasting peoples timeMatteoS

1 Answers

0
votes

By chance I have same task for now. So my decision with NetSNMP::TrapReceiver is here:

#!/usr/bin/perl

use strict;
use warnings;
use diagnostics;

use Net::SNMP;
use SNMP;
use Switch;


my $snmpTrapDestHost = "127.0.0.1";
my $snmpTrapRemotePort = 16162; #other than default trap port or we got infinite trap loop
my $snmpTrapCommunity = "public";
my $snmpTrapVersion = "2c";


my $sess = new SNMP::TrapSession(DestHost => $snmpTrapDestHost, Community => $snmpTrapCommunity, Version => $snmpTrapVersion, RemotePort => $snmpTrapRemotePort);

sub my_receiver {
    print "********** PERL RECEIVED A NOTIFICATION:\n";

    my @bunchOfVarbinds;
    foreach my $x (@{$_[1]})
    {
        printf "'%s' type='%d' value='%s'\n", $x->[0], $x->[2], $x->[1];
        my $lsOid = $x->[0];
        my $liOid = &SNMP::translateObj($lsOid);
        my $lsVal = $x->[1];
        my $lType = $x->[2];
        my $lVal;
# You need some convertion here, cause we got data in "human readable" format
        switch($lType)
        {
            case Net::SNMP::OBJECT_IDENTIFIER
            {
                $lType = "OBJECTID";
                if ($lsVal =~ /OID\:\s+(.*)$/)
                {
                    $lVal = $1
                }
                else
                {
                    $lVal = $lsVal;
                }
                $lVal = &SNMP::translateObj($lVal);
            }
            case Net::SNMP::TIMETICKS
            {
                $lType = "TICKS";
                if($lsVal =~ /Timeticks\:\s+\((\d+)\)\s+.*$/)
                {
                    $lVal = $1;
                }
                else
                {
                    my ($d, $h, $m, $s) = split(/\:/, $lsVal);
                    $lVal = $d * 24;
                    $lVal = ($lVal + $h)*60;
                    $lVal = ($lVal + $m)*60;
                    $lVal = ($lVal + $s)*100;
                }
            }
            case Net::SNMP::OCTET_STRING
            {
                $lType = "OCTETSTR";
                my $isHex;
                ($isHex, $lVal) = split(/STRING\:\s*/, $lsVal);
                if (!defined($lVal))
                {
                    $lVal = $lsVal;
                }
                $lVal =~ s/"//g;

                if (defined($isHex))
                {
                    if($isHex eq "Hex-")
                    {
                        $lVal =~ s/\n//g;
                        $lVal =~ s/ //g;
                    }
                }
            }
            case Net::SNMP::INTEGER
            {
                $lType = "INTEGER";
                $lVal = $lsVal;
            }
            case Net::SNMP::IPADDRESS
            {
# IPADDR
# NETADDR
                $lType = "IPADDR";
                $lVal = $lsVal;
            }
            case Net::SNMP::COUNTER
            {
# COUNTER
                $lType = "COUNTER";
                $lVal = $lsVal;
            }
            case Net::SNMP::COUNTER64
            {
# COUNTER64
                $lType = "COUNTER64";
                $lVal = $lsVal;
            }
            case Net::SNMP::GAUGE
            {
# GAUGE
                $lType = "GAUGE";
                $lVal = $lsVal;
            }
            case Net::SNMP::NULL
            {
# NULL
                $lType = "NULL";
                $lVal = $lsVal;
            }
            else
            {
# UINTEGER
# OPAQUE
                $lVal = $lsVal;
            }
        }        
        push @bunchOfVarbinds, new SNMP::Varbind([$liOid, undef, $lVal, $lType]);

    }

    my $vl = new SNMP::VarList(@bunchOfVarbinds);

    $sess->trap(
                    oid => $initiTrapProxyServiceOid,
                    uptime => $trapUptimeValue,
                    $vl
               );

    return NETSNMPTRAPD_HANDLER_OK;
}

$SNMP::use_numeric = 1;
NetSNMP::TrapReceiver::register("all", \&my_receiver) ||
 warn "failed to register perl trap handler\n";
print STDERR "Loaded perl snmptrapd handler\n";

I am newbie in perl so any fixes are appreciated.