#!/bin/bash
#*******************************************************************************
# IIIIII NNN    N  (C) 2010 INDIGEX All Rights Reserved
#   II   NN NN  N  Any redistribution or reproduction of part or all of the 
#   II   NN  NN N  content in any form is strictly prohibited.
# IIIIII NN    NN  Please contact admins@indigex.com for additional information.
#*******************************************************************************
#--------------------------------------------------------------------- 
# check_networkStats
# 
#
# Andrew Blackton [ablackton]
# Innovative Networks, Inc.
# September 24, 2010
#
# Purpose:
# Check Network Statistics
# Report on TX & RX - Packets, Bytes, and Errors
#   
#---------------------------------------------------------------------

debug=false;
log=false;
logFile=/var/tmp/ifDevLog;

IFCONFIG=/sbin/ifconfig;
procDeviceFile=/proc/net/dev;
infoFileLocation=/var/spool/nagios;
currentTime=$(date +%s);
maxCounterLimit=4294967295;
warnAtCount="1000/2000/10";
criticalAtCount="1000/2000/15";

#-------------------------------------------------------------------------------
# Start Script Functions
#-------------------------------------------------------------------------------

function usage {
	echo " check_network - Nagios Network Statistics Check Script"
	echo ""
	echo " Usage: check_netstats -d <device> -w <warninglevel> -c <criticallevel> ] [ -h ]"
	echo ""
	echo "		-d   Device"
        echo "		-w   Warning trigger level (RX/TX/Err)"
        echo "		-c   Critical trigger level (RX/TX/Err)"
	echo "		-h   Show this page"
	echo ""
}

function evaluateOptions {
	if $debug; then echo ""; echo "Parsing Command Line Arguements"; fi
	if $log; then echo "Parsing Command Line Arguements">>$logFile; fi
	if ( `test 0 -lt $#` )
	then
		while getopts ":w:c:d:h:" myarg "$@"
		do
			case $myarg in
				h|\?)
					usage
					exit;;
				d)	
					networkInterface="$OPTARG"
					if $debug; then echo "Device:                $networkInterface"; fi
					if $log; then echo "Device:                $networkInterface">>$logFile; fi
					;;
                                w)
                                        warnAtCount="$OPTARG"
					;;
                                c)
                                        criticalAtCount="$OPTARG"
					;;
				*)	# Default
					usage
					exit;;
			esac
		done
		shift `expr $OPTIND - 1`
	else
		usage
		exit
	fi
}

function getCurrentInterfaceInfoFromCommand {
	if $debug; then echo""; echo "Parsing Output..."; fi
	if $log; then echo""; echo "Parsing Output...">>$logFile; fi
	ifName=$1;
	ifCommandResults=`$IFCONFIG $ifName`;
	devAddr=`echo $ifCommandResults | sed -r 's!^.*(Ethernet HWaddr )([[0-9a-z]{2}:[a-z0-9]{2}:.*:[a-z0-9]{2}:[a-z0-9]{2}).*$!\2!'`;
	if $debug; then echo "Interface Addr- $devAddr"; fi
	if $log; then echo "Interface Addr- $devAddr">>$logFile; fi
	devIP=`echo $ifCommandResults | sed -r 's!^.*(inet addr:)([[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*$!\2!'`;
	if $debug; then echo "Interface IP  - $devIP"; fi
	if $log; then echo "Interface IP  - $devIP">>$logFile; fi
	rxPackets=`echo $ifCommandResults | sed -r 's!^.*(RX packets:)([[0-9]{1,9}) errors:.*$!\2!'`;
	if $debug; then echo "RX Packets    - $rxPackets"; fi
	if $log; then echo "RX Packets    - $rxPackets">>$logFile; fi
	rxPacketErrors=`echo $ifCommandResults | sed -r 's!^.*(RX packets:)([[0-9]{1,9})( errors:)([0-9]{1,9}).*$!\4!'`;
	if $debug; then echo "RX Packet Err - $rxPacketErrors"; fi
	if $log; then echo "RX Packet Err - $rxPacketErrors">>$logFile; fi
	txPackets=`echo $ifCommandResults | sed -r 's!^.*(TX packets:)([[0-9]{1,9}) errors:.*$!\2!'`;
	if $debug; then echo "TX Packets    - $txPackets"; fi
	if $log; then echo "TX Packets    - $txPackets">>$logFile; fi
	txPacketErrors=`echo $ifCommandResults | sed -r 's!^.*(TX packets:)([[0-9]{1,9})( errors:)([0-9]{1,9}).*$!\4!'`;
	if $debug; then echo "TX Packet Err - $txPacketErrors"; fi
	if $log; then echo "TX Packet Err - $txPacketErrors">>$logFile; fi
	rxBytes=`echo $ifCommandResults | sed -r 's!^.*(RX bytes:)([0-9]{1,9}) \(.*$!\2!'`;
	if $debug; then echo "RX Packet Err - $rxBytes"; fi
	if $log; then echo "RX Packet Err - $rxBytes">>$logFile; fi
	txBytes=`echo $ifCommandResults | sed -r 's!^.*(TX bytes:)([0-9]{1,9}) \(.*$!\2!'`;
	if $debug; then echo "TX Packet Err - $txBytes"; fi
	if $log; then echo "TX Packet Err - $txBytes">>$logFile; fi

}

