#!/bin/bash
#----------------------------------------------------------------------#
# Performs network interface profile switching (usually for notebooks) #
#  based on Patrik's rc.inet1 script                                   #
#                                                                      #
# (c) 2004 Tom Z. Meinlschmidt <tomas at meinlschmidt dot org>         #
#  feel free to contact me                                             #
#----------------------------------------------------------------------#

# include configuration
. /etc/rc.d/rc.network.conf

##################
# LOCAL SETTINGS #
##################

DEBUG="1"
MODPROBE="/sbin/modprobe"
IFCONFIG="/sbin/ifconfig"
ROUTE="/sbin/route"
DHCPCD="/sbin/dhcpcd"

# define logger
# If possible, log events in /var/log/messages:
if [ /var/run/syslogd.pid -a -x /usr/bin/logger ]; then
  LOGGER=/usr/bin/logger
else # output to stdout/stderr:
  LOGGER=/bin/cat
fi

#########
# USAGE #
#########

function usage() {
    echo "usage $0 start|stop|restart|switch [profile name]"
    exit 2
}

##################
# DEBUG MESSAGES #
##################

function debug() {
    if [ $DEBUG ]; then
        if [ "$DBGMSG" != "" ]; then
            echo "${0}: $DBGMSG" | $LOGGER
        fi
    fi
}

##########################
# FIND CONNECTION NUMBER #
##########################

