Loading include/net/cfg80211.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -1218,6 +1218,7 @@ struct cfg80211_deauth_request { const u8 *ie; const u8 *ie; size_t ie_len; size_t ie_len; u16 reason_code; u16 reason_code; bool local_state_change; }; }; /** /** Loading net/mac80211/mlme.c +23 −12 Original line number Original line Diff line number Diff line Loading @@ -3099,24 +3099,34 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, ht_cfreq, ht_oper->primary_chan, ht_cfreq, ht_oper->primary_chan, cbss->channel->band); cbss->channel->band); ht_oper = NULL; ht_oper = NULL; } else { channel_type = NL80211_CHAN_HT20; } } } } if (ht_oper) { if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { channel_type = NL80211_CHAN_HT20; /* * cfg80211 already verified that the channel itself can * be used, but it didn't check that we can do the right * HT type, so do that here as well. If HT40 isn't allowed * on this channel, disable 40 MHz operation. */ if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; else channel_type = NL80211_CHAN_HT40PLUS; channel_type = NL80211_CHAN_HT40PLUS; break; break; case IEEE80211_HT_PARAM_CHA_SEC_BELOW: case IEEE80211_HT_PARAM_CHA_SEC_BELOW: if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; else channel_type = NL80211_CHAN_HT40MINUS; channel_type = NL80211_CHAN_HT40MINUS; break; break; } } } } } if (!ieee80211_set_channel_type(local, sdata, channel_type)) { if (!ieee80211_set_channel_type(local, sdata, channel_type)) { /* can only fail due to HT40+/- mismatch */ /* can only fail due to HT40+/- mismatch */ Loading Loading @@ -3549,6 +3559,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, { { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; bool tx = !req->local_state_change; mutex_lock(&ifmgd->mtx); mutex_lock(&ifmgd->mtx); Loading @@ -3565,12 +3576,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, if (ifmgd->associated && if (ifmgd->associated && ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, req->reason_code, true, frame_buf); req->reason_code, tx, frame_buf); } else { } else { drv_mgd_prepare_tx(sdata->local, sdata); drv_mgd_prepare_tx(sdata->local, sdata); ieee80211_send_deauth_disassoc(sdata, req->bssid, ieee80211_send_deauth_disassoc(sdata, req->bssid, IEEE80211_STYPE_DEAUTH, IEEE80211_STYPE_DEAUTH, req->reason_code, true, req->reason_code, tx, frame_buf); frame_buf); } } Loading net/mac80211/wpa.c +8 −3 Original line number Original line Diff line number Diff line Loading @@ -546,14 +546,19 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) static void bip_aad(struct sk_buff *skb, u8 *aad) static void bip_aad(struct sk_buff *skb, u8 *aad) { { __le16 mask_fc; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; /* BIP AAD: FC(masked) || A1 || A2 || A3 */ /* BIP AAD: FC(masked) || A1 || A2 || A3 */ /* FC type/subtype */ /* FC type/subtype */ aad[0] = skb->data[0]; /* Mask FC Retry, PwrMgt, MoreData flags to zero */ /* Mask FC Retry, PwrMgt, MoreData flags to zero */ aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6)); mask_fc = hdr->frame_control; mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA); put_unaligned(mask_fc, (__le16 *) &aad[0]); /* A1 || A2 || A3 */ /* A1 || A2 || A3 */ memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN); memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN); } } Loading net/wireless/mlme.c +3 −9 Original line number Original line Diff line number Diff line Loading @@ -457,20 +457,14 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, .reason_code = reason, .reason_code = reason, .ie = ie, .ie = ie, .ie_len = ie_len, .ie_len = ie_len, .local_state_change = local_state_change, }; }; ASSERT_WDEV_LOCK(wdev); ASSERT_WDEV_LOCK(wdev); if (local_state_change) { if (local_state_change && (!wdev->current_bss || if (wdev->current_bss && !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))) ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(&wdev->current_bss->pub); wdev->current_bss = NULL; } return 0; return 0; } return rdev->ops->deauth(&rdev->wiphy, dev, &req); return rdev->ops->deauth(&rdev->wiphy, dev, &req); } } Loading Loading
include/net/cfg80211.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -1218,6 +1218,7 @@ struct cfg80211_deauth_request { const u8 *ie; const u8 *ie; size_t ie_len; size_t ie_len; u16 reason_code; u16 reason_code; bool local_state_change; }; }; /** /** Loading
net/mac80211/mlme.c +23 −12 Original line number Original line Diff line number Diff line Loading @@ -3099,24 +3099,34 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, ht_cfreq, ht_oper->primary_chan, ht_cfreq, ht_oper->primary_chan, cbss->channel->band); cbss->channel->band); ht_oper = NULL; ht_oper = NULL; } else { channel_type = NL80211_CHAN_HT20; } } } } if (ht_oper) { if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { channel_type = NL80211_CHAN_HT20; /* * cfg80211 already verified that the channel itself can * be used, but it didn't check that we can do the right * HT type, so do that here as well. If HT40 isn't allowed * on this channel, disable 40 MHz operation. */ if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; else channel_type = NL80211_CHAN_HT40PLUS; channel_type = NL80211_CHAN_HT40PLUS; break; break; case IEEE80211_HT_PARAM_CHA_SEC_BELOW: case IEEE80211_HT_PARAM_CHA_SEC_BELOW: if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; else channel_type = NL80211_CHAN_HT40MINUS; channel_type = NL80211_CHAN_HT40MINUS; break; break; } } } } } if (!ieee80211_set_channel_type(local, sdata, channel_type)) { if (!ieee80211_set_channel_type(local, sdata, channel_type)) { /* can only fail due to HT40+/- mismatch */ /* can only fail due to HT40+/- mismatch */ Loading Loading @@ -3549,6 +3559,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, { { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; bool tx = !req->local_state_change; mutex_lock(&ifmgd->mtx); mutex_lock(&ifmgd->mtx); Loading @@ -3565,12 +3576,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, if (ifmgd->associated && if (ifmgd->associated && ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, req->reason_code, true, frame_buf); req->reason_code, tx, frame_buf); } else { } else { drv_mgd_prepare_tx(sdata->local, sdata); drv_mgd_prepare_tx(sdata->local, sdata); ieee80211_send_deauth_disassoc(sdata, req->bssid, ieee80211_send_deauth_disassoc(sdata, req->bssid, IEEE80211_STYPE_DEAUTH, IEEE80211_STYPE_DEAUTH, req->reason_code, true, req->reason_code, tx, frame_buf); frame_buf); } } Loading
net/mac80211/wpa.c +8 −3 Original line number Original line Diff line number Diff line Loading @@ -546,14 +546,19 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) static void bip_aad(struct sk_buff *skb, u8 *aad) static void bip_aad(struct sk_buff *skb, u8 *aad) { { __le16 mask_fc; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; /* BIP AAD: FC(masked) || A1 || A2 || A3 */ /* BIP AAD: FC(masked) || A1 || A2 || A3 */ /* FC type/subtype */ /* FC type/subtype */ aad[0] = skb->data[0]; /* Mask FC Retry, PwrMgt, MoreData flags to zero */ /* Mask FC Retry, PwrMgt, MoreData flags to zero */ aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6)); mask_fc = hdr->frame_control; mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA); put_unaligned(mask_fc, (__le16 *) &aad[0]); /* A1 || A2 || A3 */ /* A1 || A2 || A3 */ memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN); memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN); } } Loading
net/wireless/mlme.c +3 −9 Original line number Original line Diff line number Diff line Loading @@ -457,20 +457,14 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, .reason_code = reason, .reason_code = reason, .ie = ie, .ie = ie, .ie_len = ie_len, .ie_len = ie_len, .local_state_change = local_state_change, }; }; ASSERT_WDEV_LOCK(wdev); ASSERT_WDEV_LOCK(wdev); if (local_state_change) { if (local_state_change && (!wdev->current_bss || if (wdev->current_bss && !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))) ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(&wdev->current_bss->pub); wdev->current_bss = NULL; } return 0; return 0; } return rdev->ops->deauth(&rdev->wiphy, dev, &req); return rdev->ops->deauth(&rdev->wiphy, dev, &req); } } Loading