#!/bin/bash
#
# $Id: $
# $ManualTag: V0.2 $ ;)
#
# By François TOURDE <francois@tourde.org>, based on work of
# Andrew McMillan, Catalyst IT Ltd,
# (c) 2007 licensed for use under the GPL version 2
#
# Parameters:
#   -  first form: [<interface>,](start|stop)
#   - second form: [<interface>,](<ESSID pattern>),(<WPA-PSK key>)
#
# <interface> 	Interface to test.  If omitted, use INTERFACE variable (from detect.conf)
#
# start|stop    If wpa_supplicant is not started, used to start or stop it. Further wpa configs
#               will be done using wpa_cli.
#
# <ESSID pattern>  A pattern that should match the ESSID we are looking for.
#
# WPA-PSK key   A WPA-PSK key, using the format accepted by "iwconfig".  This is only applied
#               if the pattern match is successful.
#
# Environment variables:
#
# INTERFACE	Default interface name to use if not specified
# DEBUGWHEREAMI Turn on debugging output (0 for debug msgs, 1 for execution tracing)
# 
# Examples:
#     testwpa eth1,start                        dummy
#     set INTERFACE eth1
#     testwpa mylan,my_secret_code              my_location
#     testwpa stop                              dummy
#

# Turn on execution tracing, for debugging...
[ -n "$DEBUGWHEREAMI" ] && set -o xtrace
[ -n "$DEBUGWHEREAMI" ] && echo "0:$0, 1:$1, 2:$2"

PARAMETERS=${1:-"start"}
WHEREAMILOCK=$LOCKDIR/whereami.started
WPAKEY=""
PATTERN=""
ACTION="test"
INTERFACE=${INTERFACE:-eth0}
[ -n "$DEBUGWHEREAMI" ] && echo "\$1>$1<"

case ${PARAMETERS} in
  *,start)
    [ -n "$DEBUGWHEREAMI" ] && echo "interface,start"
    # First form
    INTERFACE="${1/,start}"
    ACTION="start"
    ;;
  *,stop)
    [ -n "$DEBUGWHEREAMI" ] && echo "interface,stop"
    # First form
    INTERFACE="${1/,stop}"
    ACTION="stop"
    ;;
  start)
    [ -n "$DEBUGWHEREAMI" ] && echo "start"
    # First form
    INTERFACE="${INTERFACE:-eth0}"
    ACTION="start"
    ;;
  stop)
    [ -n "$DEBUGWHEREAMI" ] && echo "stop"
    # First form
    INTERFACE="${INTERFACE:-eth0}"
    ACTION="stop"
    ;;
  *,*,*)
    [ -n "$DEBUGWHEREAMI" ] && echo "interface,essid,wpakey"
    # Third form
    INTERFACE="${1/,*}"
    WPAKEY="${1/*,}"
    PATTERN="${1/$INTERFACE,}"
    PATTERN="${PATTERN/,$WPAKEY}"
    ;;
  *,*)
    [ -n "$DEBUGWHEREAMI" ] && echo "essid,wpakey"
    # Second form
    PATTERN="${1/,*}"
    WPAKEY="${1/*,}"
    ;;
  *)
    [ -n "$DEBUGWHEREAMI" ] && echo "essid only!"
    # Second form
    PATTERN="$1"
    ;;
esac


# Setup some wpa parms
WPA_IFACE=$INTERFACE
IF_WPA_VERBOSITY=$DEBUGWHEREAMI

# source functions
if [ -f /etc/wpa_supplicant/functions.sh ]; then
	. /etc/wpa_supplicant/functions.sh
else
    [ -n "$DEBUGWHEREAMI" ] && echo "No /etc/wpa_supplicant/functions.sh usable. Check your WPA installation"
    exit 1
fi

# Other wpa parms
WPA_SUP_CONF="-C $WPA_CTRL_DIR"


######################################################
# Utility to do some supplicant operations
######################################################
launch_supplicant()
{
    # Run the wpa_supplicant daemon
    kill_supplicant
    init_wpa_supplicant || exit 1
}

######################################################
# Utility to do some supplicant operations
######################################################
conf_supplicant()
{
    # We can call supplicant client to setup link
    conf_wpa_supplicant || { kill_supplicant; exit 1;}
}

######################################################
# Utility to do some supplicant operations
######################################################
kill_supplicant()
{
    # stop the wpa_supplicant daemon
    kill_wpa_supplicant
}


######################################################
# The main task
# Start and stop must return errors, because they're
# not now tips to find network.
#
# wpa_state possible values:  WPA_DISCONNECTED,WPA_INACTIVE,WPA_SCANNING,WPA_ASSOCIATING,WPA_ASSOCIATED,
#                             WPA_4WAY_HANDSHAKE,WPA_GROUP_HANDSHAKE,WPA_COMPLETED
######################################################
case ${ACTION} in
    start)
	# Launch wpa_supplicant, with standard parms
	launch_supplicant $INTERFACE
	STATUS=1
	;;
    stop)
	# Stop supplicant
	kill_supplicant $INTERFACE
	STATUS=1
	;;
    test)
	# Now, we must test link
	wpa_cli scan
	if wpa_cli scan_results|grep --quiet "$PATTERN"; then
	    [ -n "$DEBUGWHEREAMI" ] && echo "Found SSID!"
	    # Starting the link... The following commands must be checked
	    # for a {OK, FAIL} return message... later :)
	    NETID=$(wpa_cli add_network)
	    wpa_cli select_network $NETID
	    wpa_cli set_network $NETID ssid '"'$PATTERN'"'
	    wpa_cli set_network $NETID key_mgmt WPA-PSK
	    wpa_cli set_network $NETID psk '"'$WPAKEY'"'
	    # Now, we must check network link... following handshaking mechanism
	    STATUS=-1
	    while [ $STATUS == -1 ] ; do
		STATUS_TEXT=$(wpa_cli status|grep "wpa_state="|sed -e 's/.*=//')
		[ -n "$DEBUGWHEREAMI" ] && echo "Connection state: "${STATUS_TEXT}
		case ${STATUS_TEXT} in
		    SCANNING|ASSOCIAT*|*_HANDSHAKE)
			sleep 1;
			;;
		    COMPLETED)
			[ -n "$DEBUGWHEREAMI" ] && echo "Connection complete"
			STATUS=0
			;;
		    *)
			[ -n "$DEBUGWHEREAMI" ] && echo "Connection not completed"
			STATUS=1
			;;
		esac
	    done
	else
	    [ -n "$DEBUGWHEREAMI" ] && echo "SSID not found"
	    STATUS=1
	fi
	;;
    *)
	;;
esac

exit $STATUS
