#!/bin/bash

#################################################################################
#                                                                               #
#                  ALL THIS SCRIPT IS UNDER GPL LICENSE                         #
# Version 0.1                                                                   #
# Title:     fw-conntrack                                                       #
# Author:    Alexander Bech  (alex |at| bakarasse |dot| de)                     #
# Date:      2010-04-18                                                         #
# Purpose:   Monitoring and graphing iptables conntrack table                   #
# Platforms: Uni*                                                               #
# Tested:    Xymon 4.2.3                                                        #
#                                                                               #
# History:                                                                      #
# 2010-04-18                                                                    #
# Version 0.1 - Initial version.                                                #
#                                                                               #
#################################################################################

#
# Debian based systems have CLIENTHOSTNAME set
# when not set, you can set MACHINE here
# MACHINE=""

if [ -z "${CLIENTHOSTNAME}" ]
then
    # not debian-based
    if [ -z "${MACHINE}" ]
    then
        echo "Error: MACHINE not defined !"
        exit 1
    fi
else
    # Debian-based
    MACHINE=${CLIENTHOSTNAME}
fi

TEST="fw-conntrack"		# Name of the column
COLOR="green"			# By default, everything is OK
ERRORCOLOR="yellow"		# or clear ?

# Change to fit your system/wills :
# Warning/alarm if conntrack table is filled. Percent:
declare -i PERCENT_WARN=80
declare -i PERCENT_ALARM=90

#################################################################################################
#												#
#  hobbit user can not read the files in /proc/net/ip_conntrack					#
#  and /proc/sys/net/ipv4/netfilter/ip_conntrack_[max|count]					#
#  On my machines this files are written for hobbit to ${BBTMP}					#
#  by root from cron job "hobbit-helper".							#
#  The script can be found on http://www.bakarasse.de						#
#												#
#  */5 * * * * root /usr/bin/bbcmd ${HOBBITCLIENTHOME}/ext-helper/hobbit-fw-conntrack-helper	#
#												#
CONNTRACK_FILE="$BBTMP/ip_conntrack"								#
CONNTRACK_COUNT_FILE="$BBTMP/ip_conntrack_count"						#
CONNTRACK_MAX_FILE="$BBTMP/ip_conntrack_max"							#
#												#
#################################################################################################

BB="${XYMON}"
BBDISP="${XYMSRV}"

# here work...
LC_ALL=C
LANG=C
LANGUAGE=C
MSG=""
COLORMSG=""

# DEBUG="TRUE"
function debug () {
if [ "${DEBUG}" = "TRUE" ]
then
    echo "Debug: $@"
fi
}

function senderrormessage () {
    debug "${MSG}"
    ${BB} ${BBDISP} "status ${MACHINE}.${TEST} ${COLOR} ${DATE}
    ${MSG}"
}

DATE=$(date)

if [ ! -e ${CONNTRACK_FILE} ]
then
    MSG="Error - CONNTRACK_FILE ${CONNTRACK_FILE} not found"
    COLOR="${ERRORCOLOR}"
    senderrormessage
    exit 0
fi
if [ ! -e ${CONNTRACK_MAX_FILE} ]
then
    MSG="Error - CONNTRACK_MAX_FILE ${CONNTRACK_MAX_FILE} not found"
    COLOR="${ERRORCOLOR}"
    senderrormessage
    exit 0
fi
if [ ! -e ${CONNTRACK_COUNT_FILE} ]
then
    MSG="Error - CONNTRACK_COUNT_FILE ${CONNTRACK_COUNT_FILE} not found"
    COLOR="${ERRORCOLOR}"
    senderrormessage
    exit 0
fi

# Avoid race condition when hobbit-helper rolled by cron job:
while [ -e ${BBTMP}/fw-conntrack-helper.lock ]
    do debug "sleep 1"; sleep 1
done

touch ${BBTMP}/fw-conntrack-worker.lock
trap "${RM} ${BBTMP}/fw-conntrack-worker.lock" 0 1 2 3 15

STARTTIME=$(date +%s.%N)

declare -i ASSURED=0
declare -i UNREPLIED=0
declare -i NATED=0
declare -i TCP=0
declare -i TCP_ESTABLISHED=0
declare -i TCP_TIME_WAIT=0
declare -i TCP_FIN_WAIT=0
declare -i TCP_SYN_SENT=0
declare -i TCP_SYN_RECV=0
declare -i TCP_LAST_ACK=0
declare -i TCP_CLOSE_WAIT=0
declare -i TCP_CLOSE=0
declare -i UDP=0
declare -i ICMP=0

