#!/bin/sh
########################################################################
# Begin $rc_base/init.d/wlan_client
#
# Description : Wireless client initscript
#
########################################################################

. /etc/sysconfig/rc
. ${rc_functions}

eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)

WIRELESS_CONFIG="/var/ipfire/ethernet/wireless"

function device_is_wireless() {
	local device=${1}

	if [ -d "/sys/class/net/${device}/wireless" ]; then
		return 0
	fi

	return 1
}

function wpa_supplicant_make_config() {
	local device=${1}
	local config=${2}
	shift 2

	# Check if device is wireless.
	local wireless="false"
	if device_is_wireless ${device}; then
		wireless="true"
	fi

	# Write a configuration file header.
	(
		echo "#"
		echo "# THIS FILE IS AUTOMATICALLY GENERATED AND"
		echo "# ANY CUSTOM CHANGES WILL BE OVERWRITTEN!"
		echo "#"
		echo
		echo "ctrl_interface=/var/run/wpa_supplicant"
		echo
	) > ${config}

	local items=0

	local line
	while IFS="," read -ra line; do
		# Skip commented lines.
		[ "${line:0:1}" = "#" ] && continue

		# Skip disabled entries.
		[ "${line[2]}" = "on" ] || continue

		wpa_supplicant_config_line \
			${device} ${config} \
			--wireless="${wireless}" \
			--mode="${line[3]}" \
			--wpa-mode="${line[4]}" \
			--ssid="${line[5]}" \
			--psk="${line[6]}" \
			--priority="${line[7]}"

		items=$(( ${items} + 1 ))

	done < ${WIRELESS_CONFIG}

	# Return exit code 2, when there are no entries in the
	# configuration file.
	if [ "${items}" = "0" ]; then
		return 2
	fi

	return 0
}

function wpa_supplicant_config_line() {
	local device=${1}
	local config=${2}
	shift 2

	local auth_alg
	local proto
	local key_mgmt
	local pairwise
	local group
	local mode
	local priority
	local psk
	local ssid
	local wep_tx_keyidx
	local wep_key0
	local wireless="true"
	local wpa_mode

	while [ $# -gt 0 ]; do
		case "${1}" in
			--mode=*)
				mode=${1#--mode=}
				;;
			--priority=*)
				priority=${1#--priority=}
				;;
			--psk=*)
				psk=${1#--psk=}
				;;
			--ssid=*)
				ssid=${1#--ssid=}
				;;
			--wireless=*)
				wireless=${1#--wireless=}
				;;
			--wpa-mode=*)
				wpa_mode=${1#--wpa-mode=}
				;;
		esac
		shift
	done

	case "${mode}" in
		WPA2)
			auth_alg="OPEN"
			proto="RSN"
			key_mgmt="WPA-PSK"
			;;
		WPA)
			auth_alg="OPEN"
			proto="WPA"
			key_mgmt="WPA-PSK"
			;;
		WEP)
			auth_alg="SHARED"
			key_mgmt="NONE"

			wep_tx_keyidx=0
			wep_key0=${psk}
			psk=""
			;;
		NONE)
			auth_alg="OPEN"
			key_mgmt="NONE"
			;;
		*)
			# Unsupported mode.
			return 1
			;;
	esac

	if [ "${mode}" = "WPA" -o "${mode}" = "WPA2" ]; then
		case "${wpa_mode}" in
			CCMP-CCMP)
				pairwise="CCMP"
				group="CCMP"
				;;
			CCMP-TKIP)
				pairwise="CCMP"
				group="TKIP"
				;;
			TKIP-TKIP)
				pairwise="TKIP"
				group="TKIP"
				;;
			*)
				pairwise="CCMP TKIP"
				group="CCMP TKIP"
				;;
		esac
	fi

	(
		echo "network={"

		if [ -n "${ssid}" ]; then
			echo "	ssid=\"${ssid}\""
		fi
		if [ "${wireless}" = "true" ]; then
			echo "	scan_ssid=1"
		fi
		if [ -n "${auth_alg}" ]; then
			echo "	auth_alg=${auth_alg}"
		fi
		if [ -n "${key_mgmt}" ]; then
			echo "	key_mgmt=${key_mgmt}"
		fi
		if [ -n "${psk}" ]; then
			echo "	psk=\"${psk}\""
		fi
		if [ -n "${wep_tx_keyidx}" ]; then
			echo "	wep_tx_keyidx=${wep_tx_keyidx}"
		fi
		if [ -n "${wep_key0}" ]; then
			echo "	wep_key0=\"${wep_key0}\""
		fi
		if [ -n "${proto}" ]; then
			echo "	proto=${proto}"
		fi
		if [ -n "${pairwise}" -a -n "${group}" ]; then
			echo "	pairwise=${pairwise}"
			echo "	group=${group}"
		fi
		if [ -n "${priority}" ]; then
			echo "	priority=${priority}"
		fi

		echo "}"
		echo
	) >> ${config}
}

function wpa_supplicant_start() {
	local device=${1}
	local config="/etc/wpa_supplicant.conf"

	# Write configuration file.
	wpa_supplicant_make_config ${device} ${config}
	[ $? -eq 0 ] || return 0

	# Build wpa_supplicant command line.
	local wpa_suppl_cmd="wpa_supplicant -B -qqq -i${device} -c${config}"

	if device_is_wireless ${device}; then
		wpa_suppl_cmd="${wpa_suppl_cmd} -Dwext"
	else
		wpa_suppl_cmd="${wpa_suppl_cmd} -Dwired"
	fi

	# Run the shiz.
	boot_mesg "Starting wireless client on ${RED_DEV}..."
	loadproc ${wpa_suppl_cmd}

	# Run wpa_cli to handle reconnection events.
	boot_mesg "Starting wireless event handler on ${RED_DEV}..."
	wpa_cli -B -a /etc/rc.d/init.d/networking/wpa_supplicant.exe
}

function wpa_supplicant_stop() {
	boot_mesg "Stopping wireless event handler on ${RED_DEV}..."
	killproc wpa_cli

	# wpa_cli does not send a disconnect event when get stopped.
	# So we manually have to send it to the wpa_supplicant.exe.
	/etc/rc.d/init.d/networking/wpa_supplicant.exe "${RED_DEV}" DISCONNECTED

	boot_mesg "Stopping wireless client on ${RED_DEV}..."
	killproc wpa_supplicant
	
	# Tidy up /tmp directory.
	rm -f /tmp/wpa_ctrl_*
}

case "${1}" in
	start)
		if [ -n "${RED_DEV}" ] && device_is_wireless ${RED_DEV}; then
			wpa_supplicant_start ${RED_DEV}
		fi
		;;

	stop)
		if [ -n "${RED_DEV}" ] && device_is_wireless ${RED_DEV}; then
			wpa_supplicant_stop
		fi
		;;

	restart)
		${0} stop
		sleep 1
		${0} start
		;;

	status)
		statusproc wpa_supplicant
		;;

	*)
		echo "Usage: ${0} {start|stop|restart|status}"
		exit 1
		;;
esac

# End $rc_base/init.d/wlan_client
