#!/bin/sh

. /usr/bin/scriptlib
IPSEC_IFACE=ipsec0
IPSEC_STAT_RUN=/var/run/pluto/ipsec.statistic.run
IPSEC_STAT_FILE=/var/run/pluto/ipsec.statistic
IPSEC_CLEAN=/var/run/pluto/ipsec.clean

cfg_reload()
{
	/usr/bin/gen_ipsecconf
	ipsec auto --rereadall
}

print_usage()
{
	echo "Usage:"
	echo "     $0 {start|stop|reload|restart}"
	echo "     $0 {add|del|up|down|reload} tunnel_idx"
	echo "     $0 state tunnel_idx [new_state]"
	echo "     $0 dyncli {add|del} ip_address"
	echo "     $0 statistic {start|stop|renew} "
	echo "     $0 statistic {add|del|reset|get_outgoing|get_incoming} tunnel_idx"
}

add_active_tun()
{
	ACTIVE_TUN=`rdcsman 0x80700007 u32`
	let "ACTIVE_TUN = $ACTIVE_TUN + 1"
	wrcsman "0x80700007 $ACTIVE_TUN"
}

del_active_tun()
{
	ACTIVE_TUN=`rdcsman 0x80700007 u32`
	let "ACTIVE_TUN = $ACTIVE_TUN - 1"
	wrcsman "0x80700007 $ACTIVE_TUN"
}

set_state()
{
	IDX=`printf "0x807001%02X" $1`
	CNT_TYPE=`rdcsman $IDX u32`
	wrcsman "$IDX $2"
}

add_tunnel()
{
	IDX=`printf "0x007003%02X" $1`
	KEYMOD=`rdcsman $IDX u32`
	if [ "$KEYMOD"  == "0" ]; then
		IDX=`printf "0x00704B%02X" $1`
		CNT_TYPE=`rdcsman $IDX u32`
		if [ "$CNT_TYPE" == "0" ]; then
			set_state $1 9
			ipsec auto --add $1
			ipsec auto --up $1
		elif [ "$CNT_TYPE" == "1" ]; then
			set_state $1 3
		elif [ "$CNT_TYPE" == "2" ]; then
			ipsec auto --add $1
			ipsec auto --route $1
			set_state $1 2
		fi
	else 
		/usr/bin/imkt add $1
		add_active_tun
		set_state $1 1
	fi
}
     
del_tunnel()
{
	IDX=`printf "0x807001%02X" $1`
	STAT=`rdcsman $IDX u32`
	if [ "$STAT" == "1" ]; then
		del_active_tun
	fi
	# we do not know the old type of this tunnel
	# delete both of them
	ipsec auto --delete $1
	/usr/bin/imkt del $1
	set_state $1 0
}

start_statistic()
{
    if [ -f $IPSEC_STAT_RUN ]; then
        return 
    fi
    iptables -N IPSEC_PKTIN
    iptables -N IPSEC_PKTOUT
    
    iptables -A INPUT -i $IPSEC_IFACE -j IPSEC_PKTIN
    iptables -A FORWARD -i $IPSEC_IFACE -j IPSEC_PKTIN
    iptables -A FORWARD -o $IPSEC_IFACE -j IPSEC_PKTOUT
    iptables -A OUTPUT -o $IPSEC_IFACE -j IPSEC_PKTOUT   
    
    local max_tun=`rdcsman 0x00700040 u32`
    local i=1
    while [ $i -le $max_tun ]; do
	    IDX=`printf "0x007002%02X" $i`
        local tun_enable=`rdcsman $IDX u32`

	    IDX=`printf "0x807001%02X" $i`
        local cnt_status=`rdcsman $IDX u32`
        
        if [ $tun_enable -eq 1 ] && [ $cnt_status -eq 1 ]; then
            ipsec-action statistic add $i
        fi
        $((i=i+1))
    done
    touch $IPSEC_STAT_RUN
}

