^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * mac80211 TDLS handling code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2014, Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright 2014 Intel Mobile Communications GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright 2015 - 2016 Intel Deutschland GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2019 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/ieee80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/log2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <net/cfg80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/rtnetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "ieee80211_i.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "driver-ops.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "rate.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "wme.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* give usermode some time for retries in setting up the TDLS session */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define TDLS_PEER_SETUP_TIMEOUT (15 * HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) void ieee80211_tdls_peer_del_work(struct work_struct *wk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct ieee80211_sub_if_data *sdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct ieee80211_local *local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) sdata = container_of(wk, struct ieee80211_sub_if_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) u.mgd.tdls_peer_del_work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) mutex_lock(&local->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (!is_zero_ether_addr(sdata->u.mgd.tdls_peer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) tdls_dbg(sdata, "TDLS del peer %pM\n", sdata->u.mgd.tdls_peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) sta_info_destroy_addr(sdata, sdata->u.mgd.tdls_peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) eth_zero_addr(sdata->u.mgd.tdls_peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) mutex_unlock(&local->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static void ieee80211_tdls_add_ext_capab(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) bool chan_switch = local->hw.wiphy->features &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) bool wider_band = ieee80211_hw_check(&local->hw, TDLS_WIDER_BW) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) !ifmgd->tdls_wider_bw_prohibited;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) bool buffer_sta = ieee80211_hw_check(&local->hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) SUPPORTS_TDLS_BUFFER_STA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct ieee80211_supported_band *sband = ieee80211_get_sband(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) bool vht = sband && sband->vht_cap.vht_supported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) u8 *pos = skb_put(skb, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) *pos++ = WLAN_EID_EXT_CAPABILITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) *pos++ = 8; /* len */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) *pos++ = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) *pos++ = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) *pos++ = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) *pos++ = (chan_switch ? WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH : 0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) (buffer_sta ? WLAN_EXT_CAPA4_TDLS_BUFFER_STA : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) *pos++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) *pos++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) *pos++ = (vht && wider_band) ? WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static u8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) ieee80211_tdls_add_subband(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct sk_buff *skb, u16 start, u16 end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) u16 spacing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u8 subband_cnt = 0, ch_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct ieee80211_channel *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct cfg80211_chan_def chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int i, subband_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct wiphy *wiphy = sdata->local->hw.wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) for (i = start; i <= end; i += spacing) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (!ch_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) subband_start = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) ch = ieee80211_get_channel(sdata->local->hw.wiphy, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (ch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* we will be active on the channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) cfg80211_chandef_create(&chandef, ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) NL80211_CHAN_NO_HT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (cfg80211_reg_can_beacon_relax(wiphy, &chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) sdata->wdev.iftype)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ch_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * check if the next channel is also part of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * this allowed range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * we've reached the end of a range, with allowed channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (ch_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u8 *pos = skb_put(skb, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) *pos++ = ieee80211_frequency_to_channel(subband_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) *pos++ = ch_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) subband_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) ch_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /* all channels in the requested range are allowed - add them here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (ch_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) u8 *pos = skb_put(skb, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) *pos++ = ieee80211_frequency_to_channel(subband_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) *pos++ = ch_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) subband_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return subband_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ieee80211_tdls_add_supp_channels(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * Add possible channels for TDLS. These are channels that are allowed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * to be active.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) u8 subband_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) u8 *pos = skb_put(skb, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) *pos++ = WLAN_EID_SUPPORTED_CHANNELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * 5GHz and 2GHz channels numbers can overlap. Ignore this for now, as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * this doesn't happen in real world scenarios.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* 2GHz, with 5MHz spacing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) subband_cnt = ieee80211_tdls_add_subband(sdata, skb, 2412, 2472, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* 5GHz, with 20MHz spacing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) subband_cnt += ieee80211_tdls_add_subband(sdata, skb, 5000, 5825, 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) *pos = 2 * subband_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static void ieee80211_tdls_add_oper_classes(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) u8 *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) u8 op_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (!ieee80211_chandef_to_operating_class(&sdata->vif.bss_conf.chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) &op_class))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) pos = skb_put(skb, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) *pos++ = WLAN_EID_SUPPORTED_REGULATORY_CLASSES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) *pos++ = 2; /* len */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) *pos++ = op_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) *pos++ = op_class; /* give current operating class as alternate too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static void ieee80211_tdls_add_bss_coex_ie(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) u8 *pos = skb_put(skb, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) *pos++ = WLAN_EID_BSS_COEX_2040;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) *pos++ = 1; /* len */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) *pos++ = WLAN_BSS_COEX_INFORMATION_REQUEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) u16 status_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /* The capability will be 0 when sending a failure code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (status_code != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) sband = ieee80211_get_sband(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (sband && sband->band == NL80211_BAND_2GHZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return WLAN_CAPABILITY_SHORT_SLOT_TIME |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) WLAN_CAPABILITY_SHORT_PREAMBLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static void ieee80211_tdls_add_link_ie(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct sk_buff *skb, const u8 *peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) bool initiator)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct ieee80211_tdls_lnkie *lnkid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) const u8 *init_addr, *rsp_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (initiator) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) init_addr = sdata->vif.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) rsp_addr = peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) init_addr = peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) rsp_addr = sdata->vif.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) lnkid = skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) lnkid->ie_type = WLAN_EID_LINK_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) memcpy(lnkid->bssid, sdata->u.mgd.bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) memcpy(lnkid->init_sta, init_addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) memcpy(lnkid->resp_sta, rsp_addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) ieee80211_tdls_add_aid(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) u8 *pos = skb_put(skb, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) *pos++ = WLAN_EID_AID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) *pos++ = 2; /* len */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) put_unaligned_le16(sdata->vif.bss_conf.aid, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /* translate numbering in the WMM parameter IE to the mac80211 notation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static enum ieee80211_ac_numbers ieee80211_ac_from_wmm(int ac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) switch (ac) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) WARN_ON_ONCE(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return IEEE80211_AC_BE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return IEEE80211_AC_BK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return IEEE80211_AC_VI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return IEEE80211_AC_VO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static u8 ieee80211_wmm_aci_aifsn(int aifsn, bool acm, int aci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) u8 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) ret = aifsn & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (acm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) ret |= 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) ret |= (aci << 5) & 0x60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static u8 ieee80211_wmm_ecw(u16 cw_min, u16 cw_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return ((ilog2(cw_min + 1) << 0x0) & 0x0f) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) ((ilog2(cw_max + 1) << 0x4) & 0xf0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static void ieee80211_tdls_add_wmm_param_ie(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct ieee80211_wmm_param_ie *wmm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct ieee80211_tx_queue_params *txq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) wmm = skb_put_zero(skb, sizeof(*wmm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) wmm->element_id = WLAN_EID_VENDOR_SPECIFIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) wmm->len = sizeof(*wmm) - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) wmm->oui[1] = 0x50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) wmm->oui[2] = 0xf2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) wmm->oui_type = 2; /* WME */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) wmm->oui_subtype = 1; /* WME param */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) wmm->version = 1; /* WME ver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) wmm->qos_info = 0; /* U-APSD not in use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * Use the EDCA parameters defined for the BSS, or default if the AP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * doesn't support it, as mandated by 802.11-2012 section 10.22.4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) for (i = 0; i < IEEE80211_NUM_ACS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) txq = &sdata->tx_conf[ieee80211_ac_from_wmm(i)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) wmm->ac[i].aci_aifsn = ieee80211_wmm_aci_aifsn(txq->aifs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) txq->acm, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) wmm->ac[i].cw = ieee80211_wmm_ecw(txq->cw_min, txq->cw_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) wmm->ac[i].txop_limit = cpu_to_le16(txq->txop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) ieee80211_tdls_chandef_vht_upgrade(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct sta_info *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* IEEE802.11ac-2013 Table E-4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) u16 centers_80mhz[] = { 5210, 5290, 5530, 5610, 5690, 5775 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct cfg80211_chan_def uc = sta->tdls_chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) enum nl80211_chan_width max_width = ieee80211_sta_cap_chan_bw(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* only support upgrading non-narrow channels up to 80Mhz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (max_width == NL80211_CHAN_WIDTH_5 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) max_width == NL80211_CHAN_WIDTH_10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (max_width > NL80211_CHAN_WIDTH_80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) max_width = NL80211_CHAN_WIDTH_80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (uc.width >= max_width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) * Channel usage constrains in the IEEE802.11ac-2013 specification only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * allow expanding a 20MHz channel to 80MHz in a single way. In
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * addition, there are no 40MHz allowed channels that are not part of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * the allowed 80MHz range in the 5GHz spectrum (the relevant one here).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) for (i = 0; i < ARRAY_SIZE(centers_80mhz); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (abs(uc.chan->center_freq - centers_80mhz[i]) <= 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) uc.center_freq1 = centers_80mhz[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) uc.center_freq2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) uc.width = NL80211_CHAN_WIDTH_80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (!uc.center_freq1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /* proceed to downgrade the chandef until usable or the same as AP BW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) while (uc.width > max_width ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) (uc.width > sta->tdls_chandef.width &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) !cfg80211_reg_can_beacon_relax(sdata->local->hw.wiphy, &uc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) sdata->wdev.iftype)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) ieee80211_chandef_downgrade(&uc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (!cfg80211_chandef_identical(&uc, &sta->tdls_chandef)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) tdls_dbg(sdata, "TDLS ch width upgraded %d -> %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) sta->tdls_chandef.width, uc.width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * the station is not yet authorized when BW upgrade is done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * locking is not required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) sta->tdls_chandef = uc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) struct sk_buff *skb, const u8 *peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) u8 action_code, bool initiator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) const u8 *extra_ies, size_t extra_ies_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) struct ieee80211_sta_ht_cap ht_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct ieee80211_sta_vht_cap vht_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) struct sta_info *sta = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) size_t offset = 0, noffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) u8 *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) sband = ieee80211_get_sband(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) ieee80211_add_srates_ie(sdata, skb, false, sband->band);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) ieee80211_add_ext_srates_ie(sdata, skb, false, sband->band);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) ieee80211_tdls_add_supp_channels(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /* add any custom IEs that go before Extended Capabilities */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (extra_ies_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static const u8 before_ext_cap[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) WLAN_EID_SUPP_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) WLAN_EID_COUNTRY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) WLAN_EID_EXT_SUPP_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) WLAN_EID_SUPPORTED_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) WLAN_EID_RSN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) noffset = ieee80211_ie_split(extra_ies, extra_ies_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) before_ext_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) ARRAY_SIZE(before_ext_cap),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) skb_put_data(skb, extra_ies + offset, noffset - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) offset = noffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) ieee80211_tdls_add_ext_capab(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /* add the QoS element if we support it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (local->hw.queues >= IEEE80211_NUM_ACS &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) action_code != WLAN_PUB_ACTION_TDLS_DISCOVER_RES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) ieee80211_add_wmm_info_ie(skb_put(skb, 9), 0); /* no U-APSD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /* add any custom IEs that go before HT capabilities */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (extra_ies_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static const u8 before_ht_cap[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) WLAN_EID_SUPP_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) WLAN_EID_COUNTRY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) WLAN_EID_EXT_SUPP_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) WLAN_EID_SUPPORTED_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) WLAN_EID_RSN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) WLAN_EID_EXT_CAPABILITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) WLAN_EID_QOS_CAPA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) WLAN_EID_FAST_BSS_TRANSITION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) WLAN_EID_TIMEOUT_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) noffset = ieee80211_ie_split(extra_ies, extra_ies_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) before_ht_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) ARRAY_SIZE(before_ht_cap),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) skb_put_data(skb, extra_ies + offset, noffset - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) offset = noffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) mutex_lock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) /* we should have the peer STA if we're already responding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (action_code == WLAN_TDLS_SETUP_RESPONSE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) sta = sta_info_get(sdata, peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (WARN_ON_ONCE(!sta)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) mutex_unlock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) sta->tdls_chandef = sdata->vif.bss_conf.chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) ieee80211_tdls_add_oper_classes(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * with TDLS we can switch channels, and HT-caps are not necessarily
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * the same on all bands. The specification limits the setup to a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * single HT-cap, so use the current band for now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if ((action_code == WLAN_TDLS_SETUP_REQUEST ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) ht_cap.ht_supported) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ieee80211_apply_htcap_overrides(sdata, &ht_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /* disable SMPS in TDLS initiator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) ht_cap.cap |= WLAN_HT_CAP_SM_PS_DISABLED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) << IEEE80211_HT_CAP_SM_PS_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) ieee80211_ie_build_ht_cap(pos, &ht_cap, ht_cap.cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) } else if (action_code == WLAN_TDLS_SETUP_RESPONSE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) ht_cap.ht_supported && sta->sta.ht_cap.ht_supported) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) /* the peer caps are already intersected with our own */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) memcpy(&ht_cap, &sta->sta.ht_cap, sizeof(ht_cap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) ieee80211_ie_build_ht_cap(pos, &ht_cap, ht_cap.cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (ht_cap.ht_supported &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) (ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) ieee80211_tdls_add_bss_coex_ie(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* add any custom IEs that go before VHT capabilities */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) if (extra_ies_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) static const u8 before_vht_cap[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) WLAN_EID_SUPP_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) WLAN_EID_COUNTRY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) WLAN_EID_EXT_SUPP_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) WLAN_EID_SUPPORTED_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) WLAN_EID_RSN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) WLAN_EID_EXT_CAPABILITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) WLAN_EID_QOS_CAPA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) WLAN_EID_FAST_BSS_TRANSITION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) WLAN_EID_TIMEOUT_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) WLAN_EID_MULTI_BAND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) noffset = ieee80211_ie_split(extra_ies, extra_ies_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) before_vht_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) ARRAY_SIZE(before_vht_cap),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) skb_put_data(skb, extra_ies + offset, noffset - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) offset = noffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) /* build the VHT-cap similarly to the HT-cap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if ((action_code == WLAN_TDLS_SETUP_REQUEST ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) vht_cap.vht_supported) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) ieee80211_apply_vhtcap_overrides(sdata, &vht_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) /* the AID is present only when VHT is implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (action_code == WLAN_TDLS_SETUP_REQUEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) ieee80211_tdls_add_aid(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) ieee80211_ie_build_vht_cap(pos, &vht_cap, vht_cap.cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) } else if (action_code == WLAN_TDLS_SETUP_RESPONSE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) vht_cap.vht_supported && sta->sta.vht_cap.vht_supported) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) /* the peer caps are already intersected with our own */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) memcpy(&vht_cap, &sta->sta.vht_cap, sizeof(vht_cap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) /* the AID is present only when VHT is implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) ieee80211_tdls_add_aid(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) ieee80211_ie_build_vht_cap(pos, &vht_cap, vht_cap.cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * if both peers support WIDER_BW, we can expand the chandef to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * a wider compatible one, up to 80MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) ieee80211_tdls_chandef_vht_upgrade(sdata, sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) mutex_unlock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) /* add any remaining IEs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (extra_ies_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) noffset = extra_ies_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) skb_put_data(skb, extra_ies + offset, noffset - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct sk_buff *skb, const u8 *peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) bool initiator, const u8 *extra_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) size_t extra_ies_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) size_t offset = 0, noffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) struct sta_info *sta, *ap_sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) u8 *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) sband = ieee80211_get_sband(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) mutex_lock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) sta = sta_info_get(sdata, peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) ap_sta = sta_info_get(sdata, ifmgd->bssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (WARN_ON_ONCE(!sta || !ap_sta)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) mutex_unlock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) sta->tdls_chandef = sdata->vif.bss_conf.chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /* add any custom IEs that go before the QoS IE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (extra_ies_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) static const u8 before_qos[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) WLAN_EID_RSN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) noffset = ieee80211_ie_split(extra_ies, extra_ies_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) before_qos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) ARRAY_SIZE(before_qos),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) skb_put_data(skb, extra_ies + offset, noffset - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) offset = noffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) /* add the QoS param IE if both the peer and we support it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (local->hw.queues >= IEEE80211_NUM_ACS && sta->sta.wme)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) ieee80211_tdls_add_wmm_param_ie(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) /* add any custom IEs that go before HT operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (extra_ies_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static const u8 before_ht_op[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) WLAN_EID_RSN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) WLAN_EID_QOS_CAPA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) WLAN_EID_FAST_BSS_TRANSITION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) WLAN_EID_TIMEOUT_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) noffset = ieee80211_ie_split(extra_ies, extra_ies_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) before_ht_op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) ARRAY_SIZE(before_ht_op),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) skb_put_data(skb, extra_ies + offset, noffset - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) offset = noffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) * if HT support is only added in TDLS, we need an HT-operation IE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) * add the IE as required by IEEE802.11-2012 9.23.3.2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (!ap_sta->sta.ht_cap.ht_supported && sta->sta.ht_cap.ht_supported) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) u16 prot = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) ieee80211_ie_build_ht_oper(pos, &sta->sta.ht_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) &sdata->vif.bss_conf.chandef, prot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) /* only include VHT-operation if not on the 2.4GHz band */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (sband->band != NL80211_BAND_2GHZ &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) sta->sta.vht_cap.vht_supported) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) * if both peers support WIDER_BW, we can expand the chandef to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * a wider compatible one, up to 80MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) ieee80211_tdls_chandef_vht_upgrade(sdata, sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) pos = skb_put(skb, 2 + sizeof(struct ieee80211_vht_operation));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) ieee80211_ie_build_vht_oper(pos, &sta->sta.vht_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) &sta->tdls_chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) mutex_unlock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /* add any remaining IEs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (extra_ies_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) noffset = extra_ies_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) skb_put_data(skb, extra_ies + offset, noffset - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) ieee80211_tdls_add_chan_switch_req_ies(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct sk_buff *skb, const u8 *peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) bool initiator, const u8 *extra_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) size_t extra_ies_len, u8 oper_class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) struct cfg80211_chan_def *chandef)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) struct ieee80211_tdls_data *tf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) size_t offset = 0, noffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (WARN_ON_ONCE(!chandef))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) tf = (void *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) tf->u.chan_switch_req.target_channel =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) ieee80211_frequency_to_channel(chandef->chan->center_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) tf->u.chan_switch_req.oper_class = oper_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (extra_ies_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) static const u8 before_lnkie[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) WLAN_EID_SECONDARY_CHANNEL_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) noffset = ieee80211_ie_split(extra_ies, extra_ies_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) before_lnkie,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) ARRAY_SIZE(before_lnkie),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) skb_put_data(skb, extra_ies + offset, noffset - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) offset = noffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) /* add any remaining IEs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (extra_ies_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) noffset = extra_ies_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) skb_put_data(skb, extra_ies + offset, noffset - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) ieee80211_tdls_add_chan_switch_resp_ies(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) struct sk_buff *skb, const u8 *peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) u16 status_code, bool initiator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) const u8 *extra_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) size_t extra_ies_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (status_code == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (extra_ies_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) skb_put_data(skb, extra_ies, extra_ies_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) struct sk_buff *skb, const u8 *peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) u8 action_code, u16 status_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) bool initiator, const u8 *extra_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) size_t extra_ies_len, u8 oper_class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) struct cfg80211_chan_def *chandef)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) switch (action_code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) case WLAN_TDLS_SETUP_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) case WLAN_TDLS_SETUP_RESPONSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (status_code == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) ieee80211_tdls_add_setup_start_ies(sdata, skb, peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) action_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) initiator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) extra_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) extra_ies_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) case WLAN_TDLS_SETUP_CONFIRM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (status_code == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) ieee80211_tdls_add_setup_cfm_ies(sdata, skb, peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) initiator, extra_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) extra_ies_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) case WLAN_TDLS_TEARDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) case WLAN_TDLS_DISCOVERY_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (extra_ies_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) skb_put_data(skb, extra_ies, extra_ies_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (status_code == 0 || action_code == WLAN_TDLS_TEARDOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) ieee80211_tdls_add_chan_switch_req_ies(sdata, skb, peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) initiator, extra_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) extra_ies_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) oper_class, chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) ieee80211_tdls_add_chan_switch_resp_ies(sdata, skb, peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) status_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) initiator, extra_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) extra_ies_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) const u8 *peer, u8 action_code, u8 dialog_token,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) u16 status_code, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) struct ieee80211_tdls_data *tf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) tf = skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) memcpy(tf->da, peer, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) memcpy(tf->sa, sdata->vif.addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) tf->ether_type = cpu_to_be16(ETH_P_TDLS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) /* network header is after the ethernet header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) skb_set_network_header(skb, ETH_HLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) switch (action_code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) case WLAN_TDLS_SETUP_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) tf->category = WLAN_CATEGORY_TDLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) tf->action_code = WLAN_TDLS_SETUP_REQUEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) skb_put(skb, sizeof(tf->u.setup_req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) tf->u.setup_req.dialog_token = dialog_token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) tf->u.setup_req.capability =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) status_code));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) case WLAN_TDLS_SETUP_RESPONSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) tf->category = WLAN_CATEGORY_TDLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) skb_put(skb, sizeof(tf->u.setup_resp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) tf->u.setup_resp.status_code = cpu_to_le16(status_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) tf->u.setup_resp.dialog_token = dialog_token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) tf->u.setup_resp.capability =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) status_code));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) case WLAN_TDLS_SETUP_CONFIRM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) tf->category = WLAN_CATEGORY_TDLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) skb_put(skb, sizeof(tf->u.setup_cfm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) tf->u.setup_cfm.dialog_token = dialog_token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) case WLAN_TDLS_TEARDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) tf->category = WLAN_CATEGORY_TDLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) tf->action_code = WLAN_TDLS_TEARDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) skb_put(skb, sizeof(tf->u.teardown));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) tf->u.teardown.reason_code = cpu_to_le16(status_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) case WLAN_TDLS_DISCOVERY_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) tf->category = WLAN_CATEGORY_TDLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) skb_put(skb, sizeof(tf->u.discover_req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) tf->u.discover_req.dialog_token = dialog_token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) tf->category = WLAN_CATEGORY_TDLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) tf->action_code = WLAN_TDLS_CHANNEL_SWITCH_REQUEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) skb_put(skb, sizeof(tf->u.chan_switch_req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) tf->category = WLAN_CATEGORY_TDLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) tf->action_code = WLAN_TDLS_CHANNEL_SWITCH_RESPONSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) skb_put(skb, sizeof(tf->u.chan_switch_resp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) tf->u.chan_switch_resp.status_code = cpu_to_le16(status_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) const u8 *peer, u8 action_code, u8 dialog_token,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) u16 status_code, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) struct ieee80211_mgmt *mgmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) mgmt = skb_put_zero(skb, 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) memcpy(mgmt->da, peer, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) IEEE80211_STYPE_ACTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) switch (action_code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) mgmt->u.action.u.tdls_discover_resp.action_code =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) mgmt->u.action.u.tdls_discover_resp.dialog_token =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) dialog_token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) mgmt->u.action.u.tdls_discover_resp.capability =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) status_code));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) static struct sk_buff *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) ieee80211_tdls_build_mgmt_packet_data(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) const u8 *peer, u8 action_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) u8 dialog_token, u16 status_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) bool initiator, const u8 *extra_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) size_t extra_ies_len, u8 oper_class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) struct cfg80211_chan_def *chandef)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) skb = netdev_alloc_skb(sdata->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) local->hw.extra_tx_headroom +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) max(sizeof(struct ieee80211_mgmt),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) sizeof(struct ieee80211_tdls_data)) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) 50 + /* supported rates */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) 10 + /* ext capab */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) 26 + /* max(WMM-info, WMM-param) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) 2 + max(sizeof(struct ieee80211_ht_cap),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) sizeof(struct ieee80211_ht_operation)) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) 2 + max(sizeof(struct ieee80211_vht_cap),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) sizeof(struct ieee80211_vht_operation)) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) 50 + /* supported channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) 3 + /* 40/20 BSS coex */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) 4 + /* AID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) 4 + /* oper classes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) extra_ies_len +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) sizeof(struct ieee80211_tdls_lnkie));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) skb_reserve(skb, local->hw.extra_tx_headroom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) switch (action_code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) case WLAN_TDLS_SETUP_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) case WLAN_TDLS_SETUP_RESPONSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) case WLAN_TDLS_SETUP_CONFIRM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) case WLAN_TDLS_TEARDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) case WLAN_TDLS_DISCOVERY_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) ret = ieee80211_prep_tdls_encap_data(local->hw.wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) sdata->dev, peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) action_code, dialog_token,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) status_code, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) ret = ieee80211_prep_tdls_direct(local->hw.wiphy, sdata->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) peer, action_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) dialog_token, status_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) ret = -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) ieee80211_tdls_add_ies(sdata, skb, peer, action_code, status_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) initiator, extra_ies, extra_ies_len, oper_class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) const u8 *peer, u8 action_code, u8 dialog_token,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) u16 status_code, u32 peer_capability,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) bool initiator, const u8 *extra_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) size_t extra_ies_len, u8 oper_class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) struct cfg80211_chan_def *chandef)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) struct sk_buff *skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) struct sta_info *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) u32 flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) sta = sta_info_get(sdata, peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) /* infer the initiator if we can, to support old userspace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) switch (action_code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) case WLAN_TDLS_SETUP_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (sta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) set_sta_flag(sta, WLAN_STA_TDLS_INITIATOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) sta->sta.tdls_initiator = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) case WLAN_TDLS_SETUP_CONFIRM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) case WLAN_TDLS_DISCOVERY_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) initiator = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) case WLAN_TDLS_SETUP_RESPONSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) * In some testing scenarios, we send a request and response.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) * Make the last packet sent take effect for the initiator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) * value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (sta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) clear_sta_flag(sta, WLAN_STA_TDLS_INITIATOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) sta->sta.tdls_initiator = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) initiator = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) case WLAN_TDLS_TEARDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) /* any value is ok */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) ret = -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (sta && test_sta_flag(sta, WLAN_STA_TDLS_INITIATOR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) initiator = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) skb = ieee80211_tdls_build_mgmt_packet_data(sdata, peer, action_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) dialog_token, status_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) initiator, extra_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) extra_ies_len, oper_class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) ieee80211_tx_skb(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * we should default to AC_VI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) switch (action_code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) case WLAN_TDLS_SETUP_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) case WLAN_TDLS_SETUP_RESPONSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) skb->priority = 256 + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) skb->priority = 256 + 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) * Set the WLAN_TDLS_TEARDOWN flag to indicate a teardown in progress.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) * Later, if no ACK is returned from peer, we will re-send the teardown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) * packet through the AP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if ((action_code == WLAN_TDLS_TEARDOWN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) ieee80211_hw_check(&sdata->local->hw, REPORTS_TX_ACK_STATUS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) bool try_resend; /* Should we keep skb for possible resend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) /* If not sending directly to peer - no point in keeping skb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) sta = sta_info_get(sdata, peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) try_resend = sta && test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) spin_lock_bh(&sdata->u.mgd.teardown_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) if (try_resend && !sdata->u.mgd.teardown_skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) /* Mark it as requiring TX status callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) IEEE80211_TX_INTFL_MLME_CONN_TX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) * skb is copied since mac80211 will later set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) * properties that might not be the same as the AP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) * such as encryption, QoS, addresses, etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) * No problem if skb_copy() fails, so no need to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) sdata->u.mgd.teardown_skb = skb_copy(skb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) sdata->u.mgd.orig_teardown_skb = skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) spin_unlock_bh(&sdata->u.mgd.teardown_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) /* disable bottom halves when entering the Tx path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) local_bh_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) __ieee80211_subif_start_xmit(skb, dev, flags, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) local_bh_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) const u8 *peer, u8 action_code, u8 dialog_token,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) u16 status_code, u32 peer_capability, bool initiator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) const u8 *extra_ies, size_t extra_ies_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) enum ieee80211_smps_mode smps_mode = sdata->u.mgd.driver_smps_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) /* don't support setup with forced SMPS mode that's not off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) if (smps_mode != IEEE80211_SMPS_AUTOMATIC &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) smps_mode != IEEE80211_SMPS_OFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) tdls_dbg(sdata, "Aborting TDLS setup due to SMPS mode %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) smps_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) mutex_lock(&local->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) /* we don't support concurrent TDLS peer setups */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (!is_zero_ether_addr(sdata->u.mgd.tdls_peer) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) !ether_addr_equal(sdata->u.mgd.tdls_peer, peer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) * make sure we have a STA representing the peer so we drop or buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) * non-TDLS-setup frames to the peer. We can't send other packets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) * during setup through the AP path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) * Allow error packets to be sent - sometimes we don't even add a STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) * before failing the setup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (status_code == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if (!sta_info_get(sdata, peer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) ret = -ENOLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) ieee80211_flush_queues(local, sdata, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) memcpy(sdata->u.mgd.tdls_peer, peer, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) mutex_unlock(&local->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) /* we cannot take the mutex while preparing the setup packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) dialog_token, status_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) peer_capability, initiator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) extra_ies, extra_ies_len, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) mutex_lock(&local->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) eth_zero_addr(sdata->u.mgd.tdls_peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) mutex_unlock(&local->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) ieee80211_queue_delayed_work(&sdata->local->hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) &sdata->u.mgd.tdls_peer_del_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) TDLS_PEER_SETUP_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) mutex_unlock(&local->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) ieee80211_tdls_mgmt_teardown(struct wiphy *wiphy, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) const u8 *peer, u8 action_code, u8 dialog_token,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) u16 status_code, u32 peer_capability,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) bool initiator, const u8 *extra_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) size_t extra_ies_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) struct sta_info *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) * No packets can be transmitted to the peer via the AP during setup -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) * the STA is set as a TDLS peer, but is not authorized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) * During teardown, we prevent direct transmissions by stopping the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) * queues and flushing all direct packets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) ieee80211_stop_vif_queues(local, sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) ieee80211_flush_queues(local, sdata, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) dialog_token, status_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) peer_capability, initiator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) extra_ies, extra_ies_len, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) sdata_err(sdata, "Failed sending TDLS teardown packet %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) * Remove the STA AUTH flag to force further traffic through the AP. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) * the STA was unreachable, it was already removed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) sta = sta_info_get(sdata, peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) clear_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) ieee80211_wake_vif_queues(local, sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) const u8 *peer, u8 action_code, u8 dialog_token,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) u16 status_code, u32 peer_capability,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) bool initiator, const u8 *extra_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) size_t extra_ies_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) /* make sure we are in managed mode, and associated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) if (sdata->vif.type != NL80211_IFTYPE_STATION ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) !sdata->u.mgd.associated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) switch (action_code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) case WLAN_TDLS_SETUP_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) case WLAN_TDLS_SETUP_RESPONSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) ret = ieee80211_tdls_mgmt_setup(wiphy, dev, peer, action_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) dialog_token, status_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) peer_capability, initiator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) extra_ies, extra_ies_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) case WLAN_TDLS_TEARDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) ret = ieee80211_tdls_mgmt_teardown(wiphy, dev, peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) action_code, dialog_token,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) status_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) peer_capability, initiator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) extra_ies, extra_ies_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) case WLAN_TDLS_DISCOVERY_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) * Protect the discovery so we can hear the TDLS discovery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) * response frame. It is transmitted directly and not buffered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) * by the AP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) drv_mgd_protect_tdls_discover(sdata->local, sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) case WLAN_TDLS_SETUP_CONFIRM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) /* no special handling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) action_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) dialog_token,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) status_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) peer_capability,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) initiator, extra_ies,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) extra_ies_len, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) tdls_dbg(sdata, "TDLS mgmt action %d peer %pM status %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) action_code, peer, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) static void iee80211_tdls_recalc_chanctx(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) struct sta_info *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) struct ieee80211_chanctx_conf *conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) struct ieee80211_chanctx *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) enum nl80211_chan_width width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) mutex_lock(&local->chanctx_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) lockdep_is_held(&local->chanctx_mtx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) if (conf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) width = conf->def.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) sband = local->hw.wiphy->bands[conf->def.chan->band];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) ctx = container_of(conf, struct ieee80211_chanctx, conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) ieee80211_recalc_chanctx_chantype(local, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) /* if width changed and a peer is given, update its BW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) if (width != conf->def.width && sta &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) enum ieee80211_sta_rx_bandwidth bw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) bw = ieee80211_chan_width_to_rx_bw(conf->def.width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) bw = min(bw, ieee80211_sta_cap_rx_bw(sta));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) if (bw != sta->sta.bandwidth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) sta->sta.bandwidth = bw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) rate_control_rate_update(local, sband, sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) IEEE80211_RC_BW_CHANGED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) * if a TDLS peer BW was updated, we need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) * recalc the chandef width again, to get the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) * correct chanctx min_def
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) ieee80211_recalc_chanctx_chantype(local, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) mutex_unlock(&local->chanctx_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) static int iee80211_tdls_have_ht_peers(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) struct sta_info *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) bool result = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) if (!sta->sta.tdls || sta->sdata != sdata || !sta->uploaded ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) !test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) !test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) !sta->sta.ht_cap.ht_supported)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) result = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) iee80211_tdls_recalc_ht_protection(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) struct sta_info *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) bool tdls_ht;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) u16 protection = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) u16 opmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) /* Nothing to do if the BSS connection uses HT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) tdls_ht = (sta && sta->sta.ht_cap.ht_supported) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) iee80211_tdls_have_ht_peers(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) opmode = sdata->vif.bss_conf.ht_operation_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) if (tdls_ht)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) opmode |= protection;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) opmode &= ~protection;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (opmode == sdata->vif.bss_conf.ht_operation_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) sdata->vif.bss_conf.ht_operation_mode = opmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) const u8 *peer, enum nl80211_tdls_operation oper)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) struct sta_info *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) if (sdata->vif.type != NL80211_IFTYPE_STATION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) switch (oper) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) case NL80211_TDLS_ENABLE_LINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) case NL80211_TDLS_DISABLE_LINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) case NL80211_TDLS_TEARDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) case NL80211_TDLS_SETUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) case NL80211_TDLS_DISCOVERY_REQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) /* We don't support in-driver setup/teardown/discovery */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) /* protect possible bss_conf changes and avoid concurrency in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) * ieee80211_bss_info_change_notify()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) sdata_lock(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) mutex_lock(&local->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) switch (oper) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) case NL80211_TDLS_ENABLE_LINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) if (sdata->vif.csa_active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) tdls_dbg(sdata, "TDLS: disallow link during CSA\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) mutex_lock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) sta = sta_info_get(sdata, peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) if (!sta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) mutex_unlock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) ret = -ENOLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) iee80211_tdls_recalc_chanctx(sdata, sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) iee80211_tdls_recalc_ht_protection(sdata, sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) mutex_unlock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) WARN_ON_ONCE(is_zero_ether_addr(sdata->u.mgd.tdls_peer) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) !ether_addr_equal(sdata->u.mgd.tdls_peer, peer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) case NL80211_TDLS_DISABLE_LINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) * The teardown message in ieee80211_tdls_mgmt_teardown() was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) * created while the queues were stopped, so it might still be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) * pending. Before flushing the queues we need to be sure the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) * message is handled by the tasklet handling pending messages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) * otherwise we might start destroying the station before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) * sending the teardown packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) * Note that this only forces the tasklet to flush pendings -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) * not to stop the tasklet from rescheduling itself.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) tasklet_kill(&local->tx_pending_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) /* flush a potentially queued teardown packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) ieee80211_flush_queues(local, sdata, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) ret = sta_info_destroy_addr(sdata, peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) mutex_lock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) iee80211_tdls_recalc_ht_protection(sdata, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) mutex_unlock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) iee80211_tdls_recalc_chanctx(sdata, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) ret = -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) if (ret == 0 && ether_addr_equal(sdata->u.mgd.tdls_peer, peer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) cancel_delayed_work(&sdata->u.mgd.tdls_peer_del_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) eth_zero_addr(sdata->u.mgd.tdls_peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) ieee80211_queue_work(&sdata->local->hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) &sdata->u.mgd.request_smps_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) mutex_unlock(&local->mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) sdata_unlock(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) void ieee80211_tdls_oper_request(struct ieee80211_vif *vif, const u8 *peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) enum nl80211_tdls_operation oper,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) u16 reason_code, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) sdata_err(sdata, "Discarding TDLS oper %d - not STA or disconnected\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) oper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) cfg80211_tdls_oper_request(sdata->dev, peer, oper, reason_code, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) EXPORT_SYMBOL(ieee80211_tdls_oper_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) iee80211_tdls_add_ch_switch_timing(u8 *buf, u16 switch_time, u16 switch_timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) struct ieee80211_ch_switch_timing *ch_sw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) *buf++ = WLAN_EID_CHAN_SWITCH_TIMING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) *buf++ = sizeof(struct ieee80211_ch_switch_timing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) ch_sw = (void *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) ch_sw->switch_time = cpu_to_le16(switch_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) ch_sw->switch_timeout = cpu_to_le16(switch_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) /* find switch timing IE in SKB ready for Tx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) static const u8 *ieee80211_tdls_find_sw_timing_ie(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) struct ieee80211_tdls_data *tf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) const u8 *ie_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) * Get the offset for the new location of the switch timing IE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) * The SKB network header will now point to the "payload_type"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) * element of the TDLS data frame struct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) tf = container_of(skb->data + skb_network_offset(skb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) struct ieee80211_tdls_data, payload_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) ie_start = tf->u.chan_switch_req.variable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) return cfg80211_find_ie(WLAN_EID_CHAN_SWITCH_TIMING, ie_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) skb->len - (ie_start - skb->data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) static struct sk_buff *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) ieee80211_tdls_ch_sw_tmpl_get(struct sta_info *sta, u8 oper_class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) struct cfg80211_chan_def *chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) u32 *ch_sw_tm_ie_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) struct ieee80211_sub_if_data *sdata = sta->sdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) u8 extra_ies[2 + sizeof(struct ieee80211_sec_chan_offs_ie) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) 2 + sizeof(struct ieee80211_ch_switch_timing)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) int extra_ies_len = 2 + sizeof(struct ieee80211_ch_switch_timing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) u8 *pos = extra_ies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) * if chandef points to a wide channel add a Secondary-Channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) * Offset information element
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) if (chandef->width == NL80211_CHAN_WIDTH_40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) struct ieee80211_sec_chan_offs_ie *sec_chan_ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) bool ht40plus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) *pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) *pos++ = sizeof(*sec_chan_ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) sec_chan_ie = (void *)pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) ht40plus = cfg80211_get_chandef_type(chandef) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) NL80211_CHAN_HT40PLUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) sec_chan_ie->sec_chan_offs = ht40plus ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) IEEE80211_HT_PARAM_CHA_SEC_ABOVE :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) IEEE80211_HT_PARAM_CHA_SEC_BELOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) pos += sizeof(*sec_chan_ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) extra_ies_len += 2 + sizeof(struct ieee80211_sec_chan_offs_ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) /* just set the values to 0, this is a template */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) iee80211_tdls_add_ch_switch_timing(pos, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) skb = ieee80211_tdls_build_mgmt_packet_data(sdata, sta->sta.addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) WLAN_TDLS_CHANNEL_SWITCH_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) 0, 0, !sta->sta.tdls_initiator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) extra_ies, extra_ies_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) oper_class, chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) skb = ieee80211_build_data_template(sdata, skb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) if (IS_ERR(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) tdls_dbg(sdata, "Failed building TDLS channel switch frame\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) if (ch_sw_tm_ie_offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) const u8 *tm_ie = ieee80211_tdls_find_sw_timing_ie(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) if (!tm_ie) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) tdls_dbg(sdata, "No switch timing IE in TDLS switch\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) *ch_sw_tm_ie_offset = tm_ie - skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) tdls_dbg(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) "TDLS channel switch request template for %pM ch %d width %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) sta->sta.addr, chandef->chan->center_freq, chandef->width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) ieee80211_tdls_channel_switch(struct wiphy *wiphy, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) const u8 *addr, u8 oper_class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) struct cfg80211_chan_def *chandef)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) struct sta_info *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) struct sk_buff *skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) u32 ch_sw_tm_ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) if (chandef->chan->freq_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) /* this may work, but is untested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) mutex_lock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) sta = sta_info_get(sdata, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) if (!sta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) tdls_dbg(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) "Invalid TDLS peer %pM for channel switch request\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) if (!test_sta_flag(sta, WLAN_STA_TDLS_CHAN_SWITCH)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) tdls_dbg(sdata, "TDLS channel switch unsupported by %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) ret = -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) skb = ieee80211_tdls_ch_sw_tmpl_get(sta, oper_class, chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) &ch_sw_tm_ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) ret = drv_tdls_channel_switch(local, sdata, &sta->sta, oper_class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) chandef, skb, ch_sw_tm_ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) set_sta_flag(sta, WLAN_STA_TDLS_OFF_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) mutex_unlock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) ieee80211_tdls_cancel_channel_switch(struct wiphy *wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) const u8 *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) struct sta_info *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) mutex_lock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) sta = sta_info_get(sdata, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) if (!sta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) tdls_dbg(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) "Invalid TDLS peer %pM for channel switch cancel\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) if (!test_sta_flag(sta, WLAN_STA_TDLS_OFF_CHANNEL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) tdls_dbg(sdata, "TDLS channel switch not initiated by %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) drv_tdls_cancel_channel_switch(local, sdata, &sta->sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) clear_sta_flag(sta, WLAN_STA_TDLS_OFF_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) mutex_unlock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) static struct sk_buff *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) ieee80211_tdls_ch_sw_resp_tmpl_get(struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) u32 *ch_sw_tm_ie_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) struct ieee80211_sub_if_data *sdata = sta->sdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) u8 extra_ies[2 + sizeof(struct ieee80211_ch_switch_timing)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) /* initial timing are always zero in the template */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) iee80211_tdls_add_ch_switch_timing(extra_ies, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) skb = ieee80211_tdls_build_mgmt_packet_data(sdata, sta->sta.addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) WLAN_TDLS_CHANNEL_SWITCH_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) 0, 0, !sta->sta.tdls_initiator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) extra_ies, sizeof(extra_ies), 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) skb = ieee80211_build_data_template(sdata, skb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) if (IS_ERR(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) tdls_dbg(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) "Failed building TDLS channel switch resp frame\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) if (ch_sw_tm_ie_offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) const u8 *tm_ie = ieee80211_tdls_find_sw_timing_ie(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) if (!tm_ie) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) tdls_dbg(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) "No switch timing IE in TDLS switch resp\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) *ch_sw_tm_ie_offset = tm_ie - skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) tdls_dbg(sdata, "TDLS get channel switch response template for %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) ieee80211_process_tdls_channel_switch_resp(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) struct ieee802_11_elems elems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) struct sta_info *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) struct ieee80211_tdls_data *tf = (void *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) bool local_initiator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) int baselen = offsetof(typeof(*tf), u.chan_switch_resp.variable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) struct ieee80211_tdls_ch_sw_params params = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) params.action_code = WLAN_TDLS_CHANNEL_SWITCH_RESPONSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) params.timestamp = rx_status->device_timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) if (skb->len < baselen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) tdls_dbg(sdata, "TDLS channel switch resp too short: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) mutex_lock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) sta = sta_info_get(sdata, tf->sa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) if (!sta || !test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) tdls_dbg(sdata, "TDLS chan switch from non-peer sta %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) tf->sa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) params.sta = &sta->sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) params.status = le16_to_cpu(tf->u.chan_switch_resp.status_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) if (params.status != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) goto call_drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) ieee802_11_parse_elems(tf->u.chan_switch_resp.variable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) skb->len - baselen, false, &elems,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) if (elems.parse_error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) tdls_dbg(sdata, "Invalid IEs in TDLS channel switch resp\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) if (!elems.ch_sw_timing || !elems.lnk_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) tdls_dbg(sdata, "TDLS channel switch resp - missing IEs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) /* validate the initiator is set correctly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) local_initiator =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) !memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) if (local_initiator == sta->sta.tdls_initiator) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) params.tmpl_skb =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) ieee80211_tdls_ch_sw_resp_tmpl_get(sta, ¶ms.ch_sw_tm_ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) if (!params.tmpl_skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) call_drv:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) drv_tdls_recv_channel_switch(sdata->local, sdata, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) tdls_dbg(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) "TDLS channel switch response received from %pM status %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) tf->sa, params.status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) mutex_unlock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) dev_kfree_skb_any(params.tmpl_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) struct ieee802_11_elems elems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) struct cfg80211_chan_def chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) struct ieee80211_channel *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) enum nl80211_channel_type chan_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) int freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) u8 target_channel, oper_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) bool local_initiator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) struct sta_info *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) enum nl80211_band band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) struct ieee80211_tdls_data *tf = (void *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) int baselen = offsetof(typeof(*tf), u.chan_switch_req.variable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) struct ieee80211_tdls_ch_sw_params params = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) params.action_code = WLAN_TDLS_CHANNEL_SWITCH_REQUEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) params.timestamp = rx_status->device_timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) if (skb->len < baselen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) tdls_dbg(sdata, "TDLS channel switch req too short: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) target_channel = tf->u.chan_switch_req.target_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) oper_class = tf->u.chan_switch_req.oper_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) * We can't easily infer the channel band. The operating class is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) * ambiguous - there are multiple tables (US/Europe/JP/Global). The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) * solution here is to treat channels with number >14 as 5GHz ones,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) * and specifically check for the (oper_class, channel) combinations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) * where this doesn't hold. These are thankfully unique according to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) * IEEE802.11-2012.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) * We consider only the 2GHz and 5GHz bands and 20MHz+ channels as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) * valid here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) if ((oper_class == 112 || oper_class == 2 || oper_class == 3 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) oper_class == 4 || oper_class == 5 || oper_class == 6) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) target_channel < 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) band = NL80211_BAND_5GHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) band = target_channel < 14 ? NL80211_BAND_2GHZ :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) NL80211_BAND_5GHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) freq = ieee80211_channel_to_frequency(target_channel, band);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) if (freq == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) tdls_dbg(sdata, "Invalid channel in TDLS chan switch: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) target_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) chan = ieee80211_get_channel(sdata->local->hw.wiphy, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) if (!chan) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) tdls_dbg(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) "Unsupported channel for TDLS chan switch: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) target_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) ieee802_11_parse_elems(tf->u.chan_switch_req.variable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) skb->len - baselen, false, &elems, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) if (elems.parse_error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) tdls_dbg(sdata, "Invalid IEs in TDLS channel switch req\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) if (!elems.ch_sw_timing || !elems.lnk_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) tdls_dbg(sdata, "TDLS channel switch req - missing IEs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) if (!elems.sec_chan_offs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) chan_type = NL80211_CHAN_HT20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) switch (elems.sec_chan_offs->sec_chan_offs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) chan_type = NL80211_CHAN_HT40PLUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) chan_type = NL80211_CHAN_HT40MINUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) chan_type = NL80211_CHAN_HT20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) cfg80211_chandef_create(&chandef, chan, chan_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) /* we will be active on the TDLS link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) if (!cfg80211_reg_can_beacon_relax(sdata->local->hw.wiphy, &chandef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) sdata->wdev.iftype)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) tdls_dbg(sdata, "TDLS chan switch to forbidden channel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) mutex_lock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) sta = sta_info_get(sdata, tf->sa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) if (!sta || !test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) tdls_dbg(sdata, "TDLS chan switch from non-peer sta %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) tf->sa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) params.sta = &sta->sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) /* validate the initiator is set correctly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) local_initiator =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) !memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) if (local_initiator == sta->sta.tdls_initiator) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) /* peer should have known better */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) if (!sta->sta.ht_cap.ht_supported && elems.sec_chan_offs &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) elems.sec_chan_offs->sec_chan_offs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) tdls_dbg(sdata, "TDLS chan switch - wide chan unsupported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) ret = -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) params.chandef = &chandef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) params.tmpl_skb =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) ieee80211_tdls_ch_sw_resp_tmpl_get(sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) ¶ms.ch_sw_tm_ie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) if (!params.tmpl_skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) drv_tdls_recv_channel_switch(sdata->local, sdata, ¶ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) tdls_dbg(sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) "TDLS ch switch request received from %pM ch %d width %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) tf->sa, params.chandef->chan->center_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) params.chandef->width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) mutex_unlock(&local->sta_mtx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) dev_kfree_skb_any(params.tmpl_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) ieee80211_process_tdls_channel_switch(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) struct ieee80211_tdls_data *tf = (void *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) struct wiphy *wiphy = sdata->local->hw.wiphy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) /* make sure the driver supports it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) if (!(wiphy->features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) /* we want to access the entire packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) if (skb_linearize(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) * The packet/size was already validated by mac80211 Rx path, only look
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) * at the action type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) switch (tf->action_code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) ieee80211_process_tdls_channel_switch_req(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) ieee80211_process_tdls_channel_switch_resp(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) WARN_ON_ONCE(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) void ieee80211_teardown_tdls_peers(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) struct sta_info *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) u16 reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) if (!sta->sta.tdls || sta->sdata != sdata || !sta->uploaded ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) !test_sta_flag(sta, WLAN_STA_AUTHORIZED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) ieee80211_tdls_oper_request(&sdata->vif, sta->sta.addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) NL80211_TDLS_TEARDOWN, reason,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) void ieee80211_tdls_chsw_work(struct work_struct *wk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) struct ieee80211_local *local =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) container_of(wk, struct ieee80211_local, tdls_chsw_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) struct ieee80211_sub_if_data *sdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) struct ieee80211_tdls_data *tf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) while ((skb = skb_dequeue(&local->skb_queue_tdls_chsw))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) tf = (struct ieee80211_tdls_data *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) list_for_each_entry(sdata, &local->interfaces, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) if (!ieee80211_sdata_running(sdata) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) sdata->vif.type != NL80211_IFTYPE_STATION ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) !ether_addr_equal(tf->da, sdata->vif.addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) ieee80211_process_tdls_channel_switch(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) void ieee80211_tdls_handle_disconnect(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) const u8 *peer, u16 reason)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) struct ieee80211_sta *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) sta = ieee80211_find_sta(&sdata->vif, peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) if (!sta || !sta->tdls) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) tdls_dbg(sdata, "disconnected from TDLS peer %pM (Reason: %u=%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) peer, reason,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) ieee80211_get_reason_code_string(reason));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) ieee80211_tdls_oper_request(&sdata->vif, peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) NL80211_TDLS_TEARDOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) }