nl80211: Fix send_frame freq for IBSS

bss->freq was not updated for IBSS, so whatever old value was stored
from a previous AP mode operation could end up having been used as the
channel when trying to send Authentication frames in an RSN IBSS. This
resulted in the frame not sent (cfg80211 rejects it) and potentially not
being able to re-establish connection due to 4-way handshake failing
with replay counter mismatches. Fix this by learning the operating
channel of the IBSS both when join event is received and when a
management frame is being transmitted since the IBSS may have changed
channels due to merges.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2014-05-14 00:47:42 +03:00
parent c126cb4d1c
commit c7caac56b7

View file

@ -587,6 +587,7 @@ struct nl80211_bss_info_arg {
struct wpa_driver_nl80211_data *drv; struct wpa_driver_nl80211_data *drv;
struct wpa_scan_results *res; struct wpa_scan_results *res;
unsigned int assoc_freq; unsigned int assoc_freq;
unsigned int ibss_freq;
u8 assoc_bssid[ETH_ALEN]; u8 assoc_bssid[ETH_ALEN];
}; };
@ -1424,11 +1425,12 @@ static unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv)
ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg); ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
msg = NULL; msg = NULL;
if (ret == 0) { if (ret == 0) {
unsigned int freq = drv->nlmode == NL80211_IFTYPE_ADHOC ?
arg.ibss_freq : arg.assoc_freq;
wpa_printf(MSG_DEBUG, "nl80211: Operating frequency for the " wpa_printf(MSG_DEBUG, "nl80211: Operating frequency for the "
"associated BSS from scan results: %u MHz", "associated BSS from scan results: %u MHz", freq);
arg.assoc_freq); if (freq)
if (arg.assoc_freq) drv->assoc_freq = freq;
drv->assoc_freq = arg.assoc_freq;
return drv->assoc_freq; return drv->assoc_freq;
} }
wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d " wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
@ -2036,6 +2038,8 @@ static void mlme_event_michael_mic_failure(struct i802_bss *bss,
static void mlme_event_join_ibss(struct wpa_driver_nl80211_data *drv, static void mlme_event_join_ibss(struct wpa_driver_nl80211_data *drv,
struct nlattr *tb[]) struct nlattr *tb[])
{ {
unsigned int freq;
if (tb[NL80211_ATTR_MAC] == NULL) { if (tb[NL80211_ATTR_MAC] == NULL) {
wpa_printf(MSG_DEBUG, "nl80211: No address in IBSS joined " wpa_printf(MSG_DEBUG, "nl80211: No address in IBSS joined "
"event"); "event");
@ -2047,6 +2051,13 @@ static void mlme_event_join_ibss(struct wpa_driver_nl80211_data *drv,
wpa_printf(MSG_DEBUG, "nl80211: IBSS " MACSTR " joined", wpa_printf(MSG_DEBUG, "nl80211: IBSS " MACSTR " joined",
MAC2STR(drv->bssid)); MAC2STR(drv->bssid));
freq = nl80211_get_assoc_freq(drv);
if (freq) {
wpa_printf(MSG_DEBUG, "nl80211: IBSS on frequency %u MHz",
freq);
drv->first_bss->freq = freq;
}
wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
} }
@ -5337,6 +5348,13 @@ static int bss_info_handler(struct nl_msg *msg, void *arg)
wpa_printf(MSG_DEBUG, "nl80211: Associated on %u MHz", wpa_printf(MSG_DEBUG, "nl80211: Associated on %u MHz",
_arg->assoc_freq); _arg->assoc_freq);
} }
if (status == NL80211_BSS_STATUS_IBSS_JOINED &&
bss[NL80211_BSS_FREQUENCY]) {
_arg->ibss_freq =
nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
wpa_printf(MSG_DEBUG, "nl80211: IBSS-joined on %u MHz",
_arg->ibss_freq);
}
if (status == NL80211_BSS_STATUS_ASSOCIATED && if (status == NL80211_BSS_STATUS_ASSOCIATED &&
bss[NL80211_BSS_BSSID]) { bss[NL80211_BSS_BSSID]) {
os_memcpy(_arg->assoc_bssid, os_memcpy(_arg->assoc_bssid,
@ -6996,6 +7014,12 @@ static int wpa_driver_nl80211_send_frame(struct i802_bss *bss,
u64 cookie; u64 cookie;
int res; int res;
if (freq == 0 && drv->nlmode == NL80211_IFTYPE_ADHOC) {
freq = nl80211_get_assoc_freq(drv);
wpa_printf(MSG_DEBUG,
"nl80211: send_frame - Use assoc_freq=%u for IBSS",
freq);
}
if (freq == 0) { if (freq == 0) {
wpa_printf(MSG_DEBUG, "nl80211: send_frame - Use bss->freq=%u", wpa_printf(MSG_DEBUG, "nl80211: send_frame - Use bss->freq=%u",
bss->freq); bss->freq);