stop_statistic()
{
    iptables -D INPUT -i $IPSEC_IFACE -j IPSEC_PKTIN
    iptables -D FORWARD -i $IPSEC_IFACE -j IPSEC_PKTIN
    iptables -D FORWARD -o $IPSEC_IFACE -j IPSEC_PKTOUT
    iptables -D OUTPUT -o $IPSEC_IFACE -j IPSEC_PKTOUT 

    iptables -F IPSEC_PKTIN
    iptables -F IPSEC_PKTOUT
    iptables -X IPSEC_PKTIN
    iptables -X IPSEC_PKTOUT

    rm -f $IPSEC_STAT_FILE $IPSEC_CLEAN.* $IPSEC_STAT_RUN
}

renew_statistic()
{
   rm -f $IPSEC_STAT_FILE
   iptables -vnxL > $IPSEC_STAT_FILE
}

add_statistic()
{
    local TUN_IDX="$1"
    local SUBNET="$2"
    local NETMASK="$3"

    sl_get_uptime CNTTIME
    local IDX=`printf "0x807004%02X" $TUN_IDX`                            
    wrcsman "$IDX $CNTTIME"
    iptables -A IPSEC_PKTIN -s $SUBNET/$NETMASK -j RETURN
    iptables -A IPSEC_PKTOUT -d $SUBNET/$NETMASK -j RETURN  

    echo "#!/bin/sh" > $IPSEC_CLEAN.$TUN_IDX
    echo "wrcsman \"$IDX 0x0\"" >> $IPSEC_CLEAN.$TUN_IDX
    echo "iptables -D IPSEC_PKTIN -s $SUBNET/$NETMASK -j RETURN"  >> $IPSEC_CLEAN.$TUN_IDX
    echo "iptables -D IPSEC_PKTOUT -d $SUBNET/$NETMASK -j RETURN" >> $IPSEC_CLEAN.$TUN_IDX
    chmod +x $IPSEC_CLEAN.$TUN_IDX
}

del_statistic()
{
    local TUN_IDX="$1"
    local SUBNET="$2"
    local NETMASK="$3"  

    if [ -f $IPSEC_CLEAN.$TUN_IDX ]; then
        . $IPSEC_CLEAN.$TUN_IDX
        rm -f $IPSEC_CLEAN.$TUN_IDX
    else
        local IDX=`printf "0x807004%02X" $TUN_IDX`                            
        wrcsman "$IDX 0x0"
        iptables -D IPSEC_PKTIN -s $SUBNET/$NETMASK -j RETURN
        iptables -D IPSEC_PKTOUT -d $SUBNET/$NETMASK -j RETURN 
    fi
}

get_outgoing_statistic()
{
    local TUN_IDX="$1"
    local SUBNET="$2"
    local NETMASK="$3"  
    [ ! -f $IPSEC_STAT_FILE ] && renew_statistic
    NETMASK=`tsf_mask -m $NETMASK`
    if [ $NETMASK -eq 32 ]; then 
        awk "{if(\$9==\"$SUBNET\"){print \$2}}" $IPSEC_STAT_FILE
    else
        awk "{if(\$9==\"$SUBNET/$NETMASK\"){print \$2}}" $IPSEC_STAT_FILE
    fi
}

get_incoming_statistic()
{
    local TUN_IDX="$1"
    local SUBNET="$2"
    local NETMASK="$3"  
    [ ! -f $IPSEC_STAT_FILE ] && renew_statistic
    NETMASK=`tsf_mask -m $NETMASK`
    if [ $NETMASK -eq 32 ]; then 
        awk "{if(\$8==\"$SUBNET\"){print \$2}}" $IPSEC_STAT_FILE
    else
        awk "{if(\$8==\"$SUBNET/$NETMASK\"){print \$2}}" $IPSEC_STAT_FILE
    fi
}

reset_statistic()
{
    local TUN_IDX="$1"
    local SUBNET="$2"
    local NETMASK="$3"  
    del_statistic $TUN_IDX $SUBNET $NETMASK
    add_statistic $TUN_IDX $SUBNET $NETMASK
}

chk_stealth()
{
    # For NAT (Stealth Mode)
    local stealth_mode=`rdcsman 0x0015000E u8`
    if [ $stealth_mode == "1" ]; then                                                 
        nat restart
    fi    
}

# main ##########################################################

case "$1" in
	start)
        # HW NAT may affect VPN throughput
        [ "`lsmod | grep hw_nat`" != "" ] && rmmod hw_nat  
		/usr/bin/gen_ipsecconf
   	 	ipsec setup start
		/usr/bin/imkt add all
        chk_stealth
		;;

	stop)
		/usr/bin/imkt del all
		ipsec setup stop
        chk_stealth
		;;	

	restart)
		/usr/bin/imkt del all
		/usr/bin/gen_ipsecconf
		ipsec setup restart
		/usr/bin/imkt add all
        chk_stealth
		;;	

	reload)
		cfg_reload
		if [ "$2" != "" ]; then
			del_tunnel $2
			add_tunnel $2
		fi
		;;	

	add)
		if [ "$2" != "" ]; then
			add_tunnel $2
		fi
		;;	

	del)
		if [ "$2" != "" ]; then
			del_tunnel $2
		fi
		;;	

	up)
		if [ "$2" != "" ]; then
			IDX=`printf "0x007003%02X" $2`
			KEYMOD=`rdcsman $IDX u32`
			if [ "$KEYMOD"  == "0" ]; then
                ipsec auto --rereadsecrets
                
				IDX=`printf "0x00704B%02X" $2`
				CNT_TYPE=`rdcsman $IDX u32`
				if [ "$CNT_TYPE" == "1" ]; then
					ipsec auto --add $2
				fi
				set_state $2 9
				ipsec auto --up $2
			fi
		fi
		;;	

	down)
		if [ "$2" != "" ]; then
			IDX=`printf "0x007003%02X" $2`
			KEYMOD=`rdcsman $IDX u32`
			if [ "$KEYMOD"  == "0" ]; then
				del_active_tun
				IDX=`printf "0x00704B%02X" $2`
				CNT_TYPE=`rdcsman $IDX u32`
				if [ "$CNT_TYPE" == "0" ]; then
					ipsec auto --down $2
                    sleep 2
					#set_state $2 9
					ipsec auto --up $2
				elif [ "$CNT_TYPE" == "1" ]; then
					ipsec auto --delete $2
					set_state $2 3
				else
					ipsec auto --down $2
					set_state $2 2
				fi
			fi
		fi
		;;	

	err_down)
		if [ "$2" != "" ]; then
            IDX=`printf "0x00704B%02X" $2`
            CNT_TYPE=`rdcsman $IDX u32`
            if [ "$CNT_TYPE" == "0" ]; then
                ipsec auto --down $2 
                sleep 3

                logger "Auto-Reconnect for IPSec tunnel $2 ... "
                #set_state $2 9
                ipsec auto --replace $2 
                ipsec auto --rereadsecrets
                ipsec auto --up $2 
            fi
		fi
		;;        

	state)
		if [ "$2" != "" ]; then
			IDX=`printf "0x807001%02X" $2`
			STAT=`rdcsman $IDX u32`
			if [ "$3" == "" ]; then
				echo "Tunnel $2: $STAT"
				exit 1
			fi
			if [ "$3" == "0" ] || [ "$3" == "3" ]; then
                ipsec-action statistic del $2
				if [ "$STAT" == "1" ]; then
					del_active_tun
				fi
				if [ "$2" == "0" ]; then
					DYN_TUN=`rdcsman 0x80700008 u32`
					let "DYN_TUN = $DYN_TUN - 1"
					wrcsman "0x80700008 $DYN_TUN"
					if [ $DYN_TUN -eq 0 ]; then
						set_state $2 2
					fi
					exit 1
				fi
			fi
			if [ "$3" == "1" ]; then
                ipsec-action statistic add $2
				if [ "$2" == "0" ]; then
					DYN_TUN=`rdcsman 0x80700008 u32`
					let "DYN_TUN = $DYN_TUN + 1"
					wrcsman "0x80700008 $DYN_TUN"
					add_active_tun
				elif [ "$STAT" != "1" ]; then
					add_active_tun
				fi
			fi
			if [ $3 -ne $STAT ]; then
				set_state $2 $3
			fi
		fi
		;;	

	dyncli)
		if [ "$2" == "" ] || [ "$3" == "" ]; then
			exit 1
		fi
		IDX=0
		DYN_CLI=start
		if [ "$2" == "add" ]; then
			# find a empty slot
			while [ "$DYN_CLI" != "" ]; do
				SLOT=`printf "0x807010%02X" $IDX`
				DYN_CLI=`rdcsman $SLOT ipv4`
				if [ "$DYN_CLI" != "0.0.0.0" ]; then
					let "IDX = $IDX + 1"
				else
					wrcsman "$SLOT {$3}"
					exit 0
				fi
				if [ $IDX -eq 32 ]; then
					echo "No room for client $3"
					exit 1
				fi
			done

		elif [ "$2" == "del" ]; then
			# fine the peer ip
			while [ "$DYN_CLI" != "" ]; do
				SLOT=`printf "0x807010%02X" $IDX`
				DYN_CLI=`rdcsman $SLOT ipv4`
				if [ "$DYN_CLI" != "$3" ]; then
					let "IDX = $IDX + 1"
				else
					wrcsman "$SLOT {0.0.0.0}"
					exit 0
				fi
				if [ $IDX -eq 32 ]; then
					echo "No match for client $3"
					exit 1
				fi
			done
		fi
		;;	

    statistic)
		if [ "$2" == "" ]; then
            exit 1
        fi
		if [ "$2" == "start" ]; then
            start_statistic
		elif [ "$2" == "stop" ]; then
            stop_statistic
		elif [ "$2" == "renew" ]; then
            renew_statistic
        else
            if [ "$3" == "" ]; then
                exit 1
            fi

            IDX=`printf "0x007002%02X" $3`                            
            TUN_EN=`rdcsman $IDX u32`
            if [ $TUN_EN -eq 0 ]; then
                exit 1
            fi

            IDX=`printf "0x007003%02X" $3`
            KEYMOD=`rdcsman $IDX u32`
            if [ "$KEYMOD"  == "0" ]; then 
                IDX=`printf "0x007006%02X" $3`
                SUBNET=`rdcsman $IDX ipv4` 

                IDX=`printf "0x007007%02X" $3`
                NETMASK=`rdcsman $IDX ipv4` 
            else
                IDX=`printf "0x00700B%02X" $3`
                SUBNET=`rdcsman $IDX ipv4` 

                IDX=`printf "0x00700C%02X" $3`
                NETMASK=`rdcsman $IDX ipv4` 
            fi 

            if [ "$2" == "add" ]; then
                add_statistic $3 $SUBNET $NETMASK 
            elif [ "$2" == "del" ]; then
                del_statistic $3 $SUBNET $NETMASK
            elif [ "$2" == "reset" ]; then
                reset_statistic $3 $SUBNET $NETMASK
            elif [ "$2" == "get_outgoing" ]; then
                get_outgoing_statistic $3 $SUBNET $NETMASK 
            elif [ "$2" == "get_incoming" ]; then
                get_incoming_statistic $3 $SUBNET $NETMASK 
            fi
        fi
		;;	

	*)
		print_usage
		exit 1
esac

exit 0		
			
		
		
	
			
