web developer & system programmer

coder . cl

ramblings and thoughts on programming...


configuring snmptrapd

published: 16-07-2010 / updated: 16-07-2010
posted in: perl, programming, sysadmin, tips
by Daniel Molina Wegener

snmptrapd(8) is a SNMP trap daemon, in other words, it captures SNMP notifications from the network and similar devices. In this post I will try to explain how to configure this daemon to allow a network server to process SNMP traps using both, embeded perl handlers for snmptrapd(8) and plain standard input — or stdin — handlers.

daemon configuration

The daemon is quite easy to configure, you must setup the snmptrapd.conf(5snmp) file. For this configuration, you must read your desired configuration options, such as logging and execution. For example if we have a community called inetsnmp, we can configure the file to allow traps from that community and also configure a trap handler written in perl.


# configure inetsnmp community to allow logging,
# execution of handlers and network traffic.
authCommunity   log,execute,net         inetsnmp

# perl embeded handler.
perl do "/usr/share/snmp/handler/trapdembed.pl"

This configuration is not enough, the snmptrapd(8) daemon uses hosts.allow(5) facility, so we need to add the proper rule in that file:


snmptrapd : 192.168.100.0/255.255.255.0 : allow
snmptrapd : 10.10.10.0/255.255.255.0 : allow

the embeded perl handler

#!/usr/bin/perl -w
#

# strict perl is better
use strict;
use FileHandle;
use Data::Dumper;
use NetSNMP::TrapReceiver;

# we create a sample/demo log file...
my $log = FileHandle->new("/var/log/snmptrapsample.log", "a+") ||
    die "Failed to open log file";

# how we process an SNMP variable
sub process_var {
    my ($var) = @_;
    my %res;
    my $name = "$var->[0]";
    my ($vt, $vv) = split /: /, "$var->[1]";
    $res{'oid'} = $name;
    $res{'type'} = $vt;
    $res{'value'} = $vv;
    return %res;
}

# our default receiver
sub default_receiver {
    my ($pdu, $ivars) = @_;
    my %vars;
    $log->print(Dumper($pdu));
    foreach my $k (@{$_[1]}) {
        $vars{$k->[0]} = process_var($k);
    }
    $log->print(Dumper(%vars));
    $log->flush;
}

# every OIDs pass through the default_receiver
NetSNMP::TrapReceiver::register("all", &default_receiver) ||
    die "Failed to laod Sample Trap Receivern";

# status message...
print STDERR "Loaded Sample Trap Receivern";

This perl(1) handler will allow you basically to create a handler which is capable to process SNMP notifications creating two main variables on the handler itself $pdu which is the reference to the %pdu hash and %vars hash. Both hashes contains the proper data to process the request as you want:


%pdu = {
    'notificationtype' => 'TRAP',
    'receivedfrom' => 'UDP: [10.10.10.1]:53951->[192.168.100.5]',
    'version' => 1,
    'errorstatus' => 0,
    'messageid' => 0,
    'community' => 'public',
    'transactionid' => 1,
    'errorindex' => 0,
    'requestid' => 1012897136
};


%vars = {
    'IF-MIB::ifDescr' => {
        'value' => 'eth0',
        'type' => 'STRING',
        'oid' => 'IF-MIB::ifDescr'
    },
    'IF-MIB::ifAdminStatus.1' => {
        'value' => '1',
        'type' => 'INTEGER',
        'oid' => 'IF-MIB::ifAdminStatus.1'
    },
    'DISMAN-EVENT-MIB::sysUpTimeInstance' => {
        'value' => '(0) 0:00:00.00',
        'type' => 'Timeticks',
        'oid' => 'DISMAN-EVENT-MIB::sysUpTimeInstance'
    },
    'IF-MIB::ifIndex.1' => {
        'value' => '1',
        'type' => 'INTEGER',
        'oid' => 'IF-MIB::ifIndex.1'
    },
    'SNMPv2-MIB::snmpTrapOID.0' => {
        'value' => 'IF-MIB::linkUp',
        'type' => 'OID',
        'oid' => 'SNMPv2-MIB::snmpTrapOID.0'
    },
    'IF-MIB::ifOperStatus.1' => {
        'value' => '1',
        'type' => 'INTEGER',
        'oid' => 'IF-MIB::ifOperStatus.1'
    }
};

Where each OID or variable, can be treated by using the NetSNMP::OID package. Fora stdin handler, if you don’t know about perl(1), the difference is made on the snmptrapd.conf(5snmp) file, instead of configuring a global perl script which itself registers which OIDs will handle, you need to configure a global trap handler or each handler for each OID that you want to handle:


# configure inetsnmp community to allow logging,
# execution of handlers and network traffic.
authCommunity   log,execute,net         inetsnmp

traphandle     default           /usr/share/snmp/handler/defaultstding.py   default
traphandle     IF-MIB::linkUp    /usr/share/snmp/handler/ifuphandler.py     up

This will make your script or application to receive the OID data from stdin as follows:

router
UDP: [10.10.10.1]:37745->[192.168.100.5]
DISMAN-EVENT-MIB::sysUpTimeInstance 0:0:00:00.00
SNMPv2-MIB::snmpTrapOID.0 IF-MIB::linkUp
IF-MIB::ifIndex.1 1
IF-MIB::ifAdminStatus.1 up
IF-MIB::ifOperStatus.1 up
IF-MIB::ifDescr eth0

And also will require that you will enable in some manner the processing of that data as plain text.

Good luck configuring SNMP traps :)


No coments yet.

post a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>