#!/bin/sh
# Check CARP status on BSD machines
# - Works with either no parameter on standard configurations (slave has an advskew > 0)
# - Possible to override expected state definition with -M/-B flags
#
# Author : Stephane LAPIE <stephane.lapie@asahinet.com>

cd `dirname $0`
DIR=`pwd`
SCRIPT=`basename $0`

usage()
{
	echo "Usage: $0 [-h] [-B|-M] [NIC]"
	echo "	-B : Expects the NICs to be in BACKUP mode"
	echo "	-M : Expects the NICs to be in MASTER mode"
	echo "	If no NICs are specified, all currently CARP enabled ones will be checked"
	exit 3
}

exit_nagios()
{
	case $1 in
		0)
			echo "OK - $2"
			;;
		1)
			echo "WARNING - $2"
			;;
		2)
			echo "CRITICAL - $2"
			;;
		*)
			echo "UNKNOWN - $2"
			;;
	esac
}

###############################################################################
# Check OS

OS=`uname -s`
if ! (echo "$OS" | grep -E "FreeBSD|OpenBSD" >/dev/null) ; then
	echo "UNKNOWN - OS '$OS' not supported by this script"
	exit 3
fi

###############################################################################
# Check if CARP is used

CARP_OUTPUT=`ifconfig | grep "carp:"`
if [ -z "$CARP_OUTPUT" ] ; then
	exit_nagios 3 "No NIC is CARP enabled"
fi

###############################################################################
# Parse arguments

OK_MODE=ADVSKEW
NG_MODE=""

GETOPT_TEMP=`getopt MBh "$@"`
eval set -- "$GETOPT_TEMP"

while true ; do
	case "$1" in
		-M)
			OK_MODE=MASTER;
			NG_MODE=BACKUP;
			shift
			;;
		-B)
			OK_MODE=BACKUP;
			NG_MODE=MASTER;
			shift
			;;
		-h)
			usage
			;;
		--) shift ; break ;;
		*) echo "Internal error!"; exit 3 ;;
	esac
done

###############################################################################
# Check NIC list

NIC_LIST=`ifconfig -l`
NICS="$@"

# If no NIC was specified only keep the CARP enabled ones
if [ -z "$NICS" ] ; then
	for nic in $NIC_LIST ; do
		if (ifconfig $nic | grep "carp:" >/dev/null) ; then
			NICS="$NICS $nic"
		fi
	done
fi

return_code=0 # Default to OK
return_msg="CARP Status :"
# Check status of each CARP enabled NIC
for nic in $NICS ; do
	carp_output=`ifconfig $nic | grep "carp:" | tr -d '\t'`
	# carp: MASTER vhid 232 advbase 1 advskew 0
	# carp: BACKUP vhid 232 advbase 1 advskew 100
	carp_status=`echo "$carp_output" | sed 's/^carp: //;s/ .*//'`
	# MASTER
	# BACKUP
	if [ -z "$carp_status" ] ; then # NIC was not CARP enabled ?
		return_msg="${return_msg} ${nic} is not CARP enabled"
		if [ "$return_code" -lt 3 ] ; then return_code=3 ; fi
	else
		carp_advskew=`echo "$carp_output" | sed 's/.* advskew \([0-9][0-9]*\)/\1/'`
		# advskew 0 -> should be MASTER
		# advskew > 0 -> should be BACKUP

		return_msg="${return_msg} ${nic} is ${carp_status}"
		case $OK_MODE in
			MASTER|BACKUP)
				if [ "$carp_status" == "$OK_MODE" ] ; then
					return_msg="${return_msg} (OK)"
				elif [ "$carp_status" == "$NG_MODE" ] ; then
					return_msg="${return_msg} (CRITICAL)"
					if [ "$return_code" -lt 2 ] ; then return_code=2 ; fi
				else
					return_msg="${return_msg} (UNKNOWN)"
					if [ "$return_code" -lt 3 ] ; then return_code=3 ; fi
				fi
				;;
			ADVSKEW)
				if [ "$carp_advskew" -eq 0 ] ; then # advskew > 0, should be BACKUP
					if [ "$carp_status" = "MASTER" ] ; then
						return_msg="${return_msg} (OK)"
					elif [ "$carp_status" = "BACKUP" ] ; then
						return_msg="${return_msg} (CRITICAL)"
						if [ "$return_code" -lt 2 ] ; then return_code=2 ; fi
					else
						return_msg="${return_msg} (UNKNOWN)"
						if [ "$return_code" -lt 3 ] ; then return_code=3 ; fi
					fi
				else
					if [ "$carp_status" = "BACKUP" ] ; then
						return_msg="${return_msg} (OK)"
					elif [ "$carp_status" = "MASTER" ] ; then
						return_msg="${return_msg} (CRITICAL)"
						if [ "$return_code" -lt 2 ] ; then return_code=2 ; fi
					else
						return_msg="${return_msg} (UNKNOWN)"
						if [ "$return_code" -lt 3 ] ; then return_code=3 ; fi
					fi
				fi
				;;
		esac
	fi
	return_msg="${return_msg};"
done

exit_nagios "$return_code" "$return_msg"
