diff options
-rw-r--r-- | net/mac80211/mlme.c | 71 |
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 | ||
614 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | 616 | static 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 | ||
659 | void ieee80211_send_pspoll(struct ieee80211_local *local, | 655 | void 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); |