v1.5 branch refresh based upon upstream master @ c8677ca89e53e3be7988d54280fce166cc894a7e
[librecmc/librecmc.git] / package / kernel / mac80211 / files / lib / netifd / wireless / mac80211.sh
index 82c374353ec98259e57c2568843ca9ef6b3a4ca2..244260a2dd8f2b48ee07fda139a5d45c10603548 100644 (file)
@@ -411,6 +411,34 @@ mac80211_check_ap() {
        has_ap=1
 }
 
+mac80211_iw_interface_add() {
+       local phy="$1"
+       local ifname="$2"
+       local type="$3"
+       local wdsflag="$4"
+       local rc
+
+       iw phy "$phy" interface add "$ifname" type "$type" $wdsflag
+       rc="$?"
+
+       [ "$rc" = 233 ] && {
+               # Device might have just been deleted, give the kernel some time to finish cleaning it up
+               sleep 1
+
+               iw phy "$phy" interface add "$ifname" type "$type" $wdsflag
+               rc="$?"
+       }
+
+       [ "$rc" = 233 ] && {
+               # Device might not support virtual interfaces, so the interface never got deleted in the first place.
+               # Check if the interface already exists, and avoid failing in this case.
+               ip link show dev "$ifname" >/dev/null 2>/dev/null && rc=0
+       }
+
+       [ "$rc" != 0 ] && wireless_setup_failed INTERFACE_CREATION_FAILED
+       return $rc
+}
+
 mac80211_prepare_vif() {
        json_select config
 
@@ -437,7 +465,7 @@ mac80211_prepare_vif() {
        # It is far easier to delete and create the desired interface
        case "$mode" in
                adhoc)
-                       iw phy "$phy" interface add "$ifname" type adhoc
+                       mac80211_iw_interface_add "$phy" "$ifname" adhoc || return
                ;;
                ap)
                        # Hostapd will handle recreating the interface and
@@ -451,21 +479,21 @@ mac80211_prepare_vif() {
                        mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return
 
                        [ -n "$hostapd_ctrl" ] || {
-                               iw phy "$phy" interface add "$ifname" type __ap
+                               mac80211_iw_interface_add "$phy" "$ifname" __ap || return
                                hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}"
                        }
                ;;
                mesh)
-                       iw phy "$phy" interface add "$ifname" type mp
+                       mac80211_iw_interface_add "$phy" "$ifname" mp || return
                ;;
                monitor)
-                       iw phy "$phy" interface add "$ifname" type monitor
+                       mac80211_iw_interface_add "$phy" "$ifname" monitor || return
                ;;
                sta)
                        local wdsflag=
                        staidx="$(($staidx + 1))"
                        [ "$wds" -gt 0 ] && wdsflag="4addr on"
-                       iw phy "$phy" interface add "$ifname" type managed $wdsflag
+                       mac80211_iw_interface_add "$phy" "$ifname" managed "$wdsflag" || return
                        [ "$powersave" -gt 0 ] && powersave="on" || powersave="off"
                        iw "$ifname" set power_save "$powersave"
                ;;
@@ -490,10 +518,20 @@ mac80211_prepare_vif() {
 
 mac80211_setup_supplicant() {
        wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1
-       wpa_supplicant_add_network "$ifname"
+       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}
 }
 
+mac80211_setup_supplicant_noctl() {
+       wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1
+       wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan"
+       wpa_supplicant_run "$ifname"
+}
+
 mac80211_setup_adhoc_htmode() {
        case "$htmode" in
                VHT20|HT20) ibss_htmode=HT20;;
@@ -572,6 +610,51 @@ mac80211_setup_adhoc() {
                ${keyspec:+keys $keyspec}
 }
 