function find_connection() {
    CONNS=${#CONNECTIONS[@]}
    CONN_NUMBER=0
    for ((;CONNS;CONNS--)); do
        if [ "${CONNECTIONS[$CONNS]}" == "$PROFILE_NAME" ]; then
            CONN_NUMBER=$CONNS
            break
        fi
    done
    if [ $CONN_NUMBER -eq 0 ];then
        DBGMSG="Cannot find connection with name '$PROFILE_NAME'. Aborted."
        echo $DBGMSG
        debug
        exit 2
    fi
    DBGMSG="Using connection with number '$CONN_NUMBER'."
    debug
}

#################
# DO THE SWITCH #
#################

function do_switch() {
    INTERFACE=${USEIF[$CONN_NUMBER]};
    if [ "$INTERFACE" == "" ]; then
        DBGMSG="Interface not specified, using 'eth0' as default."
        INTERFACE="eth0"
        debug
    fi
    # interface test, if not running, try to load module
    if ! grep $INTERFACE: /proc/net/dev 1>/dev/null ; then
        if $MODPROBE -c | grep -w "alias $INTERFACE" | grep -vw "alias $INTERFACE off" >/dev/null ; then
            DBGMSG="Interface $INTERFACE not up, trying to load module"
            debug
            $MODPROBE $INTERFACE
        fi
    fi
    if ! grep $INTERFACE: /proc/net/dev 1>/dev/null ; then
        DBGMSG="Cannot initialize interface '$INTERFACE'. Aborted."
        debug
        exit 2
    fi

    # process all the wireless stuffs
    if [ "${IS_WIRELESS[$CONN_NUMBER]}" == "yes" ]; then
        if [ -x /etc/rc.d/rc.wireless ]; then
            DBGMSG="Processing wireless stuffs on '$INTERFACE'"
            . /etc/rc.d/rc.wireless $INTERFACE
            debug
        else
            DBGMSG="Wireless failed, rc.wireless is not executable."
            debug
        fi
    fi

    # test if IPADDR or USE_DHCP is set, otherwise do abort
    if [ ! "${IPADDR[$CONN_NUMBER]}" ]; then
        if [ ! "${USE_DHCP[$CONN_NUMBER]}" ]; then
            DBGMSG="No IP address or DHCP specified. Aborted."
            debug
            exit 2
        else
            DBGMSG="Using DHCP/'$INTERFACE'"
            DHCP="1"
        fi
    else
        IP_ADDRESS=${IPADDR[$CONN_NUMBER]}
        NET_MASK=${NETMASK[$CONN_NUMBER]}
        DBGMSG="Using IP address '$IP_ADDRESS'/'$INTERFACE'"
        debug
        if [ "$NET_MASK" == "" ]; then
            NET_MASK="255.255.255.0"
            DBGMSG="Network mask not specified, using 255.255.255.0 as default"
        fi
    fi
    debug
    # initialize interface
    # DHCP required?
    if [ "$DHCP" == "1" ]; then
        DHCPHOSTNAME=${DHCP_HOSTNAME[$CONN_NUMBER]}
        if [ "$DHCPHOSTNAME" != "" ]; then
            DBGMSG="Starting DHCP with hostname '$DHCPHOSTNAME' at '$INTERFACE'"
          $DHCPCD -d -t 10 -h $DHCPHOSTNAME $INTERFACE
        else
          DBGMSG="Starting DHCP at '$INTERFACE'"
          $DHCPCD -d -t 10 $INTERFACE
        fi
        debug
    else
        # set static IP address
        # calc broadcast
        BROADCAST=`/bin/ipmask $NET_MASK $IP_ADDRESS | cut -f 1 -d ' '`
        DBGMSG="Setting interface $INTERFACE with IP address $IP_ADDRESS/$NET_MASK (broadcast $BROADCAST)"
        $IFCONFIG $INTERFACE $IP_ADDRESS broadcast $BROADCAST netmask $NET_MASK
        debug
        # set default gateway
        GATEWAY=${GATEWAY[$CONN_NUMBER]}
        if [ "$GATEWAY" != "" ]; then
            if $ROUTE -n | grep "^0.0.0.0" 1>/dev/null; then
                # default route found, need to delete it first
                DBGMSG="Found default route, route deleted."
                debug
                $ROUTE del default 2>&1 | $LOGGER
            fi
            DBGMSG="Adding default route through '$GATEWAY'/$INTERFACE, metric 1."
            debug
            $ROUTE add default gw $GATEWAY dev $INTERFACE metric 1 2>&1 | $LOGGER
        fi
    fi
}

########################################
# PERFORMS INTERFACE SETTING SWITCHING #
########################################

function switch() {
    if [ "$ARR_PROFILE_NAME" == "" ]; then
        usage
    fi
    for PROFILE_NAME in $ARR_PROFILE_NAME; do
        DBGMSG="Switch profile to '$PROFILE_NAME'"
        debug
        CONN_NUMBER=PROFILE_NAME
        find_connection
        SHUTDOWN=${SHUTDOWN_OTHER_FIRST[$CONN_NUMBER]}
        if [ "$SHUTDOWN" != "" ]; then
            do_shutdown
        fi
        do_switch
    done
}

#########################
# SHUTDOWN AN INTERFACE # 
#########################

function shutdown_interface() {
    # is interface alive?
    if grep $INTERFACE: /proc/net/dev 1>/dev/null ; then
        DBGMSG="Shutting down interface '$INTERFACE'"
        debug
        # is there any dhcpcd to this interface?
        if ps auxw | grep -i dhcpcd | grep -i $INTERFACE 1>/dev/null; then
            $DHCPCD -k -d $INTERFACE 2>&1 | $LOGGER
            DBGMSG="Shutting down dhcpcd..."
            sleep 1
            debug
        fi
        # shutdown interface
        # test if is interface loaded via modprobe
        if $MODPROBE -c | grep -w "alias $INTERFACE" | grep -vw "alias $INTERFACE off" >/dev/null ; then
            DBGMSG="Releasing module for interface '$INTERFACE'"
            $MODPROBE -r $INTERFACE 2>&1 | $LOGGER
        else
            # so shutdown interface
            DBGMSG="Making interface '$INTERFACE' down."
            $IFCONFIG $INTERFACE down 2>&1 | $LOGGER
        fi
        debug
    fi
}

################################
# PERFORMS INTERFACES SHUTDOWN #
################################

function do_shutdown() {
    if [ "$SHUTDOWN" == "*" ]; then
        # shutdown all interfaces
        for INTERFACE in `grep ":" /proc/net/dev | grep -v lo | awk -F ":" '{print $1}' | tr -d " "`; do
            shutdown_interface
        done
    else
        # shutdown interface
        INTERFACE=$SHUTDOWN
        shutdown_interface
    fi
}

function do_start() {
    if [ "$DEFAULT" != "" ]; then
        ARR_PROFILE_NAME=$DEFAULT
        switch
    fi
}
function do_stop() {
    sleep 1
}

function do_restart() {
    do_stop
    do_start
}

########
# MAIN #
########

case "$1" in
 'start')
    do_start
    ;;
 'stop')
    do_stop
    ;;
 'restart')
    do_restart
    ;;
 'switch')
    if [ "${2}" == "" ]; then
        usage
    fi
    ARR_PROFILE_NAME=$2
    switch;
    ;;
*)
    # the default is to load all defined interface at the boot time
    do_start
esac

# End of file