#!/bin/sh

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

PATH=$PATH:/usr/bin:/usr/sbin:/bin:/sbin

VERSION=0.1
PROG=$(basename $0)

STATE_EXIT=$STATE_UNKNOWN

NMAP=$(which nmap)
if [[ $? -eq 1 ]]; then
   echo "CRITICAL - nmap not found"
   exit $STATE_CRITICAL
fi

print_help()
{
    cat <<'EOF'
Usage: check_network_port.sh -H <HOST_ADDRESS> -p <PORT>

A Nagios Plugin that checks if the specified host is listening on specified
TCP/UDP port.  

Options:
  -h  --help                print this help message
  -V  --version             print program version
  -H  <HOST_ADDRESS>        The host, the specified port is to be tested on
  -p  <PORT>                The port number the host should listen to.

Examples:

To check, if host myserver is listening on the port 80:
  $ ./check_network_port.sh -H myserver -p 80
EOF
} #

print_version()
{
    cat <<EOF
$PROG $VERSION
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software.  You may redistribute copies of it under the terms of
the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
There is NO WARRANTY, to the extent permitted by law.

Written by Stefan Peters (s.peters [at] marienhospital-arnsberg.de)
EOF
} #

# check, if the option-parameters are ok
SHORTOPTS="p:H:h:V"
LONGOPTS="help,version"

if $(getopt -T >/dev/null 2>&1) ; [ $? = 4 ] ; then
    OPTS=$(getopt -o $SHORTOPTS --long $LONGOPTS -n "$PROG" -- "$@")
else
    case $1 in --help) print_help ; exit 0 ;; esac
    case $1 in --version) print_version ; exit 0 ;; esac
    OPTS=$(getopt $SHORTOPTS "$@")
fi

# we did not get the correct values 
if [ $? -ne 0 ]; then
    print_help;
    exit 1
fi

# variables can be set
eval set -- "$OPTS"

declare -i PORT
PORT=0
while [ $# -gt 0 ]; do
    case $1 in
        -h|--help)
            print_help
            exit 0
            ;;
        -V|--version)
            print_version
            exit 0
            ;;
        -H)
            HOST=$2
            shift 2
            ;;
        -p)
            PORT=$2
            shift 2
            ;;
        --)
            shift
            break
            ;;
        *)
            echo "Internal Error: option processing error: $1" 1>&2
            exit $STATE_UNKNOWN
            ;;
    esac
done

MAX_PORT_NUM=65535
if test ! $PORT -eq $PORT 2> /dev/null
then
    echo "Invalid port number";
    exit $STATE_UNKNOWN;
fi;
if test $PORT -ge $MAX_PORT_NUM -o $PORT -le 0
then
    echo "You MUST specify a valid listening port with option: '--port=PORT'"
    exit $STATE_UNKNOWN;
fi;

PORT_PROTO_STATE=$(${NMAP} ${HOST}  -PN -p ${PORT} |grep ^${PORT} | sed 's/\// /' |awk '{print $2" "$3}')
PORT_PROTO=$(echo $PORT_PROTO_STATE | awk '{ print $1 }')
PORT_STATE=$(echo $PORT_PROTO_STATE | awk '{ print $2 }')


if [ "$PORT_STATE" == "open" ]; then
   echo -ne "OK - "
   STATE_EXIT=$STATE_OK
fi

if [ "$PORT_STATE" == "closed" ]; then
   echo -ne "CRITICAL - "
   STATE_EXIT=$STATE_CRITICAL
fi

if [ "$PORT_STATE" == "" ]; then
   echo "CRITICAL - Host not reachable";
   exit $STATE_CRITICAL
else
   if [ "$STATE_EXIT" == "$STATE_UNKNOWN" ]; then
      echo -ne "UNKNOWN - "
   fi
   echo "Port ${PORT} (${PORT_PROTO}) is ${PORT_STATE}";
fi

exit $STATE_EXIT;
