#!/bin/bash
#  Copyright (C) 2014-2016 STROMASYS.
#  All rights reserved.
VER_NO=1.6
NCU_LOG=/var/log/ncu.log
NCU_CFG=/etc/ncu.cfg
NCU_BR_CFG=/etc/ncu_br.cfg
NCU_VLAN_CFG=/etc/ncu_vlan.cfg
NCU_BAK=/tmp/ncu.bak
NCU_BR_BAK=/tmp/ncu_br.bak
NCU_VLAN_BAK=/etc/ncu_vlan.bak
NMCLI_VER=`nmcli --ver | sed -r -e 's/^[^[:digit:]]*([[:digit:].]+)([^[:digit:]^\.]|$).*/\1/'`
IFCONFIG=/sbin/ifconfig
iptuntap=`ip tuntap 2>&1 1>/dev/null | wc -l`
if [ -f /usr/sbin/brctl -a  \( "$iptuntap" = "0" -o -f /sbin/tunctl \) ] ; then
    BRTUN=yes
fi
if [ -f /sbin/vconfig -o -f /usr/sbin/vconfig ] ; then
    VLANPRESENT=yes
fi

p_flags()
{
    ethtool -K $1 rx $2
    ethtool -K $1 tx $2
    ethtool -K $1 sg $2
    ethtool -K $1 gso $2
    ethtool -K $1 gro $2
    ethtool -K $1 txvlan $2
    ethtool -K $1 rxvlan $2
}

p_ipaddr() { 
    $IFCONFIG $1 | grep -E '(inet\s*addr|inet)(:|\s)\s*[0-9]' | sed -e 's/.*\(inet\s*addr\|inet\)\(:\|\s\)\s*\([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\).*/\3/'
}

p_bridge()
{
    dname=$1
    tap_num=$2
    
    inf=$dname
    
    ethx=`$IFCONFIG -a | grep -E "^$dname(:\s|\s)" | sed 's/\(:\s\|\s\).*//'`
    br_name=br0_$inf
    if [ x$ethx == x ] ; then
	echo "Interface '$dname' does not exist";
	return;
    fi
    eth=$dname
    p_flags $eth off
    echo "Binding bridge to $eth..."
    ethip=`p_ipaddr $eth`
    route=`ip route | grep default |  awk '{print $3}'`
    route_through=`ip route | grep default |   sed 's/.*dev //g' |  awk '{print $1}'`
    if [ "x$route_through" != "x$eth" ] ; then
	route=''
    fi

    echo $br_name $ethip Route[$route] $route_through

    echo -n "Forming the bridge: ..1"
   
    echo -n "..2"
    $IFCONFIG $eth 0.0.0.0 promisc up
    
    echo -n "..3"
    /usr/sbin/brctl addbr $br_name
    echo -n "..4"
    /usr/sbin/brctl addif $br_name $eth
    echo -n "..5"
    for (( td=0 ; td < tap_num; td ++))
    do
	echo -n "."
	if [ $iptuntap != 0 ] ; then
	    tdev=`/usr/sbin/tunctl -b`
	else
	    tdevn=`ip tuntap | wc -l`
	    tdev=tap$tdevn
	    ip tuntap add $tdev mode tap 
	fi
	echo -n ". addif $tdev "
	/usr/sbin/brctl addif $br_name $tdev
	$IFCONFIG $tdev promisc up
    done
    echo -n "..7"
     /usr/sbin/brctl stp $br_name off
    echo -n "..8"

    if [ "x$ethip" != x ] ; then
	$IFCONFIG $br_name $ethip up
	if [ "x$route" != "x" ] ; then
	    echo -n "..9"
	    /sbin/route add default gw $route
	fi
    else
	$IFCONFIG $br_name up
    fi
    echo -n " "
    echo  " done!"
    echo "Formed bridge $br_name  attached over $eth...";
}