CONNTRACK_MAX=$(< ${CONNTRACK_MAX_FILE})
CONNTRACK_COUNT=$(< ${CONNTRACK_COUNT_FILE})
debug "connections=${CONNTRACK_COUNT}"

# calculate percent:
CONNTRACK_WARN=$((${CONNTRACK_MAX} * ${PERCENT_WARN} / 100))
CONNTRACK_ALARM=$((${CONNTRACK_MAX} * ${PERCENT_ALARM} / 100))
PERCENT=$(echo "${CONNTRACK_COUNT} ${CONNTRACK_MAX}" | ${AWK} '{ printf "%-6.3f", $1*100/$2 }')
debug "percent=${PERCENT}"

if [ ${CONNTRACK_COUNT} -gt ${CONNTRACK_WARN} ]; then COLOR="yellow"; COLORMSG="&yellow over ${PERCENT_WARN} &#37; of the conntrack table is filled"; fi
if [ ${CONNTRACK_COUNT} -gt ${CONNTRACK_ALARM} ]; then COLOR="red"; COLORMSG="&red over ${PERCENT_ALARM} &#37; of the conntrack table is filled"; fi

# Evaluate conntrack table:
CONNTRACK_TABLE=$(< ${CONNTRACK_FILE})
ASSURED=$(echo "${CONNTRACK_TABLE}" | ${GREP} "ASSURED" | ${WC})

ORIGIFS=${IFS}
IFS=$'\n'

for LINE in ${CONNTRACK_TABLE}
do
    IFS=${ORIGIFS}
    set -- ${LINE}
    case ${1}
    in
    tcp)
	((TCP++))
	if [ ${11} = "[UNREPLIED]" ]; then	
	    if [ ${5:4} != ${13:4} -o ${6:4} != ${12:4} ]; then ((NATED++)); fi
	else
	    if [ ${5:4} != ${12:4} -o ${6:4} != ${11:4} ]; then ((NATED++)); fi
	fi

    	case ${4}
	in
	ESTABLISHED)
	    ((TCP_ESTABLISHED++))
	;;
	TIME_WAIT)
	    ((TCP_TIME_WAIT++))
	;;
	FIN_WAIT)
	    ((TCP_FIN_WAIT++))
	;;
	SYN_SENT)
	    ((TCP_SYN_SENT++))
	;;
	SYN_RECV)
	    ((TCP_SYN_RECV++))
	;;
	LAST_ACK)
	    ((TCP_LAST_ACK++))
	;;
	CLOSE_WAIT)
	    ((TCP_CLOSE_WAIT++))
	;;
	CLOSE)
	    ((TCP_CLOSE++))
	;;
	esac
    ;;
    udp)
	((UDP++))
	if [ ${10} = "[UNREPLIED]" ]; then	
	    if [ ${4:4} != ${12:4} -o ${5:4} != ${11:4} ]; then ((NATED++)); fi
	else
	    if [ ${4:4} != ${11:4} -o ${5:4} != ${10:4} ]; then ((NATED++)); fi
	fi
    ;;	
    icmp)
	((ICMP++))
	if [ ${11} = "[UNREPLIED]" ]; then	
	    if [ ${4:4} != ${13:4} -o ${5:4} != ${12:4} ]; then ((NATED++)); fi
	else
	    if [ ${4:4} != ${12:4} -o ${5:4} != ${11:4} ]; then ((NATED++)); fi
	fi
    ;;	
    esac
done
IFS=${ORIGIFS}

ENDTIME=$(date +%s.%N)
RUNTIME=$(echo "${STARTTIME} ${ENDTIME}" | ${AWK} '{print $2 - $1}')

MSG="${COLORMSG}
Conntrack in use = ${PERCENT} &#37;

connections = ${CONNTRACK_COUNT}
assured = ${ASSURED}
nated = ${NATED}

tcp = ${TCP}
udp = ${UDP}
icmp = ${ICMP}

tcp:
established = ${TCP_ESTABLISHED}
time_wait = ${TCP_TIME_WAIT}
fin_wait = ${TCP_FIN_WAIT}
syn_sent = ${TCP_SYN_SENT}
syn_recv = ${TCP_SYN_RECV}
last_ack = ${TCP_LAST_ACK}
close_wait = ${TCP_CLOSE_WAIT}
close = ${TCP_CLOSE}

runtime = ${RUNTIME}
"

# Tell Hobbit about it:
${BB} ${BBDISP} "status ${MACHINE}.${TEST} ${COLOR} `date`
${MSG}
"
debug "${BB} ${BBDISP} status ${MACHINE}.${TEST} ${COLOR} `date`
${MSG}
"
