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