Commit e132eb09fdd2b8a2db7af79e01b2d798604f63d9

Authored by Emmanuel Grumbach
Committed by Greg Kroah-Hartman
1 parent 8788737af3

mac80211: don't Tx a deauth frame if the AP forbade Tx

[ Upstream commit 6c18b27d6e5c6a7206364eae2b47bc8d8b2fa68f ]

If the driver fails to properly prepare for the channel
switch, mac80211 will disconnect. If the CSA IE had mode
set to 1, it means that the clients are not allowed to send
any Tx on the current channel, and that includes the
deauthentication frame.

Make sure that we don't send the deauthentication frame in
this case.

In iwlwifi, this caused a failure to flush queues since the
firmware already closed the queues after having parsed the
CSA IE. Then mac80211 would wait until the deauthentication
frame would go out (drv_flush(drop=false)) and that would
never happen.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 1 changed file with 15 additions and 2 deletions Side-by-side Diff

... ... @@ -1280,6 +1280,16 @@
1280 1280 cbss->beacon_interval));
1281 1281 return;
1282 1282 drop_connection:
  1283 + /*
  1284 + * This is just so that the disconnect flow will know that
  1285 + * we were trying to switch channel and failed. In case the
  1286 + * mode is 1 (we are not allowed to Tx), we will know not to
  1287 + * send a deauthentication frame. Those two fields will be
  1288 + * reset when the disconnection worker runs.
  1289 + */
  1290 + sdata->vif.csa_active = true;
  1291 + sdata->csa_block_tx = csa_ie.mode;
  1292 +
1283 1293 ieee80211_queue_work(&local->hw, &ifmgd->csa_connection_drop_work);
1284 1294 mutex_unlock(&local->chanctx_mtx);
1285 1295 mutex_unlock(&local->mtx);
... ... @@ -2450,6 +2460,7 @@
2450 2460 struct ieee80211_local *local = sdata->local;
2451 2461 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2452 2462 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
  2463 + bool tx;
2453 2464  
2454 2465 sdata_lock(sdata);
2455 2466 if (!ifmgd->associated) {
... ... @@ -2457,6 +2468,8 @@
2457 2468 return;
2458 2469 }
2459 2470  
  2471 + tx = !sdata->csa_block_tx;
  2472 +
2460 2473 /* AP is probably out of range (or not reachable for another reason) so
2461 2474 * remove the bss struct for that AP.
2462 2475 */
... ... @@ -2464,7 +2477,7 @@
2464 2477  
2465 2478 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
2466 2479 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
2467   - true, frame_buf);
  2480 + tx, frame_buf);
2468 2481 mutex_lock(&local->mtx);
2469 2482 sdata->vif.csa_active = false;
2470 2483 ifmgd->csa_waiting_bcn = false;
... ... @@ -2475,7 +2488,7 @@
2475 2488 }
2476 2489 mutex_unlock(&local->mtx);
2477 2490  
2478   - ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true,
  2491 + ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), tx,
2479 2492 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
2480 2493  
2481 2494 sdata_unlock(sdata);