| .. | .. |
|---|
| 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 | }; |
|---|