#! /usr/local/bin/perl # $Id: linksys_snmptrap.pl,v 1.19 2004/06/12 15:45:31 user Exp $ =head1 NAME linksys_snmptrap - Capture and decode a Linksys BEFSR41 SNMP trap. =head1 SYNOPSIS To use this as a stand-alone program to work on a captured SNMP trap, try this: linksys_snmptrap [--logfile /tmp/log_file] [--nosyslog] < snmp_trap This program is meant to be called by snmptrapd. I do not understand snmptrapd entirely. To use this program, create /etc/snmp/snmptrapd.conf containing this line: traphandle SNMPv2-SMI::enterprises.3093.2.2.1.0.1 /path/linksys_snmptrap Then, the formatted and decoded data will be logged to syslog. =head1 COPYRIGHT Copyright 2004 auto92089@hushmail.com This program is free for non-commercial use. Contact author for terms of commercial use. =cut use strict; use warnings; $|++; # If set, log file to which we should dump everything. my $log_file; my $syslog = 1; # By default, don't log this aabbccdd msg added in recent firmware revisions. my $aabbccdd = 0; use Getopt::Long; my $result = GetOptions("log=s" => \$log_file, "syslog!" => \$syslog, "aabbccdd!" => \$aabbccdd); if (defined($log_file)) { my $appending = -f $log_file; open(FILE, ">>$log_file"); print FILE "\n" if $appending; } sub read_snmp_trap { my ($fh) = @_; my ($continuation, $key, $value, %entries) = 0; while (<$fh>) { print FILE $_ if defined($log_file); chomp; if ($continuation) { $value .= " $_"; } else { ($key, $value) = split / /, $_, 2; } # If we have an odd number of double-quotes, # this continues on the next line of input. $continuation = ($value =~ tr/"/"/) % 2; unless ($continuation) { $value =~ /"(.*)"/ and $value = $1; $entries{$key} = $value; } } return \%entries; } use Sys::Syslog; my $sender_name = ; chomp $sender_name; my $sender_ip = ; chomp $sender_ip; print FILE "$sender_name\n$sender_ip\n" if defined($log_file); my $snmp_stuff = read_snmp_trap(*STDIN); my $data; $_ = $$snmp_stuff{"SNMPv2-SMI::enterprises.3093.1.1.0"}; if (defined) { if ($syslog) { openlog "linksys", "cons", "user"; # If it is in hex, convert from hex to ASCII. if (/^([[:xdigit:]][[:xdigit:]] )*$/) { s/([[:xdigit:]][[:xdigit:]]) /chr hex $1/eg; # Remove the trailing newline from the encoded string. chomp; } # If this is in a five-field format, re-format it slightly. if (/@([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+)/) { my $dir = $1; my $src_name = $2; my $src_port = $3; my $dst_name = $4; my $dst_port = $5; $_ = "$dir $src_name:$src_port -> $dst_name:$dst_port"; syslog "warning", "$sender_name($sender_ip) $_"; } else { syslog "warning", "$sender_name($sender_ip) $_" if $aabbccdd; } closelog; } exit 0; } # Unexpected input, dump info to somewhere useful. exit 1;