.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * mac80211 configuration hooks for cfg80211 |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> |
---|
5 | 6 | * Copyright 2013-2015 Intel Mobile Communications GmbH |
---|
6 | 7 | * Copyright (C) 2015-2017 Intel Deutschland GmbH |
---|
7 | | - * Copyright (C) 2018 Intel Corporation |
---|
8 | | - * |
---|
9 | | - * This file is GPLv2 as found in COPYING. |
---|
| 8 | + * Copyright (C) 2018-2020 Intel Corporation |
---|
10 | 9 | */ |
---|
11 | 10 | |
---|
12 | 11 | #include <linux/ieee80211.h> |
---|
.. | .. |
---|
15 | 14 | #include <linux/slab.h> |
---|
16 | 15 | #include <net/net_namespace.h> |
---|
17 | 16 | #include <linux/rcupdate.h> |
---|
| 17 | +#include <linux/fips.h> |
---|
18 | 18 | #include <linux/if_ether.h> |
---|
19 | 19 | #include <net/cfg80211.h> |
---|
20 | 20 | #include "ieee80211_i.h" |
---|
.. | .. |
---|
152 | 152 | struct vif_params *params) |
---|
153 | 153 | { |
---|
154 | 154 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
---|
| 155 | + struct ieee80211_local *local = sdata->local; |
---|
| 156 | + struct sta_info *sta; |
---|
155 | 157 | int ret; |
---|
156 | 158 | |
---|
157 | 159 | ret = ieee80211_if_change_type(sdata, type); |
---|
158 | 160 | if (ret) |
---|
159 | 161 | return ret; |
---|
160 | 162 | |
---|
161 | | - if (type == NL80211_IFTYPE_AP_VLAN && |
---|
162 | | - params && params->use_4addr == 0) { |
---|
| 163 | + if (type == NL80211_IFTYPE_AP_VLAN && params->use_4addr == 0) { |
---|
163 | 164 | RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); |
---|
164 | 165 | ieee80211_check_fast_rx_iface(sdata); |
---|
165 | | - } else if (type == NL80211_IFTYPE_STATION && |
---|
166 | | - params && params->use_4addr >= 0) { |
---|
| 166 | + } else if (type == NL80211_IFTYPE_STATION && params->use_4addr >= 0) { |
---|
| 167 | + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
---|
| 168 | + |
---|
| 169 | + if (params->use_4addr == ifmgd->use_4addr) |
---|
| 170 | + return 0; |
---|
| 171 | + |
---|
167 | 172 | sdata->u.mgd.use_4addr = params->use_4addr; |
---|
| 173 | + if (!ifmgd->associated) |
---|
| 174 | + return 0; |
---|
| 175 | + |
---|
| 176 | + mutex_lock(&local->sta_mtx); |
---|
| 177 | + sta = sta_info_get(sdata, ifmgd->bssid); |
---|
| 178 | + if (sta) |
---|
| 179 | + drv_sta_set_4addr(local, sdata, &sta->sta, |
---|
| 180 | + params->use_4addr); |
---|
| 181 | + mutex_unlock(&local->sta_mtx); |
---|
| 182 | + |
---|
| 183 | + if (params->use_4addr) |
---|
| 184 | + ieee80211_send_4addr_nullfunc(local, sdata); |
---|
168 | 185 | } |
---|
169 | 186 | |
---|
170 | 187 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { |
---|
.. | .. |
---|
353 | 370 | return 0; |
---|
354 | 371 | } |
---|
355 | 372 | |
---|
| 373 | +static int ieee80211_set_tx(struct ieee80211_sub_if_data *sdata, |
---|
| 374 | + const u8 *mac_addr, u8 key_idx) |
---|
| 375 | +{ |
---|
| 376 | + struct ieee80211_local *local = sdata->local; |
---|
| 377 | + struct ieee80211_key *key; |
---|
| 378 | + struct sta_info *sta; |
---|
| 379 | + int ret = -EINVAL; |
---|
| 380 | + |
---|
| 381 | + if (!wiphy_ext_feature_isset(local->hw.wiphy, |
---|
| 382 | + NL80211_EXT_FEATURE_EXT_KEY_ID)) |
---|
| 383 | + return -EINVAL; |
---|
| 384 | + |
---|
| 385 | + sta = sta_info_get_bss(sdata, mac_addr); |
---|
| 386 | + |
---|
| 387 | + if (!sta) |
---|
| 388 | + return -EINVAL; |
---|
| 389 | + |
---|
| 390 | + if (sta->ptk_idx == key_idx) |
---|
| 391 | + return 0; |
---|
| 392 | + |
---|
| 393 | + mutex_lock(&local->key_mtx); |
---|
| 394 | + key = key_mtx_dereference(local, sta->ptk[key_idx]); |
---|
| 395 | + |
---|
| 396 | + if (key && key->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX) |
---|
| 397 | + ret = ieee80211_set_tx_key(key); |
---|
| 398 | + |
---|
| 399 | + mutex_unlock(&local->key_mtx); |
---|
| 400 | + return ret; |
---|
| 401 | +} |
---|
| 402 | + |
---|
356 | 403 | static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, |
---|
357 | 404 | u8 key_idx, bool pairwise, const u8 *mac_addr, |
---|
358 | 405 | struct key_params *params) |
---|
.. | .. |
---|
367 | 414 | if (!ieee80211_sdata_running(sdata)) |
---|
368 | 415 | return -ENETDOWN; |
---|
369 | 416 | |
---|
| 417 | + if (pairwise && params->mode == NL80211_KEY_SET_TX) |
---|
| 418 | + return ieee80211_set_tx(sdata, mac_addr, key_idx); |
---|
| 419 | + |
---|
370 | 420 | /* reject WEP and TKIP keys if WEP failed to initialize */ |
---|
371 | 421 | switch (params->cipher) { |
---|
372 | 422 | case WLAN_CIPHER_SUITE_WEP40: |
---|
373 | 423 | case WLAN_CIPHER_SUITE_TKIP: |
---|
374 | 424 | case WLAN_CIPHER_SUITE_WEP104: |
---|
375 | | - if (IS_ERR(local->wep_tx_tfm)) |
---|
| 425 | + if (WARN_ON_ONCE(fips_enabled)) |
---|
376 | 426 | return -EINVAL; |
---|
377 | | - break; |
---|
378 | 427 | case WLAN_CIPHER_SUITE_CCMP: |
---|
379 | 428 | case WLAN_CIPHER_SUITE_CCMP_256: |
---|
380 | 429 | case WLAN_CIPHER_SUITE_AES_CMAC: |
---|
.. | .. |
---|
397 | 446 | |
---|
398 | 447 | if (pairwise) |
---|
399 | 448 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; |
---|
| 449 | + |
---|
| 450 | + if (params->mode == NL80211_KEY_NO_TX) |
---|
| 451 | + key->conf.flags |= IEEE80211_KEY_FLAG_NO_AUTO_TX; |
---|
400 | 452 | |
---|
401 | 453 | mutex_lock(&local->sta_mtx); |
---|
402 | 454 | |
---|
.. | .. |
---|
534 | 586 | if (pairwise && key_idx < NUM_DEFAULT_KEYS) |
---|
535 | 587 | key = rcu_dereference(sta->ptk[key_idx]); |
---|
536 | 588 | else if (!pairwise && |
---|
537 | | - key_idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) |
---|
| 589 | + key_idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS + |
---|
| 590 | + NUM_DEFAULT_BEACON_KEYS) |
---|
538 | 591 | key = rcu_dereference(sta->gtk[key_idx]); |
---|
539 | 592 | } else |
---|
540 | 593 | key = rcu_dereference(sdata->keys[key_idx]); |
---|
.. | .. |
---|
574 | 627 | case WLAN_CIPHER_SUITE_BIP_CMAC_256: |
---|
575 | 628 | BUILD_BUG_ON(offsetof(typeof(kseq), ccmp) != |
---|
576 | 629 | offsetof(typeof(kseq), aes_cmac)); |
---|
577 | | - /* fall through */ |
---|
| 630 | + fallthrough; |
---|
578 | 631 | case WLAN_CIPHER_SUITE_BIP_GMAC_128: |
---|
579 | 632 | case WLAN_CIPHER_SUITE_BIP_GMAC_256: |
---|
580 | 633 | BUILD_BUG_ON(offsetof(typeof(kseq), ccmp) != |
---|
581 | 634 | offsetof(typeof(kseq), aes_gmac)); |
---|
582 | | - /* fall through */ |
---|
| 635 | + fallthrough; |
---|
583 | 636 | case WLAN_CIPHER_SUITE_GCMP: |
---|
584 | 637 | case WLAN_CIPHER_SUITE_GCMP_256: |
---|
585 | 638 | BUILD_BUG_ON(offsetof(typeof(kseq), ccmp) != |
---|
.. | .. |
---|
642 | 695 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
---|
643 | 696 | |
---|
644 | 697 | ieee80211_set_default_mgmt_key(sdata, key_idx); |
---|
| 698 | + |
---|
| 699 | + return 0; |
---|
| 700 | +} |
---|
| 701 | + |
---|
| 702 | +static int ieee80211_config_default_beacon_key(struct wiphy *wiphy, |
---|
| 703 | + struct net_device *dev, |
---|
| 704 | + u8 key_idx) |
---|
| 705 | +{ |
---|
| 706 | + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
---|
| 707 | + |
---|
| 708 | + ieee80211_set_default_beacon_key(sdata, key_idx); |
---|
645 | 709 | |
---|
646 | 710 | return 0; |
---|
647 | 711 | } |
---|
.. | .. |
---|
782 | 846 | memcpy(new->data, resp, resp_len); |
---|
783 | 847 | |
---|
784 | 848 | if (csa) |
---|
785 | | - memcpy(new->csa_counter_offsets, csa->counter_offsets_presp, |
---|
| 849 | + memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_presp, |
---|
786 | 850 | csa->n_counter_offsets_presp * |
---|
787 | | - sizeof(new->csa_counter_offsets[0])); |
---|
| 851 | + sizeof(new->cntdwn_counter_offsets[0])); |
---|
788 | 852 | |
---|
789 | 853 | rcu_assign_pointer(sdata->u.ap.probe_resp, new); |
---|
790 | 854 | if (old) |
---|
791 | 855 | kfree_rcu(old, rcu_head); |
---|
| 856 | + |
---|
| 857 | + return 0; |
---|
| 858 | +} |
---|
| 859 | + |
---|
| 860 | +static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata, |
---|
| 861 | + struct cfg80211_fils_discovery *params) |
---|
| 862 | +{ |
---|
| 863 | + struct fils_discovery_data *new, *old = NULL; |
---|
| 864 | + struct ieee80211_fils_discovery *fd; |
---|
| 865 | + |
---|
| 866 | + if (!params->tmpl || !params->tmpl_len) |
---|
| 867 | + return -EINVAL; |
---|
| 868 | + |
---|
| 869 | + fd = &sdata->vif.bss_conf.fils_discovery; |
---|
| 870 | + fd->min_interval = params->min_interval; |
---|
| 871 | + fd->max_interval = params->max_interval; |
---|
| 872 | + |
---|
| 873 | + old = sdata_dereference(sdata->u.ap.fils_discovery, sdata); |
---|
| 874 | + new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL); |
---|
| 875 | + if (!new) |
---|
| 876 | + return -ENOMEM; |
---|
| 877 | + new->len = params->tmpl_len; |
---|
| 878 | + memcpy(new->data, params->tmpl, params->tmpl_len); |
---|
| 879 | + rcu_assign_pointer(sdata->u.ap.fils_discovery, new); |
---|
| 880 | + |
---|
| 881 | + if (old) |
---|
| 882 | + kfree_rcu(old, rcu_head); |
---|
| 883 | + |
---|
| 884 | + return 0; |
---|
| 885 | +} |
---|
| 886 | + |
---|
| 887 | +static int |
---|
| 888 | +ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata, |
---|
| 889 | + struct cfg80211_unsol_bcast_probe_resp *params) |
---|
| 890 | +{ |
---|
| 891 | + struct unsol_bcast_probe_resp_data *new, *old = NULL; |
---|
| 892 | + |
---|
| 893 | + if (!params->tmpl || !params->tmpl_len) |
---|
| 894 | + return -EINVAL; |
---|
| 895 | + |
---|
| 896 | + old = sdata_dereference(sdata->u.ap.unsol_bcast_probe_resp, sdata); |
---|
| 897 | + new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL); |
---|
| 898 | + if (!new) |
---|
| 899 | + return -ENOMEM; |
---|
| 900 | + new->len = params->tmpl_len; |
---|
| 901 | + memcpy(new->data, params->tmpl, params->tmpl_len); |
---|
| 902 | + rcu_assign_pointer(sdata->u.ap.unsol_bcast_probe_resp, new); |
---|
| 903 | + |
---|
| 904 | + if (old) |
---|
| 905 | + kfree_rcu(old, rcu_head); |
---|
| 906 | + |
---|
| 907 | + sdata->vif.bss_conf.unsol_bcast_probe_resp_interval = |
---|
| 908 | + params->interval; |
---|
| 909 | + |
---|
| 910 | + return 0; |
---|
| 911 | +} |
---|
| 912 | + |
---|
| 913 | +static int ieee80211_set_ftm_responder_params( |
---|
| 914 | + struct ieee80211_sub_if_data *sdata, |
---|
| 915 | + const u8 *lci, size_t lci_len, |
---|
| 916 | + const u8 *civicloc, size_t civicloc_len) |
---|
| 917 | +{ |
---|
| 918 | + struct ieee80211_ftm_responder_params *new, *old; |
---|
| 919 | + struct ieee80211_bss_conf *bss_conf; |
---|
| 920 | + u8 *pos; |
---|
| 921 | + int len; |
---|
| 922 | + |
---|
| 923 | + if (!lci_len && !civicloc_len) |
---|
| 924 | + return 0; |
---|
| 925 | + |
---|
| 926 | + bss_conf = &sdata->vif.bss_conf; |
---|
| 927 | + old = bss_conf->ftmr_params; |
---|
| 928 | + len = lci_len + civicloc_len; |
---|
| 929 | + |
---|
| 930 | + new = kzalloc(sizeof(*new) + len, GFP_KERNEL); |
---|
| 931 | + if (!new) |
---|
| 932 | + return -ENOMEM; |
---|
| 933 | + |
---|
| 934 | + pos = (u8 *)(new + 1); |
---|
| 935 | + if (lci_len) { |
---|
| 936 | + new->lci_len = lci_len; |
---|
| 937 | + new->lci = pos; |
---|
| 938 | + memcpy(pos, lci, lci_len); |
---|
| 939 | + pos += lci_len; |
---|
| 940 | + } |
---|
| 941 | + |
---|
| 942 | + if (civicloc_len) { |
---|
| 943 | + new->civicloc_len = civicloc_len; |
---|
| 944 | + new->civicloc = pos; |
---|
| 945 | + memcpy(pos, civicloc, civicloc_len); |
---|
| 946 | + pos += civicloc_len; |
---|
| 947 | + } |
---|
| 948 | + |
---|
| 949 | + bss_conf->ftmr_params = new; |
---|
| 950 | + kfree(old); |
---|
792 | 951 | |
---|
793 | 952 | return 0; |
---|
794 | 953 | } |
---|
.. | .. |
---|
840 | 999 | new->tail_len = new_tail_len; |
---|
841 | 1000 | |
---|
842 | 1001 | if (csa) { |
---|
843 | | - new->csa_current_counter = csa->count; |
---|
844 | | - memcpy(new->csa_counter_offsets, csa->counter_offsets_beacon, |
---|
| 1002 | + new->cntdwn_current_counter = csa->count; |
---|
| 1003 | + memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_beacon, |
---|
845 | 1004 | csa->n_counter_offsets_beacon * |
---|
846 | | - sizeof(new->csa_counter_offsets[0])); |
---|
| 1005 | + sizeof(new->cntdwn_counter_offsets[0])); |
---|
847 | 1006 | } |
---|
848 | 1007 | |
---|
849 | 1008 | /* copy in head */ |
---|
.. | .. |
---|
861 | 1020 | |
---|
862 | 1021 | err = ieee80211_set_probe_resp(sdata, params->probe_resp, |
---|
863 | 1022 | params->probe_resp_len, csa); |
---|
864 | | - if (err < 0) |
---|
| 1023 | + if (err < 0) { |
---|
| 1024 | + kfree(new); |
---|
865 | 1025 | return err; |
---|
| 1026 | + } |
---|
866 | 1027 | if (err == 0) |
---|
867 | 1028 | changed |= BSS_CHANGED_AP_PROBE_RESP; |
---|
| 1029 | + |
---|
| 1030 | + if (params->ftm_responder != -1) { |
---|
| 1031 | + sdata->vif.bss_conf.ftm_responder = params->ftm_responder; |
---|
| 1032 | + err = ieee80211_set_ftm_responder_params(sdata, |
---|
| 1033 | + params->lci, |
---|
| 1034 | + params->lci_len, |
---|
| 1035 | + params->civicloc, |
---|
| 1036 | + params->civicloc_len); |
---|
| 1037 | + |
---|
| 1038 | + if (err < 0) { |
---|
| 1039 | + kfree(new); |
---|
| 1040 | + return err; |
---|
| 1041 | + } |
---|
| 1042 | + |
---|
| 1043 | + changed |= BSS_CHANGED_FTM_RESPONDER; |
---|
| 1044 | + } |
---|
868 | 1045 | |
---|
869 | 1046 | rcu_assign_pointer(sdata->u.ap.beacon, new); |
---|
870 | 1047 | |
---|
.. | .. |
---|
886 | 1063 | BSS_CHANGED_BEACON | |
---|
887 | 1064 | BSS_CHANGED_SSID | |
---|
888 | 1065 | BSS_CHANGED_P2P_PS | |
---|
889 | | - BSS_CHANGED_TXPOWER; |
---|
890 | | - int err; |
---|
| 1066 | + BSS_CHANGED_TXPOWER | |
---|
| 1067 | + BSS_CHANGED_TWT; |
---|
| 1068 | + int i, err; |
---|
891 | 1069 | int prev_beacon_int; |
---|
892 | 1070 | |
---|
893 | 1071 | old = sdata_dereference(sdata->u.ap.beacon, sdata); |
---|
894 | 1072 | if (old) |
---|
895 | 1073 | return -EALREADY; |
---|
896 | 1074 | |
---|
897 | | - switch (params->smps_mode) { |
---|
898 | | - case NL80211_SMPS_OFF: |
---|
899 | | - sdata->smps_mode = IEEE80211_SMPS_OFF; |
---|
900 | | - break; |
---|
901 | | - case NL80211_SMPS_STATIC: |
---|
902 | | - sdata->smps_mode = IEEE80211_SMPS_STATIC; |
---|
903 | | - break; |
---|
904 | | - case NL80211_SMPS_DYNAMIC: |
---|
905 | | - sdata->smps_mode = IEEE80211_SMPS_DYNAMIC; |
---|
906 | | - break; |
---|
907 | | - default: |
---|
908 | | - return -EINVAL; |
---|
909 | | - } |
---|
910 | | - sdata->u.ap.req_smps = sdata->smps_mode; |
---|
| 1075 | + if (params->smps_mode != NL80211_SMPS_OFF) |
---|
| 1076 | + return -ENOTSUPP; |
---|
| 1077 | + |
---|
| 1078 | + sdata->smps_mode = IEEE80211_SMPS_OFF; |
---|
911 | 1079 | |
---|
912 | 1080 | sdata->needed_rx_chains = sdata->local->rx_chains; |
---|
913 | 1081 | |
---|
914 | 1082 | prev_beacon_int = sdata->vif.bss_conf.beacon_int; |
---|
915 | 1083 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; |
---|
| 1084 | + |
---|
| 1085 | + if (params->he_cap && params->he_oper) { |
---|
| 1086 | + sdata->vif.bss_conf.he_support = true; |
---|
| 1087 | + sdata->vif.bss_conf.htc_trig_based_pkt_ext = |
---|
| 1088 | + le32_get_bits(params->he_oper->he_oper_params, |
---|
| 1089 | + IEEE80211_HE_OPERATION_DFLT_PE_DURATION_MASK); |
---|
| 1090 | + sdata->vif.bss_conf.frame_time_rts_th = |
---|
| 1091 | + le32_get_bits(params->he_oper->he_oper_params, |
---|
| 1092 | + IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK); |
---|
| 1093 | + changed |= BSS_CHANGED_HE_OBSS_PD; |
---|
| 1094 | + |
---|
| 1095 | + if (params->he_bss_color.enabled) |
---|
| 1096 | + changed |= BSS_CHANGED_HE_BSS_COLOR; |
---|
| 1097 | + } |
---|
916 | 1098 | |
---|
917 | 1099 | mutex_lock(&local->mtx); |
---|
918 | 1100 | err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, |
---|
.. | .. |
---|
933 | 1115 | sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt; |
---|
934 | 1116 | sdata->control_port_over_nl80211 = |
---|
935 | 1117 | params->crypto.control_port_over_nl80211; |
---|
| 1118 | + sdata->control_port_no_preauth = |
---|
| 1119 | + params->crypto.control_port_no_preauth; |
---|
936 | 1120 | sdata->encrypt_headroom = ieee80211_cs_headroom(sdata->local, |
---|
937 | 1121 | ¶ms->crypto, |
---|
938 | 1122 | sdata->vif.type); |
---|
.. | .. |
---|
944 | 1128 | params->crypto.control_port_no_encrypt; |
---|
945 | 1129 | vlan->control_port_over_nl80211 = |
---|
946 | 1130 | params->crypto.control_port_over_nl80211; |
---|
| 1131 | + vlan->control_port_no_preauth = |
---|
| 1132 | + params->crypto.control_port_no_preauth; |
---|
947 | 1133 | vlan->encrypt_headroom = |
---|
948 | 1134 | ieee80211_cs_headroom(sdata->local, |
---|
949 | 1135 | ¶ms->crypto, |
---|
.. | .. |
---|
953 | 1139 | sdata->vif.bss_conf.dtim_period = params->dtim_period; |
---|
954 | 1140 | sdata->vif.bss_conf.enable_beacon = true; |
---|
955 | 1141 | sdata->vif.bss_conf.allow_p2p_go_ps = sdata->vif.p2p; |
---|
| 1142 | + sdata->vif.bss_conf.twt_responder = params->twt_responder; |
---|
| 1143 | + memcpy(&sdata->vif.bss_conf.he_obss_pd, ¶ms->he_obss_pd, |
---|
| 1144 | + sizeof(struct ieee80211_he_obss_pd)); |
---|
| 1145 | + memcpy(&sdata->vif.bss_conf.he_bss_color, ¶ms->he_bss_color, |
---|
| 1146 | + sizeof(struct ieee80211_he_bss_color)); |
---|
| 1147 | + sdata->vif.bss_conf.s1g = params->chandef.chan->band == |
---|
| 1148 | + NL80211_BAND_S1GHZ; |
---|
956 | 1149 | |
---|
957 | 1150 | sdata->vif.bss_conf.ssid_len = params->ssid_len; |
---|
958 | 1151 | if (params->ssid_len) |
---|
.. | .. |
---|
969 | 1162 | sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |= |
---|
970 | 1163 | IEEE80211_P2P_OPPPS_ENABLE_BIT; |
---|
971 | 1164 | |
---|
972 | | - err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL); |
---|
973 | | - if (err < 0) { |
---|
974 | | - ieee80211_vif_release_channel(sdata); |
---|
975 | | - return err; |
---|
| 1165 | + sdata->beacon_rate_set = false; |
---|
| 1166 | + if (wiphy_ext_feature_isset(local->hw.wiphy, |
---|
| 1167 | + NL80211_EXT_FEATURE_BEACON_RATE_LEGACY)) { |
---|
| 1168 | + for (i = 0; i < NUM_NL80211_BANDS; i++) { |
---|
| 1169 | + sdata->beacon_rateidx_mask[i] = |
---|
| 1170 | + params->beacon_rate.control[i].legacy; |
---|
| 1171 | + if (sdata->beacon_rateidx_mask[i]) |
---|
| 1172 | + sdata->beacon_rate_set = true; |
---|
| 1173 | + } |
---|
976 | 1174 | } |
---|
| 1175 | + |
---|
| 1176 | + if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) |
---|
| 1177 | + sdata->vif.bss_conf.beacon_tx_rate = params->beacon_rate; |
---|
| 1178 | + |
---|
| 1179 | + err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL); |
---|
| 1180 | + if (err < 0) |
---|
| 1181 | + goto error; |
---|
977 | 1182 | changed |= err; |
---|
| 1183 | + |
---|
| 1184 | + if (params->fils_discovery.max_interval) { |
---|
| 1185 | + err = ieee80211_set_fils_discovery(sdata, |
---|
| 1186 | + ¶ms->fils_discovery); |
---|
| 1187 | + if (err < 0) |
---|
| 1188 | + goto error; |
---|
| 1189 | + changed |= BSS_CHANGED_FILS_DISCOVERY; |
---|
| 1190 | + } |
---|
| 1191 | + |
---|
| 1192 | + if (params->unsol_bcast_probe_resp.interval) { |
---|
| 1193 | + err = ieee80211_set_unsol_bcast_probe_resp(sdata, |
---|
| 1194 | + ¶ms->unsol_bcast_probe_resp); |
---|
| 1195 | + if (err < 0) |
---|
| 1196 | + goto error; |
---|
| 1197 | + changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP; |
---|
| 1198 | + } |
---|
978 | 1199 | |
---|
979 | 1200 | err = drv_start_ap(sdata->local, sdata); |
---|
980 | 1201 | if (err) { |
---|
.. | .. |
---|
983 | 1204 | if (old) |
---|
984 | 1205 | kfree_rcu(old, rcu_head); |
---|
985 | 1206 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); |
---|
986 | | - ieee80211_vif_release_channel(sdata); |
---|
987 | | - return err; |
---|
| 1207 | + goto error; |
---|
988 | 1208 | } |
---|
989 | 1209 | |
---|
990 | 1210 | ieee80211_recalc_dtim(local, sdata); |
---|
.. | .. |
---|
995 | 1215 | netif_carrier_on(vlan->dev); |
---|
996 | 1216 | |
---|
997 | 1217 | return 0; |
---|
| 1218 | + |
---|
| 1219 | +error: |
---|
| 1220 | + mutex_lock(&local->mtx); |
---|
| 1221 | + ieee80211_vif_release_channel(sdata); |
---|
| 1222 | + mutex_unlock(&local->mtx); |
---|
| 1223 | + |
---|
| 1224 | + return err; |
---|
998 | 1225 | } |
---|
999 | 1226 | |
---|
1000 | 1227 | static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, |
---|
.. | .. |
---|
1031 | 1258 | struct ieee80211_local *local = sdata->local; |
---|
1032 | 1259 | struct beacon_data *old_beacon; |
---|
1033 | 1260 | struct probe_resp *old_probe_resp; |
---|
| 1261 | + struct fils_discovery_data *old_fils_discovery; |
---|
| 1262 | + struct unsol_bcast_probe_resp_data *old_unsol_bcast_probe_resp; |
---|
1034 | 1263 | struct cfg80211_chan_def chandef; |
---|
1035 | 1264 | |
---|
1036 | 1265 | sdata_assert_lock(sdata); |
---|
.. | .. |
---|
1039 | 1268 | if (!old_beacon) |
---|
1040 | 1269 | return -ENOENT; |
---|
1041 | 1270 | old_probe_resp = sdata_dereference(sdata->u.ap.probe_resp, sdata); |
---|
| 1271 | + old_fils_discovery = sdata_dereference(sdata->u.ap.fils_discovery, |
---|
| 1272 | + sdata); |
---|
| 1273 | + old_unsol_bcast_probe_resp = |
---|
| 1274 | + sdata_dereference(sdata->u.ap.unsol_bcast_probe_resp, |
---|
| 1275 | + sdata); |
---|
1042 | 1276 | |
---|
1043 | 1277 | /* abort any running channel switch */ |
---|
1044 | 1278 | mutex_lock(&local->mtx); |
---|
.. | .. |
---|
1062 | 1296 | /* remove beacon and probe response */ |
---|
1063 | 1297 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); |
---|
1064 | 1298 | RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL); |
---|
| 1299 | + RCU_INIT_POINTER(sdata->u.ap.fils_discovery, NULL); |
---|
| 1300 | + RCU_INIT_POINTER(sdata->u.ap.unsol_bcast_probe_resp, NULL); |
---|
1065 | 1301 | kfree_rcu(old_beacon, rcu_head); |
---|
1066 | 1302 | if (old_probe_resp) |
---|
1067 | 1303 | kfree_rcu(old_probe_resp, rcu_head); |
---|
1068 | | - sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF; |
---|
| 1304 | + if (old_fils_discovery) |
---|
| 1305 | + kfree_rcu(old_fils_discovery, rcu_head); |
---|
| 1306 | + if (old_unsol_bcast_probe_resp) |
---|
| 1307 | + kfree_rcu(old_unsol_bcast_probe_resp, rcu_head); |
---|
| 1308 | + |
---|
| 1309 | + kfree(sdata->vif.bss_conf.ftmr_params); |
---|
| 1310 | + sdata->vif.bss_conf.ftmr_params = NULL; |
---|
1069 | 1311 | |
---|
1070 | 1312 | __sta_info_flush(sdata, true); |
---|
1071 | 1313 | ieee80211_free_keys(sdata, true); |
---|
1072 | 1314 | |
---|
1073 | 1315 | sdata->vif.bss_conf.enable_beacon = false; |
---|
| 1316 | + sdata->beacon_rate_set = false; |
---|
1074 | 1317 | sdata->vif.bss_conf.ssid_len = 0; |
---|
1075 | 1318 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); |
---|
1076 | 1319 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
---|
.. | .. |
---|
1176 | 1419 | ieee80211_mps_sta_status_update(sta); |
---|
1177 | 1420 | changed |= ieee80211_mps_set_sta_local_pm(sta, |
---|
1178 | 1421 | sdata->u.mesh.mshcfg.power_mode); |
---|
| 1422 | + |
---|
| 1423 | + ewma_mesh_tx_rate_avg_init(&sta->mesh->tx_rate_avg); |
---|
| 1424 | + /* init at low value */ |
---|
| 1425 | + ewma_mesh_tx_rate_avg_add(&sta->mesh->tx_rate_avg, 10); |
---|
| 1426 | + |
---|
1179 | 1427 | break; |
---|
1180 | 1428 | case NL80211_PLINK_LISTEN: |
---|
1181 | 1429 | case NL80211_PLINK_BLOCKED: |
---|
.. | .. |
---|
1357 | 1605 | if (params->listen_interval >= 0) |
---|
1358 | 1606 | sta->listen_interval = params->listen_interval; |
---|
1359 | 1607 | |
---|
1360 | | - if (params->supported_rates) { |
---|
| 1608 | + if (params->sta_modify_mask & STATION_PARAM_APPLY_STA_TXPOWER) { |
---|
| 1609 | + sta->sta.txpwr.type = params->txpwr.type; |
---|
| 1610 | + if (params->txpwr.type == NL80211_TX_POWER_LIMITED) |
---|
| 1611 | + sta->sta.txpwr.power = params->txpwr.power; |
---|
| 1612 | + ret = drv_sta_set_txpwr(local, sdata, sta); |
---|
| 1613 | + if (ret) |
---|
| 1614 | + return ret; |
---|
| 1615 | + } |
---|
| 1616 | + |
---|
| 1617 | + if (params->supported_rates && params->supported_rates_len) { |
---|
1361 | 1618 | ieee80211_parse_bitrates(&sdata->vif.bss_conf.chandef, |
---|
1362 | 1619 | sband, params->supported_rates, |
---|
1363 | 1620 | params->supported_rates_len, |
---|
.. | .. |
---|
1376 | 1633 | if (params->he_capa) |
---|
1377 | 1634 | ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, |
---|
1378 | 1635 | (void *)params->he_capa, |
---|
1379 | | - params->he_capa_len, sta); |
---|
| 1636 | + params->he_capa_len, |
---|
| 1637 | + (void *)params->he_6ghz_capa, |
---|
| 1638 | + sta); |
---|
1380 | 1639 | |
---|
1381 | 1640 | if (params->opmode_notif_used) { |
---|
1382 | 1641 | /* returned value is only needed for rc update, but the |
---|
.. | .. |
---|
1391 | 1650 | |
---|
1392 | 1651 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
---|
1393 | 1652 | sta_apply_mesh_params(local, sta, params); |
---|
| 1653 | + |
---|
| 1654 | + if (params->airtime_weight) |
---|
| 1655 | + sta->airtime_weight = params->airtime_weight; |
---|
1394 | 1656 | |
---|
1395 | 1657 | /* set the STA state after all sta info from usermode has been set */ |
---|
1396 | 1658 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) || |
---|
.. | .. |
---|
1424 | 1686 | if (ether_addr_equal(mac, sdata->vif.addr)) |
---|
1425 | 1687 | return -EINVAL; |
---|
1426 | 1688 | |
---|
1427 | | - if (is_multicast_ether_addr(mac)) |
---|
| 1689 | + if (!is_valid_ether_addr(mac)) |
---|
1428 | 1690 | return -EINVAL; |
---|
1429 | 1691 | |
---|
1430 | 1692 | if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER) && |
---|
.. | .. |
---|
1545 | 1807 | |
---|
1546 | 1808 | rcu_assign_pointer(vlansdata->u.vlan.sta, sta); |
---|
1547 | 1809 | __ieee80211_check_fast_rx_iface(vlansdata); |
---|
| 1810 | + drv_sta_set_4addr(local, sta->sdata, &sta->sta, true); |
---|
1548 | 1811 | } |
---|
1549 | 1812 | |
---|
1550 | 1813 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && |
---|
.. | .. |
---|
1571 | 1834 | goto out_err; |
---|
1572 | 1835 | |
---|
1573 | 1836 | mutex_unlock(&local->sta_mtx); |
---|
1574 | | - |
---|
1575 | | - if ((sdata->vif.type == NL80211_IFTYPE_AP || |
---|
1576 | | - sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && |
---|
1577 | | - sta->known_smps_mode != sta->sdata->bss->req_smps && |
---|
1578 | | - test_sta_flag(sta, WLAN_STA_AUTHORIZED) && |
---|
1579 | | - sta_info_tx_streams(sta) != 1) { |
---|
1580 | | - ht_dbg(sta->sdata, |
---|
1581 | | - "%pM just authorized and MIMO capable - update SMPS\n", |
---|
1582 | | - sta->sta.addr); |
---|
1583 | | - ieee80211_send_smps_action(sta->sdata, |
---|
1584 | | - sta->sdata->bss->req_smps, |
---|
1585 | | - sta->sta.addr, |
---|
1586 | | - sta->sdata->vif.bss_conf.bssid); |
---|
1587 | | - } |
---|
1588 | 1837 | |
---|
1589 | 1838 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
---|
1590 | 1839 | params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { |
---|
.. | .. |
---|
1688 | 1937 | MPATH_INFO_EXPTIME | |
---|
1689 | 1938 | MPATH_INFO_DISCOVERY_TIMEOUT | |
---|
1690 | 1939 | MPATH_INFO_DISCOVERY_RETRIES | |
---|
1691 | | - MPATH_INFO_FLAGS; |
---|
| 1940 | + MPATH_INFO_FLAGS | |
---|
| 1941 | + MPATH_INFO_HOP_COUNT | |
---|
| 1942 | + MPATH_INFO_PATH_CHANGE; |
---|
1692 | 1943 | |
---|
1693 | 1944 | pinfo->frame_qlen = mpath->frame_queue.qlen; |
---|
1694 | 1945 | pinfo->sn = mpath->sn; |
---|
.. | .. |
---|
1708 | 1959 | pinfo->flags |= NL80211_MPATH_FLAG_FIXED; |
---|
1709 | 1960 | if (mpath->flags & MESH_PATH_RESOLVED) |
---|
1710 | 1961 | pinfo->flags |= NL80211_MPATH_FLAG_RESOLVED; |
---|
| 1962 | + pinfo->hop_count = mpath->hop_count; |
---|
| 1963 | + pinfo->path_change_count = mpath->path_change_count; |
---|
1711 | 1964 | } |
---|
1712 | 1965 | |
---|
1713 | 1966 | static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, |
---|
.. | .. |
---|
1823 | 2076 | const struct mesh_setup *setup) |
---|
1824 | 2077 | { |
---|
1825 | 2078 | u8 *new_ie; |
---|
1826 | | - const u8 *old_ie; |
---|
1827 | 2079 | struct ieee80211_sub_if_data *sdata = container_of(ifmsh, |
---|
1828 | 2080 | struct ieee80211_sub_if_data, u.mesh); |
---|
| 2081 | + int i; |
---|
1829 | 2082 | |
---|
1830 | 2083 | /* allocate information elements */ |
---|
1831 | 2084 | new_ie = NULL; |
---|
1832 | | - old_ie = ifmsh->ie; |
---|
1833 | 2085 | |
---|
1834 | 2086 | if (setup->ie_len) { |
---|
1835 | 2087 | new_ie = kmemdup(setup->ie, setup->ie_len, |
---|
.. | .. |
---|
1839 | 2091 | } |
---|
1840 | 2092 | ifmsh->ie_len = setup->ie_len; |
---|
1841 | 2093 | ifmsh->ie = new_ie; |
---|
1842 | | - kfree(old_ie); |
---|
1843 | 2094 | |
---|
1844 | 2095 | /* now copy the rest of the setup parameters */ |
---|
1845 | 2096 | ifmsh->mesh_id_len = setup->mesh_id_len; |
---|
.. | .. |
---|
1863 | 2114 | |
---|
1864 | 2115 | sdata->vif.bss_conf.beacon_int = setup->beacon_interval; |
---|
1865 | 2116 | sdata->vif.bss_conf.dtim_period = setup->dtim_period; |
---|
| 2117 | + |
---|
| 2118 | + sdata->beacon_rate_set = false; |
---|
| 2119 | + if (wiphy_ext_feature_isset(sdata->local->hw.wiphy, |
---|
| 2120 | + NL80211_EXT_FEATURE_BEACON_RATE_LEGACY)) { |
---|
| 2121 | + for (i = 0; i < NUM_NL80211_BANDS; i++) { |
---|
| 2122 | + sdata->beacon_rateidx_mask[i] = |
---|
| 2123 | + setup->beacon_rate.control[i].legacy; |
---|
| 2124 | + if (sdata->beacon_rateidx_mask[i]) |
---|
| 2125 | + sdata->beacon_rate_set = true; |
---|
| 2126 | + } |
---|
| 2127 | + } |
---|
1866 | 2128 | |
---|
1867 | 2129 | return 0; |
---|
1868 | 2130 | } |
---|
.. | .. |
---|
1974 | 2236 | nconf->dot11MeshAwakeWindowDuration; |
---|
1975 | 2237 | if (_chg_mesh_attr(NL80211_MESHCONF_PLINK_TIMEOUT, mask)) |
---|
1976 | 2238 | conf->plink_timeout = nconf->plink_timeout; |
---|
| 2239 | + if (_chg_mesh_attr(NL80211_MESHCONF_CONNECTED_TO_GATE, mask)) |
---|
| 2240 | + conf->dot11MeshConnectedToMeshGate = |
---|
| 2241 | + nconf->dot11MeshConnectedToMeshGate; |
---|
| 2242 | + if (_chg_mesh_attr(NL80211_MESHCONF_NOLEARN, mask)) |
---|
| 2243 | + conf->dot11MeshNolearn = nconf->dot11MeshNolearn; |
---|
| 2244 | + if (_chg_mesh_attr(NL80211_MESHCONF_CONNECTED_TO_AS, mask)) |
---|
| 2245 | + conf->dot11MeshConnectedToAuthServer = |
---|
| 2246 | + nconf->dot11MeshConnectedToAuthServer; |
---|
1977 | 2247 | ieee80211_mbss_info_change_notify(sdata, BSS_CHANGED_BEACON); |
---|
1978 | 2248 | return 0; |
---|
1979 | 2249 | } |
---|
.. | .. |
---|
2047 | 2317 | } |
---|
2048 | 2318 | |
---|
2049 | 2319 | if (!sdata->vif.bss_conf.use_short_slot && |
---|
2050 | | - sband->band == NL80211_BAND_5GHZ) { |
---|
| 2320 | + (sband->band == NL80211_BAND_5GHZ || |
---|
| 2321 | + sband->band == NL80211_BAND_6GHZ)) { |
---|
2051 | 2322 | sdata->vif.bss_conf.use_short_slot = true; |
---|
2052 | 2323 | changed |= BSS_CHANGED_ERP_SLOT; |
---|
2053 | 2324 | } |
---|
.. | .. |
---|
2184 | 2455 | * for now fall through to allow scanning only when |
---|
2185 | 2456 | * beaconing hasn't been configured yet |
---|
2186 | 2457 | */ |
---|
2187 | | - /* fall through */ |
---|
| 2458 | + fallthrough; |
---|
2188 | 2459 | case NL80211_IFTYPE_AP: |
---|
2189 | 2460 | /* |
---|
2190 | 2461 | * If the scan has been forced (and the driver supports |
---|
.. | .. |
---|
2511 | 2782 | } |
---|
2512 | 2783 | #endif |
---|
2513 | 2784 | |
---|
2514 | | -int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata, |
---|
2515 | | - enum ieee80211_smps_mode smps_mode) |
---|
2516 | | -{ |
---|
2517 | | - struct sta_info *sta; |
---|
2518 | | - enum ieee80211_smps_mode old_req; |
---|
2519 | | - |
---|
2520 | | - if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP)) |
---|
2521 | | - return -EINVAL; |
---|
2522 | | - |
---|
2523 | | - if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) |
---|
2524 | | - return 0; |
---|
2525 | | - |
---|
2526 | | - old_req = sdata->u.ap.req_smps; |
---|
2527 | | - sdata->u.ap.req_smps = smps_mode; |
---|
2528 | | - |
---|
2529 | | - /* AUTOMATIC doesn't mean much for AP - don't allow it */ |
---|
2530 | | - if (old_req == smps_mode || |
---|
2531 | | - smps_mode == IEEE80211_SMPS_AUTOMATIC) |
---|
2532 | | - return 0; |
---|
2533 | | - |
---|
2534 | | - ht_dbg(sdata, |
---|
2535 | | - "SMPS %d requested in AP mode, sending Action frame to %d stations\n", |
---|
2536 | | - smps_mode, atomic_read(&sdata->u.ap.num_mcast_sta)); |
---|
2537 | | - |
---|
2538 | | - mutex_lock(&sdata->local->sta_mtx); |
---|
2539 | | - list_for_each_entry(sta, &sdata->local->sta_list, list) { |
---|
2540 | | - /* |
---|
2541 | | - * Only stations associated to our AP and |
---|
2542 | | - * associated VLANs |
---|
2543 | | - */ |
---|
2544 | | - if (sta->sdata->bss != &sdata->u.ap) |
---|
2545 | | - continue; |
---|
2546 | | - |
---|
2547 | | - /* This station doesn't support MIMO - skip it */ |
---|
2548 | | - if (sta_info_tx_streams(sta) == 1) |
---|
2549 | | - continue; |
---|
2550 | | - |
---|
2551 | | - /* |
---|
2552 | | - * Don't wake up a STA just to send the action frame |
---|
2553 | | - * unless we are getting more restrictive. |
---|
2554 | | - */ |
---|
2555 | | - if (test_sta_flag(sta, WLAN_STA_PS_STA) && |
---|
2556 | | - !ieee80211_smps_is_restrictive(sta->known_smps_mode, |
---|
2557 | | - smps_mode)) { |
---|
2558 | | - ht_dbg(sdata, "Won't send SMPS to sleeping STA %pM\n", |
---|
2559 | | - sta->sta.addr); |
---|
2560 | | - continue; |
---|
2561 | | - } |
---|
2562 | | - |
---|
2563 | | - /* |
---|
2564 | | - * If the STA is not authorized, wait until it gets |
---|
2565 | | - * authorized and the action frame will be sent then. |
---|
2566 | | - */ |
---|
2567 | | - if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED)) |
---|
2568 | | - continue; |
---|
2569 | | - |
---|
2570 | | - ht_dbg(sdata, "Sending SMPS to %pM\n", sta->sta.addr); |
---|
2571 | | - ieee80211_send_smps_action(sdata, smps_mode, sta->sta.addr, |
---|
2572 | | - sdata->vif.bss_conf.bssid); |
---|
2573 | | - } |
---|
2574 | | - mutex_unlock(&sdata->local->sta_mtx); |
---|
2575 | | - |
---|
2576 | | - sdata->smps_mode = smps_mode; |
---|
2577 | | - ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps); |
---|
2578 | | - |
---|
2579 | | - return 0; |
---|
2580 | | -} |
---|
2581 | | - |
---|
2582 | 2785 | int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata, |
---|
2583 | 2786 | enum ieee80211_smps_mode smps_mode) |
---|
2584 | 2787 | { |
---|
.. | .. |
---|
2860 | 3063 | |
---|
2861 | 3064 | len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len + |
---|
2862 | 3065 | beacon->proberesp_ies_len + beacon->assocresp_ies_len + |
---|
2863 | | - beacon->probe_resp_len; |
---|
| 3066 | + beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len; |
---|
2864 | 3067 | |
---|
2865 | 3068 | new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL); |
---|
2866 | 3069 | if (!new_beacon) |
---|
.. | .. |
---|
2902 | 3105 | new_beacon->probe_resp = pos; |
---|
2903 | 3106 | memcpy(pos, beacon->probe_resp, beacon->probe_resp_len); |
---|
2904 | 3107 | pos += beacon->probe_resp_len; |
---|
| 3108 | + } |
---|
| 3109 | + |
---|
| 3110 | + /* might copy -1, meaning no changes requested */ |
---|
| 3111 | + new_beacon->ftm_responder = beacon->ftm_responder; |
---|
| 3112 | + if (beacon->lci) { |
---|
| 3113 | + new_beacon->lci_len = beacon->lci_len; |
---|
| 3114 | + new_beacon->lci = pos; |
---|
| 3115 | + memcpy(pos, beacon->lci, beacon->lci_len); |
---|
| 3116 | + pos += beacon->lci_len; |
---|
| 3117 | + } |
---|
| 3118 | + if (beacon->civicloc) { |
---|
| 3119 | + new_beacon->civicloc_len = beacon->civicloc_len; |
---|
| 3120 | + new_beacon->civicloc = pos; |
---|
| 3121 | + memcpy(pos, beacon->civicloc, beacon->civicloc_len); |
---|
| 3122 | + pos += beacon->civicloc_len; |
---|
2905 | 3123 | } |
---|
2906 | 3124 | |
---|
2907 | 3125 | return new_beacon; |
---|
.. | .. |
---|
3079 | 3297 | break; |
---|
3080 | 3298 | |
---|
3081 | 3299 | if ((params->n_counter_offsets_beacon > |
---|
3082 | | - IEEE80211_MAX_CSA_COUNTERS_NUM) || |
---|
| 3300 | + IEEE80211_MAX_CNTDWN_COUNTERS_NUM) || |
---|
3083 | 3301 | (params->n_counter_offsets_presp > |
---|
3084 | | - IEEE80211_MAX_CSA_COUNTERS_NUM)) |
---|
| 3302 | + IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) |
---|
3085 | 3303 | return -EINVAL; |
---|
3086 | 3304 | |
---|
3087 | 3305 | csa.counter_offsets_beacon = params->counter_offsets_beacon; |
---|
.. | .. |
---|
3138 | 3356 | #ifdef CONFIG_MAC80211_MESH |
---|
3139 | 3357 | case NL80211_IFTYPE_MESH_POINT: { |
---|
3140 | 3358 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
---|
3141 | | - |
---|
3142 | | - if (params->chandef.width != sdata->vif.bss_conf.chandef.width) |
---|
3143 | | - return -EINVAL; |
---|
3144 | 3359 | |
---|
3145 | 3360 | /* changes into another band are not supported */ |
---|
3146 | 3361 | if (sdata->vif.bss_conf.chandef.chan->band != |
---|
.. | .. |
---|
3212 | 3427 | lockdep_is_held(&local->chanctx_mtx)); |
---|
3213 | 3428 | if (!conf) { |
---|
3214 | 3429 | err = -EBUSY; |
---|
| 3430 | + goto out; |
---|
| 3431 | + } |
---|
| 3432 | + |
---|
| 3433 | + if (params->chandef.chan->freq_offset) { |
---|
| 3434 | + /* this may work, but is untested */ |
---|
| 3435 | + err = -EOPNOTSUPP; |
---|
3215 | 3436 | goto out; |
---|
3216 | 3437 | } |
---|
3217 | 3438 | |
---|
.. | .. |
---|
3310 | 3531 | |
---|
3311 | 3532 | spin_lock_irqsave(&local->ack_status_lock, spin_flags); |
---|
3312 | 3533 | id = idr_alloc(&local->ack_status_frames, ack_skb, |
---|
3313 | | - 1, 0x10000, GFP_ATOMIC); |
---|
| 3534 | + 1, 0x2000, GFP_ATOMIC); |
---|
3314 | 3535 | spin_unlock_irqrestore(&local->ack_status_lock, spin_flags); |
---|
3315 | 3536 | |
---|
3316 | 3537 | if (id < 0) { |
---|
.. | .. |
---|
3326 | 3547 | return 0; |
---|
3327 | 3548 | } |
---|
3328 | 3549 | |
---|
3329 | | -static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, |
---|
| 3550 | +static void |
---|
| 3551 | +ieee80211_update_mgmt_frame_registrations(struct wiphy *wiphy, |
---|
3330 | 3552 | struct wireless_dev *wdev, |
---|
3331 | | - u16 frame_type, bool reg) |
---|
| 3553 | + struct mgmt_frame_regs *upd) |
---|
3332 | 3554 | { |
---|
3333 | 3555 | struct ieee80211_local *local = wiphy_priv(wiphy); |
---|
3334 | 3556 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
---|
| 3557 | + u32 preq_mask = BIT(IEEE80211_STYPE_PROBE_REQ >> 4); |
---|
| 3558 | + u32 action_mask = BIT(IEEE80211_STYPE_ACTION >> 4); |
---|
| 3559 | + bool global_change, intf_change; |
---|
3335 | 3560 | |
---|
3336 | | - switch (frame_type) { |
---|
3337 | | - case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ: |
---|
3338 | | - if (reg) { |
---|
3339 | | - local->probe_req_reg++; |
---|
3340 | | - sdata->vif.probe_req_reg++; |
---|
3341 | | - } else { |
---|
3342 | | - if (local->probe_req_reg) |
---|
3343 | | - local->probe_req_reg--; |
---|
| 3561 | + global_change = |
---|
| 3562 | + (local->probe_req_reg != !!(upd->global_stypes & preq_mask)) || |
---|
| 3563 | + (local->rx_mcast_action_reg != |
---|
| 3564 | + !!(upd->global_mcast_stypes & action_mask)); |
---|
| 3565 | + local->probe_req_reg = upd->global_stypes & preq_mask; |
---|
| 3566 | + local->rx_mcast_action_reg = upd->global_mcast_stypes & action_mask; |
---|
3344 | 3567 | |
---|
3345 | | - if (sdata->vif.probe_req_reg) |
---|
3346 | | - sdata->vif.probe_req_reg--; |
---|
3347 | | - } |
---|
| 3568 | + intf_change = (sdata->vif.probe_req_reg != |
---|
| 3569 | + !!(upd->interface_stypes & preq_mask)) || |
---|
| 3570 | + (sdata->vif.rx_mcast_action_reg != |
---|
| 3571 | + !!(upd->interface_mcast_stypes & action_mask)); |
---|
| 3572 | + sdata->vif.probe_req_reg = upd->interface_stypes & preq_mask; |
---|
| 3573 | + sdata->vif.rx_mcast_action_reg = |
---|
| 3574 | + upd->interface_mcast_stypes & action_mask; |
---|
3348 | 3575 | |
---|
3349 | | - if (!local->open_count) |
---|
3350 | | - break; |
---|
| 3576 | + if (!local->open_count) |
---|
| 3577 | + return; |
---|
3351 | 3578 | |
---|
3352 | | - if (sdata->vif.probe_req_reg == 1) |
---|
3353 | | - drv_config_iface_filter(local, sdata, FIF_PROBE_REQ, |
---|
3354 | | - FIF_PROBE_REQ); |
---|
3355 | | - else if (sdata->vif.probe_req_reg == 0) |
---|
3356 | | - drv_config_iface_filter(local, sdata, 0, |
---|
3357 | | - FIF_PROBE_REQ); |
---|
| 3579 | + if (intf_change && ieee80211_sdata_running(sdata)) |
---|
| 3580 | + drv_config_iface_filter(local, sdata, |
---|
| 3581 | + sdata->vif.probe_req_reg ? |
---|
| 3582 | + FIF_PROBE_REQ : 0, |
---|
| 3583 | + FIF_PROBE_REQ); |
---|
3358 | 3584 | |
---|
| 3585 | + if (global_change) |
---|
3359 | 3586 | ieee80211_configure_filter(local); |
---|
3360 | | - break; |
---|
3361 | | - default: |
---|
3362 | | - break; |
---|
3363 | | - } |
---|
3364 | 3587 | } |
---|
3365 | 3588 | |
---|
3366 | 3589 | static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant) |
---|
.. | .. |
---|
3476 | 3699 | } |
---|
3477 | 3700 | |
---|
3478 | 3701 | local_bh_disable(); |
---|
3479 | | - ieee80211_xmit(sdata, sta, skb, 0); |
---|
| 3702 | + ieee80211_xmit(sdata, sta, skb); |
---|
3480 | 3703 | local_bh_enable(); |
---|
3481 | 3704 | |
---|
3482 | 3705 | ret = 0; |
---|
.. | .. |
---|
3793 | 4016 | return ret; |
---|
3794 | 4017 | } |
---|
3795 | 4018 | |
---|
| 4019 | +static int |
---|
| 4020 | +ieee80211_get_ftm_responder_stats(struct wiphy *wiphy, |
---|
| 4021 | + struct net_device *dev, |
---|
| 4022 | + struct cfg80211_ftm_responder_stats *ftm_stats) |
---|
| 4023 | +{ |
---|
| 4024 | + struct ieee80211_local *local = wiphy_priv(wiphy); |
---|
| 4025 | + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
---|
| 4026 | + |
---|
| 4027 | + return drv_get_ftm_responder_stats(local, sdata, ftm_stats); |
---|
| 4028 | +} |
---|
| 4029 | + |
---|
| 4030 | +static int |
---|
| 4031 | +ieee80211_start_pmsr(struct wiphy *wiphy, struct wireless_dev *dev, |
---|
| 4032 | + struct cfg80211_pmsr_request *request) |
---|
| 4033 | +{ |
---|
| 4034 | + struct ieee80211_local *local = wiphy_priv(wiphy); |
---|
| 4035 | + struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(dev); |
---|
| 4036 | + |
---|
| 4037 | + return drv_start_pmsr(local, sdata, request); |
---|
| 4038 | +} |
---|
| 4039 | + |
---|
| 4040 | +static void |
---|
| 4041 | +ieee80211_abort_pmsr(struct wiphy *wiphy, struct wireless_dev *dev, |
---|
| 4042 | + struct cfg80211_pmsr_request *request) |
---|
| 4043 | +{ |
---|
| 4044 | + struct ieee80211_local *local = wiphy_priv(wiphy); |
---|
| 4045 | + struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(dev); |
---|
| 4046 | + |
---|
| 4047 | + return drv_abort_pmsr(local, sdata, request); |
---|
| 4048 | +} |
---|
| 4049 | + |
---|
| 4050 | +static int ieee80211_set_tid_config(struct wiphy *wiphy, |
---|
| 4051 | + struct net_device *dev, |
---|
| 4052 | + struct cfg80211_tid_config *tid_conf) |
---|
| 4053 | +{ |
---|
| 4054 | + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
---|
| 4055 | + struct sta_info *sta; |
---|
| 4056 | + int ret; |
---|
| 4057 | + |
---|
| 4058 | + if (!sdata->local->ops->set_tid_config) |
---|
| 4059 | + return -EOPNOTSUPP; |
---|
| 4060 | + |
---|
| 4061 | + if (!tid_conf->peer) |
---|
| 4062 | + return drv_set_tid_config(sdata->local, sdata, NULL, tid_conf); |
---|
| 4063 | + |
---|
| 4064 | + mutex_lock(&sdata->local->sta_mtx); |
---|
| 4065 | + sta = sta_info_get_bss(sdata, tid_conf->peer); |
---|
| 4066 | + if (!sta) { |
---|
| 4067 | + mutex_unlock(&sdata->local->sta_mtx); |
---|
| 4068 | + return -ENOENT; |
---|
| 4069 | + } |
---|
| 4070 | + |
---|
| 4071 | + ret = drv_set_tid_config(sdata->local, sdata, &sta->sta, tid_conf); |
---|
| 4072 | + mutex_unlock(&sdata->local->sta_mtx); |
---|
| 4073 | + |
---|
| 4074 | + return ret; |
---|
| 4075 | +} |
---|
| 4076 | + |
---|
| 4077 | +static int ieee80211_reset_tid_config(struct wiphy *wiphy, |
---|
| 4078 | + struct net_device *dev, |
---|
| 4079 | + const u8 *peer, u8 tids) |
---|
| 4080 | +{ |
---|
| 4081 | + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
---|
| 4082 | + struct sta_info *sta; |
---|
| 4083 | + int ret; |
---|
| 4084 | + |
---|
| 4085 | + if (!sdata->local->ops->reset_tid_config) |
---|
| 4086 | + return -EOPNOTSUPP; |
---|
| 4087 | + |
---|
| 4088 | + if (!peer) |
---|
| 4089 | + return drv_reset_tid_config(sdata->local, sdata, NULL, tids); |
---|
| 4090 | + |
---|
| 4091 | + mutex_lock(&sdata->local->sta_mtx); |
---|
| 4092 | + sta = sta_info_get_bss(sdata, peer); |
---|
| 4093 | + if (!sta) { |
---|
| 4094 | + mutex_unlock(&sdata->local->sta_mtx); |
---|
| 4095 | + return -ENOENT; |
---|
| 4096 | + } |
---|
| 4097 | + |
---|
| 4098 | + ret = drv_reset_tid_config(sdata->local, sdata, &sta->sta, tids); |
---|
| 4099 | + mutex_unlock(&sdata->local->sta_mtx); |
---|
| 4100 | + |
---|
| 4101 | + return ret; |
---|
| 4102 | +} |
---|
| 4103 | + |
---|
3796 | 4104 | const struct cfg80211_ops mac80211_config_ops = { |
---|
3797 | 4105 | .add_virtual_intf = ieee80211_add_iface, |
---|
3798 | 4106 | .del_virtual_intf = ieee80211_del_iface, |
---|
.. | .. |
---|
3804 | 4112 | .get_key = ieee80211_get_key, |
---|
3805 | 4113 | .set_default_key = ieee80211_config_default_key, |
---|
3806 | 4114 | .set_default_mgmt_key = ieee80211_config_default_mgmt_key, |
---|
| 4115 | + .set_default_beacon_key = ieee80211_config_default_beacon_key, |
---|
3807 | 4116 | .start_ap = ieee80211_start_ap, |
---|
3808 | 4117 | .change_beacon = ieee80211_change_beacon, |
---|
3809 | 4118 | .stop_ap = ieee80211_stop_ap, |
---|
.. | .. |
---|
3859 | 4168 | .mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait, |
---|
3860 | 4169 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, |
---|
3861 | 4170 | .set_cqm_rssi_range_config = ieee80211_set_cqm_rssi_range_config, |
---|
3862 | | - .mgmt_frame_register = ieee80211_mgmt_frame_register, |
---|
| 4171 | + .update_mgmt_frame_registrations = |
---|
| 4172 | + ieee80211_update_mgmt_frame_registrations, |
---|
3863 | 4173 | .set_antenna = ieee80211_set_antenna, |
---|
3864 | 4174 | .get_antenna = ieee80211_get_antenna, |
---|
3865 | 4175 | .set_rekey_data = ieee80211_set_rekey_data, |
---|
.. | .. |
---|
3888 | 4198 | .set_multicast_to_unicast = ieee80211_set_multicast_to_unicast, |
---|
3889 | 4199 | .tx_control_port = ieee80211_tx_control_port, |
---|
3890 | 4200 | .get_txq_stats = ieee80211_get_txq_stats, |
---|
| 4201 | + .get_ftm_responder_stats = ieee80211_get_ftm_responder_stats, |
---|
| 4202 | + .start_pmsr = ieee80211_start_pmsr, |
---|
| 4203 | + .abort_pmsr = ieee80211_abort_pmsr, |
---|
| 4204 | + .probe_mesh_link = ieee80211_probe_mesh_link, |
---|
| 4205 | + .set_tid_config = ieee80211_set_tid_config, |
---|
| 4206 | + .reset_tid_config = ieee80211_reset_tid_config, |
---|
3891 | 4207 | }; |
---|