From a5546e6c40074a4c95b7bcf192a68e95e87ad306 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@openwrt.org>
Date: Fri, 22 Dec 2006 07:58:06 +0000
Subject: [PATCH] lots of enhancements for the madwifi script (hostapd calls
 for ap with wpa implemented, two kinds of wds support added - by essid or by
 bssid, various bugfixes)

SVN-Revision: 5888
---
 package/madwifi/files/lib/wifi/madwifi.sh | 161 +++++++++++++++++-----
 1 file changed, 125 insertions(+), 36 deletions(-)

diff --git a/package/madwifi/files/lib/wifi/madwifi.sh b/package/madwifi/files/lib/wifi/madwifi.sh
index 569c96e710..de9870ce65 100755
--- a/package/madwifi/files/lib/wifi/madwifi.sh
+++ b/package/madwifi/files/lib/wifi/madwifi.sh
@@ -1,5 +1,4 @@
 #!/bin/sh
-set -x
 append DRIVERS "atheros"
 
 scan_atheros() {
@@ -20,15 +19,22 @@ scan_atheros() {
 			;;
 			wds)
 				config_get addr "$vif" bssid
-				${addr:+append wds "$addr"}
+				config_get ssid "$vif" ssid
+				[ -z "$addr" -a -n "$ssid" ] && {
+					config_set "$vif" wds 1
+					config_set "$vif" mode sta
+					mode="sta"
+					addr="$ssid"
+				}
+				${addr:+append $mode "$vif"}
 			;;
 			*) echo "$device($vif): Invalid mode, ignored."; continue;;
 		esac
 	done
 
-	case "${adhoc:+1}:${sta:+}:${ap+1}" in
+	case "${adhoc:+1}:${sta:+1}:${ap+1}" in
 		# valid mode combinations
-		1::);;
+		1::) wds="";;
 		:1:1)config_set "$device" nosbeacon 1;; # AP+STA, can't use beacon timers for STA
 		:1:);;
 		::1);;
@@ -36,13 +42,84 @@ scan_atheros() {
 		*) echo "$device: Invalid mode combination in config"; return 1;;
 	esac
 
-	config_set "$device" vifs "${ap:+$ap }${adhoc:+$adhoc }${sta:+$sta }"
+	config_set "$device" vifs "${ap:+$ap }${adhoc:+$adhoc }${sta:+$sta }${wds:+$wds }"
+}
+
+hostapd_setup_vif() {
+	local vif="$1"
+	local driver="$2"
+	local hostapd_cfg=
+
+	# Examples:
+	# psk-mixed/tkip 	=> WPA1+2 PSK, TKIP
+	# wpa-psk2/tkip+aes	=> WPA2 PSK, CCMP+TKIP
+	# wpa2/tkip+aes 	=> WPA2 RADIUS, CCMP+TKIP
+	# ...
+
+	# TODO: move this parsing function somewhere generic, so that
+	# later it can be reused by drivers that don't use hostapd
 	
-	[ -z "$adhoc" ] && config_set "$device" wds "$wdsifs"
+	# crypto defaults: WPA2 vs WPA1
+	case "$enc" in
+		wpa2*|WPA2*|*PSK2*|*psk2*)
+			wpa=2
+			crypto="CCMP"
+		;;
+		*mixed*)
+			wpa=3
+			crypto="CCMP TKIP"
+		;;
+		*) 
+			wpa=1
+			crypto="TKIP"
+		;;
+	esac
+
+	# explicit override for crypto setting
+	case "$enc" in
+		*tkip+aes|*TKIP+AES|*tkip+ccmp|*TKIP+CCMP) crypto="CCMP TKIP";;
+		*tkip|*TKIP) crypto="TKIP";;
+		*aes|*AES|*ccmp|*CCMP) crypto="CCMP";;
+	esac
+	
+	# use crypto/auth settings for building the hostapd config
+	case "$enc" in
+		*psk*|*PSK*)
+			config_get psk "$vif" key
+			append hostapd_cfg "wpa_passphrase=$psk" "$N"
+		;;
+		*wpa*|*WPA*)
+		# FIXME: add wpa+radius here
+		;;
+		*)
+			return 0;
+		;;
+	esac
+	config_get ifname "$vif" ifname
+	config_get bridge "$vif" bridge
+	config_get ssid "$vif" ssid
+	cat > /var/run/hostapd-$ifname.conf <<EOF
+driver=$driver
+interface=$ifname
+${bridge:+bridge=$bridge}
+ssid=$ssid
+debug=0
+wpa=$wpa
+wpa_pairwise=$crypto
+$hostapd_cfg
+EOF
+	hostapd -B /var/run/hostapd-$ifname.conf
 }
 
 disable_atheros() (
 	local device="$1"
+
+	# kill all running hostapd and wpa_supplicant processes that
+	# are running on atheros vifs 
+	for pid in `pidof hostapd wpa_supplicant`; do
+		grep ath /proc/$pid/cmdline >/dev/null && \
+			kill $pid
+	done
 	
 	include /lib/network
 	cd /proc/sys/net
@@ -50,16 +127,17 @@ disable_atheros() (
 		grep "$device" "$dev/%parent" >/dev/null 2>/dev/null && {
 			ifconfig "$dev" down 
 			unbridge "$dev"
-			wlanconfig $dev destroy
+			wlanconfig "$dev" destroy
 		}
 	done
+	return 0
 )
 
 enable_atheros() {
 	config_get channel "$device" channel
-	config_get wds "$device" wds
 	config_get vifs "$device" vifs
-
+	
+	disable_atheros "$device"
 	for vif in $vifs; do
 		nosbeacon=
 		config_get ifname "$vif" ifname
@@ -70,12 +148,19 @@ enable_atheros() {
 		
 		config_get ifname "$vif" ifname
 		ifname=$(wlanconfig "$ifname" create wlandev "$device" wlanmode "$mode" ${nosbeacon:+nosbeacon})
-		config_set "$vif" ifname "$ifname"
-		
 		[ $? -ne 0 ] && {
-			echo "enable_atheros($device): Failed to set up vif $ifname" >&2
+			echo "enable_atheros($device): Failed to set up $mode vif $ifname" >&2
 			continue
 		}
+		config_set "$vif" ifname "$ifname"
+
+		config_get wds "$vif" wds
+		case "$wds" in
+			1|on|enabled) wds=1;;
+			*) wds=0;;
+		esac
+		iwpriv "$ifname" wds "$wds"
+
 		wpa=
 		case "$enc" in
 			WEP|wep)
