#!/bin/bash

# check_default_gw.sh - check default gateway(s) Nagios plugin

# This script will check if default gateway is up. It can handle multiple
# gateways, usually present in OSFP/BGP/dynamic routing protocol
# environments.  Uses "ip" command from iproute2 package and awk.

# Example:

# check_default_gw.sh -p zebra -g 10.100.121.252:10.100.121.251 -x
#    check for gw(s) set up by zebra; warn if any extra gw is present and/or
#    if default gw was not brought up by zebra (but it's kernel's instead
#    for ex.)

# Note: gateway order in -g is not important

# Copyright 2011 Rafał Frühling <rafamiga@gmail.com>

# LICENCE: GPL
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# you should have received a copy of the GNU General Public License
# along with this program (or with Nagios); if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA
#
# Based on check_gtw.sh by Luigi Balzano

PROGNAME=`basename $0`
PROGPATH=`echo $0 | /bin/sed -e 's,[\\/][^\\/][^\\/]*$,,'`
REVISION=`echo '$Revision: 9401 $' | sed -e 's/[^0-9.]//g'`
TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`

ip_exe=/sbin/ip

STATE_UNKNOWN=3
STATE_CRITICAL=2
STATE_WARNING=1
STATE_OK=0

print_usage() {
    echo "Usage: ${PROGNAME} -h"
    echo "Usage: ${PROGNAME} -v"
    echo "Usage: ${PROGNAME} [-p EXPECTED_PROTO] [-o] [-w] [-x] -g EXPECTED_DEF_GW1:EXPECTED_DEF_GW2:EXPECTED_DEF_GW3:..."
    echo ""
    echo "    -g <ip[:ip[:...]]]>: IP(s) if default gateway(s)"
    echo "    -c: fail if any expected gateway is missing (default: warn)"
    echo "    -x: warn if extra gateways are up"
    echo "    -p <proto>: warn if routing proto is not what's expected (checked after gateways)"
    echo "    -o: fail if routing proto is not what's set by -p (forces check to be perfomed before gateways; useful for dynamic routing)"
    }
 
print_help() {
    print_revision "$PROGNAME" $REVISION
    echo ""
    print_usage
    echo ""
    echo "Plugin to check if default gateway(s) is(are) present or missing. Most useful in multiple-gw OSPF environments."
    echo ""
    }

# No command line arguments are supplied for this script. Print help

if [ "$#" -eq "0" ]; then
    print_usage
    exit ${STATE_UNKNOWN}
fi

# Print help with --help

if [[ ("$#" -eq "1") && ("$1" = "--help") ]]; then
    print_help
    exit ${STATE_UNKNOWN}
fi

unset EXPECTED
unset WARN_MISSING
unset ROUTE_PROTO
CHECK_PROTO_1ST=0
FAIL_MISSING=0
WARN_EXTRA=0

while getopts "vhcxog:p:" option
do
    case ${option} in
        h     ) print_help
            exit ${STATE_UNKNOWN};;
        v     ) print_revision "${PROGNAME}" ${REVISION}
            exit ${STATE_UNKNOWN};;
        c     ) FAIL_MISSING=1;;
        x     ) WARN_EXTRA=1;;
        g     ) EXPECTED=${OPTARG};;
        p     ) ROUTE_PROTO=${OPTARG};;
        o     ) CHECK_PROTO_1ST=1;;
        *     ) print_usage
            exit ${STATE_UNKNOWN};;   # DEFAULT
    esac
done

if [ -z "${EXPECTED}" ]; then
    echo "UNKNOWN - Missing gateway(s) definition. See help (-h)."
    exit ${STATE_UNKNOWN}
fi

TRACE=`${ip_exe} route list 0/0 2>&1`
GATEWAYS=`echo "${TRACE}" | awk -F " " '/via/ { for (i=1; i<=NF; i++) { if ($i == "via") { printf("%s\n", $(i+1)); break; } } }' 2>&1`
RPROTO=`echo "${TRACE}" | awk -F " " '/proto/ { for (i=1; i<=NF; i++) { if ($i == "proto") { printf("%s\n", $(i+1)); break; } } }' 2>&1`

if [ -z "${GATEWAYS}" ]; then
    echo "CRITICAL - found no default gateways (checked using '${ip_exe} route list 0/0')"
    exit ${STATE_CRITICAL}
fi

if [ -z "${RPROTO}" ]; then
    echo "CRITIAL - no default gateway route proto (checked using '${ip_exe}) THIS SHOULD NEVER HAPPEN!"
    exit ${STATE_CRITICAL}
fi

if [ -n "${ROUTE_PROTO}" ] && [ ${CHECK_PROTO_1ST} -eq 1 ] && [ "${RPROTO}" != "${ROUTE_PROTO}" ] ; then
    echo "CRITIAL - default gateway set up by '${RPROTO}' proto; expecting '${ROUTE_PROTO}' instead."
    exit ${STATE_CRITICAL}
fi

MISSING_GWS=`echo "${GATEWAYS}" | awk -v gws=${EXPECTED} '
    BEGIN {
        split(gws,gws_a,":");
        }
    {
    for (i in gws_a) {
        if ( $1 == gws_a[i] ) {
                delete gws_a[i];
                }
            }
        }
    END {
        for (i in gws_a) {
            printf("%s ",gws_a[i]);
            }
        }
'`

if [ -n "${MISSING_GWS}" ]; then
    if [ ${FAIL_MISSING} -eq 0 ]; then
        echo "WARNING - missing gateway(s): ${MISSING_GWS}"
        exit ${STATE_WARNING}
    else
        echo "CRITICAL - missing gateway(s): ${MISSING_GWS}"
        exit ${STATE_CRITICAL}
    fi
fi

if [ ${WARN_EXTRA} -eq 1 ]; then
    EXTRA_GWS=`echo "${GATEWAYS}" | awk -v gws=${EXPECTED} '
    BEGIN {
        split(gws,gws_a,":");
        }
    {
    gw[$1]=1
    }
    END {
        for (i in gws_a) {
            delete gw[gws_a[i]];
            }
        for (i in gw) {
            printf("%s ",i);
            }
        }
'`

    if [ -n "${EXTRA_GWS}" ]; then
#        if [ ${FAIL_MISSING} -eq 0 ]; then
            echo "WARNING - extra gateway(s): ${EXTRA_GWS}"
            exit ${STATE_WARNING}
#        else
#            echo "CRITICAL - missing gateway(s): ${MISSING_GWS}"
#            exit ${STATE_CRITICAL}
#        fi
    fi
fi # if warn extra

if [ -n "${ROUTE_PROTO}" ] && [ "${RPROTO}" != "${ROUTE_PROTO}" ]; then
    echo "WARNING - default gateway set up by '${RPROTO}' proto; expecting '${ROUTE_PROTO}' instead."
    exit ${STATE_WARNING}
fi

echo "OK - default gateway(s) '${EXPECTED}' set up by '${ROUTE_PROTO}' are up and active."
exit ${STATE_OK}
