aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/mlme.c71
1 files changed, 38 insertions, 33 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index edba1d8158fc..82d49341eaa0 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -88,6 +88,8 @@ MODULE_PARM_DESC(probe_wait_ms,
88#define TMR_RUNNING_TIMER 0 88#define TMR_RUNNING_TIMER 0
89#define TMR_RUNNING_CHANSW 1 89#define TMR_RUNNING_CHANSW 1
90 90
91#define DEAUTH_DISASSOC_LEN (24 /* hdr */ + 2 /* reason */)
92
91/* 93/*
92 * All cfg80211 functions have to be called outside a locked 94 * All cfg80211 functions have to be called outside a locked
93 * section so that they can acquire a lock themselves... This 95 * section so that they can acquire a lock themselves... This
@@ -613,47 +615,41 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
613 615
614static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, 616static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
615 const u8 *bssid, u16 stype, 617 const u8 *bssid, u16 stype,
616 u16 reason, bool cfg80211_locked, 618 u16 reason, bool send_frame,
617 bool send_frame) 619 u8 *frame_buf)
618{ 620{
619 struct ieee80211_local *local = sdata->local; 621 struct ieee80211_local *local = sdata->local;
620 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 622 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
621 struct sk_buff *skb; 623 struct sk_buff *skb;
622 struct ieee80211_mgmt *mgmt; 624 struct ieee80211_mgmt *mgmt = (void *)frame_buf;
623
624 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
625 if (!skb)
626 return;
627 625
628 skb_reserve(skb, local->hw.extra_tx_headroom); 626 /* build frame */
629 627 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
630 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); 628 mgmt->duration = 0; /* initialize only */
631 memset(mgmt, 0, 24); 629 mgmt->seq_ctrl = 0; /* initialize only */
632 memcpy(mgmt->da, bssid, ETH_ALEN); 630 memcpy(mgmt->da, bssid, ETH_ALEN);
633 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); 631 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
634 memcpy(mgmt->bssid, bssid, ETH_ALEN); 632 memcpy(mgmt->bssid, bssid, ETH_ALEN);
635 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
636 skb_put(skb, 2);
637 /* u.deauth.reason_code == u.disassoc.reason_code */ 633 /* u.deauth.reason_code == u.disassoc.reason_code */
638 mgmt->u.deauth.reason_code = cpu_to_le16(reason); 634 mgmt->u.deauth.reason_code = cpu_to_le16(reason);
639 635
640 if (stype == IEEE80211_STYPE_DEAUTH) 636 if (send_frame) {
641 if (cfg80211_locked) 637 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
642 __cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); 638 DEAUTH_DISASSOC_LEN);
643 else 639 if (!skb)
644 cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); 640 return;
645 else
646 if (cfg80211_locked)
647 __cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
648 else
649 cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
650 if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED))
651 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
652 641
653 if (send_frame) 642 skb_reserve(skb, local->hw.extra_tx_headroom);
643
644 /* copy in frame */
645 memcpy(skb_put(skb, DEAUTH_DISASSOC_LEN),
646 mgmt, DEAUTH_DISASSOC_LEN);
647
648 if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED))
649 IEEE80211_SKB_CB(skb)->flags |=
650 IEEE80211_TX_INTFL_DONT_ENCRYPT;
654 ieee80211_tx_skb(sdata, skb); 651 ieee80211_tx_skb(sdata, skb);
655 else 652 }
656 kfree_skb(skb);
657} 653}
658 654
659void ieee80211_send_pspoll(struct ieee80211_local *local, 655void ieee80211_send_pspoll(struct ieee80211_local *local,
@@ -1675,6 +1671,7 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
1675 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1671 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1676 struct ieee80211_local *local = sdata->local; 1672 struct ieee80211_local *local = sdata->local;
1677 u8 bssid[ETH_ALEN]; 1673 u8 bssid[ETH_ALEN];
1674 u8 frame_buf[DEAUTH_DISASSOC_LEN];
1678 1675
1679 mutex_lock(&ifmgd->mtx); 1676 mutex_lock(&ifmgd->mtx);
1680 if (!ifmgd->associated) { 1677 if (!ifmgd->associated) {
@@ -1697,7 +1694,8 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
1697 ieee80211_send_deauth_disassoc(sdata, bssid, 1694 ieee80211_send_deauth_disassoc(sdata, bssid,
1698 IEEE80211_STYPE_DEAUTH, 1695 IEEE80211_STYPE_DEAUTH,
1699 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, 1696 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
1700 false, true); 1697 false, frame_buf);
1698 cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN);
1701 1699
1702 mutex_lock(&local->mtx); 1700 mutex_lock(&local->mtx);
1703 ieee80211_recalc_idle(local); 1701 ieee80211_recalc_idle(local);
@@ -2696,6 +2694,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
2696{ 2694{
2697 struct ieee80211_local *local = sdata->local; 2695 struct ieee80211_local *local = sdata->local;
2698 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2696 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2697 u8 frame_buf[DEAUTH_DISASSOC_LEN];
2699 2698
2700 ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | 2699 ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
2701 IEEE80211_STA_BEACON_POLL); 2700 IEEE80211_STA_BEACON_POLL);
@@ -2708,7 +2707,8 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
2708 */ 2707 */
2709 ieee80211_send_deauth_disassoc(sdata, bssid, 2708 ieee80211_send_deauth_disassoc(sdata, bssid,
2710 IEEE80211_STYPE_DEAUTH, 2709 IEEE80211_STYPE_DEAUTH,
2711 reason, false, true); 2710 reason, false, frame_buf);
2711 cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN);
2712 2712
2713 mutex_lock(&local->mtx); 2713 mutex_lock(&local->mtx);
2714 ieee80211_recalc_idle(local); 2714 ieee80211_recalc_idle(local);
@@ -3444,6 +3444,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
3444{ 3444{
3445 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3445 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3446 bool assoc_bss = false; 3446 bool assoc_bss = false;
3447 u8 frame_buf[DEAUTH_DISASSOC_LEN];
3447 3448
3448 mutex_lock(&ifmgd->mtx); 3449 mutex_lock(&ifmgd->mtx);
3449 3450
@@ -3463,7 +3464,8 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
3463 3464
3464 ieee80211_send_deauth_disassoc(sdata, req->bssid, 3465 ieee80211_send_deauth_disassoc(sdata, req->bssid,
3465 IEEE80211_STYPE_DEAUTH, 3466 IEEE80211_STYPE_DEAUTH,
3466 req->reason_code, true, true); 3467 req->reason_code, true, frame_buf);
3468 __cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN);
3467 if (assoc_bss) 3469 if (assoc_bss)
3468 sta_info_flush(sdata->local, sdata); 3470 sta_info_flush(sdata->local, sdata);
3469 3471
@@ -3479,6 +3481,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
3479{ 3481{
3480 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3482 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3481 u8 bssid[ETH_ALEN]; 3483 u8 bssid[ETH_ALEN];
3484 u8 frame_buf[DEAUTH_DISASSOC_LEN];
3482 3485
3483 mutex_lock(&ifmgd->mtx); 3486 mutex_lock(&ifmgd->mtx);
3484 3487
@@ -3502,8 +3505,10 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
3502 mutex_unlock(&ifmgd->mtx); 3505 mutex_unlock(&ifmgd->mtx);
3503 3506
3504 ieee80211_send_deauth_disassoc(sdata, req->bss->bssid, 3507 ieee80211_send_deauth_disassoc(sdata, req->bss->bssid,
3505 IEEE80211_STYPE_DISASSOC, req->reason_code, 3508 IEEE80211_STYPE_DISASSOC,
3506 true, !req->local_state_change); 3509 req->reason_code,
3510 !req->local_state_change, frame_buf);
3511 __cfg80211_send_disassoc(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN);
3507 sta_info_flush(sdata->local, sdata); 3512 sta_info_flush(sdata->local, sdata);
3508 3513
3509 mutex_lock(&sdata->local->mtx); 3514 mutex_lock(&sdata->local->mtx);