#!/bin/sh

. /usr/bin/l2tpc-header
L2TPC_QOS_ECHO=/var/run/l2tpc.qos
TC_UPLOAD_FLAG=/var/run/tc.upload
  
usage()
{
    echo "Usage:"
    echo "l2tpc-acton start   -> start L2TP client and autoconnect"
    echo "l2tpc-acton stop    -> stop all current L2TP connections, except WAN type L2TP connection"
    echo "l2tpc-acton restart -> restart L2TP client"
    echo "l2tpc-acton update  -> update L2TP clients' connection status for UI"
    echo "l2tpc-acton status  -> show L2TP clients' connection status from CSID"
    echo "l2tpc-acton show-config -> show L2TP clients' configuration from CSID"
}

update_status()
{
    addr=`get_csid_addr $CSID_C_L2TP_CLI_QOS_ENABLE 0`
    l2tpc_qos_enable=`rdcsman $addr u8` 
    if [ $l2tpc_qos_enable -eq 1 ]; then
        start_qos
    else
        stop_qos
    fi    

    for i in $TUN_LIST
    do
        addr=`get_csid_addr $CSID_C_L2TP_CLI_USER_ENABLE $i`
        tun_enable=`rdcsman $addr u8`
        if [ $tun_enable -eq 0 ]; then
            continue
        fi   

        addr=`get_csid_addr $CSID_S_L2TP_CLI_PEER_IFNAME $i`
        iface=`rdcsman $addr str`

        addr=`get_csid_addr $CSID_S_L2TP_CLI_PEER_PID $i`
        cnt_pid=`rdcsman $addr u16`
        
        addr=`get_csid_addr $CSID_C_L2TP_CLI_CONNECT_TYPE $i`
        cnt_type=`rdcsman $addr u8` 
 
        if [ -z "$iface" ]; then
            if [ $cnt_type -eq $L2TP_CNT_TYPE_AUTORECONNECT ]; then
                echo "L2TP tunnel $i restart automatically ... "
                l2tpc-start $i
            elif [ $cnt_type -eq $L2TP_CNT_TYPE_ONDEMAND ]; then
                echo "L2TP tunnel $i restarts on-demand... "
                l2tpc-ondemand start $i
            fi  
            continue
        fi

        iface_exist=`ifconfig $iface 2>/dev/null | grep inet | cut -d ':' -f3 | cut -d ' ' -f1`
        if [ ! -z "$iface_exist" ]; then 
            continue
        fi

        echo "L2TP tunnel $i is disconnect !"
        l2tpc-stop $i $cnt_pid  # NOTE: dial-on-demand connection will restart here

        if [ $cnt_type -eq $L2TP_CNT_TYPE_AUTORECONNECT ]; then
            echo "L2TP tunnel $i restart automatically ... "
            l2tpc-start $i
        fi
    done     
}

show_cnt_status()
{
    for i in $TUN_LIST
    do
        addr=`get_csid_addr $CSID_C_L2TP_CLI_TUNLNAME $i`
        tun_name=`rdcsman $addr str`
        if [ -z "$tun_name" ]; then
            continue
        fi 

        echo "L2TP Tunnel $i"
        addr=`get_csid_addr $CSID_S_L2TP_CLI_PEER_IFNAME $i`
        echo IFace: `rdcsman $addr str`

        addr=`get_csid_addr $CSID_S_L2TP_CLI_PEER_PID $i` 
        echo PID: `rdcsman $addr u32`

        addr=`get_csid_addr $CSID_S_L2TP_CLI_PEER_VIRTUAL_IP $i`
        echo Virtual IP: `rdcsman $addr ipv4`

        addr=`get_csid_addr $CSID_S_L2TP_CLI_PEER_REMOTE_IP $i`
        echo Remote IP: `rdcsman $addr ipv4`
        echo ""
    done 
}