#function getEarlierInterfaceInfo {
#}

function checkInfoFileState {
	checkFile=$1;
	if [ -e $checkFile ]; then 
		if $debug; then echo ""; echo "Checking File Freshness..."; fi
		if $log; then echo "Checking File Freshness...">>$logFile; fi
		secondsUpTime=$((`cut -f1 -d' ' /proc/uptime | cut -f1 -d.`));
		#if $debug; then echo "The machine has been on for $secondsUpTime secs."; fi
		timeFileModified=$(stat -c %Y $checkFile);
		#if $debug; then echo "The info file was last modified $timeFileModified."; fi
		#if $debug; then echo "Time is currently $timeFileModified secs."; fi
		secondsSinceModified=$(( $currentTime - $timeFileModified));
		#if $debug; then echo "Time Since Modified $secondsSinceModified secs."; fi
		if [ $secondsSinceModified -gt $secondsUpTime ]; then
			if $debug; then echo "The machine has rebooted since last check."; fi	
			if $log; then echo "The machine has rebooted since last check.">>$logFile; fi	
			if $debug; then echo "Write Current Device Information and Exit."; fi
			if $log; then echo "Write Current Device Information and Exit.">>$logFile; fi
			copyCurrentInterfaceFileInfo $checkFile;
	    		exitDescription="UNKNOWN";
			exitStatusCode=3;
	    		resultsOutput="System has rebooted since last check";
			summaryOutput;
		fi
		if $debug; then echo "Passes Checkout"; fi
		if $log; then echo "Passes Checkout">>$logFile; fi
	else
		if $debug; then echo ""; echo "No info file available."; fi
		if $log; then echo "No info file available.">>$logFile; fi
		if $debug; then echo "Write Current Device Information and Exit."; fi
		if $log; then echo "Write Current Device Information and Exit.">>$logFile; fi
		copyCurrentInterfaceFileInfo $checkFile;
	    	exitDescription="UNKNOWN";
		exitStatusCode=3;
	    	resultsOutput="Statistical Comparison not Available, writting current stats to file";
		summaryOutput;
	fi
	
}

function createInfoFile {
  if $debug; then echo ""; echo "Creating Statistical Info File..."; fi
  if $log; then echo "Creating Statistical Info File...">>$logFile; fi
  infoFile="$interfaceInfoFile";
  if $debug; then echo "Writing to $infoFile"; fi
  if $log; then echo "Writing to $infoFile">>$logFile; fi
  echo "RX Packets: $rxPackets; RX Errors: $rxPacketErrors; TX Packets: $txPackets; TX Errors: $txPacketErrors; RX Bytes: $rxBytes; TX Bytes: $txBytes;" > $infoFile ;
  if $debug; then echo "RX Packets: $rxPackets; RX Errors: $rxPacketErrors; TX Packets: $txPackets; TX Errors: $txPacketErrors; RX Bytes: $rxBytes; TX Bytes: $txBytes;" ; fi
  if $log; then echo "RX Packets: $rxPackets; RX Errors: $rxPacketErrors; TX Packets: $txPackets; TX Errors: $txPacketErrors; RX Bytes: $rxBytes; TX Bytes: $txBytes;">>$logFile ; fi
}

