mac80211: restricted automatic channel selection
[openwrt.git] / package / kernel / mac80211 / files / lib / netifd / wireless / mac80211.sh
index e6241de..43c01d3 100644 (file)
@@ -21,8 +21,9 @@ drv_mac80211_init_device_config() {
        config_add_string hwmode
        config_add_int beacon_int chanbw frag rts
        config_add_int rxantenna txantenna antenna_gain txpower distance
-       config_add_boolean noscan
+       config_add_boolean noscan ht_coex
        config_add_array ht_capab
+       config_add_array channels
        config_add_boolean \
                rxldpc \
                short_gi_80 \
@@ -42,6 +43,7 @@ drv_mac80211_init_device_config() {
                greenfield \
                short_gi_20 \
                short_gi_40 \
+               max_amsdu \
                dsss_cck_40
 }
 
@@ -54,6 +56,7 @@ drv_mac80211_init_iface_config() {
        config_add_int maxassoc
        config_add_int max_listen_int
        config_add_int dtim_period
+       config_add_int start_disabled
 
        # mesh
        config_add_string mesh_id
@@ -87,8 +90,9 @@ mac80211_hostapd_setup_base() {
        json_select config
 
        [ "$auto_channel" -gt 0 ] && channel=acs_survey
+       [ "$auto_channel" -gt 0 ] && json_get_values channel_list channels
 
-       json_get_vars noscan htmode
+       json_get_vars noscan ht_coex
        json_get_values ht_capab_list ht_capab
 
        ieee80211n=1
@@ -125,6 +129,9 @@ mac80211_hostapd_setup_base() {
        [ -n "$ieee80211n" ] && {
                append base_cfg "ieee80211n=1" "$N"
 
+               set_default ht_coex 0
+               append base_cfg "ht_coex=$ht_coex" "$N"
+
                json_get_vars \
                        ldpc:1 \
                        greenfield:0 \
@@ -132,6 +139,7 @@ mac80211_hostapd_setup_base() {
                        short_gi_40:1 \
                        tx_stbc:1 \
                        rx_stbc:3 \
+                       max_amsdu:1 \
                        dsss_cck_40:1
 
                ht_cap_mask=0
@@ -152,6 +160,7 @@ mac80211_hostapd_setup_base() {
                        RX-STBC1:0x300:0x100:1 \
                        RX-STBC12:0x300:0x200:1 \
                        RX-STBC123:0x300:0x300:1 \
+                       MAX-AMSDU-7935:0x800::$max_amsdu \
                        DSSS_CCK-40:0x1000::$dsss_cck_40
 
                ht_capab="$ht_capab$ht_capab_flags"
@@ -294,6 +303,7 @@ mac80211_hostapd_setup_base() {
        hostapd_prepare_device_config "$hostapd_conf_file" nl80211
        cat >> "$hostapd_conf_file" <<EOF
 ${channel:+channel=$channel}
+${channel_list:+chanlist=$channel_list}
 ${noscan:+noscan=$noscan}
 $base_cfg
 
@@ -311,12 +321,13 @@ mac80211_hostapd_setup_bss() {
        append hostapd_cfg "$type=$ifname" "$N"
 
        hostapd_set_bss_options hostapd_cfg "$vif" || return 1
-       json_get_vars wds dtim_period max_listen_int
+       json_get_vars wds dtim_period max_listen_int start_disabled
 
        set_default wds 0
+       set_default start_disabled 0
 
        [ "$wds" -gt 0 ] && append hostapd_cfg "wds_sta=1" "$N"
-       [ "$staidx" -gt 0 ] && append hostapd_cfg "start_disabled=1" "$N"
+       [ "$staidx" -gt 0 -o "$start_disabled" -eq 1 ] && append hostapd_cfg "start_disabled=1" "$N"
 
        cat >> /var/run/hostapd-$phy.conf <<EOF
 $hostapd_cfg
@@ -326,6 +337,13 @@ ${max_listen_int:+max_listen_interval=$max_listen_int}
 EOF
 }
 
+mac80211_get_addr() {
+       local phy="$1"
+       local idx="$(($2 + 1))"
+
+       head -n $(($macidx + 1)) /sys/class/ieee80211/${phy}/addresses | tail -n1
+}
+
 mac80211_generate_mac() {
        local phy="$1"
        local id="${macidx:-0}"
@@ -333,7 +351,18 @@ mac80211_generate_mac() {
        local ref="$(cat /sys/class/ieee80211/${phy}/macaddress)"
        local mask="$(cat /sys/class/ieee80211/${phy}/address_mask)"
 
-       [ "$mask" = "00:00:00:00:00:00" ] && mask="ff:ff:ff:ff:ff:ff";
+       [ "$mask" = "00:00:00:00:00:00" ] && {
+               mask="ff:ff:ff:ff:ff:ff";
+
+               [ "$(wc -l < /sys/class/ieee80211/${phy}/addresses)" -gt 1 ] && {
+                       addr="$(mac80211_get_addr "$phy" "$id")"
+                       [ -n "$addr" ] && {
+                               echo "$addr"
+                               return
+                       }
+               }
+       }
+
        local oIFS="$IFS"; IFS=":"; set -- $mask; IFS="$oIFS"
 
        local mask1=$1
@@ -424,17 +453,12 @@ mac80211_prepare_vif() {
                        mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return
 
                        [ -n "$hostapd_ctrl" ] || {
-                               iw phy "$phy" interface add "$ifname" type managed
+                               iw phy "$phy" interface add "$ifname" type __ap
                                hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}"
                        }
                ;;
                mesh)
-                       json_get_vars key mesh_id
-                       if [ -n "$key" ]; then
-                               iw phy "$phy" interface add "$ifname" type mp
-                       else
-                               iw phy "$phy" interface add "$ifname" type mp mesh_id "$mesh_id"
-                       fi
+                       iw phy "$phy" interface add "$ifname" type mp
                ;;
                monitor)
                        iw phy "$phy" interface add "$ifname" type monitor
@@ -460,7 +484,7 @@ mac80211_prepare_vif() {
                # All interfaces must have unique mac addresses
                # which can either be explicitly set in the device
                # section, or automatically generated
-               ifconfig "$ifname" hw ether "$macaddr"
+               ip link set dev "$ifname" address "$macaddr"
        fi
 
        json_select ..
@@ -472,11 +496,43 @@ mac80211_setup_supplicant() {
        wpa_supplicant_run "$ifname" ${hostapd_ctrl:+-H $hostapd_ctrl}
 }
 
+mac80211_setup_adhoc_htmode() {
+       case "$htmode" in
+               VHT20|HT20) ibss_htmode=HT20;;
+               HT40*|VHT40|VHT80|VHT160)
+                       case "$hwmode" in
+                               a)
+                                       case "$(( ($channel / 4) % 2 ))" in
+                                               1) ibss_htmode="HT40+" ;;
+                                               0) ibss_htmode="HT40-";;
+                                       esac
+                               ;;
+                               *)
+                                       case "$htmode" in
+                                               HT40+) ibss_htmode="HT40+";;
+                                               HT40-) ibss_htmode="HT40-";;
+                                               *)
+                                                       if [ "$channel" -lt 7 ]; then
+                                                               ibss_htmode="HT40+"
+                                                       else
+                                                               ibss_htmode="HT40-"
+                                                       fi
+                                               ;;
+                                       esac
+                               ;;
+                       esac
+                       [ "$auto_channel" -gt 0 ] && ibss_htmode="HT40+"
+               ;;
+               *) ibss_htmode="" ;;
+       esac
+
+}
+
 mac80211_setup_adhoc() {
        json_get_vars bssid ssid key mcast_rate
 
        keyspec=
-       [ "$auth_type" == "wep" ] && {
+       [ "$auth_type" = "wep" ] && {
                set_default key 1
                case "$key" in
                        [1234])
@@ -499,13 +555,13 @@ mac80211_setup_adhoc() {
 
        brstr=
        for br in $basic_rate_list; do
-               hostapd_add_rate brstr "$br"
+               wpa_supplicant_add_rate brstr "$br"
        done
 
        mcval=
-       [ -n "$mcast_rate" ] && hostapd_add_rate mcval "$mcast_rate"
+       [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
 
-       iw dev "$ifname" ibss join "$ssid" $freq $htmode fixed-freq $bssid \
+       iw dev "$ifname" ibss join "$ssid" $freq $ibss_htmode fixed-freq $bssid \
                ${beacon_int:+beacon-interval $beacon_int} \
                ${brstr:+basic-rates $brstr} \
                ${mcval:+mcast-rate $mcval} \
@@ -524,7 +580,7 @@ mac80211_setup_vif() {
        json_get_vars mode
        json_get_var vif_txpower txpower
 
-       ifconfig "$ifname" up || {
+       ip link set dev "$ifname" up || {
                wireless_setup_vif_failed IFUP_ERROR
                json_select ..
                return
@@ -535,26 +591,33 @@ mac80211_setup_vif() {
 
        case "$mode" in
                mesh)
-                       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"
-                       done
-
-                       # authsae
+                       # 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_setup_vif_failed AUTHSAE_NOT_INSTALLED
-                                       json_select ..
-                                       return
+                                       wireless_vif_parse_encryption
+                                       mac80211_setup_supplicant || failed=1
                                fi
+                       else
+                               json_get_vars mesh_id mcast_rate
+
+                               mcval=
+                               [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
+
+                               iw dev "$ifname" mesh join "$mesh_id" ${mcval:+mcast-rate $mcval}
                        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"
+                       done
                ;;
                adhoc)
                        wireless_vif_parse_encryption
+                       mac80211_setup_adhoc_htmode
                        if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then
                                mac80211_setup_supplicant || failed=1
                        else
@@ -580,7 +643,7 @@ mac80211_interface_cleanup() {
        local phy="$1"
 
        for wdev in $(list_phy_interfaces "$phy"); do
-               ifconfig "$wdev" down 2>/dev/null
+               ip link set dev "$wdev" down 2>/dev/null
                iw dev "$wdev" del
        done
 }
@@ -596,7 +659,7 @@ drv_mac80211_setup() {
                country chanbw distance \
                txpower antenna_gain \
                rxantenna txantenna \
-               frag rts beacon_int
+               frag rts beacon_int htmode
        json_get_values basic_rate_list basic_rate
        json_select ..