show_config()
{
    addr=`get_csid_addr $CSID_C_L2TP_CLI_ENABLE 0`
    l2tpc_enable=`rdcsman $addr u8`
    if [ $l2tpc_enable -eq 1 ]; then
        echo "L2TP Client is enable"
    else
        echo "L2TP Client is disenable"  
    fi

    for i in $TUN_LIST
    do
        addr=`get_csid_addr $CSID_C_L2TP_CLI_TUNLNAME $i`
        tun_name=`rdcsman $addr str`
        if [ -z "$tun_name" ]; then
            continue
        fi
        
        addr=`get_csid_addr $CSID_C_L2TP_CLI_USER_ENABLE $i`
        user_enable=`rdcsman $addr u8`
        echo "Tunnel #$i ($tun_name) user_enable: $user_enable"
        
        #addr=`get_csid_addr $CSID_C_L2TP_CLI_PEERIP $i`
        #peer_ip=`rdcsman $addr ipv4`

        addr=`get_csid_addr $CSID_C_L2TP_CLI_PEERIP_STR $i`
        peer_ip=`rdcsman $addr str`

        addr=`get_csid_addr $CSID_C_L2TP_CLI_USER $i`
        account=`rdcsman $addr str`

        addr=`get_csid_addr $CSID_C_L2TP_CLI_PASSWORD $i`
        passwd=`rdcsman $addr str`
        echo "peer_ip: $peer_ip account: $account passwd: $passwd "

        addr=`get_csid_addr $CSID_C_L2TP_CLI_ROUTE $i`
        route=`rdcsman $addr str`

        addr=`get_csid_addr $CSID_C_L2TP_CLI_CONNECT_TYPE $i`
        cnt_type=`rdcsman $addr u8`

        addr=`get_csid_addr $CSID_C_L2TP_CLI_MPPE $i`
        mppe=`rdcsman $addr u8`

        addr=`get_csid_addr $CSID_C_L2TP_CLI_NAT $i`
        nat=`rdcsman $addr u8`
        echo "route: $route, cnt_type: $cnt_type, is_mppe: $mppe, is_nat: $nat"
        echo ""
    done 
    exit 1
}       

start_cnt()
{
    for i in $TUN_LIST
    do
        addr=`get_csid_addr $CSID_C_L2TP_CLI_USER_ENABLE $i`
        tun_enable=`rdcsman $addr u8`
        if [ $tun_enable -eq 0 ]; then
            continue
        fi

        addr=`get_csid_addr $CSID_S_L2TP_CLI_PEER_PID $i`
        cnt_pid=`rdcsman $addr u16`

        addr=`get_csid_addr $CSID_C_L2TP_CLI_CONNECT_TYPE $i`
        cnt_type=`rdcsman $addr u8`

        if [ $cnt_pid -eq 0 ]; then 
            if [ $cnt_type -eq $L2TP_CNT_TYPE_AUTORECONNECT ]; then
                echo "L2TP tunnel $i starts automatically ... "
                l2tpc-start $i
            elif [ $cnt_type -eq $L2TP_CNT_TYPE_ONDEMAND ]; then
                echo "L2TP tunnel $i starts on-demand... "
                l2tpc-ondemand start $i
            fi
        fi
    done 
}

stop_cnt()
{
    for i in $TUN_LIST
    do
        addr=`get_csid_addr $CSID_S_L2TP_CLI_PEER_PID $i`
        cnt_pid=`rdcsman $addr u16`
        if [ $cnt_pid -gt 0 ] && [ $cnt_pid -lt 65535 ]; then
            echo "L2TP tunnel $i disconnect !"
            l2tpc-stop $i $cnt_pid
            wrcsman "$addr 0"
        else 
            addr=`get_csid_addr $CSID_C_L2TP_CLI_CONNECT_TYPE $i`
            cnt_type=`rdcsman $addr u8`
            if [ $cnt_type -eq $L2TP_CNT_TYPE_ONDEMAND ]; then
                echo "L2TP tunnel $i stop on-demand... "
                l2tpc-ondemand stop $i
            fi
        fi
    done   
    killall l2tp-ondemand >/dev/null 2>&1
}

