#!/usr/bin/perl # # This little program was written becuase I had a few freebsd # machines that were not giving out the right information for # snmpd's ifInOctets and ifOutOctets, thus remote monitoring # for this information via snmpd was useless to me. # # After some heavy reading into some of the features ucd-snmpd # provides I found a feature called "pass-through", which is a # setting within the snmpd.conf that allows you to (unlike the # exec option), pass entire mib tree's to an external program or # script. Hence I can take data that is normally generated by # snmpd (and in my case the failure to generate), and make it # spit out the RIGHT information. # # This script uses the .1.3.6.1.2.1.2.2.1.10 and .16 oid tree's # which are the default inoctets and outoctets. It reads the # information it needs to get from netstat. This supports both # "get" requests and "getnext" requests. # # From what I have seen, this is *bsd only (due to the way it # gets its information from netstat), yet can easily be changed # to work with other unix variants.. # # In order to utilize this script, in your specified snmpd.conf # put these lines somewhere in the file: # # pass .1.3.6.1.2.1.2.2.1.16 /local/bin/snmp-pass.pl # pass .1.3.6.1.2.1.2.2.1.10 /local/bin/snmp-pass.pl # # For quicker responses and a little faster output, try # compiling this program using perlcc. # # Mark Thomas use strict; my $oidreplace = ".1.3.6.1.2.1.2.2.1"; my $in = 10; my $out = 16; my $bytes = 0; my $gorn = $ARGV[0]; my $oid = $ARGV[1]; if ($gorn eq "-g") { if ($oid =~ /$oidreplace/) { my $num = $oid; $num =~ s/.*\.(\d+)\.(\d+$)/$1 $2/g; my $inorout = $1; my $num = $2; my(@ints) = get_int_info(); my $num_ints = @ints; if ($num > $num_ints) { print "$num to big\n"; exit 0; } my $num_get = $num - 1; if ($num_get < 0) { print "$num to small\n"; exit; } if ($inorout eq $in) { $bytes = get_in_bytes($ints[$num_get]); } elsif ($inorout eq $out) { $bytes = get_out_bytes($ints[$num_get]); } else { exit 0; } do_output($bytes,$oid); } else { exit; } } elsif ($gorn eq "-n") { if ($oid =~ /$oidreplace/) { my(@ints) = get_int_info(); my $num_ints = @ints; if ($oid =~ /.1.3.6.1.2.1.2.2.1.10$/) { my $yoid = "$oidreplace.10.1"; $bytes = get_in_bytes($ints[0]); do_gn_output($bytes,$yoid); } elsif ($oid =~ /.1.3.6.1.2.1.2.2.1.16$/) { my $yoid = "$oidreplace.16.1"; $bytes = get_out_bytes($ints[0]); do_gn_output($bytes,$yoid); } elsif ($oid =~ /$oidreplace.\d+.\d+$/) { my $num = $oid; $num =~ s/.*\.(\d+)\.(\d+$)/$1 $2/g; my $inorout = $1; my $num = $2; my $numforint = $num; my $numforoid = $num + 1; if ($num+1 > $num_ints) { print "$num to big\n"; exit 0; } if ($inorout eq $in) { $bytes = get_in_bytes($ints[$num]); } elsif ($inorout eq $out) { $bytes = get_out_bytes($ints[$num]); } my $yoid = "$oidreplace.$inorout.$numforoid"; do_output($bytes,$yoid); } else { exit 0; } } else { exit 0; } } else { exit; } sub do_output { my($data,$yoid) = @_; if ($data eq "") { $data = 0; } print "$yoid\n"; print "counter\n"; print "$data\n"; exit 0; } sub get_int_info { my $ifconfig = `/sbin/ifconfig -l 2>/dev/null`; $ifconfig =~ s/ /,/g; $ifconfig =~ s/\n//g; my(@ints) = split(/,/, $ifconfig); return @ints; } sub get_in_bytes { my ($int_name) = $_[0]; my @netstat = `/usr/bin/netstat -b -I $int_name`; my $good_inf = $netstat[1]; $good_inf =~ s/\://g; $good_inf =~ s/\D+/ /g; $good_inf =~ s/^\s//g; my($nu,$nu,$nu,$nu,$nu,$nu,$nu,$inbytes,$nu,$nu,$outbytes,$nu) = split(/ /, $good_inf); return $inbytes; } sub get_out_bytes { my ($int_name) = $_[0]; my @netstat = `/usr/bin/netstat -b -I $int_name`; my $good_inf = $netstat[1]; $good_inf =~ s/\://g; $good_inf =~ s/\D+/ /g; $good_inf =~ s/^\s//g; my($nu,$nu,$nu,$nu,$nu,$nu,$nu,$inbytes,$nu,$nu,$outbytes,$nu) = split(/ /, $good_inf); return $outbytes; }