xref: /freebsd/usr.sbin/bsdconfig/share/media/wlan.subr (revision d0b2dbfa0ecf2bbc9709efc5e20baf8e4b44bbbf)
155620f43SDevin Teskeif [ ! "$_MEDIA_WLAN_SUBR" ]; then _MEDIA_WLAN_SUBR=1
255620f43SDevin Teske#
355620f43SDevin Teske# Copyright (c) 2013-2016 Devin Teske
455620f43SDevin Teske# All rights reserved.
555620f43SDevin Teske#
655620f43SDevin Teske# Redistribution and use in source and binary forms, with or without
755620f43SDevin Teske# modification, are permitted provided that the following conditions
855620f43SDevin Teske# are met:
955620f43SDevin Teske# 1. Redistributions of source code must retain the above copyright
1055620f43SDevin Teske#    notice, this list of conditions and the following disclaimer.
1155620f43SDevin Teske# 2. Redistributions in binary form must reproduce the above copyright
1255620f43SDevin Teske#    notice, this list of conditions and the following disclaimer in the
1355620f43SDevin Teske#    documentation and/or other materials provided with the distribution.
1455620f43SDevin Teske#
1555620f43SDevin Teske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1655620f43SDevin Teske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1755620f43SDevin Teske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1855620f43SDevin Teske# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1955620f43SDevin Teske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2055620f43SDevin Teske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2155620f43SDevin Teske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2255620f43SDevin Teske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2355620f43SDevin Teske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2455620f43SDevin Teske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2555620f43SDevin Teske# SUCH DAMAGE.
2655620f43SDevin Teske#
2755620f43SDevin Teske#
2855620f43SDevin Teske############################################################ INCLUDES
2955620f43SDevin Teske
3055620f43SDevin TeskeBSDCFG_SHARE="/usr/share/bsdconfig"
3155620f43SDevin Teske. $BSDCFG_SHARE/common.subr || exit 1
3255620f43SDevin Teskef_dprintf "%s: loading includes..." media/wlan.subr
3355620f43SDevin Teskef_include $BSDCFG_SHARE/device.subr
3455620f43SDevin Teskef_include $BSDCFG_SHARE/dialog.subr
3555620f43SDevin Teskef_include $BSDCFG_SHARE/strings.subr
3655620f43SDevin Teskef_include $BSDCFG_SHARE/sysrc.subr
3755620f43SDevin Teske
3855620f43SDevin TeskeBSDCFG_LIBE="/usr/libexec/bsdconfig"
3955620f43SDevin Teskef_include_lang $BSDCFG_LIBE/include/messages.subr
4055620f43SDevin Teske
4155620f43SDevin Teske############################################################ GLOBALS
4255620f43SDevin Teske
4355620f43SDevin TeskeNWIRELESS_CONFIGS=0
4455620f43SDevin TeskeNWSCAN_RESULTS=0
4555620f43SDevin Teske
4655620f43SDevin Teske#
4755620f43SDevin Teske# Settings used while interacting with various dialog(1) menus
4855620f43SDevin Teske#
4955620f43SDevin Teske: ${DIALOG_MENU_WLAN_SCAN_DURATION:=5}
5055620f43SDevin Teske: ${DIALOG_MENU_WLAN_SHOW_ALL=}
5155620f43SDevin Teske: ${DIALOG_MENU_WLAN_SHOW_CONFIGURED=1}
5255620f43SDevin Teske: ${DIALOG_MENU_WLAN_SHOW_SCAN_RESULTS=1}
5355620f43SDevin Teske
5455620f43SDevin Teske#
5555620f43SDevin Teske# Structure to contain the wpa_supplicant.conf(5) default overrides
5655620f43SDevin Teske#
5755620f43SDevin Teskef_struct_define WPA_DEFAULTS \
5855620f43SDevin Teske	ap_scan			\
5955620f43SDevin Teske	ctrl_interface		\
6055620f43SDevin Teske	ctrl_interface_group	\
6155620f43SDevin Teske	eapol_version		\
6255620f43SDevin Teske	fast_reauth
6355620f43SDevin Teske
6455620f43SDevin Teske#
6555620f43SDevin Teske# Structure of wpa_supplicant.conf(5) network={ ... } entry
6655620f43SDevin Teske#
6755620f43SDevin Teskef_struct_define WPA_NETWORK \
6855620f43SDevin Teske	anonymous_identity	\
6955620f43SDevin Teske	auth_alg		\
7055620f43SDevin Teske	bssid			\
7155620f43SDevin Teske	ca_cert			\
7255620f43SDevin Teske	ca_cert2		\
7355620f43SDevin Teske	client_cert		\
7455620f43SDevin Teske	client_cert2		\
7555620f43SDevin Teske	dh_file			\
7655620f43SDevin Teske	dh_file2		\
7755620f43SDevin Teske	eap			\
7855620f43SDevin Teske	eap_workaround		\
7955620f43SDevin Teske	eapol_flags		\
8055620f43SDevin Teske	eappsk			\
8155620f43SDevin Teske	engine			\
8255620f43SDevin Teske	engine_id		\
8355620f43SDevin Teske	frequency		\
8455620f43SDevin Teske	group			\
8555620f43SDevin Teske	identity		\
8655620f43SDevin Teske	key_id			\
8755620f43SDevin Teske	key_mgmt		\
8855620f43SDevin Teske	mixed_cell		\
8955620f43SDevin Teske	mode			\
9055620f43SDevin Teske	nai			\
9155620f43SDevin Teske	pac_file		\
9255620f43SDevin Teske	pairwise		\
9355620f43SDevin Teske	password		\
9455620f43SDevin Teske	pcsc			\
9555620f43SDevin Teske	phase1			\
9655620f43SDevin Teske	phase2			\
9755620f43SDevin Teske	pin			\
9855620f43SDevin Teske	priority		\
9955620f43SDevin Teske	private_key		\
10055620f43SDevin Teske	private_key2		\
10155620f43SDevin Teske	private_key2_passwd	\
10255620f43SDevin Teske	private_key_passwd	\
10355620f43SDevin Teske	proto			\
10455620f43SDevin Teske	psk			\
10555620f43SDevin Teske	scan_ssid		\
10655620f43SDevin Teske	server_nai		\
10755620f43SDevin Teske	ssid			\
10855620f43SDevin Teske	subject_match		\
10955620f43SDevin Teske	subject_match2		\
11055620f43SDevin Teske	wep_key0		\
11155620f43SDevin Teske	wep_key1		\
11255620f43SDevin Teske	wep_key2		\
11355620f43SDevin Teske	wep_key3		\
11455620f43SDevin Teske	wpa_ptk_rekey		\
11555620f43SDevin Teske	wep_tx_keyidx
11655620f43SDevin Teske
11755620f43SDevin Teske#
11855620f43SDevin Teske# The following properties are ``Lists'' and as such should not be quoted.
11955620f43SDevin Teske# Everything else should be quoted.
12055620f43SDevin Teske#
12155620f43SDevin TeskeWPA_NETWORK_LIST_PROPERTIES="
12255620f43SDevin Teske	auth_algo
12355620f43SDevin Teske	eap
12455620f43SDevin Teske	group
12555620f43SDevin Teske	key_mgmt
12655620f43SDevin Teske	pairwise
12755620f43SDevin Teske	proto
12855620f43SDevin Teske" # END-QUOTE
12955620f43SDevin Teske
13055620f43SDevin Teske#
13155620f43SDevin Teske# Structure of wpa_cli(8) `scan_results' entry
13255620f43SDevin Teske#
13355620f43SDevin Teskef_struct_define WPA_SCAN_RESULT \
13455620f43SDevin Teske	bssid	\
13555620f43SDevin Teske	flags	\
13655620f43SDevin Teske	freq	\
13755620f43SDevin Teske	siglev	\
13855620f43SDevin Teske	ssid
13955620f43SDevin Teske
14055620f43SDevin Teske#
14155620f43SDevin Teske# Structure of a menu item in the wireless editor
14255620f43SDevin Teske#
14355620f43SDevin Teskef_struct_define WLAN_MENU_ITEM \
14455620f43SDevin Teske	letter		\
14555620f43SDevin Teske	ssid		\
14655620f43SDevin Teske	nconfigs	\
14755620f43SDevin Teske	nfound		\
14855620f43SDevin Teske	help
14955620f43SDevin Teske
15055620f43SDevin Teske############################################################ FUNCTIONS
15155620f43SDevin Teske
15255620f43SDevin Teske# f_wpa_supplicant_init $file
15355620f43SDevin Teske#
15455620f43SDevin Teske# Initialize $file with basic contents of new wpa_supplicant.conf(5).
15555620f43SDevin Teske#
15655620f43SDevin Teskef_wpa_supplicant_init()
15755620f43SDevin Teske{
15855620f43SDevin Teske	local funcname=f_wpa_supplicant_init
15955620f43SDevin Teske	local conf_file="$1" tmpfile
16055620f43SDevin Teske
16155620f43SDevin Teske	# Create a temporary file
16255620f43SDevin Teske	f_eval_catch -k tmpfile $funcname mktemp 'mktemp -t "%s"' "$pgm" ||
16355620f43SDevin Teske		return $FAILURE
16455620f43SDevin Teske
16555620f43SDevin Teske	# Make it unreadable by anyone but ourselves
16655620f43SDevin Teske	f_eval_catch $funcname chmod \
16755620f43SDevin Teske		'chmod 0600 "%s"' "$tmpfile" || return $FAILURE
16855620f43SDevin Teske
16955620f43SDevin Teske	# Make it owned by root/wheel
17055620f43SDevin Teske	f_eval_catch $funcname chown \
17155620f43SDevin Teske		'chown 0:0 "%s"' "$tmpfile" || return $FAILURE
17255620f43SDevin Teske
17355620f43SDevin Teske	# Populate it
17455620f43SDevin Teske	cat <<-EOF >> "$tmpfile"
17555620f43SDevin Teske	ctrl_interface=/var/run/wpa_supplicant
17655620f43SDevin Teske	eapol_version=2
17755620f43SDevin Teske	ap_scan=1
17855620f43SDevin Teske	fast_reauth=1
17955620f43SDevin Teske	EOF
18055620f43SDevin Teske	echo >> "$tmpfile"
18155620f43SDevin Teske
18255620f43SDevin Teske	# Move it into place
18355620f43SDevin Teske	f_eval_catch $funcname mv 'mv "%s" "%s"' "$tmpfile" "$conf_file"
18455620f43SDevin Teske}
18555620f43SDevin Teske
18655620f43SDevin Teske# f_wpa_supplicant_parse $file [struct_prefix [count_var]]
18755620f43SDevin Teske#
18855620f43SDevin Teske# Parse wpa_supplicant.conf(5) $file. Default overrides are stored in a struct
18955620f43SDevin Teske# (see struct.subr for additional details) named `{struct_prefix}defaults'. See
19055620f43SDevin Teske# WPA_DEFAULTS struct definition in the GLOBALS section above.
19155620f43SDevin Teske#
19255620f43SDevin Teske# In addition, for each one of the wireless networks we parse from $file,
19355620f43SDevin Teske# create a struct named `struct_prefixN' where `N' is a number starting from 1
19455620f43SDevin Teske# and ending in $count_var (zero means no networks). See WPA_NETWORK struct
19555620f43SDevin Teske# definition in the GLOBALS section above.
19655620f43SDevin Teske#
19755620f43SDevin Teske# If a `blob-base64-*={ ... }' entry appears, a struct named
19855620f43SDevin Teske# `{struct_prefix}blob_base64_*' is created and the `data' property holds the
19955620f43SDevin Teske# base64 encoded binary data without whitespace.
20055620f43SDevin Teske#
20155620f43SDevin Teske# Custom `*={ ... }' definitions are also supported, but should be unique
20255620f43SDevin Teske# (unlike the `network' definition). A struct named `{struct_prefix}*' is
20355620f43SDevin Teske# created if at least one property is defined in the block.
20455620f43SDevin Teske#
20555620f43SDevin Teskef_wpa_supplicant_parse()
20655620f43SDevin Teske{
20755620f43SDevin Teske	local file="$1" struct_prefix="$2" count_var="$3"
20855620f43SDevin Teske
20955620f43SDevin Teske	[ "$count_var" ] && setvar "$count_var" 0
21055620f43SDevin Teske
21155620f43SDevin Teske	[ "$file" ] || file=$( f_sysrc_get wpa_supplicant_conf_file )
21255620f43SDevin Teske	if [ ! -e "$file" ]; then
21355620f43SDevin Teske		f_dprintf "%s: No such file or directory" "$file"
21455620f43SDevin Teske		return $FAILURE
21555620f43SDevin Teske	fi
21655620f43SDevin Teske
21755620f43SDevin Teske	local list_properties
21855620f43SDevin Teske	f_replaceall "$WPA_NETWORK_LIST_PROPERTIES" "$NL" "" list_properties
21955620f43SDevin Teske	eval "$( awk \
22055620f43SDevin Teske		-v count_var="$count_var"         \
22155620f43SDevin Teske		-v struct_prefix="$struct_prefix" \
22255620f43SDevin Teske		-v list_properties="$list_properties" '
22355620f43SDevin Teske	BEGIN {
22455620f43SDevin Teske		if (!count_var && !struct_prefix) exit
22555620f43SDevin Teske		blob = count = custom_struct = network = 0
22655620f43SDevin Teske		split(list_properties, lists, FS)
22755620f43SDevin Teske	}
22855620f43SDevin Teske	function set_value(struct, prop, value)
22955620f43SDevin Teske	{
23055620f43SDevin Teske		quoted = substr(value, 0, 1) == "\""
23155620f43SDevin Teske		for (l in lists) if (list = prop == lists[l]) break
23255620f43SDevin Teske		# Remove data after whitespace if unquoted and not a list
23355620f43SDevin Teske		if (!quoted && !list) sub("[[:space:]].*", "", value)
23455620f43SDevin Teske		# Otherwise if quoted and not a list, remove the quotes
23555620f43SDevin Teske		# NB: wep_keyN needs to retain quoting if/when present
23655620f43SDevin Teske		else if (quoted && !list && prop !~ /^wep_key[[:digit:]]+/) {
23755620f43SDevin Teske			sub("^\"", "", value)
23855620f43SDevin Teske			sub("\".*", "", value)
23955620f43SDevin Teske		}
24055620f43SDevin Teske		gsub(/'\''/, "'\''\\'\'\''", value) # Sanitize the value
24155620f43SDevin Teske		if (!created[struct]) {
24255620f43SDevin Teske			print "debug= f_struct_free", struct
24355620f43SDevin Teske			print "debug= f_struct_new WPA_NETWORK", struct
24455620f43SDevin Teske			created[struct] = 1
24555620f43SDevin Teske		}
24655620f43SDevin Teske		printf "debug= %s set %s '\'%s\''\n", struct, prop, value
24755620f43SDevin Teske	}
24855620f43SDevin Teske	{
24955620f43SDevin Teske		if ($1 ~ /^network={/) {
25055620f43SDevin Teske			empty = 1 # We do not increment count unless !empty
25155620f43SDevin Teske			network = 1
25255620f43SDevin Teske			next
25355620f43SDevin Teske		} else if (match($1, "^blob-base64-[[:alnum:]_./-]+={")) {
25455620f43SDevin Teske			blob = 1
25555620f43SDevin Teske			blob_data = ""
25655620f43SDevin Teske			struct = struct_prefix "blob_bas64_"
25755620f43SDevin Teske			struct = struct substr($1, 13, RLENGTH - 14)
25855620f43SDevin Teske			next
25955620f43SDevin Teske		} else if (match($1, "^[[:alnum:]_./-]+={")) {
26055620f43SDevin Teske			empty = 1
26155620f43SDevin Teske			custom_struct = 1
26255620f43SDevin Teske			struct = struct_prefix substr($1, 0, RLENGTH - 2)
26355620f43SDevin Teske			gsub(/[^[:alnum:]_]/, "_", struct)
26455620f43SDevin Teske			next
26555620f43SDevin Teske		} else if ($1 ~ /^}/) {
26655620f43SDevin Teske			if (blob) {
26755620f43SDevin Teske				gsub("[[:space:]]", "", blob_data)
26855620f43SDevin Teske				set_value(struct, "data", blob_data)
26955620f43SDevin Teske			}
27055620f43SDevin Teske			blob = custom_struct = network = 0
27155620f43SDevin Teske			next
27255620f43SDevin Teske		} else if (!match($0, /^[[:space:]]*[[:alnum:]_]+=/))
27355620f43SDevin Teske			next
27455620f43SDevin Teske
27555620f43SDevin Teske		if (blob) {
27655620f43SDevin Teske			blob_data = blob_data $0
27755620f43SDevin Teske			next
27855620f43SDevin Teske		} else if (network) {
27955620f43SDevin Teske			if (empty) { count++; empty = 0 }
28055620f43SDevin Teske			struct = struct_prefix count
28155620f43SDevin Teske		} else if (!custom_struct)
28255620f43SDevin Teske			struct = struct_prefix "defaults"
28355620f43SDevin Teske
28455620f43SDevin Teske		if (!struct_prefix) next
28555620f43SDevin Teske
28655620f43SDevin Teske		prop = substr($0, 0, RLENGTH - 1)
28755620f43SDevin Teske		sub(/^[[:space:]]*/, "", prop)
28855620f43SDevin Teske		value = substr($0, RSTART + RLENGTH)
28955620f43SDevin Teske
29055620f43SDevin Teske		set_value(struct, prop, value)
29155620f43SDevin Teske	}
29255620f43SDevin Teske	END { if (count_var) print count_var "=" count }' "$file" )"
29355620f43SDevin Teske}
29455620f43SDevin Teske
29555620f43SDevin Teske# f_wpa_scan_results_parse [struct_prefix [count_var]]
29655620f43SDevin Teske#
29755620f43SDevin Teske# Parse the results of wpa_cli(8) `scan_results' into a series of structs (see
29855620f43SDevin Teske# struct.subr for additional details) named `struct_prefixN' where `N' is a
29955620f43SDevin Teske# number starting from 1 and ending in $count_var (zero means no results). See
30055620f43SDevin Teske# WPA_SCAN_RESULT struct definition in the GLOBALS section above.
30155620f43SDevin Teske#
30255620f43SDevin Teskef_wpa_scan_results_parse()
30355620f43SDevin Teske{
30455620f43SDevin Teske	local struct_prefix="$1" count_var="$2"
30555620f43SDevin Teske
30655620f43SDevin Teske	[ "$count_var" ] && setvar "$count_var" 0
30755620f43SDevin Teske
30855620f43SDevin Teske	eval "$( wpa_cli scan_results 2> /dev/null | awk \
30955620f43SDevin Teske		-v count_var="$count_var" \
31055620f43SDevin Teske		-v struct_prefix="$struct_prefix" '
31155620f43SDevin Teske	BEGIN {
31255620f43SDevin Teske		if (!count_var && !struct_prefix) exit
31355620f43SDevin Teske		count = 0
31455620f43SDevin Teske		seg = "[[:xdigit:]][[:xdigit:]]"
31555620f43SDevin Teske		bssid = seg":"seg":"seg":"seg":"seg":"seg
31655620f43SDevin Teske		freq = siglev = flags = "[^[:space:]]+"
31755620f43SDevin Teske		S = "[[:space:]]+"
31855620f43SDevin Teske		line = bssid S freq S siglev S flags
31955620f43SDevin Teske		line = "^[[:space:]]*" line "[[:space:]]*"
32055620f43SDevin Teske	}
32155620f43SDevin Teske	function set_value(struct, prop, value)
32255620f43SDevin Teske	{
32355620f43SDevin Teske		gsub(/'\''/, "'\''\\'\'\''", value) # Sanitize the value
32455620f43SDevin Teske		if (!created[struct]) {
32555620f43SDevin Teske			print "debug= f_struct_free", struct
32655620f43SDevin Teske			print "debug= f_struct_new WPA_SCAN_RESULT", struct
32755620f43SDevin Teske			created[struct] = 1
32855620f43SDevin Teske		}
32955620f43SDevin Teske		printf "debug= %s set %s '\'%s\''\n", struct, prop, value
33055620f43SDevin Teske	}
33155620f43SDevin Teske	{
33255620f43SDevin Teske		if (!match($0, line)) next
33355620f43SDevin Teske		ssid = substr($0, RLENGTH + 1)
33455620f43SDevin Teske
33555620f43SDevin Teske		count++
33655620f43SDevin Teske		if (!struct_prefix) next
33755620f43SDevin Teske
33855620f43SDevin Teske		struct = struct_prefix count
33955620f43SDevin Teske		set_value(struct, "ssid", ssid)
34055620f43SDevin Teske		set_value(struct, "bssid",  $1)
34155620f43SDevin Teske		set_value(struct, "freq",   $2)
34255620f43SDevin Teske		set_value(struct, "siglev", $3)
34355620f43SDevin Teske		set_value(struct, "flags",  $4)
34455620f43SDevin Teske	}
34555620f43SDevin Teske	END { if (count_var) print count_var "=" count }' )"
34655620f43SDevin Teske}
34755620f43SDevin Teske
34855620f43SDevin Teske# f_wpa_scan_match_network WPA_SCAN_RESULT WPA_NETWORK
34955620f43SDevin Teske#
35055620f43SDevin Teske# Compares a WPA_SCAN_RESULT struct to a WPA_NETWORK struct. If they appear to
35155620f43SDevin Teske# be a match returns success, otherwise failure.
35255620f43SDevin Teske#
35355620f43SDevin Teskef_wpa_scan_match_network()
35455620f43SDevin Teske{
35555620f43SDevin Teske	local scan_struct="$1" wireless_struct="$2"
35655620f43SDevin Teske	local cp debug=
35755620f43SDevin Teske
35855620f43SDevin Teske	f_struct "$scan_struct" || return $FAILURE
35955620f43SDevin Teske	f_struct "$wireless_struct" || return $FAILURE
36055620f43SDevin Teske
36155620f43SDevin Teske	local scan_ssid scan_bssid
36255620f43SDevin Teske	$scan_struct get ssid scan_ssid
36355620f43SDevin Teske	$scan_struct get bssid scan_bssid
36455620f43SDevin Teske	local wireless_ssid wireless_bssid
36555620f43SDevin Teske	$wireless_struct get ssid wireless_ssid
36655620f43SDevin Teske	$wireless_struct get bssid wireless_bssid
36755620f43SDevin Teske
36855620f43SDevin Teske	local id_matched=
36955620f43SDevin Teske	if [ "$wireless_ssid" -a "$wireless_bssid" ]; then
37055620f43SDevin Teske		# Must match both SSID and BSSID
37155620f43SDevin Teske		[ "$scan_ssid" = "$wireless_ssid" -a \
37255620f43SDevin Teske		  "$scan_bssid" = "$wireless_bssid" ] && id_matched=1
37355620f43SDevin Teske	elif [ "$wireless_ssid" ]; then
37455620f43SDevin Teske		# Must match SSID only
37555620f43SDevin Teske		[ "$scan_ssid" = "$wireless_ssid" ] && id_matched=1
37655620f43SDevin Teske	elif [ "$wireless_bssid" ]; then
37755620f43SDevin Teske		# Must match BSSID only
37855620f43SDevin Teske		[ "$scan_bssid" = "$wireless_bssid" ] && id_matched=1
37955620f43SDevin Teske	fi
38055620f43SDevin Teske	[ "$id_matched" ] || return $FAILURE
38155620f43SDevin Teske
38255620f43SDevin Teske
38355620f43SDevin Teske	#
38455620f43SDevin Teske	# Get the scanned flags for the next few comparisons
38555620f43SDevin Teske	#
38655620f43SDevin Teske	local flags
38755620f43SDevin Teske	$scan_struct get flags flags
38855620f43SDevin Teske
38955620f43SDevin Teske	#
39055620f43SDevin Teske	# Compare configured key management against scanned network
39155620f43SDevin Teske	#
39255620f43SDevin Teske	if $wireless_struct get key_mgmt cp && [ "$cp" -a "$cp" != "NONE" ]
39355620f43SDevin Teske	then
39455620f43SDevin Teske		local mgmt mgmt_matched=
39555620f43SDevin Teske		for mgmt in $cp; do
39655620f43SDevin Teske			local mgmt2="$mgmt"
39755620f43SDevin Teske			[ "$mgmt" != "${mgmt#WPA-}" ] &&
39855620f43SDevin Teske				mgmt2="WPA2${mgmt#WPA}"
39955620f43SDevin Teske			case "$flags" in
40055620f43SDevin Teske			"$mgmt"|"$mgmt"-*|*-"$mgmt"|*-"$mgmt"-*)
40155620f43SDevin Teske				mgmt_matched=1 break ;;
40255620f43SDevin Teske			"$mgmt2"|"$mgmt2"-*|*-"$mgmt2"|*-"$mgmt2"-*)
40355620f43SDevin Teske				mgmt_matched=1 break ;;
40455620f43SDevin Teske			esac
40555620f43SDevin Teske		done
40655620f43SDevin Teske		[ "$mgmt_matched" ] || return $FAILURE
40755620f43SDevin Teske	fi
40855620f43SDevin Teske
40955620f43SDevin Teske	local enc type flag
41055620f43SDevin Teske
41155620f43SDevin Teske	#
41255620f43SDevin Teske	# Compare configured encryption against scanned network
41355620f43SDevin Teske	#
41455620f43SDevin Teske	for enc in psk:PSK eap:EAP \
41555620f43SDevin Teske		wep_key0:WEP wep_key1:WEP wep_key2:WEP wep_key3:WEP
41655620f43SDevin Teske	do
41755620f43SDevin Teske		type=${enc%%:*}
41855620f43SDevin Teske		flag=${enc#*:}
41955620f43SDevin Teske		{ debug= $wireless_struct get $type cp && [ "$cp" ]; } ||
42055620f43SDevin Teske			continue
42155620f43SDevin Teske		# Configured network requires encryption
42255620f43SDevin Teske		case "$flags" in "[$flag]"|*"-$flag-"*)
42355620f43SDevin Teske			break # Success; stop after first match
42455620f43SDevin Teske		esac
42555620f43SDevin Teske		return $FAILURE
42655620f43SDevin Teske	done
42755620f43SDevin Teske	cp="" # sensitive info
42855620f43SDevin Teske
42955620f43SDevin Teske	#
43055620f43SDevin Teske	# Compare scanned network encryption against configuration
43155620f43SDevin Teske	# NB: Scanned network flags indicates _one_ of PSK EAP or WEP
43255620f43SDevin Teske	# NB: Otherwise, no encryption (so encryption won't match)
43355620f43SDevin Teske	#
43455620f43SDevin Teske	local enc_wanted=
43555620f43SDevin Teske	for enc in -PSK-:psk -EAP-:eap; do
43655620f43SDevin Teske		flag=${enc%%:*}
43755620f43SDevin Teske		type=${enc#*:}
43855620f43SDevin Teske		case "$flags" in *"$flag"*)
43955620f43SDevin Teske			enc_wanted=1
44055620f43SDevin Teske			{ debug= $wireless_struct get $type cp &&
44155620f43SDevin Teske				[ "$cp" ]; } || return $FAILURE
44255620f43SDevin Teske			break # success
44355620f43SDevin Teske		esac
44455620f43SDevin Teske	done
44555620f43SDevin Teske	case "$flags" in *"[WEP]"*)
44655620f43SDevin Teske		enc_wanted=1
44755620f43SDevin Teske		local wep_found=
44855620f43SDevin Teske		for type in wep_key0 wep_key1 wep_key2 wep_key3; do
44955620f43SDevin Teske			debug= $wireless_struct get $type cp && [ "$cp" ] &&
45055620f43SDevin Teske				wep_found=1 break
45155620f43SDevin Teske		done
45255620f43SDevin Teske		[ "$wep_found" ] || return $FAILURE
45355620f43SDevin Teske	esac
45455620f43SDevin Teske	if [ ! "$enc_wanted" ]; then
45555620f43SDevin Teske		# No match if the network specifies encryption
45655620f43SDevin Teske		for type in psk eap wep_key0 wep_key1 wep_key2 wep_key3; do
45755620f43SDevin Teske			debug= $wireless_struct get $type cp && [ "$cp" ] &&
45855620f43SDevin Teske				return $FAILURE
45955620f43SDevin Teske		done
46055620f43SDevin Teske	fi
46155620f43SDevin Teske	cp="" # sensitive info
46255620f43SDevin Teske
46355620f43SDevin Teske	return $SUCCESS
46455620f43SDevin Teske}
46555620f43SDevin Teske
46655620f43SDevin Teske# f_wpa_scan_find_matches scans_prefix $scans_count \
46755620f43SDevin Teske#                         wireless_prefix $wireless_count
46855620f43SDevin Teske#
46955620f43SDevin Teske# For each struct from `{scans_prefix}1' up to `{scans_prefix}$scans_count'
47055620f43SDevin Teske# (see struct.subr for additional details) compare the wireless network info
47155620f43SDevin Teske# (defined as struct WPA_SCAN_RESULT) to that of each configured wireless
47255620f43SDevin Teske# stored in `{wireless_prefix}1' (defined as struct WPA_NETWORK) up to
47355620f43SDevin Teske# `{wireless_prefix}$wireless_count'.
47455620f43SDevin Teske#
47555620f43SDevin Teske# If a scanned network is deemed to be a match to a configured wireless
47655620f43SDevin Teske# network, a new `match' property is set on the WPA_NETWORK struct with a value
47755620f43SDevin Teske# of `{scans_prefix}N' (where N represents the scanned network that matched).
47855620f43SDevin Teske# At the same time, a new `matched' property is set on the WPA_SCAN_RESULT
47955620f43SDevin Teske# struct with a value of 1, indicating that this network has been matched to a
48055620f43SDevin Teske# stored [known] configuration and that it should not be displayed in menus.
48155620f43SDevin Teske#
48255620f43SDevin Teske# NB: If a matching entry is not correct, the user can optionally `Forget' the
48355620f43SDevin Teske# network and that will cause the WPA_SCAN_RESULT to no longer match anything,
48455620f43SDevin Teske# causing it to appear in the menus again.
48555620f43SDevin Teske#
48655620f43SDevin Teske# Return status should be ignored.
48755620f43SDevin Teske#
48855620f43SDevin Teskef_wpa_scan_find_matches()
48955620f43SDevin Teske{
49055620f43SDevin Teske	local scans_prefix="$1" scans_count="$2"
49155620f43SDevin Teske	local wireless_prefix="$3" wireless_count="$4"
49255620f43SDevin Teske	local matches
49355620f43SDevin Teske
49455620f43SDevin Teske	[ "$scans_count" -a "$wireless_count" ] || return $SUCCESS
49555620f43SDevin Teske	f_isinteger "$scans_count" || return $FAILURE
49655620f43SDevin Teske	f_isinteger "$wireless_count" || return $FAILURE
49755620f43SDevin Teske
49855620f43SDevin Teske	#
49955620f43SDevin Teske	# Go through and eradicate any flags we set in a prior run, as things
50055620f43SDevin Teske	# might have changed on us (either from the config side or scan side)
50155620f43SDevin Teske	#
50255620f43SDevin Teske	local w=1
50355620f43SDevin Teske	while [ $w -le $wireless_count ]; do
50455620f43SDevin Teske		f_struct "$wireless_prefix$w" set matches ""
50555620f43SDevin Teske		w=$(( $w + 1 ))
50655620f43SDevin Teske	done
50755620f43SDevin Teske
50855620f43SDevin Teske	#
50955620f43SDevin Teske	# Find matches and set match data on structs
51055620f43SDevin Teske	#
51155620f43SDevin Teske	local s=1
51255620f43SDevin Teske	while [ $s -le $scans_count ]; do
51355620f43SDevin Teske		f_struct "$scans_prefix$s" set matched ""
51455620f43SDevin Teske		w=1
51555620f43SDevin Teske		while [ $w -le $wireless_count ]; do
51655620f43SDevin Teske			if f_wpa_scan_match_network \
51755620f43SDevin Teske				"$scans_prefix$s" "$wireless_prefix$w"
51855620f43SDevin Teske			then
51955620f43SDevin Teske				f_struct "$scans_prefix$s" set matched 1
52055620f43SDevin Teske				debug= f_struct "$wireless_prefix$w" \
52155620f43SDevin Teske				         get matches matches
52255620f43SDevin Teske				matches="$matches${matches:+ }$scans_prefix$s"
52355620f43SDevin Teske				f_struct "$wireless_prefix$w" \
52455620f43SDevin Teske				         set matches "$matches"
52555620f43SDevin Teske				break # to next scan result
52655620f43SDevin Teske			fi
52755620f43SDevin Teske			w=$(( $w + 1 ))
52855620f43SDevin Teske		done
52955620f43SDevin Teske		s=$(( $s + 1 ))
53055620f43SDevin Teske	done
53155620f43SDevin Teske}
53255620f43SDevin Teske
53355620f43SDevin Teske# f_dialog_menu_wlandev_edit $wlandev [$defaultitem]
53455620f43SDevin Teske#
53555620f43SDevin Teske# Display a list of wireless network devices (wlan*) associated with
53655620f43SDevin Teske# $wlandev (e.g., `iwn0'). Allow the user to create and destroy wlan interfaces
53755620f43SDevin Teske# while selecting ones to be cloned at startup (by setting `wlans_$wlandev').
53855620f43SDevin Teske#
53955620f43SDevin Teskef_dialog_menu_wlandev_edit()
54055620f43SDevin Teske{
54155620f43SDevin Teske	local funcname=f_dialog_menu_wlandev_edit
54255620f43SDevin Teske	local wlandev="$1" defaultitem="$2"
54355620f43SDevin Teske	local title="$DIALOG_TITLE"
54455620f43SDevin Teske	local btitle="$DIALOG_BACKTITLE"
54555620f43SDevin Teske	local prompt # Calculated below
54655620f43SDevin Teske	local hline="$hline_arrows_tab_enter"
54755620f43SDevin Teske
54855620f43SDevin Teske	[ "$wlandev" ] || return $FAILURE
54955620f43SDevin Teske
55055620f43SDevin Teske	f_sprintf prompt "$msg_select_wlan_interfaces_for" "wlandev"
55155620f43SDevin Teske
55255620f43SDevin Teske	#
55355620f43SDevin Teske	# Initially mark wlan devices with a %parent of $wlandev
55455620f43SDevin Teske	#
55555620f43SDevin Teske	local dev devs if list_to_save=
55655620f43SDevin Teske	f_device_find "" $DEVICE_TYPE_NETWORK devs
55755620f43SDevin Teske	for dev in $devs; do
55855620f43SDevin Teske		f_struct "$dev" get name if || continue
55955620f43SDevin Teske		case "$if" in wlan[0-9]*)
56055620f43SDevin Teske			parent=$( sysctl -n net.wlan.${if#wlan}.%parent \
56155620f43SDevin Teske				2> /dev/null )
56255620f43SDevin Teske			if [ "$parent" = "$if" ]; then
56355620f43SDevin Teske				local _wlanmark_$if="X"
56455620f43SDevin Teske				list_to_save="$list_to_save $if"
56555620f43SDevin Teske			fi
56655620f43SDevin Teske		esac
56755620f43SDevin Teske	done
56855620f43SDevin Teske	list_to_save="${list_to_save# }"
56955620f43SDevin Teske
57055620f43SDevin Teske	#
57155620f43SDevin Teske	# Operate in a loop so we can create/destroy interfaces from here
57255620f43SDevin Teske	#
57355620f43SDevin Teske	while :; do
57455620f43SDevin Teske		#
57555620f43SDevin Teske		# Refresh list of wlan interfaces
57655620f43SDevin Teske		#
57755620f43SDevin Teske		local wlanlist=
57855620f43SDevin Teske		f_device_rescan_network
57955620f43SDevin Teske		f_device_find "" $DEVICE_TYPE_NETWORK devs
58055620f43SDevin Teske		for dev in $devs; do
58155620f43SDevin Teske			f_struct "$dev" get name if || continue
58255620f43SDevin Teske			case "$if" in wlan[0-9]*)
58355620f43SDevin Teske				wlanlist="$wlanlist $if"
58455620f43SDevin Teske			esac
58555620f43SDevin Teske		done
58655620f43SDevin Teske
58755620f43SDevin Teske		#
58855620f43SDevin Teske		# Build menu list of wlan devices
58955620f43SDevin Teske		#
59055620f43SDevin Teske		local menu_list="
59155620f43SDevin Teske			'> $msg_save_exit'  '$msg_return_to_previous_menu'
59255620f43SDevin Teske			'> $msg_create_new' 'wlan'
59355620f43SDevin Teske			'> $msg_destroy'    '...'
59455620f43SDevin Teske		" # END-QUOTE
59555620f43SDevin Teske		local parent X
59655620f43SDevin Teske		for if in $wlanlist; do
59755620f43SDevin Teske			f_getvar _wlanmark_$if-" " X
59855620f43SDevin Teske			menu_list="$menu_list '[$X] $if' '%parent: $parent'"
59955620f43SDevin Teske			[ "$defaultitem" = "$if" ] && defaultitem="[$X] $if"
60055620f43SDevin Teske		done
60155620f43SDevin Teske
60255620f43SDevin Teske		#
60355620f43SDevin Teske		# Ask user to make a choice
60455620f43SDevin Teske		#
60555620f43SDevin Teske		local height width rows
60655620f43SDevin Teske		eval f_dialog_menu_size height width rows \
60755620f43SDevin Teske			\"\$title\" \"\$btitle\" \"\$prompt\" \"\$hline\" \
60855620f43SDevin Teske			$menu_list
60955620f43SDevin Teske		local menu_choice
61055620f43SDevin Teske		menu_choice=$( eval $DIALOG \
61155620f43SDevin Teske			--title \"\$title\"              \
61255620f43SDevin Teske			--backtitle \"\$btitle\"         \
61355620f43SDevin Teske			--hline \"\$hline\"              \
61455620f43SDevin Teske			--ok-label \"\$msg_select\"      \
61555620f43SDevin Teske			--cancel-label \"\$msg_cancel\"  \
61655620f43SDevin Teske			--default-item \"\$defaultitem\" \
61755620f43SDevin Teske			--menu \"\$prompt\"              \
61855620f43SDevin Teske			$height $width $rows             \
61955620f43SDevin Teske			$menu_list                       \
62055620f43SDevin Teske			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
62155620f43SDevin Teske		) || return $FAILURE
62255620f43SDevin Teske		f_dialog_data_sanitize menu_choice
62355620f43SDevin Teske
62455620f43SDevin Teske		case "$menu_choice" in
62555620f43SDevin Teske		"> $msg_save_exit") # Save list to rc.conf(5) `wlans_$wlandev'
62655620f43SDevin Teske			f_eval_catch $funcname f_sysrc_set \
62755620f43SDevin Teske				'f_sysrc_set "wlans_%s" "%s"' \
62855620f43SDevin Teske				"$wlandev" "$list_to_save" || continue
62955620f43SDevin Teske			break # to success
63055620f43SDevin Teske			;;
63155620f43SDevin Teske		"> $msg_create_new") # Create new wlan interface for wlandev
63255620f43SDevin Teske			local wlan
63355620f43SDevin Teske			f_eval_catch -k wlan $funcname ifconfig \
63455620f43SDevin Teske				'ifconfig wlan create wlandev "%s"' \
63555620f43SDevin Teske				"$wlandev" || continue
63655620f43SDevin Teske			local _wlanmark_$wlan="X"
63755620f43SDevin Teske			list_to_save="$list_to_save${list_to_save:+ }$wlan"
63855620f43SDevin Teske			;;
63955620f43SDevin Teske		"> $msg_destroy") # Display a menu to pick one item to destroy
64055620f43SDevin Teske			[ "$wlanlist" ] || continue # Nothing to destroy
64155620f43SDevin Teske
64255620f43SDevin Teske			menu_list=
64355620f43SDevin Teske			for if in $wlanlist; do
64455620f43SDevin Teske				menu_list="$menu_list '$if' ''"
64555620f43SDevin Teske			done
64655620f43SDevin Teske			local msg="$msg_pick_an_interface_to_destroy"
64755620f43SDevin Teske			eval f_dialog_menu_size height width rows \
64855620f43SDevin Teske			    \"\$title\" \"$btitle\" \"\$msg\" \"\" $menu_list
64955620f43SDevin Teske			menu_choice=$( eval $DIALOG \
65055620f43SDevin Teske				--title \"\$title\"             \
65155620f43SDevin Teske				--backtitle \"\$btitle\"        \
65255620f43SDevin Teske				--ok-label \"\$msg_destroy\"    \
65355620f43SDevin Teske				--cancel-label \"\$msg_cancel\" \
65455620f43SDevin Teske				--menu \"\$msg\"                \
65555620f43SDevin Teske				$height $width $rows            \
65655620f43SDevin Teske				$menu_list                      \
65755620f43SDevin Teske				2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
65855620f43SDevin Teske			) || continue
65955620f43SDevin Teske			f_dialog_data_sanitize menu_choice
66055620f43SDevin Teske			f_eval_catch $funcname ifconfig \
66155620f43SDevin Teske				'ifconfig "%s" destroy' "$menu_choice"
66255620f43SDevin Teske			;;
66355620f43SDevin Teske		"[ ] wlan"[0-9]*) # Unmarked; Mark
66455620f43SDevin Teske			if="${menu_choice#??? }"
66555620f43SDevin Teske			local _wlanmark_$if="X"
66655620f43SDevin Teske			list_to_save="$list_to_save${list_to_save:+ }$if"
66755620f43SDevin Teske			;;
66855620f43SDevin Teske		"[X] wlan"[0-9]*) # Marked; Unmark
66955620f43SDevin Teske			menu_choice="${menu_choice#??? }"
67055620f43SDevin Teske			local _wlanmark_$menu_choice=" "
67155620f43SDevin Teske			local new_list_to_save=
67255620f43SDevin Teske			for if in $list_to_save; do
67355620f43SDevin Teske				[ "$if" = "$menu_choice" ] && continue
67455620f43SDevin Teske				new_list_to_save="$new_list_to_save $if"
67555620f43SDevin Teske			done
67655620f43SDevin Teske			list_to_save="${new_list_to_save# }"
67755620f43SDevin Teske			;;
67855620f43SDevin Teske		esac
67955620f43SDevin Teske	done
68055620f43SDevin Teske
68155620f43SDevin Teske	return $SUCCESS
68255620f43SDevin Teske}
68355620f43SDevin Teske
68455620f43SDevin Teske# f_dialog_scan_wireless
68555620f43SDevin Teske#
68655620f43SDevin Teske# Initiate a scan for wireless networks. If wpa_supplicant(8) is not running
68755620f43SDevin Teske# but a wlan interface has been created, start an instance of wpa_supplicant(8)
68855620f43SDevin Teske# with the first wlan(4) interface we find. After initiating the scan, displays
68955620f43SDevin Teske# a message for 5 seconds (with option to dismiss). Returns failure if an error
69055620f43SDevin Teske# occurs, otherwise success.
69155620f43SDevin Teske#
69255620f43SDevin Teskef_dialog_scan_wireless()
69355620f43SDevin Teske{
69455620f43SDevin Teske	local funcname=f_dialog_scan_wireless
69555620f43SDevin Teske
69655620f43SDevin Teske	#
69755620f43SDevin Teske	# Try to communicate with a running wpa_supplicant(8)
69855620f43SDevin Teske	#
69955620f43SDevin Teske	if ! f_eval_catch -d $funcname wpa_cli 'wpa_cli ping'; then
70055620f43SDevin Teske
70155620f43SDevin Teske		# If there is indeed one running, bail!
70255620f43SDevin Teske		if ps axo ucomm= | grep -qw wpa_supplicant; then
70355620f43SDevin Teske			f_show_msg "$msg_failed_to_reach_wpa_supplicant" \
70455620f43SDevin Teske			           "$msg_wpa_cli_ping_failed"
70555620f43SDevin Teske			return $FAILURE
70655620f43SDevin Teske		fi
70755620f43SDevin Teske
70855620f43SDevin Teske		# Try and find a wlan device so we can start wpa_supplicant
70955620f43SDevin Teske		local dev devs if wlan=
71055620f43SDevin Teske		f_device_rescan_network
71155620f43SDevin Teske		f_device_find "" $DEVICE_TYPE_NETWORK devs
71255620f43SDevin Teske		for dev in $devs; do
71355620f43SDevin Teske			f_struct "$dev" get name if || continue
71455620f43SDevin Teske			case "$if" in wlan[0-9]*)
71555620f43SDevin Teske				wlan=$if
71655620f43SDevin Teske				break
71755620f43SDevin Teske			esac
71855620f43SDevin Teske		done
71955620f43SDevin Teske		if [ ! "$wlan" ]; then
72055620f43SDevin Teske			# We can't start wpa_supplicant without wlan interface
72155620f43SDevin Teske			# Tell the user they have to create one by navigating
72255620f43SDevin Teske			# to a Wireless device to create a wlan interface. But
72355620f43SDevin Teske			# let's go one step further and find an interface that
72455620f43SDevin Teske			# we can provide in the prompt text.
72555620f43SDevin Teske			local wlandev=
72655620f43SDevin Teske			for if in $devs; do
72755620f43SDevin Teske				case "$if" in wlan[0-9]*) next; esac
72855620f43SDevin Teske				if f_device_is_wireless $if; then
72955620f43SDevin Teske					wlandev=$if
73055620f43SDevin Teske					break
73155620f43SDevin Teske				fi
73255620f43SDevin Teske			done
73355620f43SDevin Teske			if [ "$wlandev" ]; then
73455620f43SDevin Teske				f_show_msg "$msg_cant_start_wpa_supplicant" \
73555620f43SDevin Teske				           "$wlandev"
73655620f43SDevin Teske			else
73755620f43SDevin Teske				# Warn user, appears no wireless available
73855620f43SDevin Teske				f_show_msg "$msg_warning_no_wireless_devices"
73955620f43SDevin Teske			fi
74055620f43SDevin Teske			return $FAILURE
74155620f43SDevin Teske		fi
74255620f43SDevin Teske
74355620f43SDevin Teske		# NB: Before we can proceed to fire up wpa_supplicant(8), let's
74455620f43SDevin Teske		# make sure there is a bare-bones wpa_supplicant.conf(5) for it
74555620f43SDevin Teske		local conf_file
74655620f43SDevin Teske		conf_file=$( f_sysrc_get wpa_supplicant_conf_file )
74755620f43SDevin Teske		if [ ! -e "$conf_file" ]; then
74855620f43SDevin Teske			f_wpa_supplicant_init "$conf_file" || return $FAILURE
74955620f43SDevin Teske			f_eval_catch -d $funcname wpa_cli 'wpa_cli reconfigure'
75055620f43SDevin Teske		fi
75155620f43SDevin Teske
75255620f43SDevin Teske		# Try and start wpa_supplicant(8)
75355620f43SDevin Teske		f_eval_catch $funcname wpa_supplicant \
75455620f43SDevin Teske		        '/etc/rc.d/wpa_supplicant start "%s"' "$wlan" ||
75555620f43SDevin Teske			return $FAILURE
75655620f43SDevin Teske
75755620f43SDevin Teske		# Try to reach this new wpa_supplicant(8)
75855620f43SDevin Teske		if ! f_eval_catch -d $funcname wpa_cli 'wpa_cli ping'; then
75955620f43SDevin Teske			f_show_msg "$msg_failed_to_reach_wpa_supplicant" \
76055620f43SDevin Teske			           "$msg_wpa_cli_ping_failed"
76155620f43SDevin Teske			return $FAILURE
76255620f43SDevin Teske		fi
76355620f43SDevin Teske
76455620f43SDevin Teske	fi # ! f_quietly wpa_cli ping
76555620f43SDevin Teske
76655620f43SDevin Teske	# If we reach hear, then it should be OK to scan the airwaves
76755620f43SDevin Teske	f_eval_catch -d $funcname wpa_cli 'wpa_cli scan' || return $FAILURE
76855620f43SDevin Teske
76955620f43SDevin Teske	# Return immediately if a duration is: null or not a number >= 1
77055620f43SDevin Teske	local duration="$DIALOG_MENU_WLAN_SCAN_DURATION"
77155620f43SDevin Teske	f_isinteger "$duration" || return $SUCCESS
77255620f43SDevin Teske	[ $duration -gt 0 ] || return $SUCCESS
77355620f43SDevin Teske
77455620f43SDevin Teske	# Display a message that times-out if not dismissed manually
77555620f43SDevin Teske	local prompt
77655620f43SDevin Teske	f_sprintf prompt "$msg_scanning_wireless_pausing" "$duration"
77755620f43SDevin Teske	f_dialog_pause "$prompt" "$duration"
77855620f43SDevin Teske}
77955620f43SDevin Teske
78055620f43SDevin Teske# f_dialog_wireless_edit $ssid
78155620f43SDevin Teske#
78255620f43SDevin Teske# Display a menu to allow the user to either create a new entry for the
783*d9499d3fSCeri Davies# wpa_supplicant.conf(5) file, or to edit values for an existing entry.
78455620f43SDevin Teske#
78555620f43SDevin Teske# If more than one wireless network is found to match $ssid, a sub-menu is
78655620f43SDevin Teske# presented, allowing the user to select the desired network.
78755620f43SDevin Teske#
78855620f43SDevin Teskef_dialog_wireless_edit()
78955620f43SDevin Teske{
79055620f43SDevin Teske	local title="$DIALOG_TITLE"
79155620f43SDevin Teske	local btitle="$DIALOG_BACKTITLE"
79255620f43SDevin Teske	local prompt1="$msg_select_the_configuration_you_would_like"
79355620f43SDevin Teske	local prompt2 # Calculated below
79455620f43SDevin Teske	local hline="$hline_alnum_arrows_punc_tab_enter"
79555620f43SDevin Teske	local ssid="$1" bssid="$2"
79655620f43SDevin Teske
79755620f43SDevin Teske	f_sprintf prompt2 "$msg_wireless_network_configuration_for" "$ssid"
79855620f43SDevin Teske
79955620f43SDevin Teske	#
80055620f43SDevin Teske	# Find one or more configurations that match the SSID selection
80155620f43SDevin Teske	#
80255620f43SDevin Teske	local height1 width1 rows1 menu_list1=
80355620f43SDevin Teske	local n=0 nmatches=0 tag wssid wbssid help matches=
80455620f43SDevin Teske	while [ $n -lt $NWIRELESS_CONFIGS ]; do
80555620f43SDevin Teske		n=$(( $n + 1 ))
80655620f43SDevin Teske
80755620f43SDevin Teske		debug= f_struct WIRELESS_$n get ssid wssid
80855620f43SDevin Teske		[ "$ssid" = "$wssid" ] || continue
80955620f43SDevin Teske		debug= f_struct WIRELESS_$n get bssid wbssid
81055620f43SDevin Teske		[ "${bssid:-$wbssid}" = "$wbssid" ] || continue
81155620f43SDevin Teske
81255620f43SDevin Teske		nmatches=$(( $nmatches + 1 ))
81355620f43SDevin Teske		[ $nmatches -le ${#DIALOG_MENU_TAGS} ] || break
81455620f43SDevin Teske		f_substr -v tag "$DIALOG_MENU_TAGS" $nmatches 1
81555620f43SDevin Teske
81655620f43SDevin Teske		f_wireless_describe WIRELESS_$n help
81755620f43SDevin Teske		menu_list1="$menu_list1
81855620f43SDevin Teske			'$tag $wssid' '$wbssid' '$help'
81955620f43SDevin Teske		" # END-QUOTE
82055620f43SDevin Teske
82155620f43SDevin Teske		matches="$matches WIRELESS_$n"
82255620f43SDevin Teske	done
82355620f43SDevin Teske	if [ $nmatches -eq 0 ]; then
82455620f43SDevin Teske		f_show_msg "$msg_cannot_edit_wireless_ssid" "$ssid"
82555620f43SDevin Teske		return $FAILURE
82655620f43SDevin Teske	elif [ $nmatches -eq 1 ]; then
82755620f43SDevin Teske		struct=${matches# }
82855620f43SDevin Teske	else
82955620f43SDevin Teske		eval f_dialog_menu_with_help_size height1 width1 rows1 \
83055620f43SDevin Teske			\"\$title\" \"\$btitle\" \"\$prompt1\" \"\$hline\" \
83155620f43SDevin Teske			$menu_list1
83255620f43SDevin Teske	fi
83355620f43SDevin Teske
83455620f43SDevin Teske	#
83555620f43SDevin Teske	# Operate in a loop; for the case of $nmatches > 1, we can cycle back
83655620f43SDevin Teske	# to allow the user to make another choice after inspecting each one.
83755620f43SDevin Teske	#
83855620f43SDevin Teske	local menu_choice index struct defaultitem1=
83955620f43SDevin Teske	while :; do
84055620f43SDevin Teske		if [ $nmatches -gt 1 ]; then
84155620f43SDevin Teske			menu_choice=$( eval $DIALOG \
84255620f43SDevin Teske				--title \"\$title\"               \
84355620f43SDevin Teske				--backtitle \"\$btitle\"          \
84455620f43SDevin Teske				--hline \"\$hline\"               \
84555620f43SDevin Teske				--ok-label \"\$msg_select\"       \
84655620f43SDevin Teske				--cancel-label \"\$msg_cancel\"   \
84755620f43SDevin Teske				--item-help                       \
84855620f43SDevin Teske				--default-item \"\$defaultitem1\" \
84955620f43SDevin Teske				--menu \"\$prompt1\"              \
85055620f43SDevin Teske				$height1 $width1 $rows1           \
85155620f43SDevin Teske				$menu_list1                       \
85255620f43SDevin Teske				2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
85355620f43SDevin Teske			) || return $FAILURE
85455620f43SDevin Teske			f_dialog_data_sanitize menu_choice
85555620f43SDevin Teske			defaultitem1="$menu_choice"
85655620f43SDevin Teske			index=$( eval f_dialog_menutag2index_with_help \
85755620f43SDevin Teske				\"\$menu_choice\" $menu_list1 )
85855620f43SDevin Teske			struct=$( set -- $matches; eval echo \${$index} )
85955620f43SDevin Teske		fi
86055620f43SDevin Teske
86155620f43SDevin Teske		#
86255620f43SDevin Teske		# Operate within another loop to allow editing multiple values
86355620f43SDevin Teske		#
86455620f43SDevin Teske		local menu_list2 height2 width2 rows2 member
86555620f43SDevin Teske		while :; do
86655620f43SDevin Teske			menu_list2="
86755620f43SDevin Teske				'> $msg_save_exit'
86855620f43SDevin Teske					'$msg_return_to_previous_menu'
86955620f43SDevin Teske			" # END-QUOTE
87055620f43SDevin Teske			n=0
87155620f43SDevin Teske			for member in $_struct_typedef_WPA_NETWORK; do
87255620f43SDevin Teske				[ "$member" = "ssid" ] && continue
87355620f43SDevin Teske				debug= $struct get $member value || continue
87455620f43SDevin Teske				n=$(( $n + 1 ))
87555620f43SDevin Teske				[ $n -le ${#DIALOG_MENU_TAGS} ] || break
87655620f43SDevin Teske				f_substr -v tag "$DIALOG_MENU_TAGS" $n 1
87755620f43SDevin Teske				if [ ${#value} -gt 32 ]; then
87855620f43SDevin Teske					f_snprintf value 29 "%s" "$value"
87955620f43SDevin Teske					value="$value..."
88055620f43SDevin Teske				fi
88155620f43SDevin Teske				case "$member" in
88255620f43SDevin Teske				password|pin|private_key_passwd|psk|wep_key*)
88355620f43SDevin Teske					f_replaceall "$value" "?" "*" value ;;
88455620f43SDevin Teske				esac
88555620f43SDevin Teske				f_shell_escape "$value" value
88655620f43SDevin Teske				menu_list2="$menu_list2
88755620f43SDevin Teske					'$tag $member' '$value'
88855620f43SDevin Teske				" # END-QUOTE
88955620f43SDevin Teske			done
89055620f43SDevin Teske			eval f_dialog_menu_size height2 width2 rows2 \
89155620f43SDevin Teske				\"\$title\" \"\$btitle\" \"\$prompt2\" \
89255620f43SDevin Teske				\"\$hline\" $menu_list2
89355620f43SDevin Teske			menu_choice=$( eval $DIALOG \
89455620f43SDevin Teske				--title \"\$title\"               \
89555620f43SDevin Teske				--backtitle \"\$btitle\"          \
89655620f43SDevin Teske				--hline \"\$hline\"               \
89755620f43SDevin Teske				--ok-label \"\$msg_select\"       \
89855620f43SDevin Teske				--cancel-label \"\$msg_cancel\"   \
89955620f43SDevin Teske				--default-item \"\$defaultitem2\" \
90055620f43SDevin Teske				--menu \"\$prompt2\"              \
90155620f43SDevin Teske				$height2 $width2 $rows2           \
90255620f43SDevin Teske				$menu_list2                       \
90355620f43SDevin Teske				2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
90455620f43SDevin Teske			) || break
90555620f43SDevin Teske			f_dialog_data_sanitize menu_choice
90655620f43SDevin Teske			defaultitem2="$menu_choice"
90755620f43SDevin Teske
90855620f43SDevin Teske			# XXXDT Unfinished
90955620f43SDevin Teske		done
91055620f43SDevin Teske		[ $nmatches -eq 1 ] && break
91155620f43SDevin Teske	done
91255620f43SDevin Teske
91355620f43SDevin Teske	#
91455620f43SDevin Teske	# XXXDT Unfinished
91555620f43SDevin Teske	# This is where we display a menu that edits the entry
916*d9499d3fSCeri Davies	# And then we modify the wpa_supplicant.conf(5) config file
91755620f43SDevin Teske	# XXXDT Unfinished
91855620f43SDevin Teske	#
91955620f43SDevin Teske
92055620f43SDevin Teske	return $FAILURE # XXXDT Simulating DIALOG_CANCEL to mean ``no changes''
92155620f43SDevin Teske}
92255620f43SDevin Teske
92355620f43SDevin Teske# f_wireless_describe WPA_NETWORK [$var_to_set]
92455620f43SDevin Teske#
92555620f43SDevin Teske# Provide a description of the WPA_NETWORK struct. If $var_to_set is missing or
92655620f43SDevin Teske# NULL, the description is provided on standard output (which is less preferred
92755620f43SDevin Teske# due to performance; e.g., if called in a loop).
92855620f43SDevin Teske#
92955620f43SDevin Teskef_wireless_describe()
93055620f43SDevin Teske{
93155620f43SDevin Teske	local __struct="$1" __var_to_set="$2" debug=
93255620f43SDevin Teske
93355620f43SDevin Teske	[ "$__var_to_set" ] && setvar "$__var_to_set" ""
93455620f43SDevin Teske	f_struct "$__struct" || return $FAILURE
93555620f43SDevin Teske
93655620f43SDevin Teske	#
93755620f43SDevin Teske	# Basic description is `proto key_mgmt group eap'
93855620f43SDevin Teske	#
93955620f43SDevin Teske	local __member __cp __desc=
94055620f43SDevin Teske	for __member in proto key_mgmt group eap; do
94155620f43SDevin Teske		$__struct get $__member __cp && [ "$__cp" ] &&
94255620f43SDevin Teske			__desc="$__desc${__desc:+ }$__cp"
94355620f43SDevin Teske	done
94455620f43SDevin Teske
94555620f43SDevin Teske	local __check __kk
94655620f43SDevin Teske
94755620f43SDevin Teske	#
94855620f43SDevin Teske	# Make sure we add WEP40/WEP140 even if omitted from the key_mgmt
94955620f43SDevin Teske	# section of entry
95055620f43SDevin Teske	#
95155620f43SDevin Teske	local __wep_keyN __f_wireless_describe_first_char __length
95255620f43SDevin Teske	for __wep_keyN in wep_key0 wep_key1 wep_key2 wep_key3; do
95355620f43SDevin Teske		$__struct get $__wep_keyN __kk
95455620f43SDevin Teske		[ "$__kk" ] || continue
95555620f43SDevin Teske
95655620f43SDevin Teske		# What type is it? ASCII or HEX?
95755620f43SDevin Teske		__check=WEP
95855620f43SDevin Teske		f_substr -v __f_wireless_describe_first_char "$__kk" 1 1
95955620f43SDevin Teske		case "$__f_wireless_describe_first_char" in
96055620f43SDevin Teske		\") # ASCII
96155620f43SDevin Teske			__length=$(( ${#__kk} - 2 ))
96255620f43SDevin Teske			if [ $__length -le 5 ]; then
96355620f43SDevin Teske				__check=WEP40
96455620f43SDevin Teske			elif [ $__length -le 13 ]; then
96555620f43SDevin Teske				__check=WEP104
96655620f43SDevin Teske			fi ;;
96755620f43SDevin Teske		*) # HEX
96855620f43SDevin Teske			__length=${#__kk}
96955620f43SDevin Teske			if [ $__length -eq 10 ]; then
97055620f43SDevin Teske				__check=WEP40
97155620f43SDevin Teske			elif [ $__length -le 26 ]; then
97255620f43SDevin Teske				__check=WEP104
97355620f43SDevin Teske			fi
97455620f43SDevin Teske		esac
97555620f43SDevin Teske		__kk="" # sensitive info
97655620f43SDevin Teske
97755620f43SDevin Teske		case "$__desc" in
97855620f43SDevin Teske		*"$__check"*) : already there ;;
97955620f43SDevin Teske		*) __desc="$__desc${__desc:+ }$__check"
98055620f43SDevin Teske		esac
98155620f43SDevin Teske	done
98255620f43SDevin Teske
98355620f43SDevin Teske	#
98455620f43SDevin Teske	# Make sure we display PSK even if omitted
98555620f43SDevin Teske	# from the key_mgmt section of the entry
98655620f43SDevin Teske	#
98755620f43SDevin Teske	$__struct get psk __kk
98855620f43SDevin Teske	if [ "$__kk" ]; then
98955620f43SDevin Teske		__kk="" # sensitive info
99055620f43SDevin Teske		__check=PSK
99155620f43SDevin Teske		case "$__desc" in
99255620f43SDevin Teske		*"$__check"*) : already there ;;
99355620f43SDevin Teske		*) __desc="$__desc${__desc:+ }$__check"
99455620f43SDevin Teske		esac
99555620f43SDevin Teske	fi
99655620f43SDevin Teske
99755620f43SDevin Teske	#
99855620f43SDevin Teske	# Produce results
99955620f43SDevin Teske	#
100055620f43SDevin Teske	if [ "$__var_to_set" ]; then
100155620f43SDevin Teske		setvar "$__var_to_set" "${__desc:-NONE}"
100255620f43SDevin Teske	else
100355620f43SDevin Teske		echo "$__desc"
100455620f43SDevin Teske	fi
100555620f43SDevin Teske}
100655620f43SDevin Teske
100755620f43SDevin Teske# f_menu_wireless_configs
100855620f43SDevin Teske#
100955620f43SDevin Teske# Generates the tag/item/help triplets for wireless network menu (`--item-help'
101055620f43SDevin Teske# required) from wpa_supplicant.conf(5) [WPA_NETWORK] structs.
101155620f43SDevin Teske#
101255620f43SDevin Teskef_menu_wireless_configs()
101355620f43SDevin Teske{
101455620f43SDevin Teske	[ "$DIALOG_MENU_WLAN_SHOW_CONFIGURED" ] || return $SUCCESS
101555620f43SDevin Teske
101655620f43SDevin Teske	echo "' - $msg_configured_ssids -' ' - $msg_details -' ''"
101755620f43SDevin Teske
101855620f43SDevin Teske	local n=0 nunique=0 debug=
101955620f43SDevin Teske	local ssid ussid matches nmatches nconfigs nfound help desc w
102055620f43SDevin Teske	while [ $n -lt $NWIRELESS_CONFIGS ]; do
102155620f43SDevin Teske		n=$(( $n + 1 ))
102255620f43SDevin Teske
102355620f43SDevin Teske		f_struct WIRELESS_$n get ssid ssid
102455620f43SDevin Teske		[ ! "$DIALOG_MENU_WLAN_SHOW_ALL" -a ! "$ssid" ] && continue
102555620f43SDevin Teske
102655620f43SDevin Teske		local u=0 unique=1
102755620f43SDevin Teske		while [ $u -lt $nunique ]; do
102855620f43SDevin Teske			u=$(( $u + 1 ))
102955620f43SDevin Teske			menuitem_$u get ssid ussid
103055620f43SDevin Teske			[ "$ssid" != "$ussid" ] || unique= break
103155620f43SDevin Teske		done
103255620f43SDevin Teske		if [ "$unique" ]; then
103355620f43SDevin Teske			nunique=$(( $nunique + 1 ))
103455620f43SDevin Teske			u=$nunique
103555620f43SDevin Teske
103655620f43SDevin Teske			# Set SSID and initialize number of configs found (1)
103755620f43SDevin Teske			f_struct_new WLAN_MENU_ITEM menuitem_$u
103855620f43SDevin Teske			menuitem_$u set ssid "$ssid"
103955620f43SDevin Teske			menuitem_$u set nconfigs 1
104055620f43SDevin Teske
104155620f43SDevin Teske			# Set number of wireless networks that match config
104255620f43SDevin Teske			WIRELESS_$n get matches matches
104355620f43SDevin Teske			f_count nmatches $matches
104455620f43SDevin Teske			menuitem_$u set nfound $nmatches
104555620f43SDevin Teske
104655620f43SDevin Teske			# Set help to description of the wireless config
104755620f43SDevin Teske			f_wireless_describe WIRELESS_$n desc
104855620f43SDevin Teske			menuitem_$u set help "$desc"
104955620f43SDevin Teske		else
105055620f43SDevin Teske			# Increment number of configs found with this SSID
105155620f43SDevin Teske			menuitem_$u get nconfigs nconfigs
105255620f43SDevin Teske			nconfigs=$(( $nconfigs + 1 ))
105355620f43SDevin Teske			menuitem_$u set nconfigs $nconfigs
105455620f43SDevin Teske
105555620f43SDevin Teske			# Add number of matched networks to existing count
105655620f43SDevin Teske			WIRELESS_$n get matches matches
105755620f43SDevin Teske			f_count nmatches $matches
105855620f43SDevin Teske			menuitem_$u get nfound nfound
105955620f43SDevin Teske			nfound=$(( $nfound + $nmatches ))
106055620f43SDevin Teske			menuitem_$u set nfound $nfound
106155620f43SDevin Teske
106255620f43SDevin Teske			# Combine description with existing help
106355620f43SDevin Teske			menuitem_$u get help help
106455620f43SDevin Teske			f_wireless_describe WIRELESS_$n desc
106555620f43SDevin Teske			for w in $desc; do
106655620f43SDevin Teske				case "$help" in
106755620f43SDevin Teske				"$w"|"$w "*|*" $w"|*" $w "*) : already there ;;
106855620f43SDevin Teske				*) help="$help $w"
106955620f43SDevin Teske				esac
107055620f43SDevin Teske			done
107155620f43SDevin Teske			menuitem_$u set help "${help# }"
107255620f43SDevin Teske		fi
107355620f43SDevin Teske	done
107455620f43SDevin Teske
107555620f43SDevin Teske	n=0
107655620f43SDevin Teske	while [ $n -lt $nunique ]; do
107755620f43SDevin Teske		n=$(( $n + 1 ))
107855620f43SDevin Teske		menuitem_$n get ssid ssid
107955620f43SDevin Teske
108055620f43SDevin Teske		menuitem_$n get nconfigs nconfigs
108155620f43SDevin Teske		desc="$nconfigs $msg_configured_lc"
108255620f43SDevin Teske		[ $nconfigs -lt 10 ] && desc=" $desc"
108355620f43SDevin Teske		menuitem_$n get nfound nfound
108455620f43SDevin Teske		[ $nfound -gt 0 ] && desc="$desc $nfound $msg_found"
108555620f43SDevin Teske
108655620f43SDevin Teske		menuitem_$n get help help
108755620f43SDevin Teske		echo "'[X] $ssid' '$desc' '$help'"
108855620f43SDevin Teske	done | sort -bf | awk 'BEGIN { prefix = "" }
108955620f43SDevin Teske	{
109055620f43SDevin Teske		cur_prefix = toupper(substr($0, 6, 1))
109155620f43SDevin Teske		if (cur_prefix != "'\''" && prefix != cur_prefix ) {
109255620f43SDevin Teske			prefix = cur_prefix
109355620f43SDevin Teske			printf "'\''%c%s\n", prefix, substr($0, 2)
109455620f43SDevin Teske		} else
109555620f43SDevin Teske			printf "'\'' %s\n", substr($0, 2)
109655620f43SDevin Teske	}'
109755620f43SDevin Teske}
109855620f43SDevin Teske
109955620f43SDevin Teske# f_menu_wpa_scan_results
110055620f43SDevin Teske#
110155620f43SDevin Teske# Generates the tag/item/help triplets for wireless network menu (`--item-help'
110255620f43SDevin Teske# required) from wpa_cli(8) `scan_results' [WPA_SCAN_RESULT] structs.
110355620f43SDevin Teske#
110455620f43SDevin Teskef_menu_wpa_scan_results()
110555620f43SDevin Teske{
110655620f43SDevin Teske	[ "$DIALOG_MENU_WLAN_SHOW_SCAN_RESULTS" ] || return $SUCCESS
110755620f43SDevin Teske
110855620f43SDevin Teske	if [ "$DIALOG_MENU_WLAN_SHOW_ALL" ]; then
110955620f43SDevin Teske		echo "' - $msg_discovered_ssids -' ' - $msg_details -' ''"
111055620f43SDevin Teske	else
111155620f43SDevin Teske		echo "' - $msg_discovered_ssids -' '' ''"
111255620f43SDevin Teske	fi
111355620f43SDevin Teske
111455620f43SDevin Teske	local n=0 nunique=0 debug=
111555620f43SDevin Teske	local ssid ussid matched nfound help flags f
111655620f43SDevin Teske	while [ $n -lt $NWSCAN_RESULTS ]; do
111755620f43SDevin Teske		n=$(( $n + 1 ))
111855620f43SDevin Teske
111955620f43SDevin Teske		WSCANS_$n get ssid ssid
112055620f43SDevin Teske		[ ! "$DIALOG_MENU_WLAN_SHOW_ALL" -a ! "$ssid" ] && continue
112155620f43SDevin Teske
112255620f43SDevin Teske		WSCANS_$n get matched matched
112355620f43SDevin Teske		[ "$DIALOG_MENU_WLAN_SHOW_CONFIGURED" -a "$matched" ] &&
112455620f43SDevin Teske			continue
112555620f43SDevin Teske
112655620f43SDevin Teske		local u=0 unique=1
112755620f43SDevin Teske		while [ $u -lt $nunique ]; do
112855620f43SDevin Teske			u=$(( $u + 1 ))
112955620f43SDevin Teske			menuitem_$u get ssid ussid
113055620f43SDevin Teske			[ "$ssid" != "$ussid" ] || unique= break
113155620f43SDevin Teske		done
113255620f43SDevin Teske		if [ "$unique" ]; then
113355620f43SDevin Teske			nunique=$(( $nunique + 1 ))
113455620f43SDevin Teske			u=$nunique
113555620f43SDevin Teske
113655620f43SDevin Teske			# Set SSID and initialize number of networks found (1)
113755620f43SDevin Teske			f_struct_new WLAN_MENU_ITEM menuitem_$u
113855620f43SDevin Teske			menuitem_$u set ssid "$ssid"
113955620f43SDevin Teske			menuitem_$u set nfound 1
114055620f43SDevin Teske
114155620f43SDevin Teske			# Set help to flags
114255620f43SDevin Teske			WSCANS_$n get flags flags
114355620f43SDevin Teske			f_replaceall "$flags" "[" " " flags
114455620f43SDevin Teske			f_replaceall "$flags" "]" "" flags
114555620f43SDevin Teske			flags="${flags# }"
114655620f43SDevin Teske			case "$flags" in
114755620f43SDevin Teske			"") flags="NONE" ;;
114855620f43SDevin Teske			ESS) flags="NONE ESS" ;;
114955620f43SDevin Teske			esac
115055620f43SDevin Teske			menuitem_$u set help "$flags"
115155620f43SDevin Teske		else
115255620f43SDevin Teske			# Increment number of networks found with this SSID
115355620f43SDevin Teske			menuitem_$u get nfound nfound
115455620f43SDevin Teske			nfound=$(( $nfound + 1 ))
115555620f43SDevin Teske			menuitem_$u set nfound $nfound
115655620f43SDevin Teske
115755620f43SDevin Teske			# Combine flags into existing help
115855620f43SDevin Teske			WSCANS_$n get flags flags
115955620f43SDevin Teske			f_replaceall "$flags" "[" " " flags
116055620f43SDevin Teske			f_replaceall "$flags" "]" "" flags
116155620f43SDevin Teske			local flags_ess=
116255620f43SDevin Teske			case "$flags" in *" ESS")
116355620f43SDevin Teske				flags_ess=1
116455620f43SDevin Teske				flags="${flags% ESS}"
116555620f43SDevin Teske			esac
116655620f43SDevin Teske			local help_ess=
116755620f43SDevin Teske			menuitem_$u get help help
116855620f43SDevin Teske			case "$help" in *" ESS")
116955620f43SDevin Teske				help_ess=1
117055620f43SDevin Teske				help="${help% ESS}"
117155620f43SDevin Teske			esac
117255620f43SDevin Teske			for f in ${flags:-NONE}; do
117355620f43SDevin Teske				case "$help" in
117455620f43SDevin Teske				"$f"|"$f "*|*" $f"|*" $f "*) : already there ;;
117555620f43SDevin Teske				*) help="$help $f"
117655620f43SDevin Teske				esac
117755620f43SDevin Teske			done
117855620f43SDevin Teske			[ "$flags_ess" -a ! "$help_ess" ] && help="$help ESS"
117955620f43SDevin Teske			menuitem_$u set help "${help# }"
118055620f43SDevin Teske		fi
118155620f43SDevin Teske	done
118255620f43SDevin Teske
118355620f43SDevin Teske	local desc n=0
118455620f43SDevin Teske	while [ $n -lt $nunique ]; do
118555620f43SDevin Teske		n=$(( $n + 1 ))
118655620f43SDevin Teske		menuitem_$n get ssid ssid
118755620f43SDevin Teske
118855620f43SDevin Teske		desc=
118955620f43SDevin Teske		if [ "$DIALOG_MENU_WLAN_SHOW_ALL" ]; then
119055620f43SDevin Teske			menuitem_$n get nfound nfound
119155620f43SDevin Teske			desc="$nfound $msg_found"
119255620f43SDevin Teske			[ $nfound -lt 10 ] && desc=" $desc"
119355620f43SDevin Teske		fi
119455620f43SDevin Teske
119555620f43SDevin Teske		menuitem_$n get help help
119655620f43SDevin Teske		echo "'[ ] $ssid' '$desc' '$help'"
119755620f43SDevin Teske	done | sort -bf | awk 'BEGIN { prefix = "" }
119855620f43SDevin Teske	{
119955620f43SDevin Teske		cur_prefix = toupper(substr($0, 6, 1))
120055620f43SDevin Teske		if (cur_prefix != "'\''" && prefix != cur_prefix ) {
120155620f43SDevin Teske			prefix = cur_prefix
120255620f43SDevin Teske			printf "'\''%c%s\n", prefix, substr($0, 2)
120355620f43SDevin Teske		} else
120455620f43SDevin Teske			printf "'\'' %s\n", substr($0, 2)
120555620f43SDevin Teske	}'
120655620f43SDevin Teske}
120755620f43SDevin Teske
120855620f43SDevin Teske# f_dialog_menu_wireless_edit
120955620f43SDevin Teske#
1210*d9499d3fSCeri Davies# Display a list of wireless networks configured in wpa_supplicant.conf(5) and
121155620f43SDevin Teske# (if wpa_supplicant(8) is running) also displays scan results for unconfigured
121255620f43SDevin Teske# wireless networks.
121355620f43SDevin Teske#
121455620f43SDevin Teskef_dialog_menu_wireless_edit()
121555620f43SDevin Teske{
121655620f43SDevin Teske	local funcname=f_dialog_menu_wireless_edit
121755620f43SDevin Teske	local title="$DIALOG_TITLE"
121855620f43SDevin Teske	local btitle="$DIALOG_BACKTITLE"
121955620f43SDevin Teske	local prompt="$msg_wireless_networks_text"
122055620f43SDevin Teske	local menu_list # Calculated below
122155620f43SDevin Teske	local defaultitem= # Calculated below
122255620f43SDevin Teske	local hline="$hline_alnum_arrows_punc_tab_enter"
122355620f43SDevin Teske
122455620f43SDevin Teske	f_show_info "$msg_loading_wireless_menu"
122555620f43SDevin Teske
122655620f43SDevin Teske	local conf_file
122755620f43SDevin Teske	conf_file=$( f_sysrc_get wpa_supplicant_conf_file )
122855620f43SDevin Teske
122955620f43SDevin Teske	#
123055620f43SDevin Teske	# Operate in a loop so we can edit wpa_supplicant.conf(5) and rescan
123155620f43SDevin Teske	# for new wireless networks from here.
123255620f43SDevin Teske	#
123355620f43SDevin Teske	local do_parse=1 remake_menu=1 item
123455620f43SDevin Teske	while :; do
123555620f43SDevin Teske		#
123655620f43SDevin Teske		# If this is the first time here, parse wpa_supplicant.conf(5),
123755620f43SDevin Teske		# scan the airwaves, and compare to find matches.
123855620f43SDevin Teske		#
123955620f43SDevin Teske		if [ "$do_parse" -a "$DIALOG_MENU_WLAN_SHOW_SCAN_RESULTS" ]
124055620f43SDevin Teske		then
124155620f43SDevin Teske			f_dprintf "$funcname: Parsing wireless scan results"
124255620f43SDevin Teske			f_dialog_scan_wireless &&
124355620f43SDevin Teske				f_wpa_scan_results_parse WSCANS_ NWSCAN_RESULTS
124455620f43SDevin Teske			f_dprintf "$funcname: Parsed %i scanned networks" \
124555620f43SDevin Teske			          $NWSCAN_RESULTS
124655620f43SDevin Teske		fi
124755620f43SDevin Teske		if [ "$do_parse" -a "$DIALOG_MENU_WLAN_SHOW_CONFIGURED" ]
124855620f43SDevin Teske		then
1249*d9499d3fSCeri Davies			f_dprintf "$funcname: Parsing wpa_supplicant.conf(5)"
125055620f43SDevin Teske			f_wpa_supplicant_parse "$conf_file" \
125155620f43SDevin Teske			                       WIRELESS_ NWIRELESS_CONFIGS
125255620f43SDevin Teske			f_dprintf "%s: Parsed %i wireless configurations" \
125355620f43SDevin Teske				  $funcname $NWIRELESS_CONFIGS
125455620f43SDevin Teske			f_wpa_scan_find_matches WSCANS_ $NWSCAN_RESULTS \
125555620f43SDevin Teske			                        WIRELESS_ $NWIRELESS_CONFIGS
125655620f43SDevin Teske		fi
125755620f43SDevin Teske		do_parse=
125855620f43SDevin Teske
125955620f43SDevin Teske		if [ "$remake_menu" ]; then
126055620f43SDevin Teske			remake_menu=
126155620f43SDevin Teske
126255620f43SDevin Teske			#
126355620f43SDevin Teske			# Add both items scanned from the airwaves and networks
1264*d9499d3fSCeri Davies			# parsed from wpa_supplicant.conf(5). Latter items are
126555620f43SDevin Teske			# marked, sorted, and added to top of list above the
126655620f43SDevin Teske			# former (which are unmarked and sorted separately).
126755620f43SDevin Teske			#
126855620f43SDevin Teske			f_dprintf "$funcname: Building menu list..."
126955620f43SDevin Teske			menu_list=$(
127055620f43SDevin Teske				# Process wpa_supplicant.conf(5) structs
127155620f43SDevin Teske				f_menu_wireless_configs
127255620f43SDevin Teske				# Process wpa_cli(8) `scan_results' structs
127355620f43SDevin Teske				f_menu_wpa_scan_results
127455620f43SDevin Teske			)
127555620f43SDevin Teske			f_dprintf "$funcname: menu list built."
127655620f43SDevin Teske
127755620f43SDevin Teske			#
127855620f43SDevin Teske			# Add static top-level menu items
127955620f43SDevin Teske			#
128055620f43SDevin Teske			local XA=" " XC=" " XS=" "
128155620f43SDevin Teske			[ "$DIALOG_MENU_WLAN_SHOW_ALL"          ] && XA="X"
128255620f43SDevin Teske			[ "$DIALOG_MENU_WLAN_SHOW_CONFIGURED"   ] && XC="X"
128355620f43SDevin Teske			[ "$DIALOG_MENU_WLAN_SHOW_SCAN_RESULTS" ] && XS="X"
128455620f43SDevin Teske			menu_list="
128555620f43SDevin Teske				'> $msg_exit' '$msg_return_to_previous_menu'
128655620f43SDevin Teske					''
128755620f43SDevin Teske				'> $msg_rescan_wireless'   '*'
128855620f43SDevin Teske					'$msg_rescan_wireless_help'
128955620f43SDevin Teske				'> $msg_forget_all'        '*'
129055620f43SDevin Teske					'$msg_forget_all_help'
129155620f43SDevin Teske				'> $msg_show_configured'   '[$XC]'
129255620f43SDevin Teske					'$msg_show_configured_help'
129355620f43SDevin Teske				'> $msg_show_scan_results' '[$XS]'
129455620f43SDevin Teske					'$msg_show_scan_results_help'
129555620f43SDevin Teske				'> $msg_show_all'          '[$XA]'
129655620f43SDevin Teske					'$msg_show_all_help'
129755620f43SDevin Teske				'> $msg_manually_connect'  '...'
129855620f43SDevin Teske					'$msg_manually_connect_help'
129955620f43SDevin Teske			$menu_list" # END-QUOTE
130055620f43SDevin Teske		fi
130155620f43SDevin Teske
130255620f43SDevin Teske		local height width rows
130355620f43SDevin Teske		eval f_dialog_menu_with_help_size height width rows \
130455620f43SDevin Teske			\"\$title\" \"\$btitle\" \"\$prompt\" \"\$hline\" \
130555620f43SDevin Teske			$menu_list
130655620f43SDevin Teske
130755620f43SDevin Teske		local menu_choice
130855620f43SDevin Teske		menu_choice=$( eval $DIALOG \
130955620f43SDevin Teske			--title \"\$title\"              \
131055620f43SDevin Teske			--backtitle \"\$btitle\"         \
131155620f43SDevin Teske			--hline \"\$hline\"              \
131255620f43SDevin Teske			--ok-label \"\$msg_select\"      \
131355620f43SDevin Teske			--cancel-label \"\$msg_cancel\"  \
131455620f43SDevin Teske			--item-help                      \
131555620f43SDevin Teske			--default-item \"\$defaultitem\" \
131655620f43SDevin Teske			--menu \"\$prompt\"              \
131755620f43SDevin Teske			$height $width $rows             \
131855620f43SDevin Teske			$menu_list                       \
131955620f43SDevin Teske			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
132055620f43SDevin Teske		) || break
132155620f43SDevin Teske		f_dialog_data_sanitize menu_choice
132255620f43SDevin Teske		defaultitem="$menu_choice"
132355620f43SDevin Teske
132455620f43SDevin Teske		case "$menu_choice" in
132555620f43SDevin Teske		"> $msg_exit") break ;;
132655620f43SDevin Teske		"> $msg_rescan_wireless") do_parse=1 remake_menu=1 ;;
132755620f43SDevin Teske		"> $msg_forget_all")
132855620f43SDevin Teske			if f_noyes "$msg_forget_all_confirm"; then
132955620f43SDevin Teske				f_eval_catch $funcname rm \
133055620f43SDevin Teske					'rm -f "%s"' "$conf_file" || continue
133155620f43SDevin Teske				f_wpa_supplicant_init "$conf_file" || continue
133255620f43SDevin Teske				f_eval_catch -d $funcname wpa_cli \
133355620f43SDevin Teske					'wpa_cli reconfigure'
133455620f43SDevin Teske				f_wpa_supplicant_parse "$conf_file" \
133555620f43SDevin Teske					WIRELESS_ NWIRELESS_CONFIGS
133655620f43SDevin Teske				f_wpa_scan_find_matches \
133755620f43SDevin Teske					WSCANS_ $NWSCAN_RESULTS \
133855620f43SDevin Teske					WIRELESS_ $NWIRELESS_CONFIGS
133955620f43SDevin Teske				do_parse=1 remake_menu=1
134055620f43SDevin Teske			fi ;;
134155620f43SDevin Teske		"> $msg_show_configured")
134255620f43SDevin Teske			item=$( eval f_dialog_menutag2item_with_help \
134355620f43SDevin Teske			        		\"\$menu_choice\" $menu_list )
134455620f43SDevin Teske			if [ "$item" = "[ ]" ]; then
134555620f43SDevin Teske				DIALOG_MENU_WLAN_SHOW_CONFIGURED=1
134655620f43SDevin Teske			else
134755620f43SDevin Teske				DIALOG_MENU_WLAN_SHOW_CONFIGURED=
134855620f43SDevin Teske			fi
134955620f43SDevin Teske			remake_menu=1 ;;
135055620f43SDevin Teske		"> $msg_show_scan_results")
135155620f43SDevin Teske			item=$( eval f_dialog_menutag2item_with_help \
135255620f43SDevin Teske			        		\"\$menu_choice\" $menu_list )
135355620f43SDevin Teske			if [ "$item" = "[ ]" ]; then
135455620f43SDevin Teske				DIALOG_MENU_WLAN_SHOW_SCAN_RESULTS=1
135555620f43SDevin Teske			else
135655620f43SDevin Teske				DIALOG_MENU_WLAN_SHOW_SCAN_RESULTS=
135755620f43SDevin Teske			fi
135855620f43SDevin Teske			remake_menu=1 ;;
135955620f43SDevin Teske		"> $msg_show_all")
136055620f43SDevin Teske			item=$( eval f_dialog_menutag2item_with_help \
136155620f43SDevin Teske			        		\"\$menu_choice\" $menu_list )
136255620f43SDevin Teske			if [ "$item" = "[ ]" ]; then
136355620f43SDevin Teske				DIALOG_MENU_WLAN_SHOW_ALL=1
136455620f43SDevin Teske			else
136555620f43SDevin Teske				DIALOG_MENU_WLAN_SHOW_ALL=
136655620f43SDevin Teske			fi
136755620f43SDevin Teske			remake_menu=1 ;;
136855620f43SDevin Teske		"> $msg_manually_connect")
136955620f43SDevin Teske			f_dialog_wireless_edit && remake_menu=1 ;;
137055620f43SDevin Teske		?"[X] "*)
137155620f43SDevin Teske			ssid="${menu_choice#??X? }"
137255620f43SDevin Teske			f_dialog_wireless_edit "$ssid" || continue
137355620f43SDevin Teske			do_parse=1 remake_menu=1 ;;
137455620f43SDevin Teske		"[ ] "*)
137555620f43SDevin Teske			:
137655620f43SDevin Teske			: XXXDT Unfinished
137755620f43SDevin Teske			:
137855620f43SDevin Teske			;;
137955620f43SDevin Teske		esac
138055620f43SDevin Teske	done
138155620f43SDevin Teske
138255620f43SDevin Teske	#
138355620f43SDevin Teske	# XXXDT Unfinished
138455620f43SDevin Teske	#
138555620f43SDevin Teske}
138655620f43SDevin Teske
138755620f43SDevin Teske############################################################ MAIN
138855620f43SDevin Teske
138955620f43SDevin Teskef_dprintf "%s: Successfully loaded." media/wlan.subr
139055620f43SDevin Teske
139155620f43SDevin Teskefi # ! $_MEDIA_WLAN_SUBR
1392