start_qos()
{
    addr=`get_csid_addr $CSID_S_LOCAL_WAN_IF_NAME 0`
    wan_if="`rdcsman $addr str`"  
    [ -z "$wan_if" ] && return
    [ -f $L2TPC_QOS_ECHO ] && return
    touch $L2TPC_QOS_ECHO 

    #addr=`get_csid_addr $CSID_C_QOS_ENABLE`
    #qos_enable="`rdcsman $addr u8`"    
    if [ ! -f $TC_UPLOAD_FLAG ]; then
        logger -t "l2tpc" "Create Queue discipline for L2TP Client !"
        echo "Create Queue discipline for L2TP Client !"
        echo 1 > $TC_UPLOAD_FLAG

        local est_max_bw="10Mbps"
        local reserved_bw="32Kbps" 

        tc qdisc add dev $wan_if root handle 10: htb 
        tc class add dev $wan_if parent 10:0 classid 10:1  htb rate $est_max_bw ceil $est_max_bw
        tc class add dev $wan_if parent 10:1 classid 10:10 htb rate $reserved_bw ceil $est_max_bw prio 1
        tc qdisc add dev $wan_if parent 10:10 handle 20: pfifo
        tc filter add dev $wan_if protocol ip parent 10:0 prio 1 handle 10 fw classid 10:10  
    else
        logger -t "l2tpc" "Queue discipline already existed ! Just map Echo Request/Response to its higher priority queue !"
        echo "Queue discipline already existed ! Just map Echo Request/Response to its higher priority queue !"

        local idx=`cat $TC_UPLOAD_FLAG` 
        echo $((idx+1)) > $TC_UPLOAD_FLAG
    fi

    local prio=10
    iptables -t mangle -N l2tpc_qos
    iptables -t mangle -A POSTROUTING -j l2tpc_qos 
    iptables -t mangle -A l2tpc_qos -p udp -m multiport --dport 1701,1702 -j MARK --set-mark $prio
}

stop_qos()
{       
    [ ! -f $L2TPC_QOS_ECHO ] && return 
    rm -f $L2TPC_QOS_ECHO

    #addr=`get_csid_addr $CSID_C_QOS_ENABLE`
    #qos_enable="`rdcsman $addr u8`" 
    addr=`get_csid_addr $CSID_S_LOCAL_WAN_IF_NAME 0`
    wan_if="`rdcsman $addr str`" 
    if [ ! -f $TC_UPLOAD_FLAG ]; then
        tc qdisc del dev $wan_if root > /dev/null 2>&1 
    else
        local idx=`cat $TC_UPLOAD_FLAG` 
        if [ $idx -eq 0 ] || [ $idx -eq 1 ]; then
            tc qdisc del dev $wan_if root > /dev/null 2>&1
            rm -f $TC_UPLOAD_FLAG
        else        
            echo $((idx-1)) > $TC_UPLOAD_FLAG    
            echo "Someone uses the priority qeueues, don't remove it !"
        fi 
    fi

    iptables -t mangle -D POSTROUTING -j l2tpc_qos > /dev/null 2>&1
    iptables -t mangle -F l2tpc_qos                > /dev/null 2>&1
    iptables -t mangle -X l2tpc_qos                > /dev/null 2>&1  
}

###################### Main ##############################
main()
{
    case "$1" in
        restart)
            stop_cnt
            start_cnt
            stop_qos
            start_qos
            ;;  

        start)
            start_qos
            start_cnt
            ;;

        stop)
            stop_qos
            stop_cnt
            ;;	        

        status)
            show_cnt_status
            ;;

        show-config)
            show_config
            ;;

        update) 
            update_status
            ;;
            
        *)
            usage
            exit 1
    esac
}

main $1
			
