From b7f9742da82fa9b122e8d63e48a9a5c0dec298f2 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 14 Nov 2023 13:00:27 +0100 Subject: [PATCH] mac80211: rework interface setup, fix race condition Only tell netifd about vifs when the setup is complete and hostapd + wpa_supplicant have been notified Signed-off-by: Felix Fietkau --- .../files/lib/netifd/wireless/mac80211.sh | 159 ++++++++---------- .../network/services/hostapd/files/hostapd.sh | 7 +- 2 files changed, 74 insertions(+), 92 deletions(-) diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index 6572999fbc..cc7e143030 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -635,71 +635,6 @@ mac80211_set_ifname() { eval "ifname=\"$phy-$prefix\${idx_$prefix:-0}\"; idx_$prefix=\$((\${idx_$prefix:-0 } + 1))" } -mac80211_prepare_vif() { - json_select config - - json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file - - [ -n "$ifname" ] || { - local prefix; - - case "$mode" in - ap|sta|mesh) prefix=$mode;; - adhoc) prefix=ibss;; - monitor) prefix=mon;; - esac - - mac80211_set_ifname "$phy" "$prefix" - } - - append active_ifnames "$ifname" - set_default wds 0 - set_default powersave 0 - json_add_string _ifname "$ifname" - - default_macaddr= - if [ -z "$macaddr" ]; then - macaddr="$(mac80211_generate_mac $phy)" - macidx="$(($macidx + 1))" - default_macaddr=1 - elif [ "$macaddr" = 'random' ]; then - macaddr="$(macaddr_random)" - fi - json_add_string _macaddr "$macaddr" - json_add_string _default_macaddr "$default_macaddr" - json_select .. - - - [ "$mode" == "ap" ] && { - [ -z "$wpa_psk_file" ] && hostapd_set_psk "$ifname" - [ -z "$vlan_file" ] && hostapd_set_vlan "$ifname" - } - - json_select config - - # It is far easier to delete and create the desired interface - case "$mode" in - ap) - # Hostapd will handle recreating the interface and - # subsequent virtual APs belonging to the same PHY - if [ -n "$hostapd_ctrl" ]; then - type=bss - else - type=interface - fi - - mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return - - [ -n "$hostapd_ctrl" ] || { - ap_ifname="${ifname}" - hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" - } - ;; - esac - - json_select .. -} - mac80211_prepare_iw_htmode() { case "$htmode" in VHT20|HT20|HE20) iw_htmode=HT20;; @@ -842,17 +777,6 @@ mac80211_setup_monitor() { json_set_namespace "$prev" } -mac80211_set_vif_txpower() { - local name="$1" - - json_select config - json_get_var ifname _ifname - json_get_vars vif_txpower - json_select .. - - [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" -} - wpa_supplicant_init_config() { json_set_namespace wpa_supp prev @@ -957,19 +881,41 @@ mac80211_setup_supplicant() { return 0 } -mac80211_setup_vif() { - local name="$1" - local failed - +mac80211_prepare_vif() { json_select config - json_get_var ifname _ifname - json_get_var macaddr _macaddr - json_get_var default_macaddr _default_macaddr - json_get_vars mode wds powersave - set_default powersave 0 + json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file + local config_wpa_psk_file="$wpa_psk_file" + local config_vlan_file="$vlan_file" + + [ -n "$ifname" ] || { + local prefix; + + case "$mode" in + ap|sta|mesh) prefix=$mode;; + adhoc) prefix=ibss;; + monitor) prefix=mon;; + esac + + mac80211_set_ifname "$phy" "$prefix" + } + + append active_ifnames "$ifname" + + default_macaddr= + if [ -z "$macaddr" ]; then + macaddr="$(mac80211_generate_mac $phy)" + macidx="$(($macidx + 1))" + default_macaddr=1 + elif [ "$macaddr" = 'random' ]; then + macaddr="$(macaddr_random)" + fi + + local failed= set_default wds 0 + set_default powersave 0 + # It is far easier to delete and create the desired interface case "$mode" in mesh) json_get_vars $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING @@ -995,10 +941,48 @@ mac80211_setup_vif() { monitor) mac80211_setup_monitor ;; + ap) + # Hostapd will handle recreating the interface and + # subsequent virtual APs belonging to the same PHY + if [ -n "$hostapd_ctrl" ]; then + type=bss + else + type=interface + fi + + mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return + + [ -n "$hostapd_ctrl" ] || { + ap_ifname="${ifname}" + hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" + } + ;; esac + [ -n "$failed" ] || { + json_add_string _ifname "$ifname" + json_add_string _macaddr "$macaddr" + json_add_string _default_macaddr "$default_macaddr" + } + json_select .. - [ -n "$failed" ] || wireless_add_vif "$name" "$ifname" + + [ "$mode" == "ap" ] && { + [ -z "$config_wpa_psk_file" ] && hostapd_set_psk "$ifname" + [ -z "$config_vlan_file" ] && hostapd_set_vlan "$ifname" + } +} + +mac80211_setup_vif() { + local name="$1" + + json_select config + json_get_var ifname _ifname + json_get_vars vif_txpower + json_select .. + + [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" + [ -n "$ifname" ] && wireless_add_vif "$name" "$ifname" } get_freq() { @@ -1144,7 +1128,6 @@ drv_mac80211_setup() { mac80211_prepare_iw_htmode active_ifnames= for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif - for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy" [ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy" @@ -1155,7 +1138,7 @@ drv_mac80211_setup() { wdev_tool "$phy" set_config "$(json_dump)" $active_ifnames json_set_namespace "$prev" - for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower + for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif wireless_set_up } diff --git a/package/network/services/hostapd/files/hostapd.sh b/package/network/services/hostapd/files/hostapd.sh index 271c1f7bec..c0c39a9399 100644 --- a/package/network/services/hostapd/files/hostapd.sh +++ b/package/network/services/hostapd/files/hostapd.sh @@ -398,6 +398,7 @@ hostapd_set_vlan() { rm -f /var/run/hostapd-${ifname}.vlan for_each_vlan hostapd_set_vlan_file ${ifname} + touch /var/run/hostapd-${ifname}.vlan } hostapd_set_psk_file() { @@ -416,6 +417,7 @@ hostapd_set_psk() { rm -f /var/run/hostapd-${ifname}.psk for_each_station hostapd_set_psk_file ${ifname} + touch /var/run/hostapd-${ifname}.psk } append_iw_roaming_consortium() { @@ -688,10 +690,7 @@ hostapd_set_bss_options() { return 1 fi [ -z "$wpa_psk_file" ] && set_default wpa_psk_file /var/run/hostapd-$ifname.psk - [ -n "$wpa_psk_file" ] && { - [ -e "$wpa_psk_file" ] || touch "$wpa_psk_file" - append bss_conf "wpa_psk_file=$wpa_psk_file" "$N" - } + [ -n "$wpa_psk_file" ] && append bss_conf "wpa_psk_file=$wpa_psk_file" "$N" [ "$eapol_version" -ge "1" -a "$eapol_version" -le "2" ] && append bss_conf "eapol_version=$eapol_version" "$N" set_default dynamic_vlan 0 -- 2.30.2