#!/bin/bash
#
# Written By: Pierre SOURDEAU to AMF company [FRANCE]
# Created: 28/10/2008
# Description: Check SNMP v 1, 2c, 3 on Cisco MSFC, and return :
# 	- number of modules 
# 	- code status on each modules
#		=> warning or critical or unknown exit if any modules is not OK
#	- include graphic return
#
# Check succesfuly on Cisco 6509 and 6513
#
# License: This nagios plugin comes with ABSOLUTELY NO WARRANTY. You may redistribute copies of
# the plugins under the terms of the GNU General Public License. For more information about these 
# matters, see the GNU General Public License.
# Version: 2.3 (updated 09/04/2009)

############################################################
# Varialbles
############################################################
PROGNAME=$0
#`/bin/basename $0` #no basename on Mac OS X 10.3
PROGPATH=`echo $0 | sed -e 's,[\\/][^\\/][^\\/]*$,,'`
REVISION=`echo '$PROGNAME: 2.3 $' | sed -e 's/[^0-9.]//g'`
SNMPGET="/usr/bin/snmpget";
SNMPWALK="/usr/bin/snmpwalk";

. $PROGPATH/utils.sh

USAGE="Usage: check_cisco_msfc.sh -H hostname -V version -M modules [-C|-l|-u|-a|-d|-h]
### PARAMETERS ### 
-H Hostname (IP adresse or DNS name)
-V Version (1|2c|3)
-M Mode (modules)
### OPTIONNAL ###
-C Community (name) *** Use on Version 1|2 ***
-l Login (NoAuthNoPriv | AuthNoPriv | AuthPriv) *** Use on Version 3 ***
-u Username *** Use on Version 3 ***
-a Password *** Use on Version 3 ***
-d Debug mode
-h Help (print command usage, and quit)"

sum_value_Ok=0
sum_value_Warning=0
sum_value_Critical=0
sum_value_Unknwon=0

module_number=0
operstatus_value=([1]=unknown [2]=ok [3]=disabled [4]=okButDiagFailed [5]=boot [6]=selfTest [7]=failed [8]=missing [9]=mismatchWithParent [10]=mismatchConfig [11]=diagFailed [12]=dormant [13]=outOfServiceAdmin [14]=outOfServiceEnvTemp [15]=poweredDown [16]=poweredUp [17]=powerDenied [18]=powerCycled [19]=okButPowerOverWarning [20]=okButPowerOverCritical [21]=syncInProgress)
resetreason_value=([1]=unknown [2]=powerUp [3]=parityError [4]=clearConfigReset [5]=manualReset [6]=watchDogTimeoutReset [7]=resourceOverflowReset [8]=missingTaskReset [9]=lowVoltageReset [10]=controllerReset [11]=systemReset [12]=switchoverReset [13]=upgradeReset [14]=downgradeReset [15]=cacheErrorReset [16]=deviceDriverReset [17]=softwareExceptionReset [18]=restoreConfigReset [19]=abortRevReset [20]=burnBootReset [21]=standbyCdHealthierReset [22]=nonNativeConfigClearReset [23]=memoryProtectionErrorReset)
comm_final=""
walk_param=""

mib_slots_number=".1.3.6.1.2.1.47.1.1.1.1.13.1"
mib_modules_adminstatus=".1.3.6.1.4.1.9.9.117.1.2.1.1.1"
mib_modules_operstatus=".1.3.6.1.4.1.9.9.117.1.2.1.1.2"
mib_modules_resetreason=".1.3.6.1.4.1.9.9.117.1.2.1.1.3"
mib_modules_description="SNMPv2-SMI::mib-2.47.1.1.1.1.13"


############################################################
# Global Functions
############################################################
# Check if value is numeric or not
check_num()
{
if ! let $1 2> /dev/null
then
	if [ $1 != 0 ]
	then
		echo "Error - Not numeric value : $2 = $1"
		exit $STATE_UNKNOWN
	fi
fi
}

