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 :)