+mac80211_setup_mesh() {
+       json_get_vars ssid mesh_id mcast_rate
+
+       mcval=
+       [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
+       [ -n "$mesh_id" ] && ssid="$mesh_id"
+
+       case "$htmode" in
+               VHT20|HT20) mesh_htmode=HT20;;
+               HT40*|VHT40)
+                       case "$hwmode" in
+                               a)
+                                       case "$(( ($channel / 4) % 2 ))" in
+                                               1) mesh_htmode="HT40+" ;;
+                                               0) mesh_htmode="HT40-";;
+                                       esac
+                               ;;
+                               *)
+                                       case "$htmode" in
+                                               HT40+) mesh_htmode="HT40+";;
+                                               HT40-) mesh_htmode="HT40-";;
+                                               *)
+                                                       if [ "$channel" -lt 7 ]; then
+                                                               mesh_htmode="HT40+"
+                                                       else
+                                                               mesh_htmode="HT40-"
+                                                       fi
+                                               ;;
+                                       esac
+                               ;;
+                       esac
+               ;;
+               VHT80)
+                       mesh_htmode="80Mhz"
+               ;;
+               VHT160)
+                       mesh_htmode="160Mhz"
+               ;;
+               *) mesh_htmode="NOHT" ;;
+       esac
+       iw dev "$ifname" mesh join "$ssid" freq $freq $mesh_htmode \
+               ${mcval:+mcast-rate $mcval} \
+               beacon-interval $beacon_int
+}
+
 mac80211_setup_vif() {
        local name="$1"
        local failed
@@ -595,62 +678,13 @@ mac80211_setup_vif() {
 
        case "$mode" in
                mesh)
-                       # authsae or wpa_supplicant
-                       json_get_vars key
-                       if [ -n "$key" ]; then
-                               if [ -e "/lib/wifi/authsae.sh" ]; then
-                                       . /lib/wifi/authsae.sh
-                                       authsae_start_interface || failed=1
-                               else
-                                       wireless_vif_parse_encryption
-                                       mac80211_setup_supplicant || failed=1
-                               fi
+                       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
                        else
-                               json_get_vars mesh_id mcast_rate
-
-                               mcval=
-                               [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
-
-                               case "$htmode" in
-                                       VHT20|HT20) mesh_htmode=HT20;;
-                                       HT40*|VHT40)
-                                               case "$hwmode" in
-                                                       a)
-                                                               case "$(( ($channel / 4) % 2 ))" in
-                                                                       1) mesh_htmode="HT40+" ;;
-                                                                       0) mesh_htmode="HT40-";;
-                                                               esac
-                                                       ;;
-                                                       *)
-                                                               case "$htmode" in
-                                                                       HT40+) mesh_htmode="HT40+";;
-                                                                       HT40-) mesh_htmode="HT40-";;
-                                                                       *)
-                                                                               if [ "$channel" -lt 7 ]; then
-                                                                                       mesh_htmode="HT40+"
-                                                                               else
-                                                                                       mesh_htmode="HT40-"
-                                                                               fi
-                                                                       ;;
-                                                               esac
-                                                       ;;
-                                               esac
-                                       ;;
-                                       VHT80)
-                                               mesh_htmode="80Mhz"
-                                       ;;
-                                       VHT160)
-                                               mesh_htmode="160Mhz"
-                                       ;;
-                                       *) mesh_htmode="NOHT" ;;
-                               esac
-
-                               freq="$(get_freq "$phy" "$channel")"
-                               iw dev "$ifname" mesh join "$mesh_id" freq $freq $mesh_htmode \
-                                       ${mcval:+mcast-rate $mcval} \
-                                       beacon-interval $beacon_int
+                               mac80211_setup_mesh
                        fi
-
                        for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do
                                json_get_var mp_val "$var"
                                [ -n "$mp_val" ] && iw dev "$ifname" set mesh_param "$var" "$mp_val"
@@ -660,7 +694,8 @@ mac80211_setup_vif() {
                        wireless_vif_parse_encryption
                        mac80211_setup_adhoc_htmode
                        if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then
-                               mac80211_setup_supplicant || failed=1
+                               freq="$(get_freq "$phy" "$channel")"
+                               mac80211_setup_supplicant_noctl || failed=1
                        else
                                mac80211_setup_adhoc
                        fi
@@ -680,6 +715,13 @@ get_freq() {
        iw "$phy" info | grep -E -m1 "(\* ${chan:-....} MHz${chan:+|\\[$chan\\]})" | grep MHz | awk '{print $2}'
 }
 
+chan_is_dfs() {
+       local phy="$1"
+       local chan="$2"
+       iw "$phy" info | grep -E -m1 "(\* ${chan:-....} MHz${chan:+|\\[$chan\\]})" | grep -q "MHz.*radar detection"
+       return $!
+}
+
 mac80211_interface_cleanup() {
        local phy="$1"