You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
6.5 KiB
Bash

#!/bin/sh
. /lib/config/uci.sh
IFNAME=$1
CMD=$2
get_conf_var() {
local conf="$1"
local var="$2"
# This finds the last "$2=" in the supplicant config and strips off leading
# and trailing quotes. Generally the quotes are there if it's a passphrase and not if its a psk hex string
# (passphrase is pure ascii not escaped, not even for " inside "") and for ssid
grep "^[$(printf " \t")]*$var=" "$conf" |
awk 'BEGIN{FS="="} {a=substr($0, index($0,$2))} END{print a}' |
sed -e 's/^"\(.*\)"$/\1/'
}
add_interface() {
local radio="$1"
local ssid="$2"
local psk="$3"
local encryption="$4"
local country="$(uci_get_state delos baptization WiFiCountryCode)"
uci_add wireless wifi-iface
uci_set wireless @wifi-iface[-1] type qcawifi
uci_set wireless @wifi-iface[-1] device "$radio"
uci_set wireless @wifi-iface[-1] mode ap
uci_set wireless @wifi-iface[-1] ssid "$ssid"
uci_set wireless @wifi-iface[-1] key "$psk"
uci_set wireless @wifi-iface[-1] network lan
uci_set wireless @wifi-iface[-1] channel auto
uci_set wireless @wifi-iface[-1] country "${country:-DE}"
uci_set wireless @wifi-iface[-1] txpower 27
case $encryption in
WPA2-PSK)
uci_set wireless @wifi-iface[-1] encryption psk2
;;
WPA-PSK)
uci_set wireless @wifi-iface[-1] encryption psk
;;
NONE)
uci_set wireless @wifi-iface[-1] encryption none
;;
esac
}
add_interface_uci() {
add_interface "$1" "$2" "$3" "$4"
uci_commit wireless
}
# this implementation depends on having only max 4 SSIDs (2.4GHz/5GHz and normal/guest SSID)
overwrite_interface_uci() {
local radio="$1"
local ssid="$2"
local psk="$3"
local encryption="$4"
local index=-1
local index24=-1
local index5=-1
local radio24=wifi0 # 2.4GHz radio is normally wifi0
local radio5=wifi1 # 5GHz radio is normally wifi1
local use_common_setting=0
# check if wifi1 is 2.4GHz radio
if [ "$(uci_get_state wireless wifi1 hwmode)" == "11g" ]; then
radio24=wifi1
radio5=wifi0
fi
for id in 0 1 2 3; do
# skip guest wifi
if [ "$(uci_get_state wireless @wifi-iface[$id] dvl_guest 0)" == "0" ]; then
# search for 2.4GHz index
if [ "$(uci_get_state wireless @wifi-iface[$id] device)" == "$radio24" ]; then
index24=$id
fi
# search for 5GHz inedx
if [ "$(uci_get_state wireless @wifi-iface[$id] device)" == "$radio5" ]; then
index5=$id
fi
# search for matching entry
if [ "$(uci_get_state wireless @wifi-iface[$id] device)" == "$radio" ]; then
index=$id
fi
fi
done
# if a SSID exist of both radios check if settings are equal and if they are equal overwrite both SSID settings
if [ "$index24" != "-1" ] && [ "$index5" != "-1" ]; then
if [ "$(uci_get_state wireless @wifi-iface[$index24] ssid)" == "$(uci_get_state wireless @wifi-iface[$index5] ssid)" ] &&
[ "$(uci_get_state wireless @wifi-iface[$index24] key)" == "$(uci_get_state wireless @wifi-iface[$index5] key)" ] &&
[ "$(uci_get_state wireless @wifi-iface[$index24] encryption)" == "$(uci_get_state wireless @wifi-iface[$index5] encryption)" ] &&
[ "$(uci_get_state wireless @wifi-iface[$index24] hidden)" == "$(uci_get_state wireless @wifi-iface[$index5] hidden)" ];then
use_common_setting=1
fi
fi
# if "use common setting" modify both radio entries
if [ "$use_common_setting" == "1" ]; then
uci_set wireless @wifi-iface[$index24] ssid "$ssid"
uci_set wireless @wifi-iface[$index5] ssid "$ssid"
uci_set wireless @wifi-iface[$index24] key "$psk"
uci_set wireless @wifi-iface[$index5] key "$psk"
case $encryption in
WPA2-PSK)
uci_set wireless @wifi-iface[$index24] encryption psk2
uci_set wireless @wifi-iface[$index5] encryption psk2
;;
WPA-PSK)
uci_set wireless @wifi-iface[$index24] encryption psk
uci_set wireless @wifi-iface[$index5] encryption psk
;;
NONE)
uci_set wireless @wifi-iface[$index24] encryption none
uci_set wireless @wifi-iface[$index5] encryption none
;;
esac
elif [ "$index" != "-1" ]; then
uci_set wireless @wifi-iface[$index] ssid "$ssid"
uci_set wireless @wifi-iface[$index] key "$psk"
case $encryption in
WPA2-PSK)
uci_set wireless @wifi-iface[$index] encryption psk2
;;
WPA-PSK)
uci_set wireless @wifi-iface[$index] encryption psk
;;
NONE)
uci_set wireless @wifi-iface[$index] encryption none
;;
esac
else
add_interface "$radio" "$ssid" "$psk" "$encryption"
fi
uci_commit wireless
}
remove_interface() {
local ifname="$1"
wpa_cli -g /var/run/wpa_supplicantglobal interface_remove $ifname
[ -f /var/run/wpa_supplicant-$ifname.pid ] && kill $(cat /var/run/wpa_supplicant-$ifname.pid)
rm -rf /var/run/wpa_supplicant-${ifname}*
wlanconfig $ifname destroy
}
# stop all wps cloning instances
remove_all_interfaces() {
for ifpath in $(ls -d /sys/class/net/athClone? 2>/dev/null); do
remove_interface $(basename $ifpath)
done
}
case "$CMD" in
CONNECTED)
# only accept first connect, if wps clone not successful yet
if [ "$(uci_get_state wireless wps_clone state)" != success ]; then
uci_set_state wireless wps_clone state success
uci_revert_state wireless wps_clone reason
wpa_cli -i$IFNAME -p /var/run/wpa_supplicant-$IFNAME save_config
radio=$(cat /sys/class/net/$IFNAME/parent)
# ssid/psk are strangely escaped (escaping \ " but not ' or $), don't use
status="$(wpa_cli -i$IFNAME -p/var/run/wpa_supplicant-$IFNAME status)"
encryption=$(echo "$status" | grep ^key_mgmt=)
encryption="${encryption#*=}"
# get ssid/psk from config instead
ssid="$(get_conf_var /var/run/wpa_supplicant-$IFNAME.conf ssid)"
psk="$(get_conf_var /var/run/wpa_supplicant-$IFNAME.conf psk)"
# Check if only one ssid is allowed
if [ "for now" != "only one ssid" ]; then
overwrite_interface_uci "$radio" "$ssid" "$psk" "$encryption"
else
add_interface_uci "$radio" "$ssid" "$psk" "$encryption"
fi
remove_interface $IFNAME
# we're done, stop all remaining wps cloning instances
remove_all_interfaces
reload_config # use procd to check for config changes
else
remove_interface $IFNAME
fi
;;
WPS-OVERLAP-DETECTED |\
WPS-FAIL |\
WPS-TIMEOUT)
if [ "$(uci_get_state wireless wps_clone state)" = running ]; then
uci_set_state wireless wps_clone state failed
uci_set_state wireless wps_clone reason $CMD
remove_interface $IFNAME
remove_all_interfaces
# force re-up all wifi interfaces (not done by driver/hostapd)
for ifname in $(ubus call uci state '{"config":"wireless","type":"wifi-iface"}'|\
jsonfilter -e "$.values[@.up='1'].ifname"); do
ip link set $ifname down
ip link set $ifname up
done
fi
;;
esac