1: #!/usr/bin/perl         
   2: #
   3: # This little program was written becuase I had a few freebsd
   4: # machines that were not giving out the right information for
   5: # snmpd's ifInOctets and ifOutOctets, thus remote monitoring
   6: # for this information via snmpd was useless to me.
   7: #
   8: # After some heavy reading into some of the features ucd-snmpd
   9: # provides I found a feature called "pass-through", which is a
  10: # setting within the snmpd.conf that allows you to (unlike the
  11: # exec option), pass entire mib tree's to an external program or
  12: # script. Hence I can take data that is normally generated by
  13: # snmpd (and in my case the failure to generate), and make it
  14: # spit out the RIGHT information.
  15: #
  16: # This script uses the .1.3.6.1.2.1.2.2.1.10 and .16 oid tree's
  17: # which are the default inoctets and outoctets. It reads the
  18: # information it needs to get from netstat. This supports both
  19: # "get" requests and "getnext" requests.
  20: #
  21: # From what I have seen, this is *bsd only (due to the way it
  22: # gets its information from netstat), yet can easily be changed
  23: # to work with other unix variants..
  24: #               
  25: # In order to utilize this script, in your specified snmpd.conf
  26: # put these lines somewhere in the file:
  27: #
  28: # pass .1.3.6.1.2.1.2.2.1.16 /local/bin/snmp-pass.pl
  29: # pass .1.3.6.1.2.1.2.2.1.10 /local/bin/snmp-pass.pl
  30: # 
  31: # For quicker responses and a little faster output, try      
  32: # compiling this program using perlcc.
  33: # 
  34: # Mark Thomas <mrk@ackers.net>
  35: 
  36: use strict;
  37:  
  38: my $oidreplace = ".1.3.6.1.2.1.2.2.1";
  39: my $in = 10;
  40: my $out = 16;
  41: my $bytes = 0;
  42: my $gorn = $ARGV[0];
  43: my $oid  = $ARGV[1];
  44: 
  45: if ($gorn eq "-g") {
  46: 
  47:         if ($oid =~ /$oidreplace/) {
  48:                 my $num = $oid;
  49:                 $num =~ s/.*\.(\d+)\.(\d+$)/$1 $2/g;
  50:                 my $inorout = $1;
  51:                 my $num = $2;
  52:                 my(@ints) = get_int_info();
  53:                 my $num_ints = @ints;
  54:                 if ($num > $num_ints) { 
  55:                         print "$num to big\n";
  56:                         exit 0;
  57:                 }
  58:                 my $num_get = $num - 1;
  59:                 if ($num_get < 0) {
  60:                         print "$num to small\n";
  61:                         exit;
  62:                 }
  63:                 if ($inorout eq $in) {
  64:                         $bytes = get_in_bytes($ints[$num_get]);
  65:                 }
  66:                 elsif ($inorout eq $out) {
  67:                         $bytes = get_out_bytes($ints[$num_get]);
  68:                 }
  69:                 else {
  70:                         exit 0;
  71:                 }
  72:                 do_output($bytes,$oid);
  73:         }
  74:         else {
  75:                 exit;
  76:         }
  77: 
  78: }
  79: elsif ($gorn eq "-n") {
  80:         if ($oid =~ /$oidreplace/) {
  81:                 my(@ints) = get_int_info();
  82:                 my $num_ints = @ints;
  83:                 if ($oid =~ /.1.3.6.1.2.1.2.2.1.10$/) {
  84:                         my $yoid = "$oidreplace.10.1";
  85:                         $bytes = get_in_bytes($ints[0]);
  86:                         do_gn_output($bytes,$yoid);
  87:                 }
  88:                 elsif ($oid =~ /.1.3.6.1.2.1.2.2.1.16$/) {
  89:                         my $yoid = "$oidreplace.16.1";
  90:                         $bytes = get_out_bytes($ints[0]);
  91:                         do_gn_output($bytes,$yoid);
  92:                 }
  93:                 elsif ($oid =~ /$oidreplace.\d+.\d+$/) {
  94:                         my $num = $oid;
  95:                         $num =~ s/.*\.(\d+)\.(\d+$)/$1 $2/g;
  96:                         my $inorout = $1;
  97:                         my $num = $2;
  98:                         my $numforint = $num;
  99:                         my $numforoid = $num + 1;
 100:                         if ($num+1 > $num_ints) {
 101:                                 print "$num to big\n";
 102:                                 exit 0;
 103:                         }
 104:                         if ($inorout eq $in) {
 105:                                 $bytes = get_in_bytes($ints[$num]);
 106:                         }
 107:                         elsif ($inorout eq $out) {
 108:                                 $bytes = get_out_bytes($ints[$num]);
 109:                         }
 110:                         my $yoid = "$oidreplace.$inorout.$numforoid";
 111:                         do_output($bytes,$yoid);
 112:                 } else { exit 0; }
 113:         } else { exit 0; }
 114: }
 115: else { exit; }
 116: 
 117: sub do_output {
 118: 
 119:         my($data,$yoid) = @_;
 120:         if ($data eq "") {
 121:                 $data = 0;
 122:         }
 123:         print "$yoid\n";
 124:         print "counter\n";
 125:         print "$data\n";
 126:         exit 0;
 127: }
 128: 
 129: sub get_int_info {
 130: 
 131:         my $ifconfig = `/sbin/ifconfig -l 2>/dev/null`;
 132:         $ifconfig =~ s/ /,/g;
 133:         $ifconfig =~ s/\n//g;
 134:         my(@ints) = split(/,/, $ifconfig);
 135:         return @ints;
 136:                                 
 137: }
 138: 
 139: sub get_in_bytes {
 140:                                 
 141:         my ($int_name) = $_[0];
 142:         my @netstat = `/usr/bin/netstat -b -I $int_name`;
 143:         my $good_inf = $netstat[1];
 144:         $good_inf =~ s/\://g;
 145:         $good_inf =~ s/\D+/ /g;
 146:         $good_inf =~ s/^\s//g;
 147:         my($nu,$nu,$nu,$nu,$nu,$nu,$nu,$inbytes,$nu,$nu,$outbytes,$nu) = split(/ /, $good_inf);
 148:         return $inbytes;  
 149: }
 150: 
 151: sub get_out_bytes {
 152:         my ($int_name) = $_[0];
 153:         my @netstat = `/usr/bin/netstat -b -I $int_name`;
 154:         my $good_inf = $netstat[1];
 155:         $good_inf =~ s/\://g;
 156:         $good_inf =~ s/\D+/ /g;
 157:         $good_inf =~ s/^\s//g;
 158:         my($nu,$nu,$nu,$nu,$nu,$nu,$nu,$inbytes,$nu,$nu,$outbytes,$nu) = split(/ /, $good_inf);
 159:         return $outbytes; 
 160: }