diff options
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r-- | net/mac80211/util.c | 51 |
1 files changed, 47 insertions, 4 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 471fb0516c99..22ca35054dd0 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -792,8 +792,11 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
792 | elems->country_elem_len = elen; | 792 | elems->country_elem_len = elen; |
793 | break; | 793 | break; |
794 | case WLAN_EID_PWR_CONSTRAINT: | 794 | case WLAN_EID_PWR_CONSTRAINT: |
795 | if (elen != 1) { | ||
796 | elem_parse_failed = true; | ||
797 | break; | ||
798 | } | ||
795 | elems->pwr_constr_elem = pos; | 799 | elems->pwr_constr_elem = pos; |
796 | elems->pwr_constr_elem_len = elen; | ||
797 | break; | 800 | break; |
798 | case WLAN_EID_TIMEOUT_INTERVAL: | 801 | case WLAN_EID_TIMEOUT_INTERVAL: |
799 | elems->timeout_int = pos; | 802 | elems->timeout_int = pos; |
@@ -1004,6 +1007,45 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
1004 | ieee80211_tx_skb(sdata, skb); | 1007 | ieee80211_tx_skb(sdata, skb); |
1005 | } | 1008 | } |
1006 | 1009 | ||
1010 | void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | ||
1011 | const u8 *bssid, u16 stype, u16 reason, | ||
1012 | bool send_frame, u8 *frame_buf) | ||
1013 | { | ||
1014 | struct ieee80211_local *local = sdata->local; | ||
1015 | struct sk_buff *skb; | ||
1016 | struct ieee80211_mgmt *mgmt = (void *)frame_buf; | ||
1017 | |||
1018 | /* build frame */ | ||
1019 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); | ||
1020 | mgmt->duration = 0; /* initialize only */ | ||
1021 | mgmt->seq_ctrl = 0; /* initialize only */ | ||
1022 | memcpy(mgmt->da, bssid, ETH_ALEN); | ||
1023 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | ||
1024 | memcpy(mgmt->bssid, bssid, ETH_ALEN); | ||
1025 | /* u.deauth.reason_code == u.disassoc.reason_code */ | ||
1026 | mgmt->u.deauth.reason_code = cpu_to_le16(reason); | ||
1027 | |||
1028 | if (send_frame) { | ||
1029 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | ||
1030 | IEEE80211_DEAUTH_FRAME_LEN); | ||
1031 | if (!skb) | ||
1032 | return; | ||
1033 | |||
1034 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1035 | |||
1036 | /* copy in frame */ | ||
1037 | memcpy(skb_put(skb, IEEE80211_DEAUTH_FRAME_LEN), | ||
1038 | mgmt, IEEE80211_DEAUTH_FRAME_LEN); | ||
1039 | |||
1040 | if (sdata->vif.type != NL80211_IFTYPE_STATION || | ||
1041 | !(sdata->u.mgd.flags & IEEE80211_STA_MFP_ENABLED)) | ||
1042 | IEEE80211_SKB_CB(skb)->flags |= | ||
1043 | IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
1044 | |||
1045 | ieee80211_tx_skb(sdata, skb); | ||
1046 | } | ||
1047 | } | ||
1048 | |||
1007 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1049 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
1008 | const u8 *ie, size_t ie_len, | 1050 | const u8 *ie, size_t ie_len, |
1009 | enum ieee80211_band band, u32 rate_mask, | 1051 | enum ieee80211_band band, u32 rate_mask, |
@@ -1564,14 +1606,13 @@ static int check_mgd_smps(struct ieee80211_if_managed *ifmgd, | |||
1564 | return 0; | 1606 | return 0; |
1565 | } | 1607 | } |
1566 | 1608 | ||
1567 | /* must hold iflist_mtx */ | ||
1568 | void ieee80211_recalc_smps(struct ieee80211_local *local) | 1609 | void ieee80211_recalc_smps(struct ieee80211_local *local) |
1569 | { | 1610 | { |
1570 | struct ieee80211_sub_if_data *sdata; | 1611 | struct ieee80211_sub_if_data *sdata; |
1571 | enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF; | 1612 | enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF; |
1572 | int count = 0; | 1613 | int count = 0; |
1573 | 1614 | ||
1574 | lockdep_assert_held(&local->iflist_mtx); | 1615 | mutex_lock(&local->iflist_mtx); |
1575 | 1616 | ||
1576 | /* | 1617 | /* |
1577 | * This function could be improved to handle multiple | 1618 | * This function could be improved to handle multiple |
@@ -1600,12 +1641,14 @@ void ieee80211_recalc_smps(struct ieee80211_local *local) | |||
1600 | } | 1641 | } |
1601 | 1642 | ||
1602 | if (smps_mode == local->smps_mode) | 1643 | if (smps_mode == local->smps_mode) |
1603 | return; | 1644 | goto unlock; |
1604 | 1645 | ||
1605 | set: | 1646 | set: |
1606 | local->smps_mode = smps_mode; | 1647 | local->smps_mode = smps_mode; |
1607 | /* changed flag is auto-detected for this */ | 1648 | /* changed flag is auto-detected for this */ |
1608 | ieee80211_hw_config(local, 0); | 1649 | ieee80211_hw_config(local, 0); |
1650 | unlock: | ||
1651 | mutex_unlock(&local->iflist_mtx); | ||
1609 | } | 1652 | } |
1610 | 1653 | ||
1611 | static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id) | 1654 | static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id) |