Loading net/mac80211/cfg.c +6 −0 Original line number Diff line number Diff line Loading @@ -1071,6 +1071,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); if (sdata->wdev.cac_started) { cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); } drv_stop_ap(sdata->local, sdata); /* free all potentially still buffered bcast frames */ Loading net/mac80211/ieee80211_i.h +3 −2 Original line number Diff line number Diff line Loading @@ -1513,10 +1513,11 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, ieee80211_tx_skb_tid(sdata, skb, 7); } u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action, u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, struct ieee802_11_elems *elems, u64 filter, u32 crc); static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action, static inline void ieee802_11_parse_elems(const u8 *start, size_t len, bool action, struct ieee802_11_elems *elems) { ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0); Loading net/mac80211/iface.c +21 −7 Original line number Diff line number Diff line Loading @@ -159,10 +159,11 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) return 0; } static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr, static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr, bool check_dup) { struct ieee80211_sub_if_data *sdata; struct ieee80211_local *local = sdata->local; struct ieee80211_sub_if_data *iter; u64 new, mask, tmp; u8 *m; int ret = 0; Loading @@ -184,12 +185,15 @@ static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr, return ret; mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type == NL80211_IFTYPE_MONITOR && !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) list_for_each_entry(iter, &local->interfaces, list) { if (iter == sdata) continue; m = sdata->vif.addr; if (iter->vif.type == NL80211_IFTYPE_MONITOR && !(iter->u.mntr_flags & MONITOR_FLAG_ACTIVE)) continue; m = iter->vif.addr; tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); Loading Loading @@ -218,7 +222,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr) !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) check_dup = false; ret = ieee80211_verify_mac(sdata->local, sa->sa_data, check_dup); ret = ieee80211_verify_mac(sdata, sa->sa_data, check_dup); if (ret) return ret; Loading Loading @@ -1503,7 +1507,17 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, break; } /* * Pick address of existing interface in case user changed * MAC address manually, default to perm_addr. */ m = local->hw.wiphy->perm_addr; list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type == NL80211_IFTYPE_MONITOR) continue; m = sdata->vif.addr; break; } start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); Loading net/mac80211/mlme.c +80 −7 Original line number Diff line number Diff line Loading @@ -2502,8 +2502,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, u16 capab_info, aid; struct ieee802_11_elems elems; struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; const struct cfg80211_bss_ies *bss_ies = NULL; struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; u32 changed = 0; int err; bool ret; /* AssocResp and ReassocResp have identical structure */ Loading Loading @@ -2534,6 +2537,69 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, ifmgd->aid = aid; /* * Some APs are erroneously not including some information in their * (re)association response frames. Try to recover by using the data * from the beacon or probe response. This seems to afflict mobile * 2G/3G/4G wifi routers, reported models include the "Onda PN51T", * "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile device. */ if ((assoc_data->wmm && !elems.wmm_param) || (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && (!elems.ht_cap_elem || !elems.ht_operation)) || (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && (!elems.vht_cap_elem || !elems.vht_operation))) { const struct cfg80211_bss_ies *ies; struct ieee802_11_elems bss_elems; rcu_read_lock(); ies = rcu_dereference(cbss->ies); if (ies) bss_ies = kmemdup(ies, sizeof(*ies) + ies->len, GFP_ATOMIC); rcu_read_unlock(); if (!bss_ies) return false; ieee802_11_parse_elems(bss_ies->data, bss_ies->len, false, &bss_elems); if (assoc_data->wmm && !elems.wmm_param && bss_elems.wmm_param) { elems.wmm_param = bss_elems.wmm_param; sdata_info(sdata, "AP bug: WMM param missing from AssocResp\n"); } /* * Also check if we requested HT/VHT, otherwise the AP doesn't * have to include the IEs in the (re)association response. */ if (!elems.ht_cap_elem && bss_elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { elems.ht_cap_elem = bss_elems.ht_cap_elem; sdata_info(sdata, "AP bug: HT capability missing from AssocResp\n"); } if (!elems.ht_operation && bss_elems.ht_operation && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { elems.ht_operation = bss_elems.ht_operation; sdata_info(sdata, "AP bug: HT operation missing from AssocResp\n"); } if (!elems.vht_cap_elem && bss_elems.vht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) { elems.vht_cap_elem = bss_elems.vht_cap_elem; sdata_info(sdata, "AP bug: VHT capa missing from AssocResp\n"); } if (!elems.vht_operation && bss_elems.vht_operation && !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) { elems.vht_operation = bss_elems.vht_operation; sdata_info(sdata, "AP bug: VHT operation missing from AssocResp\n"); } } /* * We previously checked these in the beacon/probe response, so * they should be present here. This is just a safety net. Loading @@ -2541,15 +2607,17 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && (!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) { sdata_info(sdata, "HT AP is missing WMM params or HT capability/operation in AssocResp\n"); return false; "HT AP is missing WMM params or HT capability/operation\n"); ret = false; goto out; } if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && (!elems.vht_cap_elem || !elems.vht_operation)) { sdata_info(sdata, "VHT AP is missing VHT capability/operation in AssocResp\n"); return false; "VHT AP is missing VHT capability/operation\n"); ret = false; goto out; } mutex_lock(&sdata->local->sta_mtx); Loading @@ -2560,7 +2628,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, sta = sta_info_get(sdata, cbss->bssid); if (WARN_ON(!sta)) { mutex_unlock(&sdata->local->sta_mtx); return false; ret = false; goto out; } sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; Loading Loading @@ -2613,7 +2682,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, sta->sta.addr); WARN_ON(__sta_info_destroy(sta)); mutex_unlock(&sdata->local->sta_mtx); return false; ret = false; goto out; } mutex_unlock(&sdata->local->sta_mtx); Loading Loading @@ -2653,7 +2723,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); ieee80211_sta_reset_beacon_monitor(sdata); return true; ret = true; out: kfree(bss_ies); return ret; } static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, Loading net/mac80211/rate.c +1 −1 Original line number Diff line number Diff line Loading @@ -621,7 +621,7 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata, if (rates[i].idx < 0) break; rate_idx_match_mask(&rates[i], sband, mask, chan_width, rate_idx_match_mask(&rates[i], sband, chan_width, mask, mcs_mask); } } Loading Loading
net/mac80211/cfg.c +6 −0 Original line number Diff line number Diff line Loading @@ -1071,6 +1071,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); if (sdata->wdev.cac_started) { cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); } drv_stop_ap(sdata->local, sdata); /* free all potentially still buffered bcast frames */ Loading
net/mac80211/ieee80211_i.h +3 −2 Original line number Diff line number Diff line Loading @@ -1513,10 +1513,11 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, ieee80211_tx_skb_tid(sdata, skb, 7); } u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action, u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, struct ieee802_11_elems *elems, u64 filter, u32 crc); static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action, static inline void ieee802_11_parse_elems(const u8 *start, size_t len, bool action, struct ieee802_11_elems *elems) { ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0); Loading
net/mac80211/iface.c +21 −7 Original line number Diff line number Diff line Loading @@ -159,10 +159,11 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) return 0; } static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr, static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr, bool check_dup) { struct ieee80211_sub_if_data *sdata; struct ieee80211_local *local = sdata->local; struct ieee80211_sub_if_data *iter; u64 new, mask, tmp; u8 *m; int ret = 0; Loading @@ -184,12 +185,15 @@ static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr, return ret; mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type == NL80211_IFTYPE_MONITOR && !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) list_for_each_entry(iter, &local->interfaces, list) { if (iter == sdata) continue; m = sdata->vif.addr; if (iter->vif.type == NL80211_IFTYPE_MONITOR && !(iter->u.mntr_flags & MONITOR_FLAG_ACTIVE)) continue; m = iter->vif.addr; tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); Loading Loading @@ -218,7 +222,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr) !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) check_dup = false; ret = ieee80211_verify_mac(sdata->local, sa->sa_data, check_dup); ret = ieee80211_verify_mac(sdata, sa->sa_data, check_dup); if (ret) return ret; Loading Loading @@ -1503,7 +1507,17 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, break; } /* * Pick address of existing interface in case user changed * MAC address manually, default to perm_addr. */ m = local->hw.wiphy->perm_addr; list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type == NL80211_IFTYPE_MONITOR) continue; m = sdata->vif.addr; break; } start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); Loading
net/mac80211/mlme.c +80 −7 Original line number Diff line number Diff line Loading @@ -2502,8 +2502,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, u16 capab_info, aid; struct ieee802_11_elems elems; struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; const struct cfg80211_bss_ies *bss_ies = NULL; struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; u32 changed = 0; int err; bool ret; /* AssocResp and ReassocResp have identical structure */ Loading Loading @@ -2534,6 +2537,69 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, ifmgd->aid = aid; /* * Some APs are erroneously not including some information in their * (re)association response frames. Try to recover by using the data * from the beacon or probe response. This seems to afflict mobile * 2G/3G/4G wifi routers, reported models include the "Onda PN51T", * "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile device. */ if ((assoc_data->wmm && !elems.wmm_param) || (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && (!elems.ht_cap_elem || !elems.ht_operation)) || (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && (!elems.vht_cap_elem || !elems.vht_operation))) { const struct cfg80211_bss_ies *ies; struct ieee802_11_elems bss_elems; rcu_read_lock(); ies = rcu_dereference(cbss->ies); if (ies) bss_ies = kmemdup(ies, sizeof(*ies) + ies->len, GFP_ATOMIC); rcu_read_unlock(); if (!bss_ies) return false; ieee802_11_parse_elems(bss_ies->data, bss_ies->len, false, &bss_elems); if (assoc_data->wmm && !elems.wmm_param && bss_elems.wmm_param) { elems.wmm_param = bss_elems.wmm_param; sdata_info(sdata, "AP bug: WMM param missing from AssocResp\n"); } /* * Also check if we requested HT/VHT, otherwise the AP doesn't * have to include the IEs in the (re)association response. */ if (!elems.ht_cap_elem && bss_elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { elems.ht_cap_elem = bss_elems.ht_cap_elem; sdata_info(sdata, "AP bug: HT capability missing from AssocResp\n"); } if (!elems.ht_operation && bss_elems.ht_operation && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { elems.ht_operation = bss_elems.ht_operation; sdata_info(sdata, "AP bug: HT operation missing from AssocResp\n"); } if (!elems.vht_cap_elem && bss_elems.vht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) { elems.vht_cap_elem = bss_elems.vht_cap_elem; sdata_info(sdata, "AP bug: VHT capa missing from AssocResp\n"); } if (!elems.vht_operation && bss_elems.vht_operation && !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) { elems.vht_operation = bss_elems.vht_operation; sdata_info(sdata, "AP bug: VHT operation missing from AssocResp\n"); } } /* * We previously checked these in the beacon/probe response, so * they should be present here. This is just a safety net. Loading @@ -2541,15 +2607,17 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && (!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) { sdata_info(sdata, "HT AP is missing WMM params or HT capability/operation in AssocResp\n"); return false; "HT AP is missing WMM params or HT capability/operation\n"); ret = false; goto out; } if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && (!elems.vht_cap_elem || !elems.vht_operation)) { sdata_info(sdata, "VHT AP is missing VHT capability/operation in AssocResp\n"); return false; "VHT AP is missing VHT capability/operation\n"); ret = false; goto out; } mutex_lock(&sdata->local->sta_mtx); Loading @@ -2560,7 +2628,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, sta = sta_info_get(sdata, cbss->bssid); if (WARN_ON(!sta)) { mutex_unlock(&sdata->local->sta_mtx); return false; ret = false; goto out; } sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; Loading Loading @@ -2613,7 +2682,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, sta->sta.addr); WARN_ON(__sta_info_destroy(sta)); mutex_unlock(&sdata->local->sta_mtx); return false; ret = false; goto out; } mutex_unlock(&sdata->local->sta_mtx); Loading Loading @@ -2653,7 +2723,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); ieee80211_sta_reset_beacon_monitor(sdata); return true; ret = true; out: kfree(bss_ies); return ret; } static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, Loading
net/mac80211/rate.c +1 −1 Original line number Diff line number Diff line Loading @@ -621,7 +621,7 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata, if (rates[i].idx < 0) break; rate_idx_match_mask(&rates[i], sband, mask, chan_width, rate_idx_match_mask(&rates[i], sband, chan_width, mask, mcs_mask); } } Loading