#!/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