@@ -84,42 +169,45 @@ enable_atheros() {
 					iwconfig "$ifname" enc "[$idx]" "${key:-off}"
 				done
 				config_get key "$vif" key
-				iwconfig "$ifname" enc "$key"
+				iwconfig "$ifname" enc "[${key:-1}]"
 			;;
 		esac
+
 		case "$mode" in
-			ap)
-				local hostapd_cfg=
-				case "$enc" in
-					*psk*|*PSK*)
-					# FIXME: wpa
-					;;
-					*wpa*|*WPA*)
-					# FIXME: add wpa+radius here
-					;;
-				esac
+			wds)
+				config_get addr "$vif" bssid
+				iwpriv "$ifname" wds_add "$addr"
 			;;
-			sta)
-				# FIXME: implement wpa_supplicant calls here
+			*)
+				config_get ssid "$vif" ssid
 			;;
-		esac	
-		
-		config_get ssid "$vif" ssid
-		append if_up "iwconfig $ifname essid $ssid channel $channel" ";$N"
-		append if_up "sleep 1" ";$N"
-		append if_up "ifconfig $ifname up" ";$N"
+		esac
+		iwconfig "$ifname" channel "$channel"
+		ifconfig "$ifname" up
 		
 		local net_cfg bridge
 		net_cfg="$(find_net_config "$vif")"
 		[ -z "$net_cfg" ] || {
 			bridge="$(bridge_interface "$net_cfg")"
-			append if_up "start_net '$ifname' '$net_cfg'" ";$N"
+			config_set "$vif" bridge "$bridge"
+			start_net "$ifname" "$net_cfg"
 		}
-		# TODO: start hostapd
+		case "$mode" in
+			ap)
+				hostapd_setup_vif "$vif" madwifi || {
+					echo "enable_atheros($device): Failed to set up wpa for interface $ifname" >&2
+					# make sure this wifi interface won't accidentally stay open without encryption
+					ifconfig "$ifname" down
+					wlanconfig "$ifname" destroy
+					continue
+				}
+			;;
+			wds|sta)
+				iwconfig "$ifname" essid "$ssid"
+				# FIXME: implement wpa_supplicant calls here
+			;;
+		esac
 	done
-	
-	#killall -KILL $hostapd >&- 2>&-
-	eval "$if_up"
 }
 
 
@@ -136,6 +224,7 @@ config wifi-device  $dev
 
 config wifi-iface
 	option device   $dev
+#	option network	lan
 	option mode     ap
 	option ssid     OpenWrt
 	option hidden   0
-- 
2.30.2