p_bridge_cleanup()
{
    eth=$1
    br_name=br0_$eth
    if grep -w $eth $NCU_BR_CFG 1>/dev/null ; then
	grep -vw $eth $NCU_BR_CFG > $NCU_BR_BAK
	mv $NCU_BR_BAK $NCU_BR_CFG
    else
	echo "ERROR: $br_name $eth did not configured"
	echo -e "Are you sure to cleanup it anyway [no]:"
	read -p "" ans
	if [ x$ans != xyes ] ; then
	    return
	fi
    fi
    if [[ ! -f /usr/sbin/brctl ]]; then
	echo Install 'bridge-utils' packadge please...
	exit 5
    fi
    xbr=`/usr/sbin/brctl show | grep $br_name`
    if [ "x$xbr" == x ] ; then
	echo "Failed to query for bridge $br_name - nothing to cleanup";
	return
    fi

    ethip=`p_ipaddr $br_name`
    route=`ip route | grep default |  awk '{print $3}'`
    route_through=`ip route | grep default |   sed 's/.*dev //g' |  awk '{print $1}'`
    if [ "x$route_through" != "x$br_name" ] ; then
	route=''
    fi

    echo "Cleanup bridge $br_name with ip $ethip over $eth...";
    echo -n "Removing the bridge: ..1"

    $IFCONFIG $br_name down
    echo -n "..2"
    for i in `/usr/sbin/brctl show $br_name | sed 's/.*\s//g'`; do
	if [ "x$i" == xinterfaces ] ; then
	    if="";
            tdev="";
	else
	    echo  " delif $i "
	    /usr/sbin/brctl delif $br_name  $i
	    if [ "x`echo $i | grep tap`" != x ] ; then
		if [ $iptuntap != 0 ] ;then
		    /usr/sbin/tunctl -d $i # > /dev/null
		else
		    ip tuntap del $i mode tap 
		fi
	    fi
	fi
    done
    echo -n "..5"
    /usr/sbin/brctl delbr $br_name
    echo -n "..6"
    $IFCONFIG $eth 0.0.0.0 -promisc up
    echo -n "..7"
    $IFCONFIG $eth down
    echo -n "..8"
    $IFCONFIG $eth up

    if [ "x$ethip" != x ] ; then
	echo -n "..9"
	$IFCONFIG $eth down
	echo -n "..10";
	$IFCONFIG $eth $ethip up
	if [ "x$route" != "x" ] ; then
	    echo -n "..11"
	    /sbin/route add default gw $route
	fi
    fi
    echo -n " "
    inf=$eth
    while true; do
	ethtool -K $inf rx on
	ethtool -K $inf tx on
	ethtool -K $inf sg on
	ethtool -K $inf gso on
	ethtool -K $inf gro on
	ethtool -K $inf txvlan on
	ethtool -K $inf rxvlan on
	break;
    done  >> $NCU_LOG
    echo " done!";
}  2>>$NCU_LOG
if [ "run" == "$1" ] ; then
    if [ -f $NCU_VLAN_CFG -a "$VLANPRESENT" = "yes" ] ; then
	while read ZZ ipaddr netmask ; do
	    eth=`echo ${ZZ} | sed -e "s/\..*//"`
	    vlanid=`echo ${ZZ} | sed -e "s/.*\.//"`
	    if [ -n "$eth" ] ; then
		/sbin/vconfig add $eth $vlanid
		if [ -n "$ipaddr" ] ; then
		    if [ -n "$netmask" ] ; then
			$IFCONFIG $ZZ $ipaddr netmask $netmask
		    else
		        $IFCONFIG $ZZ $ipaddr
		    fi
		fi
		$IFCONFIG $ZZ up
	    fi
	done <$NCU_VLAN_CFG
    fi
    if [ -f $NCU_BR_CFG -a "$BRTUN" = "yes" ] ; then
        eth=""
        for ZZ in $( cat  $NCU_BR_CFG ) ; do
	    if [ x$eth == x ] ; then
	        eth=$ZZ
	    else
	        p_bridge $eth $ZZ
	        eth=""
	    fi
        done
    fi
    if [[ -f $NCU_CFG ]] ; then
        for eth in $( cat  $NCU_CFG ) ; do
	    echo  $eth dedicated to charon
	    if [[ $NMCLI_VER < 0.9.9.0 ]] ; then
	        nmcli dev disconnect iface $eth
	    else
	        nmcli dev disconnect  $eth
	    fi
            p_flags $eth off
        done
    fi
fi
