WPA_CLI="wpa_cli -p /run/wpa_supplicant" # Uses wpa_supplicant to check for association to a network # wpa_check interface [timeout] wpa_check() { local timeout=0 INTERFACE="$1" TIMEOUT="${2:-15}" CONDITION="${3:-COMPLETED}" # CONDITION is required as wired connections are ready at ASSOCIATED not COMPLETED FS#20150 while [[ $timeout -lt "$TIMEOUT" ]]; do ( # Sometimes wpa_supplicant isn't ready so silence errors for 2s only to avoid hiding real errors if [[ $timeout -lt 2 ]]; then eval $($WPA_CLI -i "$INTERFACE" status 2> /dev/null | fgrep "wpa_state=") else eval $($WPA_CLI -i "$INTERFACE" status | fgrep "wpa_state=") fi [[ "$wpa_state" = "$CONDITION" ]] ) && return 0 sleep 1 let timeout++ done echo "$wpa_state" # wpa_cli -i "$INTERFACE" terminate >/dev/null 2>&1 # callers sometimes called stop_wpa, which does more but seems redundant # termination should either be handled properly here, or by callers stop_wpa "$INTERFACE" return 1 } start_wpa() { local INTERFACE="$1" WPA_CONF="$2" WPA_DRIVER="$3" shift 3 local WPA_OPTS="$*" wpa_supplicant -B -P "/run/wpa_supplicant_${INTERFACE}.pid" -i "$INTERFACE" -D "$WPA_DRIVER" -c "$WPA_CONF" $WPA_OPTS sleep 1 if [[ ! -f "/run/wpa_supplicant_${INTERFACE}.pid" ]]; then return 1 fi } stop_wpa() { $WPA_CLI -i "$1" terminate &> /dev/null sleep 1 # JP: need this else the file tends to disappear after [[ -f ... ]] but before cat... # see if [[ -f "/run/wpa_supplicant_$1.pid" ]]; then kill "$(cat "/run/wpa_supplicant_$1.pid")" &>/dev/null & fi } # Return a filename containing a list of network APs and ESSIDs found (sorted by decreasing signal strength) # list_networks interface list_networks() { wpa_supplicant_scan_info "$1" 1,5 } wpa_supplicant_scan_info() { local INTERFACE="$1" fields="$2" essids # temp file used, as keeping ESSID's with spaces in their name in arrays # is hard, obscure and kinda nasty. This is simpler and clearer. [[ -z "$INTERFACE" ]] && return 1 essids=$(mktemp --tmpdir essid.XXXXXXXX) wpa_supplicant -B -i"$INTERFACE" -Dnl80211,wext -C/run/wpa_supplicant -P/run/wpa_supplicant.pid || return 1 $WPA_CLI -i "$INTERFACE" scan &> /dev/null sleep 2.5 $WPA_CLI -i "$INTERFACE" scan_results | grep -v "^Selected" | grep -v "^bssid" | sort -rn -k3 | sort -u -k5 | sort -rn -k3 | cut -f"$fields" > "$essids" # Fields are tab delimited # Remove extraneous output from wpa_cli # Sort by strength # Remove duplicates # Re-sort by strength as the removal disorders the list # Cut to the AP/essid fields only kill "$(cat /run/wpa_supplicant.pid)" # File of 0 length, ie. no ssid's. if [[ ! -s "$essids" ]]; then rm -f "$essids" return 1 fi echo $essids return 0 } # Requires already loaded profile make_wpa_config_file() { local interface=$1 local WPA_CONF="${TMPDIR:-/tmp}/wpa.${interface}" # substitute spaces out # make empty tmp dir with correct permissions, rename it rm -rf "$WPA_CONF" mv -f "$(mktemp -d)" "$WPA_CONF" || return 1 echo "ctrl_interface=/run/wpa_supplicant" >> "$WPA_CONF/wpa.conf" # we know $WPA_CONF now has no spaces, but it may have other nasty chars, so still needs to be quoted echo "ctrl_interface_group=${WPA_GROUP:-wheel}" >> "$WPA_CONF/wpa.conf" [[ $WPA_COUNTRY ]] && echo "country=$WPA_COUNTRY" >> "$WPA_CONF/wpa.conf" [[ -n "$ADHOC" ]] && echo "ap_scan=2" >> "$WPA_CONF/wpa.conf" echo "$WPA_CONF/wpa.conf" } # Requires already loaded profile make_wpa_config() { case $SECURITY in wep|wep-old|wpa|none|none-old) echo "ssid=\"$ESSID\"" if [[ -n "$AP" ]]; then echo "bssid=$AP" fi [[ -n "$ADHOC" ]] && echo "mode=1" ;; wpa-configsection) echo "$CONFIGSECTION" ;; *) return 1 ;; esac # Key management case $SECURITY in wep|wep-old) echo "key_mgmt=NONE" echo "wep_tx_idx=0" if [[ ${KEY:0:2} == "s:" ]]; then # TODO: does wpa_supplicant handle this as expected? echo "wep_key0=\"${KEY:2}\"" else echo "wep_key0=$KEY" fi ;; none|none-old) echo "key_mgmt=NONE" ;; wpa) if [[ "${#KEY}" -eq 64 ]]; then echo "proto=RSN WPA\npsk=$KEY" else echo "proto=RSN WPA\npsk=\"$KEY\"" fi ;; esac # Hidden SSID if checkyesno ${HIDDEN:-no}; then echo "scan_ssid=1" fi } # vim: ft=sh ts=4 et sw=4: