#!/bin/bash
# Written By: Scott McCarty
# Created: 2/2008
# Description: Used to collect counters for bgp and also status and number of prefixes in memory
# 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: 1.1

debug() {
	if [ $debug -eq 1 ]
	then
		echo "Debug: $1";
	fi
}

init() {

	# Varialbles
	debug=0
	prefixes_threshold=300000
	status_threshold=6
	tx_threshold=1
	rx_threshold=5
	current_rx_counter=0
	current_tx_counter=0
	last_rx_counter=0
	last_tx_counter=0
	total_prefixes=0
	total_status=0
	min_status=0
	total_tx=0
	total_rx=0
	neighbors=""
	community=""
	hostname=""
	neighbor_count=0
	temp_file="/tmp/check_bgp_all"

	# main
	while getopts ":n:C:H:v" options; do
		case $options in
			n ) neighbors="$neighbors $OPTARG";;
			C ) community="$OPTARG";;
			H ) hostname="$OPTARG";;
			v ) debug=1;;
			h ) usage;;
			\? ) usage;;
			* ) usage;;
		esac
	done

	# Commands
	snmpget="/usr/bin/snmpget -v1 -On -Oe -c $community"

	# Debugging
	debug "neighbors: $neighbors"
	debug "community: $community"
	debug "hostname: $hostname"

	# Error Checking
	if [ "$neighbors" == "" ] \
	&& [ "$community" == "" ] \
	&& [ "$hostname" == "" ]
	then
		echo $usage
		exit 1
	fi
}

usage() {
	echo "Usage: $0 -H <hostname> -C <community> -n <neighbor1> -n neighbor2 [...]"
	exit
}

get_status() {
	echo -n `$snmpget $hostname .1.3.6.1.2.1.15.3.1.2.$neighbor | cut -d ':' -f 2 | sed 's/ *//'`
}

get_prefixes() {
	echo -n `$snmpget $hostname 1.3.6.1.4.1.9.9.187.1.2.4.1.1.$neighbor.1.1 | head -n1 | cut -d ':' -f 2 | sed 's/ *//'`
}

get_rx() {
	echo -n `$snmpget $hostname .1.3.6.1.2.1.15.3.1.12.$neighbor | cut -d ':' -f 2 | sed 's/ *//'`
}

get_tx() {
	echo -n `$snmpget $hostname .1.3.6.1.2.1.15.3.1.13.$neighbor | cut -d ':' -f 2 | sed 's/ *//'`
}

# Get all information from current polling periods inputs from the file
get_current() {

	# Status & Number of Prefixes don't need history to be determined correctly
	export bgp_status=`get_status`
	export bgp_prefixes=`get_prefixes`

	# Messages recieved and sent are counters, so they need last value to determine current difference
	export current_rx_counter=`get_rx`||current_rx_counter=0
	export current_tx_counter=`get_tx`||current_tx_counter=0

	# Determine what current output to send to file 
	export output="$output neighbor:$neighbor:sent:$current_tx_counter:received:$current_rx_counter"

}

# Get all information from last polling periods inputs from the file
get_last() {

	if [ -e ${temp_file}.${hostname} ]
	then
		debug "Working on neighbor: $neighbor"
		last_output=`/bin/cat ${temp_file}.${hostname}|grep $neighbor|tail -n1`
		export last_rx_counter=`echo $last_output | cut -f6 -d":"`
		export last_tx_counter=`echo $last_output | cut -f4 -d":"`
	else
		export last_rx_counter=0
		export last_tx_counter=0
	fi
}

write_file() {

	if [ -f ${temp_file}.$hostname ]
	then
		if [ $debug -ne 2 ]
		then
			rm -f ${temp_file}.$hostname
		fi    

		for line in $output
		do
			echo $line >> ${temp_file}.$hostname
			debug "line: $line"
		done
		else
			touch ${temp_file}.$hostname
		fi
}

calculate_values() {

	# Determine values
	current_rx=`expr $current_rx_counter - $last_rx_counter`
	current_tx=`expr $current_tx_counter - $last_tx_counter`

	# Calculate totals
	export total_prefixes=`expr $total_prefixes + $bgp_prefixes`
	export total_status=`expr $total_status + $bgp_status`
	export total_rx=`expr $total_rx + $current_rx`
	export total_tx=`expr $total_tx + $current_tx`

	# Add count to number of neighbors checked
	neighbor_count=`expr $neighbor_count + 1`
}

poll_bgp_debug() {

	debug "neighbor: $neighbor"
	debug "output: $last_output"
	debug "current_rx_counter:$current_rx_counter last_rx_counter:$last_rx_counter received:$current_rx total_received:$total_rx"
	debug "current_tx_counter:$current_tx_counter last_tx_counter:$last_tx_counter sent:$current_tx total_tx:$total_tx"
}

poll_bgp() {
	for neighbor in $neighbors
		do
			# Receive data both last polling period and current
			get_current
			get_last
			calculate_values
			poll_bgp_debug
		done

		# When final loop is complete write the new file
		write_file
}

check_failure() {

	# Calculate final thresholds & messages
	prefixes_threshold=`expr $prefixes_threshold \* $neighbor_count`
	status_threshold=`expr $status_threshold \* $neighbor_count`
	rx_threshold=`expr $rx_threshold \* $neighbor_count`
	tx_threshold=`expr $tx_threshold \* $neighbor_count`
	assert_failure=4
	error_message=""
	status_error="BGP status did not return correct value from one or more routers"
	prefix_error="Number of prefixes in memory too low"
	rx_error="Number of messages sent too low"
	tx_error="Number of messages received too low"

	# If the test succeeds, decrement assert_failure by one
	if [ $total_status -ne $status_threshold ]; then error_message="$status_error"; else assert_failure=`expr $assert_failure - 1`; fi
	if [ $total_prefixes -lt $prefixes_threshold ]; then error_message="$error_message $prefix_error"; else assert_failure=`expr $assert_failure - 1`; fi
	if [ $total_rx -lt $rx_threshold ]; then error_message="$error_message $rx_error"; else assert_failure=`expr $assert_failure - 1`; fi
	if [ $total_tx -lt $tx_threshold ]; then error_message="$error_message $tx_error"; else assert_failure=`expr $assert_failure - 1`; fi

	debug "Assert Failure: $assert_failure"
	debug "Error Messages: $error_message"
}

report() {

	check_failure

	if [ $assert_failure -gt 0 ]
	then
		echo -n "Failed: status:$total_status prefixes:$total_prefixes sent:$total_tx received:$total_rx report: $error_message"
		exit 2
	else
		# Output to nagios
		echo -n "Success: status:$total_status prefixes:$total_prefixes sent:$total_tx received:$total_rx"
		exit 0
	fi
}



init $*
poll_bgp
report