function getInterfaceFileInfo {
  infoFile=$1;
  if [ -e $infoFile ]; then
    grep $networkInterface $infoFile | sed -r 's![ ]{2,}! !g';
  else
    exitDescription="UNKNOWN";
    exitStatusCode=3;
    resultsOutput="Unable to find $infoFile";
  fi
}

function parseStatInfo {
  if $debug; then echo ""; echo "Current Interface Stats: $currentDevInfo"; fi
  if $log; then echo "Current Interface Stats: $currentDevInfo">>$logFile; fi
  
	rxPacketsCurr=$(echo $currentDevInfo| sed -r 's!^.*:!!' | awk '{print $2}');
	if $debug; then echo "RX Packets    - $rxPacketsCurr"; fi
	rxPacketErrorsCurr=$(echo $currentDevInfo| sed -r 's!^.*:!!' | awk '{print $3}');
	if $debug; then echo "RX Packet Err - $rxPacketErrorsCurr"; fi
	txPacketsCurr=$(echo $currentDevInfo| sed -r 's!^.*:!!' | awk '{print $10}');
	if $debug; then echo "TX Packets    - $txPacketsCurr"; fi
	txPacketErrorsCurr=$(echo $currentDevInfo| sed -r 's!^.*:!!' | awk '{print $11}');
	if $debug; then echo "TX Packet Err - $txPacketErrorsCurr"; fi
	rxBytesCurr=$(echo $currentDevInfo| sed -r 's!^.*:!!' | awk '{print $1}');
	if $debug; then echo "RX Bytes      - $rxBytesCurr"; fi
	txBytesCurr=$(echo $currentDevInfo| sed -r 's!^.*:!!' | awk '{print $9}');
	if $debug; then echo "TX Bytes      - $txBytesCurr"; fi

  if $debug; then echo ""; echo "Previous Interface Stats: $prevCheckInfo"; fi

	rxPacketsPrev=$(echo $prevCheckInfo| sed -r 's!^.*:!!' | awk '{print $2}');
	if $debug; then echo "RX Packets    - $rxPacketsPrev"; fi
	rxPacketErrorsPrev=$(echo $prevCheckInfo| sed -r 's!^.*:!!' | awk '{print $3}');
	if $debug; then echo "RX Packet Err - $rxPacketErrorsPrev"; fi 
	txPacketsPrev=$(echo $prevCheckInfo| sed -r 's!^.*:!!' | awk '{print $10}'); 
	if $debug; then echo "TX Packets    - $txPacketsPrev"; fi
	txPacketErrorsPrev=$(echo $prevCheckInfo| sed -r 's!^.*:!!' | awk '{print $11}');
	if $debug; then echo "TX Packet Err - $txPacketErrorsPrev"; fi
	rxBytesPrev=$(echo $prevCheckInfo| sed -r 's!^.*:!!' | awk '{print $1}');
	if $debug; then echo "RX Bytes      - $rxBytesPrev"; fi
	txBytesPrev=$(echo $prevCheckInfo| sed -r 's!^.*:!!' | awk '{print $9}');
	if $debug; then echo "TX Bytes      - $txBytesPrev"; fi
 
  	if $debug; then echo ""; echo "Let's Calculate"; fi

	if [ $rxPacketsCurr -lt $rxPacketsPrev ] ; then
		if $debug; then echo "The RX Packet counter has rolled over."; fi
		if $log; then echo "The RX Packet counter has rolled over.">>$logFile; fi
		rxPacketCount=$(($maxPacketLimit - $rxPacketsPrev));
		rxPacketCount=$(($rxPacketCount + $rxPacketsCurr));
	else
		rxPacketCount=$(($rxPacketsCurr - $rxPacketsPrev));
	fi
	if $debug; then echo "RX Packet Count Since Last Check - $rxPacketCount"; fi
	if $log; then echo "RX Packet Count Since Last Check - $rxPacketCount">>$logFile; fi
	rxPacketCount=$(($rxPacketCount / $secondsSinceModified));
	if $debug; then echo "RX Packets/sec  - $rxPacketCount"; fi
	if $log; then echo "RX Packet/sec - $rxPacketCount">>$logFile; fi

	if [ $rxPacketErrorsCurr -lt $rxPacketErrorsPrev ] ; then
		rxErrorCount=$(($maxPacketLimit - $rxPacketErrorsPrev));
		if $debug; then echo "The counter's RX Packet Error Count has rolled."; fi
		if $log; then echo "The counter's RX Packet Error Count has rolled.">>$logFile; fi
	else
		rxErrorCount=$(($rxPacketErrorsCurr - $rxPacketErrorsPrev));
	fi
	if $debug; then echo "RX Error Count Since Last Check - $rxErrorCount"; fi
	if $log; then echo "RX Error Count Since Last Check - $rxErrorCount">>$logFile; fi

	if [ $txPacketsCurr -lt $txPacketsPrev ] ; then
		if $debug; then echo "The TX Packet counter has rolled over."; fi
		if $log; then echo "The TX Packet counter has rolled over.">>$logFile; fi
		txPacketCount=$(($maxPacketLimit - $txPacketsPrev));
		txPacketCount=$(($txPacketCount + $txPacketsCurr));
	else
		txPacketCount=$(($txPacketsCurr - $txPacketsPrev));
	fi
	if $debug; then echo "TX Packet Count Since Last Check - $txPacketCount"; fi
	if $log; then echo "TX Packet Count Since Last Check - $txPacketCount">>$logFile; fi
	txPacketCount=$(($txPacketCount / $secondsSinceModified));
	if $debug; then echo "TX Packets / second - $txPacketCount"; fi
	if $log; then echo "TX Packets / second - $txPacketCount">>$logFile; fi

	if [ $txPacketErrorsCurr -lt $txPacketErrorsPrev ] ; then
		if $debug; then echo "The counter's TX Packet Error Count has rolled."; fi
		if $log; then echo "The counter's TX Packet Error Count has rolled.">>$logFile; fi
		txErrorCount=$(($maxPacketLimit - $txPacketErrorsPrev));
		txErrorCount=$(($txErrorCount + $txPacketErrorsCurr));
	else
		txErrorCount=$(($txPacketErrorsCurr - $txPacketErrorsPrev));
	fi
	if $debug; then echo "TX Error Count Since Last Check - $txErrorCount"; fi
	if $log; then echo "TX Error Count Since Last Check - $txErrorCount">>$logFile; fi

	if [ $rxBytesCurr -lt $rxBytesPrev ] ; then
		if $debug; then echo "The counter's RX Byte Count has Rolled"; fi
		if $log; then echo "The counter's RX Byte Count has Rolled">>$logFile; fi
		rxByteCount=$(($maxPacketLimit - $rxBytesPrev));
		rxByteCount=$(($rxByteCount + $rxBytesCurr));
	else
		rxByteCount=$(($rxBytesCurr - $rxBytesPrev));
	fi
	if $debug; then echo "RX Byte Count Since Last Check - $rxByteCount"; fi
	if $log; then echo "RX Byte Count Since Last Check - $rxByteCount" >> $logFile; fi
	rxByteCount=$(($rxByteCount / $secondsSinceModified));
	if $debug; then echo "RX Bytes / second - $rxByteCount"; fi
	if $log; then echo "RX Bytes /second- $rxByteCount" >> $logFile; fi

	if [ $txBytesCurr -lt $txBytesPrev ] ; then
		if $debug; then echo "The counter's TX Byte Count has Rolled"; fi
		if $log; then echo "The counter's TX Byte Count has Rolled" >> $logFile; fi
		txByteCount=$(($maxPacketLimit - $txBytesPrev));
		txByteCount=$(($txByteCount + $txBytesCurr));
	else
		txByteCount=$(($txBytesCurr - $txBytesPrev));
	fi
	if $debug; then echo "TX Byte Count Since Last Check - $txByteCount"; fi
	if $log; then echo "TX Byte Count Since Last Check - $txByteCount" >> $logFile; fi
	txByteCount=$(($txByteCount / $secondsSinceModified));
	if $debug; then echo "TX Bytes / second - $txByteCount"; fi
	if $log; then echo "TX Bytes / second - $txByteCount" >> $logFile; fi

}

