#!/bin/bash
#
# $Id: testap,v 1.9 2006/11/12 00:39:14 andrew Exp $
#
# by Andrew McMillan, Catalyst IT Ltd, (c) 2004 licensed
# for use under the GPL version 2
#
# This script uses "iwlist ${INTERFACE} scan" to see if we can connect to
# a useful local WLAN.
#
###############################################
# NOTE:  This script is something of a work in progress.  I can't have experience
# with all possible WLAN hardware, so if you need help getting it working with what
# you happen to use, feel free to call upon me.
###############################################
#
# Parameters:
#   -  first form: [<interface>,]scan
#   - second form: (<ESSID pattern>)[,WEP key]
#   -  third form: [<interface>,](<ESSID pattern>),WEP key
#
# <interface> 	Interface to test.  If omitted, use INTERFACE variable (from detect.conf)
#
# scan       	Normally we just use the last scan details (if they're less than 10 secs
#               old), but sometimes we may want to force a scan.
#
# <ESSID pattern>  A pattern that should match the ESSID we are looking for.
#
# WEP key       A WEP key like 12345bcdef (40-bit), 123456789abcdef0123456789a (128 bit),
#               or any other format accepted by "iwconfig".  This is only applied
#               if the pattern match is successful.
#
# If only two parameters are supplied, the are assumed to be the pattern and
# the WEP key to be assigned 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:
#     testap eth1,scan
#     set INTERFACE eth1
#     testap scan
#     testap eth1,othercap
#     testap eth1,apother,12345bcdef
#     testap friendap,12345bcdef
#     set INTERFACE ath0
#     testap mywlan
#

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

PARAMETERS=${1:-"scan"}
STATEDIR=${STATEDIR:-"/var/lib/whereami"}
WHEREAMILOCK=$LOCKDIR/whereami.started
ISMADWIFI="`grep ath_pci /proc/modules 2>/dev/null`"

######################################################
# Utility to do pattern match, with awkward quoting
######################################################
ap_pattern_match()
{
  egrep "ESSID:\"$1\"" "${STATEFILE}"
}

######################################################
# Test if there is an AP in our scan that matches
######################################################
test_which_ap()
{
  ap_pattern_match "$1" >/dev/null
}

######################################################
# Perform the actual scan, which gets all nearby AP
# details into a file we will use for subsequent calls
######################################################
scan_for_ap()
{
  MAXATTEMPTS=4
  IFSTATE="`ifconfig | egrep \"^${INTERFACE}[\t ]\"`"
  if [ "$IFSTATE" = "" ] ; then
    ifconfig ${INTERFACE} up
  fi

  while [ "$MAXATTEMPTS" -gt "0" ] ; do

    # Do the actual scan for APs
    /sbin/iwlist ${INTERFACE} scan >"${STATEFILE}"

    if test_which_ap '.*' ; then
      return $?
    fi

    # Otherwise we loop again until we have exceeded the attempt limit...
    sleep 1
    MAXATTEMPTS=$(( $MAXATTEMPTS - 1 ))
  done

  if [ "$IFSTATE" = "" ] ; then
    ifconfig ${INTERFACE} down
  fi
}

######################################################
# Assign the first ESSID that matched the pattern
######################################################
assign_matching_essid()
{
  FIRST_SSID="`ap_pattern_match \"$1\" | head -n1 | cut -f2 -d'\"'`"
  if [ "" != "${FIRST_SSID}" ] ; then
    # On is required for some cards (Debian bug #309279)
    iwconfig ${INTERFACE} essid on
    iwconfig ${INTERFACE} essid "${FIRST_SSID}"
  fi
}



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

STATEFILE=$STATEDIR/iwlist.$INTERFACE
mkdir -p $STATEDIR

STATUS=1
if [ "$ACTION" = "scan" ] ; then
  scan_for_ap
  STATUS=$?
fi

if [ "$PATTERN" != "" ];then
  test_which_ap "$PATTERN"
  STATUS=$?
  if [ "${STATUS}" -eq 0 ] ; then
    # We found a match, so assign that ESSID
    assign_matching_essid "${PATTERN}"

    # And apply the appropriate WEP key, or turn it off
    if [ "${WEPKEY}" = "" ] ; then
      iwconfig $INTERFACE enc off
    else
      # underscore is used as an argument separator in WEP key, in
      # order to pass multiple parameters to iwconfig
      iwconfig $INTERFACE key ${WEPKEY//_/ }
    fi
  fi
fi

exit $STATUS
