mac80211: add support for dynamically reconfiguring wifi
Change scripts to use ubus interface of hostapd/wpa_supplicant to add/remove/modify wireless interfaces instead of (re-)starting the services. Signed-off-by: John Crispin <john@phrozen.org> Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
		
							parent
							
								
									60fb4c92b6
								
							
						
					
					
						commit
						a5bc9787d4
					
				| @ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk | ||||
| PKG_NAME:=mac80211 | ||||
| 
 | ||||
| PKG_VERSION:=5.4-rc2-1 | ||||
| PKG_RELEASE:=1 | ||||
| PKG_RELEASE:=2 | ||||
| PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.4-rc2/ | ||||
| PKG_HASH:=b3baedc135b455f09f266cb77e73276ca21bceeb0f24bac2184cc4b97d09cdbf | ||||
| 
 | ||||
|  | ||||
| @ -19,6 +19,11 @@ iw() { | ||||
| 	command iw $@ || logger -t mac80211 "Failed command: iw $@" | ||||
| } | ||||
| 
 | ||||
| NEWAPLIST= | ||||
| OLDAPLIST= | ||||
| NEWSPLIST= | ||||
| OLDSPLIST= | ||||
| 
 | ||||
| drv_mac80211_init_device_config() { | ||||
| 	hostapd_common_add_device_config | ||||
| 
 | ||||
| @ -58,7 +63,7 @@ drv_mac80211_init_iface_config() { | ||||
| 
 | ||||
| 	config_add_string 'macaddr:macaddr' ifname | ||||
| 
 | ||||
| 	config_add_boolean wds powersave | ||||
| 	config_add_boolean wds powersave enable | ||||
| 	config_add_int maxassoc | ||||
| 	config_add_int max_listen_int | ||||
| 	config_add_int dtim_period | ||||
| @ -454,7 +459,7 @@ mac80211_iw_interface_add() { | ||||
| mac80211_prepare_vif() { | ||||
| 	json_select config | ||||
| 
 | ||||
| 	json_get_vars ifname mode ssid wds powersave macaddr | ||||
| 	json_get_vars ifname mode ssid wds powersave macaddr enable | ||||
| 
 | ||||
| 	[ -n "$ifname" ] || ifname="wlan${phy#phy}${if_idx:+-$if_idx}" | ||||
| 	if_idx=$((${if_idx:-0} + 1)) | ||||
| @ -490,8 +495,8 @@ mac80211_prepare_vif() { | ||||
| 
 | ||||
| 			mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return | ||||
| 
 | ||||
| 			NEWAPLIST="${NEWAPLIST}$ifname " | ||||
| 			[ -n "$hostapd_ctrl" ] || { | ||||
| 				mac80211_iw_interface_add "$phy" "$ifname" __ap || return | ||||
| 				hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" | ||||
| 			} | ||||
| 		;; | ||||
| @ -503,7 +508,7 @@ mac80211_prepare_vif() { | ||||
| 		;; | ||||
| 		sta) | ||||
| 			local wdsflag= | ||||
| 			staidx="$(($staidx + 1))" | ||||
| 			[ "$enable" = 0 ] || staidx="$(($staidx + 1))" | ||||
| 			[ "$wds" -gt 0 ] && wdsflag="4addr on" | ||||
| 			mac80211_iw_interface_add "$phy" "$ifname" managed "$wdsflag" || return | ||||
| 			[ "$powersave" -gt 0 ] && powersave="on" || powersave="off" | ||||
| @ -529,19 +534,62 @@ mac80211_prepare_vif() { | ||||
| } | ||||
| 
 | ||||
| mac80211_setup_supplicant() { | ||||
| 	local enable=$1 | ||||
| 	local add_sp=0 | ||||
| 	local spobj="$(ubus -S list | grep wpa_supplicant.${ifname})" | ||||
| 
 | ||||
| 	wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1 | ||||
| 	wpa_supplicant_prepare_interface "$ifname" nl80211 || { | ||||
| 		iw dev "$ifname" del | ||||
| 		return 1 | ||||
| 	} | ||||
| 	if [ "$mode" = "sta" ]; then | ||||
| 		wpa_supplicant_add_network "$ifname" | ||||
| 	else | ||||
| 		wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan" | ||||
| 	fi | ||||
| 	wpa_supplicant_run "$ifname" ${hostapd_ctrl:+-H $hostapd_ctrl} | ||||
| 
 | ||||
| 	NEWSPLIST="${NEWSPLIST}$ifname " | ||||
| 
 | ||||
| 	if [ "${NEWAPLIST%% *}" != "${OLDAPLIST%% *}" ]; then | ||||
| 		[ "$spobj" ] && ubus call wpa_supplicant.${phy} config_del "{\"iface\":\"$ifname\"}" | ||||
| 		add_sp=1 | ||||
| 	fi | ||||
| 	[ "$enable" = 0 ] && { | ||||
| 		ubus call wpa_supplicant.${phy} config_del "{\"iface\":\"$ifname\"}" | ||||
| 		ip link set dev "$ifname" down | ||||
| 		return 0 | ||||
| 	} | ||||
| 	[ -z "$spobj" ] && add_sp=1 | ||||
| 
 | ||||
| 	if [ "$add_sp" = "1" ]; then | ||||
| 		wpa_supplicant_run "$ifname" "$hostapd_ctrl" | ||||
| 	else | ||||
| 		ubus call $spobj reload | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| mac80211_setup_supplicant_noctl() { | ||||
| 	wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1 | ||||
| 	local enable=$1 | ||||
| 	local spobj="$(ubus -S list | grep wpa_supplicant.${ifname})" | ||||
| 	wpa_supplicant_prepare_interface "$ifname" nl80211 || { | ||||
| 		iw dev "$ifname" del | ||||
| 		return 1 | ||||
| 	} | ||||
| 
 | ||||
| 	wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan" | ||||
| 	wpa_supplicant_run "$ifname" | ||||
| 
 | ||||
| 	NEWSPLIST="${NEWSPLIST}$ifname " | ||||
| 	[ "$enable" = 0 ] && { | ||||
| 		ubus call wpa_supplicant.${phy} config_del "{\"iface\":\"$ifname\"}" | ||||
| 		ip link set dev "$ifname" down | ||||
| 		return 0 | ||||
| 	} | ||||
| 	if [ -z "$spobj" ]; then | ||||
| 		wpa_supplicant_run "$ifname" | ||||
| 	else | ||||
| 		ubus call $spobj reload | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| mac80211_setup_adhoc_htmode() { | ||||
| @ -579,12 +627,17 @@ mac80211_setup_adhoc_htmode() { | ||||
| 		;; | ||||
| 		*) ibss_htmode="" ;; | ||||
| 	esac | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| mac80211_setup_adhoc() { | ||||
| 	local enable=$1 | ||||
| 	json_get_vars bssid ssid key mcast_rate | ||||
| 
 | ||||
| 	[ "$enable" = 0 ] && { | ||||
| 		ip link set dev "$ifname" down | ||||
| 		return 0 | ||||
| 	} | ||||
| 
 | ||||
| 	keyspec= | ||||
| 	[ "$auth_type" = "wep" ] && { | ||||
| 		set_default key 1 | ||||
| @ -623,8 +676,14 @@ mac80211_setup_adhoc() { | ||||
| } | ||||
| 
 | ||||
| mac80211_setup_mesh() { | ||||
| 	local enable=$1 | ||||
| 	json_get_vars ssid mesh_id mcast_rate | ||||
| 
 | ||||
| 	[ "$enable" = 0 ] && { | ||||
| 		ip link set dev "$ifname" down | ||||
| 		return 0 | ||||
| 	} | ||||
| 
 | ||||
| 	mcval= | ||||
| 	[ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate" | ||||
| 	[ -n "$mesh_id" ] && ssid="$mesh_id" | ||||
| @ -670,6 +729,7 @@ mac80211_setup_mesh() { | ||||
| mac80211_setup_vif() { | ||||
| 	local name="$1" | ||||
| 	local failed | ||||
| 	local action=up | ||||
| 
 | ||||
| 	json_select data | ||||
| 	json_get_vars ifname | ||||
| @ -678,13 +738,15 @@ mac80211_setup_vif() { | ||||
| 	json_select config | ||||
| 	json_get_vars mode | ||||
| 	json_get_var vif_txpower txpower | ||||
| 	json_get_var vif_enable enable 1 | ||||
| 
 | ||||
| 	ip link set dev "$ifname" up || { | ||||
| 	[ "$vif_enable" = 1 ] || action=down | ||||
| 	logger ip link set dev "$ifname" $action | ||||
| 	ip link set dev "$ifname" "$action" || { | ||||
| 		wireless_setup_vif_failed IFUP_ERROR | ||||
| 		json_select .. | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	set_default vif_txpower "$txpower" | ||||
| 	[ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" | ||||
| 
 | ||||
| @ -693,9 +755,9 @@ mac80211_setup_vif() { | ||||
| 			wireless_vif_parse_encryption | ||||
| 			freq="$(get_freq "$phy" "$channel")" | ||||
| 			if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ] || chan_is_dfs "$phy" "$channel"; then | ||||
| 				mac80211_setup_supplicant || failed=1 | ||||
| 				mac80211_setup_supplicant $vif_enable || failed=1 | ||||
| 			else | ||||
| 				mac80211_setup_mesh | ||||
| 				mac80211_setup_mesh $vif_enable | ||||
| 			fi | ||||
| 			for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do | ||||
| 				json_get_var mp_val "$var" | ||||
| @ -707,13 +769,13 @@ mac80211_setup_vif() { | ||||
| 			mac80211_setup_adhoc_htmode | ||||
| 			if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then | ||||
| 				freq="$(get_freq "$phy" "$channel")" | ||||
| 				mac80211_setup_supplicant_noctl || failed=1 | ||||
| 				mac80211_setup_supplicant_noctl $vif_enable || failed=1 | ||||
| 			else | ||||
| 				mac80211_setup_adhoc | ||||
| 				mac80211_setup_adhoc $vif_enable | ||||
| 			fi | ||||
| 		;; | ||||
| 		sta) | ||||
| 			mac80211_setup_supplicant || failed=1 | ||||
| 			mac80211_setup_supplicant $vif_enable || failed=1 | ||||
| 		;; | ||||
| 	esac | ||||
| 
 | ||||
| @ -734,18 +796,26 @@ chan_is_dfs() { | ||||
| 	return $! | ||||
| } | ||||
| 
 | ||||
| mac80211_interface_cleanup() { | ||||
| 	local phy="$1" | ||||
| mac80211_vap_cleanup() { | ||||
| 	local service="$1" | ||||
| 	local vaps="$2" | ||||
| 
 | ||||
| 	for wdev in $(list_phy_interfaces "$phy"); do | ||||
| 		local wdev_phy="$(readlink /sys/class/net/${wdev}/phy80211)" | ||||
| 		wdev_phy="$(basename "$wdev_phy")" | ||||
| 		[ -n "$wdev_phy" -a "$wdev_phy" != "$phy" ] && continue | ||||
| 	for wdev in $vaps; do | ||||
| 		ubus call ${service}.${phy} config_remove "{\"iface\":\"$wdev\"}" | ||||
| 		ip link set dev "$wdev" down 2>/dev/null | ||||
| 		iw dev "$wdev" del | ||||
| 	done | ||||
| } | ||||
| 
 | ||||
| mac80211_interface_cleanup() { | ||||
| 	local phy="$1" | ||||
| 	local primary_ap=$(uci -q -P /var/state get wireless._${phy}.aplist) | ||||
| 	primary_ap=${primary_ap%% *} | ||||
| 
 | ||||
| 	mac80211_vap_cleanup hostapd "${primary_ap}" | ||||
| 	mac80211_vap_cleanup wpa_supplicant "$(uci -q -P /var/state get wireless._${phy}.splist)" | ||||
| } | ||||
| 
 | ||||
| mac80211_set_noscan() { | ||||
| 	hostapd_noscan=1 | ||||
| } | ||||
| @ -771,8 +841,10 @@ drv_mac80211_setup() { | ||||
| 		return 1 | ||||
| 	} | ||||
| 
 | ||||
| 	wireless_set_data phy="$phy" | ||||
| 	mac80211_interface_cleanup "$phy" | ||||
| 	[ -z "$(uci -q -P /var/state show wireless._${phy})" ] && { | ||||
| 		uci -q -P /var/state set wireless._${phy}=phy | ||||
| 		wireless_set_data phy="$phy" | ||||
| 	} | ||||
| 
 | ||||
| 	# convert channel to frequency | ||||
| 	[ "$auto_channel" -gt 0 ] || freq="$(get_freq "$phy" "$channel")" | ||||
| @ -822,32 +894,57 @@ drv_mac80211_setup() { | ||||
| 	[ -n "$has_ap" ] && mac80211_hostapd_setup_base "$phy" | ||||
| 
 | ||||
| 	for_each_interface "sta adhoc mesh monitor" mac80211_prepare_vif | ||||
| 	NEWAPLIST= | ||||
| 	for_each_interface "ap" mac80211_prepare_vif | ||||
| 
 | ||||
| 	OLDAPLIST=$(uci -q -P /var/state get wireless._${phy}.aplist) | ||||
| 	NEW_MD5=$(md5sum ${hostapd_conf_file}) | ||||
| 	OLD_MD5=$(uci -q -P /var/state get wireless._${phy}.md5) | ||||
| 	if [ "${NEWAPLIST}" != "${OLDAPLIST}" ]; then | ||||
| 		mac80211_vap_cleanup hostapd "${OLDAPLIST}" | ||||
| 		[ -n "${NEWAPLIST}" ] && mac80211_iw_interface_add "$phy" "${NEWAPLIST%% *}" __ap || return | ||||
| 	fi | ||||
| 	local add_ap=0 | ||||
| 	local primary_ap=${NEWAPLIST%% *} | ||||
| 	[ -n "$hostapd_ctrl" ] && { | ||||
| 		/usr/sbin/hostapd -s -P /var/run/wifi-$phy.pid -B "$hostapd_conf_file" | ||||
| 		if [ -n "$(ubus list | grep hostapd.$primary_ap)" ]; then | ||||
| 			[ "${NEW_MD5}" = "${OLD_MD5}" ] || { | ||||
| 				ubus call hostapd.$primary_ap reload | ||||
| 			} | ||||
| 		else | ||||
| 			add_ap=1 | ||||
| 			ubus call hostapd.${phy} config_add "{\"iface\":\"$primary_ap\", \"config\":\"${hostapd_conf_file}\"}" | ||||
| 		fi | ||||
| 		ret="$?" | ||||
| 		wireless_add_process "$(cat /var/run/wifi-$phy.pid)" "/usr/sbin/hostapd" 1 | ||||
| 		[ "$ret" != 0 ] && { | ||||
| 			wireless_setup_failed HOSTAPD_START_FAILED | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	uci -q -P /var/state set wireless._${phy}.aplist="${NEWAPLIST}" | ||||
| 	uci -q -P /var/state set wireless._${phy}.md5="${NEW_MD5}" | ||||
| 
 | ||||
| 	for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif | ||||
| 	[ "${add_ap}" = 1 ] && sleep 1 | ||||
| 	for_each_interface "ap" mac80211_setup_vif | ||||
| 
 | ||||
| 	NEWSPLIST= | ||||
| 	OLDSPLIST=$(uci -q -P /var/state get wireless._${phy}.splist) | ||||
| 	for_each_interface "sta adhoc mesh monitor" mac80211_setup_vif | ||||
| 
 | ||||
| 	uci -q -P /var/state set wireless._${phy}.splist="${NEWSPLIST}" | ||||
| 
 | ||||
| 	local foundvap | ||||
| 	local dropvap="" | ||||
| 	for oldvap in $OLDSPLIST; do | ||||
| 		foundvap=0 | ||||
| 		for newvap in $NEWSPLIST; do | ||||
| 			[ "$oldvap" = "$newvap" ] && foundvap=1 | ||||
| 		done | ||||
| 		[ "$foundvap" = "0" ] && dropvap="$dropvap $oldvap" | ||||
| 	done | ||||
| 	[ -n "$dropvap" ] && mac80211_vap_cleanup wpa_supplicant "$dropvap" | ||||
| 	wireless_set_up | ||||
| } | ||||
| 
 | ||||
| list_phy_interfaces() { | ||||
| 	local phy="$1" | ||||
| 	if [ -d "/sys/class/ieee80211/${phy}/device/net" ]; then | ||||
| 		ls "/sys/class/ieee80211/${phy}/device/net" 2>/dev/null; | ||||
| 	else | ||||
| 		ls "/sys/class/ieee80211/${phy}/device" 2>/dev/null | grep net: | sed -e 's,net:,,g' | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| drv_mac80211_teardown() { | ||||
| 	wireless_process_kill_all | ||||
| 
 | ||||
| @ -856,6 +953,7 @@ drv_mac80211_teardown() { | ||||
| 	json_select .. | ||||
| 
 | ||||
| 	mac80211_interface_cleanup "$phy" | ||||
| 	uci -q -P /var/state revert wireless._${phy} | ||||
| } | ||||
| 
 | ||||
| add_driver mac80211 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user