#!/bin/sh /etc/rc.common
# Copyright (C) 2011 NXP Semiconductor

START=99
PROG=6LoWPANd

iface_netsize="/64"
wireless_prefix=""


radius_clientsfile=/etc/freeradius2/clients.conf

radius_addkey()
{
    key=$1
    echo "Add to RADIUS Clients file"
    echo "" >> $radius_clientsfile
    echo "client $wireless_prefix$iface_netsize {" >> $radius_clientsfile
    echo "  secret      = $key" >> $radius_clientsfile
    echo "}" >> $radius_clientsfile
    echo "" >> $radius_clientsfile
}

radius_setkey()
{
    key=$1
    echo "Set key in RADIUS clients file"
    sed -i "/client $wireless_prefix\\$iface_netsize/ {n s/\(\W*secret\W*=\W\).*/\1$key/}" $radius_clientsfile
}


radius_key()
{
    # Magic awk IPv6 address printer
    key=`echo $1 | awk 'BEGIN {FS=":"} { for (i=1; i <= NF; i++) { if ($i=="" && i>1 && i<NF) { for (j = 1; j <= (9-NF);j++){printf "0000"}} else { printf "%04X", "0x"$i}}}'`
    
    # Check that the radius clients file exists first
    [[ ! -f $radius_clientsfile ]] && return
    [[ ! -w $radius_clientsfile ]] && return
    
    grep "$wireless_prefix" $radius_clientsfile > /dev/null
    if [[ $? -ne 0 ]]
    then
        radius_addkey $key
    else
        radius_setkey $key
    fi
    
    ps | grep radiusd | grep -v grep > /dev/null && $(/etc/init.d/radiusd stop; sleep 2; /etc/init.d/radiusd start) > /dev/null
}


confignotify()
{
    interface=$1
    script_name=$2
    
    echo "#!/bin/sh
# Automatically generated by 6LoWPANd init script
INTERFACE='$interface'
source /usr/sbin/6LoWPANd-config.sh" > $script_name
    chmod +x $script_name
}


start_6LoWPANd() {
    local section="$1"

    config_get_bool ignore "$section" ignore 0
    [ "$ignore" -ne 0 ] && return 0
    
    local serial_port
    config_get serial_port "${section}" tty
    [ -z $serial_port ] && serial_port="/dev/ttyUSB0"

    local iface
    config_get iface "${section}" interface

    local baudrate
    config_get baudrate "${section}" baudrate
    [ -z $baudrate ] && baudrate="921600"

    local channel
    config_get channel "${section}" channel 
    
    local pan
    config_get pan "${section}" pan
    
    local jennet
    config_get jennet "${section}" jennet
    
    local profile
    config_get profile "${section}" profile
    [ -z $profile ] && profile="0"

    local prefix
    config_get prefix "${section}" prefix
    wireless_prefix=$prefix
    
    local args
    args="-R -s $serial_port -B $baudrate -I $iface -c $channel -p $pan -j $jennet -P $profile -6 $prefix"
    
    local activityled
    config_get activityled "${section}" activityled
    
    if [ $activityled ] && [ "$activityled" != "none" ]
    then
        args="$args -A $activityled"
    fi

    config_notify_script_name="/tmp/6LoWPANd-config-$iface.sh"

    confignotify $iface $config_notify_script_name

    # Call shell script when configuration is known
    args="$args --confignotify=$config_notify_script_name"

    # Security related arguments
    local secure                                                      
    config_get_bool secure "${section}" secure 0
    
    local jennet_key                                                                     
    config_get jennet_key "${section}" jennet_key
    
    local auth_scheme
    config_get auth_scheme "${section}" auth_scheme
    
    local radius_ip
    config_get radius_ip "${section}" radius_ip
    
    local security_args                                         
    security_args="-k $jennet_key -a $auth_scheme"
    
    [ "$auth_scheme" -eq "1" ] && security_args="$security_args -i $radius_ip"
    
    #echo $security_args

    [ "$secure" -ne 0 ] && args="$args $security_args"

    # Module configuration arguments
    local radio_frontend
    config_get radio_frontend "${section}" radio_frontend
    [ $radio_frontend ] && args="$args -F $radio_frontend"

    local diversity
    config_get_bool diversity "${section}" diversity
    echo "Diversity: $diversity"
    if [ $diversity ] && [ "$diversity" != "0" ]
    then
        args="$args -D"
    fi
    
    echo "Starting 6LoWPANd with arguments: $args"
    
    /sbin/$PROG $args
    sleep 4

    ifconfig $iface up
    ip -6 addr add fe80::1 dev $iface
    ip -6 route add $prefix/64 dev $iface   

    [ "$secure" -ne 0 ] && radius_key $jennet_key

    local qos_enable
    config_get qos_enable "${section}" qos_enable

    if [ $qos_enable -ne 0 ]
    then
        echo "Setting up QoS on 6LoWPAN interface " $iface

        coord_address=
        attempts=0
        max_attempts=30
        while [ -z $coord_address ] && [ $attempts -lt $max_attempts ]; do
            sleep 1
            coord_address=`logread | tail | grep 6LoWPANd | grep "Module address" | awk '{print $9}'`
            let attempts=attempts+1
        done 

        if [ $attempts -lt $max_attempts ]
        then
            echo "Coordinator address: " $coord_address

            # Insert required kernel modules
            lsmod|grep sch_htb > /dev/null || insmod sch_htb
            lsmod|grep cls_u32 > /dev/null || insmod cls_u32

            # Add a htb to the interface, default to classid 12
            tc qdisc add dev $iface root handle 1: htb default 12
            
            # Add a 900k pipe to the coordinator
            tc class add dev $iface parent 1: classid 1:10 htb rate 900kbit ceil 900kbit
            tc filter add dev $iface protocol ipv6 parent 1: u32 match ip6 dst $coord_address classid 1:10

            # Add a 5k pipe with fifo to the rest of the network
            tc class add dev $iface parent 1: classid 1:12 htb rate 5kbit ceil 5kbit burst 1 cburst 1
            tc qdisc add dev $iface parent 1:12 handle 20: pfifo limit 5
        else
            echo "Could not get coordinator address"
        fi
    fi

    return $?
}


start () {
    config_load 6LoWPAN
    
    args=""
    
    config_foreach start_6LoWPANd 6LoWPANd
}


stop () {
    killall $PROG
}

