#!/usr/bin/perl -w
# vim:ts=4:sw=4:tw=78

# Update the network traffic log every minute
# * * * * * dt=`perl -e'print(time()." ".scalar(localtime(time))."\n");'`;grep : * /proc/net/dev|sed -e"s/^/$dt /" >> /var/log/netraf.log

use strict;
use lib "/home/system/nagios/libexec" ;
use vars qw($PROGNAME);
use utils qw (%ERRORS &print_revision &support);
use Getopt::Long;

use constant NETLOG => '/var/log/netraf.log';
use constant RECLEN => 161;
use constant RECS => 6;
use constant STALE => 60; # Log considered stale after 60 seconds
use constant COLS => qw(RXbytes RXpackets RXerrs RXdrop RXfifo RXframe
						RXcompressed RXmulticast TXbytes TXpackets TXerrs
						TXdrop TXfifo TXcolls TXcarrier TXcompressed);

sub print_help ();
sub print_usage ();

$PROGNAME = 'netraf';

my ($opt_c, $opt_f, $opt_w, $opt_C, $opt_W, $opt_h, $opt_V, $opt_i);

$opt_w = 1024;
$opt_c = 4096;
$opt_W = 1024;
$opt_C = 4096;
$opt_f = NETLOG;
$opt_i = 'eth0';

Getopt::Long::Configure('bundling');
GetOptions(
		"V"   => \$opt_V, "version"     => \$opt_V,
		"h"   => \$opt_h, "help"        => \$opt_h,
		"f=s" => \$opt_f, "file"        => \$opt_f,
		"i=s" => \$opt_i, "interface"   => \$opt_i,
		"w=f" => \$opt_w, "warning-tx=f" => \$opt_w,
		"W=f" => \$opt_W, "warning-rx=f" => \$opt_W,
		"c=f" => \$opt_c, "critical-tx=f" => \$opt_c,
		"C=f" => \$opt_C, "critical-rx=f" => \$opt_C);

if ($opt_V) {
        print_revision($PROGNAME, '$Id$');
        exit $ERRORS{'OK'};
}

if ($opt_h) {
        print_help();
        exit $ERRORS{'OK'};
}

$opt_f = shift unless ($opt_f);

if (! $opt_f) {
        print "No file specified\n";
        exit $ERRORS{'UNKNOWN'};
}

# Examine the file.
unless (-f $opt_f) {
        print "$opt_f: File not found\n";
        exit $ERRORS{'UNKNOWN'};
}

our %traf;
our $age = time - (stat(NETLOG))[9];

open(LOG,'<'.NETLOG) ||
	die sprintf("Unable to open file handle LOG for file %s: %s\n",NETLOG,$!);

seek(LOG,(RECLEN*-RECS()),2);
while (local $_ = <LOG>) {
	if (my ($unixtime,$datetime,$int,$data) = $_ =~
			/^(\d{10}) (.+) (\S+):\s*(.+)/) {
		my %tmp;
		@tmp{COLS()} = split(/\s+/,$data);
		$traf{$int}->{$unixtime} = \%tmp;
	}
}

close(LOG) ||
	warn sprintf("Unable to close file handle LOG for file %s: %s\n",NETLOG,$!);

for my $int (sort keys %traf) {
	my $last_unixtime;
	for my $unixtime (sort keys %{$traf{$int}}) {
		if ($last_unixtime) {
			$traf{$int}->{RXkbps} = ($traf{$int}->{$unixtime}->{RXbytes} - 
							$traf{$int}->{$last_unixtime}->{RXbytes})/1024/60;
			$traf{$int}->{TXkbps} = ($traf{$int}->{$unixtime}->{TXbytes} - 
							$traf{$int}->{$last_unixtime}->{TXbytes})/1024/60;
		}
		$last_unixtime = $unixtime;
	}
}

my $result = 'OK';
my $errstr = "%s - %s %s throughput exceeds %d (RX %d kbps, TX %d kbps)\n";

if ($age > STALE) {
	$result = 'CRITICAL';
	print "$result - $opt_f is stale; $age seconds old\n";
	exit $ERRORS{$result};
}

$result = 'WARNING';
if ($traf{$opt_i}->{TXkbps} > $opt_w) {
	printf($errstr,$result,$opt_i,'TX',$opt_w,$traf{$opt_i}->{RXkbps},$traf{$opt_i}->{TXkbps});
	exit $ERRORS{$result};
}
if ($traf{$opt_i}->{RXkbps} > $opt_W) {
	printf($errstr,$result,$opt_i,'RX',$opt_W,$traf{$opt_i}->{RXkbps},$traf{$opt_i}->{RXkbps});
	exit $ERRORS{$result};
}

$result = 'CRITICAL';
if ($traf{$opt_i}->{TXkbps} > $opt_c) {
	printf($errstr,$result,$opt_i,'TX',$opt_c,$traf{$opt_i}->{RXkbps},$traf{$opt_i}->{TXkbps});
	exit $ERRORS{$result};
}
if ($traf{$opt_i}->{RXkbps} > $opt_C) {
	printf($errstr,$result,$opt_i,'RX',$opt_C,$traf{$opt_i}->{RXkbps},$traf{$opt_i}->{RXkbps});
	exit $ERRORS{$result};
}

printf("OK - %s throughput is within bounds (RX %d kbps < %d,%d / %d kbps < TX %d,%d)\n",
		$opt_i,$traf{$opt_i}->{RXkbps},$opt_W,$opt_C,
		$traf{$opt_i}->{TXkbps},$opt_w,$opt_c);
exit $ERRORS{'OK'};


sub print_usage () {
        print "Usage:\n";
        print "  $PROGNAME [-w <kbps>] [-c <kbps>] [-W <kbps>] [-C <kbps>] -f <file> -i <interface>\n";
        print "  $PROGNAME [-h | --help]\n";
        print "  $PROGNAME [-V | --version]\n";
}

sub print_help () {
        print_revision($PROGNAME, '$Id$');
        print "Copyright (c) 2005 Nicola Worthington\n\n";
        print_usage();
        print "\n";
        print "  <kbps>  Throughput must be no more than this\n";
        print "\n";
        support();
}