.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * IBSS mode implementation |
---|
3 | 4 | * Copyright 2003-2008, Jouni Malinen <j@w1.fi> |
---|
.. | .. |
---|
8 | 9 | * Copyright 2009, Johannes Berg <johannes@sipsolutions.net> |
---|
9 | 10 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
---|
10 | 11 | * Copyright(c) 2016 Intel Deutschland GmbH |
---|
11 | | - * |
---|
12 | | - * This program is free software; you can redistribute it and/or modify |
---|
13 | | - * it under the terms of the GNU General Public License version 2 as |
---|
14 | | - * published by the Free Software Foundation. |
---|
| 12 | + * Copyright(c) 2018-2020 Intel Corporation |
---|
15 | 13 | */ |
---|
16 | 14 | |
---|
17 | 15 | #include <linux/delay.h> |
---|
.. | .. |
---|
147 | 145 | *pos++ = csa_settings->block_tx ? 1 : 0; |
---|
148 | 146 | *pos++ = ieee80211_frequency_to_channel( |
---|
149 | 147 | csa_settings->chandef.chan->center_freq); |
---|
150 | | - presp->csa_counter_offsets[0] = (pos - presp->head); |
---|
| 148 | + presp->cntdwn_counter_offsets[0] = (pos - presp->head); |
---|
151 | 149 | *pos++ = csa_settings->count; |
---|
152 | | - presp->csa_current_counter = csa_settings->count; |
---|
| 150 | + presp->cntdwn_current_counter = csa_settings->count; |
---|
153 | 151 | } |
---|
154 | 152 | |
---|
155 | 153 | /* put the remaining rates in WLAN_EID_EXT_SUPP_RATES */ |
---|
.. | .. |
---|
540 | 538 | { |
---|
541 | 539 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
---|
542 | 540 | struct cfg80211_bss *cbss; |
---|
543 | | - int err, changed = 0; |
---|
544 | 541 | |
---|
545 | 542 | sdata_assert_lock(sdata); |
---|
| 543 | + |
---|
| 544 | + /* When not connected/joined, sending CSA doesn't make sense. */ |
---|
| 545 | + if (ifibss->state != IEEE80211_IBSS_MLME_JOINED) |
---|
| 546 | + return -ENOLINK; |
---|
546 | 547 | |
---|
547 | 548 | /* update cfg80211 bss information with the new channel */ |
---|
548 | 549 | if (!is_zero_ether_addr(ifibss->bssid)) { |
---|
.. | .. |
---|
562 | 563 | ifibss->chandef = sdata->csa_chandef; |
---|
563 | 564 | |
---|
564 | 565 | /* generate the beacon */ |
---|
565 | | - err = ieee80211_ibss_csa_beacon(sdata, NULL); |
---|
566 | | - if (err < 0) |
---|
567 | | - return err; |
---|
568 | | - |
---|
569 | | - changed |= err; |
---|
570 | | - |
---|
571 | | - return changed; |
---|
| 566 | + return ieee80211_ibss_csa_beacon(sdata, NULL); |
---|
572 | 567 | } |
---|
573 | 568 | |
---|
574 | 569 | void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata) |
---|
.. | .. |
---|
790 | 785 | enum nl80211_channel_type ch_type; |
---|
791 | 786 | int err; |
---|
792 | 787 | u32 sta_flags; |
---|
| 788 | + u32 vht_cap_info = 0; |
---|
793 | 789 | |
---|
794 | 790 | sdata_assert_lock(sdata); |
---|
795 | 791 | |
---|
.. | .. |
---|
799 | 795 | case NL80211_CHAN_WIDTH_10: |
---|
800 | 796 | case NL80211_CHAN_WIDTH_20_NOHT: |
---|
801 | 797 | sta_flags |= IEEE80211_STA_DISABLE_HT; |
---|
802 | | - /* fall through */ |
---|
| 798 | + fallthrough; |
---|
803 | 799 | case NL80211_CHAN_WIDTH_20: |
---|
804 | 800 | sta_flags |= IEEE80211_STA_DISABLE_40MHZ; |
---|
805 | 801 | break; |
---|
.. | .. |
---|
807 | 803 | break; |
---|
808 | 804 | } |
---|
809 | 805 | |
---|
| 806 | + if (elems->vht_cap_elem) |
---|
| 807 | + vht_cap_info = le32_to_cpu(elems->vht_cap_elem->vht_cap_info); |
---|
| 808 | + |
---|
810 | 809 | memset(¶ms, 0, sizeof(params)); |
---|
811 | 810 | err = ieee80211_parse_ch_switch_ie(sdata, elems, |
---|
812 | 811 | ifibss->chandef.chan->band, |
---|
| 812 | + vht_cap_info, |
---|
813 | 813 | sta_flags, ifibss->bssid, &csa_ie); |
---|
814 | 814 | /* can't switch to destination channel, fail */ |
---|
815 | 815 | if (err < 0) |
---|
.. | .. |
---|
1041 | 1041 | } |
---|
1042 | 1042 | |
---|
1043 | 1043 | if (sta && !sta->sta.wme && |
---|
1044 | | - elems->wmm_info && local->hw.queues >= IEEE80211_NUM_ACS) { |
---|
| 1044 | + (elems->wmm_info || elems->s1g_capab) && |
---|
| 1045 | + local->hw.queues >= IEEE80211_NUM_ACS) { |
---|
1045 | 1046 | sta->sta.wme = true; |
---|
1046 | 1047 | ieee80211_check_fast_xmit(sta); |
---|
1047 | 1048 | } |
---|
.. | .. |
---|
1069 | 1070 | /* we both use VHT */ |
---|
1070 | 1071 | struct ieee80211_vht_cap cap_ie; |
---|
1071 | 1072 | struct ieee80211_sta_vht_cap cap = sta->sta.vht_cap; |
---|
| 1073 | + u32 vht_cap_info = |
---|
| 1074 | + le32_to_cpu(elems->vht_cap_elem->vht_cap_info); |
---|
1072 | 1075 | |
---|
1073 | | - ieee80211_chandef_vht_oper(elems->vht_operation, |
---|
| 1076 | + ieee80211_chandef_vht_oper(&local->hw, vht_cap_info, |
---|
| 1077 | + elems->vht_operation, |
---|
| 1078 | + elems->ht_operation, |
---|
1074 | 1079 | &chandef); |
---|
1075 | 1080 | memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie)); |
---|
1076 | 1081 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
---|
.. | .. |
---|
1122 | 1127 | |
---|
1123 | 1128 | ieee80211_update_sta_info(sdata, mgmt, len, rx_status, elems, channel); |
---|
1124 | 1129 | |
---|
1125 | | - bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, |
---|
1126 | | - channel); |
---|
| 1130 | + bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, channel); |
---|
1127 | 1131 | if (!bss) |
---|
1128 | 1132 | return; |
---|
1129 | 1133 | |
---|
.. | .. |
---|
1253 | 1257 | |
---|
1254 | 1258 | static void ieee80211_ibss_sta_expire(struct ieee80211_sub_if_data *sdata) |
---|
1255 | 1259 | { |
---|
| 1260 | + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
---|
1256 | 1261 | struct ieee80211_local *local = sdata->local; |
---|
1257 | 1262 | struct sta_info *sta, *tmp; |
---|
1258 | 1263 | unsigned long exp_time = IEEE80211_IBSS_INACTIVITY_LIMIT; |
---|
.. | .. |
---|
1269 | 1274 | if (time_is_before_jiffies(last_active + exp_time) || |
---|
1270 | 1275 | (time_is_before_jiffies(last_active + exp_rsn) && |
---|
1271 | 1276 | sta->sta_state != IEEE80211_STA_AUTHORIZED)) { |
---|
| 1277 | + u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
---|
| 1278 | + |
---|
1272 | 1279 | sta_dbg(sta->sdata, "expiring inactive %sSTA %pM\n", |
---|
1273 | 1280 | sta->sta_state != IEEE80211_STA_AUTHORIZED ? |
---|
1274 | 1281 | "not authorized " : "", sta->sta.addr); |
---|
1275 | 1282 | |
---|
| 1283 | + ieee80211_send_deauth_disassoc(sdata, sta->sta.addr, |
---|
| 1284 | + ifibss->bssid, |
---|
| 1285 | + IEEE80211_STYPE_DEAUTH, |
---|
| 1286 | + WLAN_REASON_DEAUTH_LEAVING, |
---|
| 1287 | + true, frame_buf); |
---|
1276 | 1288 | WARN_ON(__sta_info_destroy(sta)); |
---|
1277 | 1289 | } |
---|
1278 | 1290 | } |
---|
.. | .. |
---|
1394 | 1406 | break; |
---|
1395 | 1407 | case NL80211_CHAN_WIDTH_80P80: |
---|
1396 | 1408 | cf2 = chandef->center_freq2; |
---|
1397 | | - /* fall through */ |
---|
| 1409 | + fallthrough; |
---|
1398 | 1410 | case NL80211_CHAN_WIDTH_80: |
---|
1399 | 1411 | width = 80; |
---|
1400 | 1412 | break; |
---|
.. | .. |
---|
1602 | 1614 | return; |
---|
1603 | 1615 | |
---|
1604 | 1616 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, |
---|
1605 | | - false, &elems); |
---|
| 1617 | + false, &elems, mgmt->bssid, NULL); |
---|
1606 | 1618 | |
---|
1607 | 1619 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); |
---|
1608 | 1620 | } |
---|
.. | .. |
---|
1652 | 1664 | |
---|
1653 | 1665 | ieee802_11_parse_elems( |
---|
1654 | 1666 | mgmt->u.action.u.chan_switch.variable, |
---|
1655 | | - ies_len, true, &elems); |
---|
| 1667 | + ies_len, true, &elems, mgmt->bssid, NULL); |
---|
1656 | 1668 | |
---|
1657 | 1669 | if (elems.parse_error) |
---|
1658 | 1670 | break; |
---|
.. | .. |
---|
1758 | 1770 | int i; |
---|
1759 | 1771 | int ret; |
---|
1760 | 1772 | |
---|
| 1773 | + if (params->chandef.chan->freq_offset) { |
---|
| 1774 | + /* this may work, but is untested */ |
---|
| 1775 | + return -EOPNOTSUPP; |
---|
| 1776 | + } |
---|
| 1777 | + |
---|
1761 | 1778 | ret = cfg80211_chandef_dfs_required(local->hw.wiphy, |
---|
1762 | 1779 | ¶ms->chandef, |
---|
1763 | 1780 | sdata->wdev.iftype); |
---|