# Check Parameters
check_param()
{
if [ "$hostname" == "" ] || [ "$version" == "" ] || [ "$mode" == "" ]
then
	echo "Error - Missing parameters - hostname = $hostname : version = $version : mode = $mode"
	echo "$USAGE"
	exit $STATE_UNKNOWN
fi

case $version in
		1 | 2c)
			if [ "$community" == "" ]
			then
				echo "Error - Missing parameters - community = $community"
				echo "$USAGE"
				exit $STATE_UNKNOWN
			fi
			walk_param="-v $version -c $community $hostname";;
		3) 
			if [ "$login" == "" ] || [ "$user" == "" ] || [ "$password" == "" ]
			then
				echo "Error - Missing parameters - login = $login : user = $user : password = $password"
				echo "$USAGE"
				exit $STATE_UNKNOWN
			fi
			walk_param="-v $version -l $login -u $user -A $password $hostname";;
esac
}


# Command used to debug
debug()
{
echo "*********************************************************************"
echo "### Mode Modules ###"
echo "Number of Slots : $slot_number"
echo "Number of Modules : $module_number"

for i in $(seq $slot_number)
do
	echo "Module $i ${module_description_[$i]} : adminstatus = ${module_adminstatus_[$i]} : operstatus = ${module_operstatus_[$i]} (${operstatus_value[$"${module_operstatus_[$i]}"]}) : last reset reason : ${module_resetreason_[$i]} (${resetreason_value[$"${module_resetreason_[$i]}"]})"
done

echo "### Global Values ###"
echo "Sum values : Ok = $sum_value_Ok ; Warning = $sum_value_Warning ; Critical = $sum_value_Critical ; Unknown = $sum_value_Unknwon"
echo "Nagios return : Ok = $STATE_OK ; Warning = $STATE_WARNING ; Critical = $STATE_CRITICAL ; Unknown = $STATE_UNKNOWN"
echo "Parameters : Hostname = $hostname ; Version = $version ; Community = $community ; Mode = $mode ; warning = $warning ; critical = $critical ; login = $login ; user = $user ; password = $password"
echo "*********************************************************************"
}

# Results sent to Nagios
function_exit()
{
if [ $sum_value_Unknwon != 0 ]
then
	echo "Unknown $comm_final"
	exit $STATE_UNKNOWN
fi

if [ $sum_value_Critical != 0 ]
then
	echo "Critical $comm_final"
	exit $STATE_CRITICAL
fi

if [ $sum_value_Warning != 0 ]
then
	echo "Warning $comm_final"
	exit $STATE_WARNING
fi

if [ $sum_value_Ok != 0 ]
then
	echo "OK $comm_final"
	exit $STATE_OK
fi
}

############################################################
# Mode Modules
############################################################
# The number of slot
slots_count()
{
	slot_number=`$SNMPGET $walk_param $mib_slots_number | cut -d' ' -f4 | cut -c 8,9  | sed 's/^0//'`
	check_num $slot_number slot_number
}

# Module Admin Status for any slot
modules_check_adminstatus()
{
	for i in $(seq $slot_number)
	do
	module_adminstatus_[$i]=`$SNMPGET $walk_param $mib_modules_adminstatus."$i"000 | cut -d' ' -f4`
	if [ ${module_adminstatus_[$i]} != "Such" ]
	then
		check_num ${module_adminstatus_[$i]} module_adminstatus_[$i]
		
	fi
	done
}

# OperationnalStatus for any modules
modules_check_operstatus()
{
	for i in $(seq $slot_number)
	do
		if [ ${module_adminstatus_[$i]} = 1 ]
		then
			module_operstatus_[$i]=`$SNMPGET $walk_param $mib_modules_operstatus."$i"000 | cut -d' ' -f4`
			check_num ${module_operstatus_[$i]} module_operstatus_[$i]
			
			module_description_[$i]=`$SNMPGET $walk_param $mib_modules_description."$i"000 | cut -d' ' -f4`
			
			module_resetreason_[$i]=`$SNMPGET $walk_param $mib_modules_resetreason."$i"000 | cut -d' ' -f4`
			check_num ${module_resetreason_[$i]} module_resetreason_[$i]
			
			module_number=$(( ${module_number} + 1 ))
		fi
	done
	
	if [ $module_number -gt $slot_number ]
	then
		echo "Error - Too much modules detected : $module_number, but only $slot_number slots !"
		exit $STATE_UNKNOWN
	fi
}

