#! /bin/bash
#
# Copyright (c) 2004 SuSE Linux AG Nuernberg, Germany.
# All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA
#
# Author: Joachim Gleissner <jg@suse.de>, 2004
#
# $Id: ifup-wireless-wpa 1196 2005-04-25 07:47:39Z jg $
#

usage () {
    echo $@
    echo "usage: if{up,down,status}-wireless-wpa <config> [<interface>]  [-o <options>]"
    echo "  In most cases config==interface, for details see man 8 ifup"
    echo "options are: [on]boot : we are currently booting (or shutting down)"
    echo "             hotplug  : we are handling a hotplug event"
    echo "all other or wrong options are silently ignored"
    exit $R_USAGE
}

######################################################################
# change the working direcory and source some common files
#
R_INTERNAL=1      # internal error, e.g. no config or missing scripts
cd /etc/sysconfig/network || exit $R_INTERNAL
test -f scripts/functions && . scripts/functions || exit $R_INTERNAL
test -f ./config && . ./config

######################################################################
# check arguments and how we are called (in case of links)
#
SCRIPTNAME=${0##*/}
debug $*
ACTION=${SCRIPTNAME#if}
ACTION=${ACTION%%-wireless-wpa}
case "${ACTION}" in
    up|down|status) ;;
    check) exit $R_SUCCESS ;;
    *) usage
esac
INTERFACE=$1
case "$INTERFACE" in ""|-h|*help*) usage; esac
shift
if [ -n "$1" -a "$1" != "-o" ] ; then
    CONFIG=$INTERFACE
    INTERFACE=$1
fi
shift
test "$1" = "-o" && shift
OPTIONS=$@
MODE=manual
while [ $# -gt 0 ]; do
    case $1 in
	boot|onboot) MODE=onboot ;;
	hotplug)     MODE=hotplug ;;
	quiet)       BE_QUIET=yes ;;
	debug)       BE_QUIET=no
	             DEBUG=yes ;;
	*)           debug "unknown option $1 ignored" ;;
    esac
    shift
done


######################################################################
# check presence of global configuration file and source it
#
test -f ./wireless && . ./wireless
# ifcfg-* is more important and fragile then wireless
if [ -f ./ifcfg-$CONFIG ] ; then
    . ./ifcfg-$CONFIG
elif [ "$ACTION" != down ] ; then
    message "could not find configuration file ifcfg-$CONFIG"
fi


# $WIRELESS=yes/no can be set in a config file if there is no other way to
# find out. If it is empty we use the type we got from getcfg (HWD_INTERFACETYPE_0)
if [ "$WIRELESS" != yes -a "$HWD_INTERFACETYPE_0" != wlan ]; then
    debug "$HWD_HWDESC is not wireless, exiting"
    exit 0
fi

RETVAL=$R_SUCCESS

kill_wpa_supplicant()
{
    if [ -f /var/run/wpa_supplicant/${INTERFACE}.pid ]; then
	pid=$( cat /var/run/wpa_supplicant/${INTERFACE}.pid)
    else
	pid=$(pgrep -f ".*wpa_supplicant-$INTERFACE.conf.*")
    fi
    if [ -z "$pid" ]; then
	debug "No wpa_supplicant running on interface $INTERFACE"
	return
    fi
    kill $pid
    rm -f /var/run/wpa_supplicant-$INTERFACE.conf
}

setup_wpa()
{
    if [ -z "`type -p wpa_supplicant`" ]; then
	logerror "cannot find 'wpa_supplicant': please install package 'wpa_supplicant'"
	exit $R_ERROR
    fi
    if [ -e /var/run/wpa_supplicant-$INTERFACE.conf ]; then
	if [ -f /var/run/wpa_supplicant/${INTERFACE}.pid ]; then
	    pid=$( cat /var/run/wpa_supplicant/${INTERFACE}.pid)
	else
	    pid=$(pgrep -f ".*wpa_supplicant-$INTERFACE.conf.*")
	fi
	wpa_dead=y
	if [ -n "$pid" ]; then
	    kill -0 $pid && wpa_dead=n
	fi
	case "$wpa_dead" in
	    y)
		debug "Stale wpa_supplicant-$INTERFACE.conf found, removing"
		rm -f /var/run/wpa_supplicant-$INTERFACE.conf
		;;
	    n)
		message "`printf "    %-9s warning: wpa_supplicant already running on interface" $INTERFACE`"
		return
		;;
	esac
    fi
    if [ -n "$WIRELESS_WPA_CONF" ]; then
	if [ -e "$WIRELESS_WPA_CONF" ]; then
	    WPA_SUPP_CONF="$WIRELESS_WPA_CONF"
	else
	    logerror "Unable to setup wpa (could not open $WIRELESS_WPA_CONF)"
	    exit $R_ERROR
	fi
    else
	WPA_SUPP_CONF="/var/run/wpa_supplicant-$INTERFACE.conf"
    fi
    umask 0077
    cat > $WPA_SUPP_CONF <<EOF
ctrl_interface=/var/run/wpa_supplicant
network={
  ssid="$WIRELESS_ESSID"
  psk="$WIRELESS_WPA_PSK"
  key_mgmt=WPA-PSK
}
EOF
    if [ "$DEBUG" = "yes" ]; then
	SUPPARGS="-d 2>&1 | logger &"
    else
	SUPPARGS="-B"
    fi
    eval wpa_supplicant -i$INTERFACE -c$WPA_SUPP_CONF -D$WPA_DRIVER $SUPPARGS
}

case $ACTION in
    up)
	case "${HWD_DRIVER}" in
	    ath_pci)
		WPA_DRIVER=madwifi
		;;
	    hostap_*)
		WPA_DRIVER=hostap
		;;
	    at76c5*)
		WPA_DRIVER=atmel
		;;
	    prism54)
		WPA_DRIVER=prism54
		;;
	    ipw*)
		WPA_DRIVER=ipw
		;;
	    ndiswrapper|*.sys)
		WPA_DRIVER=ndiswrapper
		;;
	    *)
		WPA_DRIVER=unsupported
		;;
	esac
	case "$WIRELESS_AUTH_MODE" in
	    psk|PSK|wpa-psk|WPA-PSK)
		if [ "$WPA_DRIVER" = "unsupported" ]; then
		    logerror "WPA-PSK is not supported yet for this device"
		    exit $R_ERROR
		fi
		if [ -z "$WPA_DRIVER" ]; then
                    # uh, we cannot determine the driver name
		    logerror "Could not determine device driver name"
		    exit $R_ERROR
		fi
		setup_wpa
		;;
	esac
	;;
    status)
    case "$WIRELESS_AUTH_MODE" in
	psk|PSK|wpa-psk|WPA-PSK)
	if is_iface_up $INTERFACE ; then
	    # do not show wpa_cli output on boot, this may log
	    # sensible information in the boot log
	    if [ "$MODE" != "onboot" ]; then
		test -n "`type -p wpa_cli`" && wpa_cli -i$INTERFACE status
	    fi
	    RETVAL=$R_SUCCESS
	else
	    RETVAL=$R_NOTRUNNING
	fi
	;;
	*)
	exit 0
	;;
    esac
    ;;
    down)
	kill_wpa_supplicant
	;;
esac

exit $RETVAL
