#!/bin/sh
# $Id: lbcheck 687 2009-07-14 14:35:04Z root $

fatal () {
    echo "ERROR: $1 - Sleeping $INTERVAL seconds before exit."
    logger "ERROR: $1 - Sleeping $INTERVAL seconds before exit."
    sleep $INTERVAL
    exit 0    
}

warning () {
    echo "WARNING: $1"
    logger "WARNING: $1"
}

check_ipv4 () {
    [ ! -z ${LBGW} ] || fatal "IPv4 loadbalancer gateway IP not defined!"
    [ ! -z ${LBIP} ] || fatal "IPv4 loadbalancer node IP not defined!"
    [ ! -z ${LBNET} ] || fatal "IPv4 loadbalancer network not defined!"
    [ ! -z ${LBMASK} ] || fatal "IPv4 Loadbalancer netmask not defined!"
    [ ! -z ${LBIF} ] || fatal "IPv4 Loadbalancer interface not defined!"

    # Setting FIXIT to 1 will reset the loadbalancer routes.
    FIXIT=0

    # Check
    if ! ${IPBIN} address show dev ${LBIF} | grep -q "inet ${LBIP}/${LBMASK}"; then
        FIXIT=1
        warning "IPv4 loadbalancer node IP not configured on ${LBIF}."
    fi
    if ! ${IPBIN} route show | grep -q "${LBNET}.*dev ${LBIF}.*src ${LBIP}"; then
        FIXIT=1
        warning "IPv4 loadbalancer route not configured correctly."
    fi
    if ! ${IPBIN} route show table 1 | grep -q "${LBNET}.*dev ${LBIF}.*src ${LBIP}"; then
        FIXIT=1
        warning "IPv4 loadbalancer sourcebased route not configured correctly."
    fi
    if ! ${IPBIN} route show table 1 | grep -q "default via ${LBGW} dev ${LBIF}"; then
        FIXIT=1
        warning "IPv4 loadbalancer default route not configured correctly."
    fi

    if [ $FIXIT -gt 0 ]; then
        warning "Flushing IPv4 loadbalancer configuration ..."
        ${IPBIN} addr del ${LBIP}/${LBMASK} dev ${LBIF} >/dev/null 2>&1
        ${IPBIN} route flush table 1 >/dev/null 2>&1
        ${IPBIN} rule del from ${LBNET}/${LBMASK} lookup 1 >/dev/null 2>&1
        # Remove SBR entries for VIPs when defined in config file
        if [ -n "${SBRIP4}" ]; then
            for SBRIP in ${SBRIP4}
            do
                ${IPBIN} route del ${SBRIP} dev ${LBIF} src ${LBIP} >/dev/null 2>&1
            done
        fi

        warning "Setting IPv4 loadbalancer configuration ..."
        ${IPBIN} addr add ${LBIP}/${LBMASK} dev ${LBIF}
        ${IPBIN} route add ${LBNET}/${LBMASK} dev ${LBIF} src ${LBIP} table 1
        ${IPBIN} route add default via ${LBGW} table 1
        ${IPBIN} rule add from ${LBNET}/${LBMASK} lookup 1
        # Add SBR entries for VIPs when defined in lbnet file
        if [ -n "${SBRIP4}" ]; then
            for SBRIP in ${SBRIP4}
            do
                ${IPBIN} route add ${SBRIP} dev ${LBIF} src ${LBIP}
            done
        fi

    fi
}

check_ipv6 () {
    [ ! -z ${LBGW6} ] || fatal "IPv6 loadbalancer gateway IP not defined!"
    [ ! -z ${LBIP6} ] || fatal "IPv6 loadbalancer node IP not defined!"
    [ ! -z ${LBNET6} ] || fatal "IPv6 loadbalancer network not defined!"
    [ ! -z ${LBMASK6} ] || fatal "IPv6 Loadbalancer netmask not defined!"
    [ ! -z ${LBIF6} ] || fatal "IPv6 Loadbalancer interface not defined!"

    # Setting FIXIT to 1 will reset the loadbalancer routes.
    FIXIT=0

    # Check
    if ! ${IPBIN} -6 address show dev ${LBIF6} | grep -q "inet6 ${LBIP6}/${LBMASK6}"; then
        FIXIT=1
        warning "IPv6 loadbalancer node IP not configured on ${LBIF6}."
    fi
    if ! ${IPBIN} -6 route show | grep -q "${LBNET6}.*dev ${LBIF6}"; then
        FIXIT=1
        warning "IPv6 loadbalancer route not configured correctly."
    fi
    if ! ${IPBIN} -6 route show table 2 | grep -q "${LBNET6}.*dev ${LBIF6}"; then
        FIXIT=1
        warning "IPv6 loadbalancer sourcebased route not configured correctly."
    fi
    if ! ${IPBIN} -6 route show table 2 | grep -q "default via ${LBGW6} dev ${LBIF6}"; then
        FIXIT=1
        warning "IPv6 loadbalancer default route not configured correctly."
    fi

    if [ $FIXIT -gt 0 ]; then
        warning "Flushing IPv6 loadbalancer configuration ..."
        ${IPBIN} -6 addr del ${LBIP6}/${LBMASK6} dev ${LBIF6} >/dev/null 2>&1
        ${IPBIN} -6 route flush table 2 >/dev/null 2>&1
        ${IPBIN} -6 rule del from ${LBNET6}/${LBMASK6} lookup 2 >/dev/null 2>&1
        # Remove SBR entries for VIPs when defined in config file
        if [ -n "${SBRIP6}" ]; then
            for SBRIP in ${SBRIP6}
            do
                ${IPBIN} -6 route del ${SBRIP} dev ${LBIF6} src ${LBIP6} >/dev/null 2>&1
            done
        fi

        warning "Setting IPv6 loadbalancer configuration ..."
        ${IPBIN} -6 addr add ${LBIP6}/${LBMASK6} dev ${LBIF6} nodad preferred_lft 0
        ${IPBIN} -6 route add ${LBNET6}/${LBMASK6} dev ${LBIF6} src ${LBIP6} table 2
        ${IPBIN} -6 route add default via ${LBGW6} table 2
        ${IPBIN} -6 rule add from ${LBNET6}/${LBMASK6} lookup 2
        # Add SBR entries for VIPs when defined in config file
        if [ -n "${SBRIP6}" ]; then
            for SBRIP in ${SBRIP6}
            do
                ${IPBIN} -6 route add ${SBRIP} dev ${LBIF6} src ${LBIP6}
            done
        fi
    fi
}

#
# Main program loop starts here.
#

# Default interval
INTERVAL=10
IPBIN=`which ip`
CONFIG="/etc/default/bit-lbcheck"

[ -e $CONFIG ] || fatal "Default file $CONFIG could not be found."
[ -x $IPBIN ] || fatal "The 'ip' binary could not be located."

while (/bin/true); do
    . $CONFIG

    case "$RUN" in
        ipv4)
            check_ipv4
        ;;
        ipv6)
            check_ipv6
        ;;
        both)
            check_ipv4
            check_ipv6
        ;;
        *)
            warning "bit-lbcheck unconfigured or disabled. See $CONFIG for hints. Sleeping."
        ;;
    esac

    sleep $INTERVAL
done