# Translate SNMP status return by host to Nagios status
modules_sum()
{
	comm_final="$comm_final -"
	for i in $(seq $slot_number)
	do

		if [ "${module_operstatus_[$i]}" == "1" ]
		then
			module_nagiosstatus_[$i]=$STATE_UNKNOWN
			sum_value_Unknwon=$(( ${sum_value_Unknwon} + 1 ))
			comm_final="$comm_final ${module_description_[$i]}=${operstatus_value[$"${module_operstatus_[$i]}"]} (reseted by ${resetreason_value[$"${module_resetreason_[$i]}"]}),"
		fi
		
		if [ "${module_operstatus_[$i]}" == "2" ]
		then
			module_nagiosstatus_[$i]=$STATE_OK
			sum_value_Ok=$(( ${sum_value_Ok} + 1 ))
			comm_final="$comm_final ${module_description_[$i]}=${operstatus_value[$"${module_operstatus_[$i]}"]} (reseted by ${resetreason_value[$"${module_resetreason_[$i]}"]}),"
		fi
		
		if [ "${module_operstatus_[$i]}" == "4" ] || [ "${module_operstatus_[$i]}" == "5" ] || [ "${module_operstatus_[$i]}" == "6" ] || [ "${module_operstatus_[$i]}" == "19" ] || [ "${module_operstatus_[$i]}" == "20" ] || [ "${module_operstatus_[$i]}" == "21" ]
		then
			module_nagiosstatus_[$i]=$STATE_WARNING
			sum_value_Warning=$(( ${sum_value_Warning} + 1 ))
			comm_final="$comm_final ${module_description_[$i]}=${operstatus_value[$"${module_operstatus_[$i]}"]} (reseted by ${resetreason_value[$"${module_resetreason_[$i]}"]}),"
		fi

		if [ "${module_operstatus_[$i]}" == "3" ] || [ "${module_operstatus_[$i]}" == "7" ] || [ "${module_operstatus_[$i]}" == "8" ] || [ "${module_operstatus_[$i]}" == "9" ] || [ "${module_operstatus_[$i]}" == "10" ] || [ "${module_operstatus_[$i]}" == "11" ] || [ "${module_operstatus_[$i]}" == "12" ] || [ "${module_operstatus_[$i]}" == "13" ] || [ "${module_operstatus_[$i]}" == "14" ] || [ "${module_operstatus_[$i]}" == "15" ] || [ "${module_operstatus_[$i]}" == "16" ] || [ "${module_operstatus_[$i]}" == "17" ] || [ "${module_operstatus_[$i]}" == "18" ]
		then
			module_nagiosstatus_[$i]=$STATE_CRITICAL
			sum_value_Critical=$(( ${sum_value_Critical} + 1 ))
			comm_final="$comm_final ${module_description_[$i]}=${operstatus_value[$"${module_operstatus_[$i]}"]} (reseted by ${resetreason_value[$"${module_resetreason_[$i]}"]}),"
		fi
	done
	comm_final="$comm_final | Nb_Modules=$module_number Modules_OK=$sum_value_Ok Modules_Warning=$sum_value_Warning Modules_Critical=$sum_value_Critical Modules_Unknown=$sum_value_Unknwon"
}


############################################################
# Main Method
############################################################
main()
{
	# Get Options and check parameters
	while getopts H:V:C:M:l:u:a:dh option;
	do
		case $option in
			H) hostname=$OPTARG;;
			V) version=$OPTARG;;
			C) community=$OPTARG;;
			M) mode=$OPTARG;;
			l) login=$OPTARG;;
			u) user=$OPTARG;;
			a) password=$OPTARG;;
			d) debug=1;;
			h) echo "$USAGE"
			exit $STATE_UNKNOWN;;
		esac
	done

	check_param


	### Mode 1 - Failover ### 
	if [ "$mode" == "modules" ]
	then
		# Functions lunch
		slots_count
		modules_check_adminstatus
		modules_check_operstatus
		modules_sum
	fi


	if [ "$debug" == 1 ]
	then
		debug
	fi

	function_exit
}

main $*

# Default exit
echo "Unknown - No result sent to nagios - End of script"
exit $STATE_UNKNOWN