mirror of https://github.com/hak5/openwrt.git
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>master
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