function copyCurrentInterfaceFileInfo {
  if $debug; then echo ""; echo "Creating Statistical Info File with Current Information"; fi
  if $log; then echo "Creating Statistical Info File with Current Information" >> $logFile; fi
  resultFile=$1;
  if $debug; then echo "Writing to $resultFile"; fi
  if $log; then echo "Writing to $resultFile" >> $logFile; fi
  echo $currentDevInfo > $resultFile;
  if $debug; then echo "Result File Contents:"; echo $(cat $resultFile); fi
  if $log; then echo "Result File Contents:">> $logFile; echo $(cat $resultFile)>>$logFile; fi
}

function formatOutput {
	if $debug; then echo ""; echo "Formating Output"; fi
	if $log; then echo "Formating Output" >>$logFile; fi
	rxWarnAtPacketCount=`echo $warnAtCount | awk -F/ '{print $1}'`
	txWarnAtPacketCount=`echo $warnAtCount | awk -F/ '{print $2}'`
	warnAtErrorCount=`echo $warnAtCount | awk -F/ '{print $3}'`
	rxCriticalAtPacketCount=`echo $criticalAtCount | awk -F/ '{print $1}'`
	txCriticalAtPacketCount=`echo $criticalAtCount | awk -F/ '{print $2}'`
	criticalAtErrorCount=`echo $criticalAtCount | awk -F/ '{print $3}'`

	resultsOutput="RX - $rxPacketCount/s; TX - $txPacketCount/s; RX Errors - $rxErrorCount/s; TX Errors - $txErrorCount/s; RX Bytes - $rxByteCount B/s; TX Bytes - $txByteCount B/s";
	perfDataOutput=`echo "packets.RX="$rxPacketCount";$rxWarnAtPacketCount;$rxCriticalAtPacketCount packets.TX="$txPacketCount";$txWarnAtPacketCount;$txCriticalAtPacketCount errors.RX="$rxErrorCount";$warnAtErrorCount;$criticalAtErrorCount errors.TX="$txErrorCount";$warnAtErrorCount;$criticalAtErrorCount bytes.RX="$rxByteCount"B bytes.TX="$txByteCount"B"`
	if $debug; then echo $perfDataOutput; fi
	if $log; then echo $perfDataOutput >> $logFile; fi

	if [ "$rxPacketCount" -ge "$rxCriticalAtPacketCount" ] || [ "$txPacketCount" -ge "$txCriticalAtPacketCount" ] || [ "$rxErrorCount" -ge "$criticalAtErrorCount" ] || [ "$txErrorCount" -ge "$criticalAtErrorCount" ] ; then
		if $debug; then echo "Critical Packet Alert"; fi
		if $log; then echo "Critical Packet Alert">> $logFile; fi
		exitDescription="CRITICAL";
		exitStatusCode=2;
	elif [ "$rxPacketCount" -ge "$rxWarnAtPacketCount" ] || [ "$txPacketCount" -ge "$txWarnAtPacketCount" ] || [ "$rxErrorCount" -ge "$warnAtErrorCount" ] || [ "$txErrorCount" -ge "$warnAtErrorCount" ] ; then
		if $debug; then echo "Packet Counts Seem High"; fi
		if $log; then echo "Packet Counts Seem High">>$logFile; fi
		exitDescription="WARNING";
		exitStatusCode=1;
	else
		if $debug; then echo "Packet Counts Seem Normal"; fi
		if $log; then echo "Packet Counts Seem Normal">>$logFile; fi
		exitDescription="OK";
		exitStatusCode=0;
	fi
}

function summaryOutput {
	echo "$exitDescription: $resultsOutput |$perfDataOutput "
	exit $exitStatusCode
}


#-------------------------------------------------------------------------------
# End Script Functions
#-------------------------------------------------------------------------------


#-------------------------------------------------------------------------------
# Calling Script Functions
#-------------------------------------------------------------------------------
evaluateOptions $@;
# Declare Location of Interface Statistics File
interfaceInfoFile="$infoFileLocation/$networkInterface.info";
# Get Current Information about Devices
currentDevInfo=$(getInterfaceFileInfo $procDeviceFile)
# Check if machine has been rebooted or if not information file is available
checkInfoFileState $interfaceInfoFile;
# Get Statistics from Previous Check
prevCheckInfo=$(getInterfaceFileInfo "$interfaceInfoFile")
# Parse Information from Files and Calculate Differences
parseStatInfo $currentDevInfo $prevCheckInfo;
# Format Output for Nagios
formatOutput;
# Create Updated Statistics File
copyCurrentInterfaceFileInfo $interfaceInfoFile;
# Print Summary and Exit
summaryOutput;
