From: David Spinadel Date: Mon, 15 Feb 2016 14:53:25 +0000 (+0200) Subject: MBO: Send MBO WNM-Notification Request frames to notify changes X-Git-Tag: hostap_2_6~859 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.git;a=commitdiff_plain;h=2d5b8614b7df19d670ae6cc29db3b3022801d8a8 MBO: Send MBO WNM-Notification Request frames to notify changes Send a WNM-Notification Request frame with Non-preferred Channel Report subelement if the non-preferred channels list changes during an association. Signed-off-by: David Spinadel --- diff --git a/wpa_supplicant/mbo.c b/wpa_supplicant/mbo.c index 369232e..f35a1de 100644 --- a/wpa_supplicant/mbo.c +++ b/wpa_supplicant/mbo.c @@ -68,15 +68,40 @@ static void wpas_mbo_non_pref_chan_attr(struct wpa_supplicant *wpa_s, } -static void wpas_mbo_non_pref_chan_attrs(struct wpa_supplicant *wpa_s, - struct wpabuf *mbo) +static void wpas_mbo_non_pref_chan_subelem_hdr(struct wpabuf *mbo, u8 len) +{ + wpabuf_put_u8(mbo, WLAN_EID_VENDOR_SPECIFIC); + wpabuf_put_u8(mbo, len); /* Length */ + wpabuf_put_be24(mbo, OUI_WFA); + wpabuf_put_u8(mbo, MBO_ATTR_ID_NON_PREF_CHAN_REPORT); +} + + +static void wpas_mbo_non_pref_chan_subelement(struct wpa_supplicant *wpa_s, + struct wpabuf *mbo, u8 start, + u8 end) +{ + size_t size = end - start + 8; + + if (size + 2 > wpabuf_tailroom(mbo)) + return; + + wpas_mbo_non_pref_chan_subelem_hdr(mbo, size); + wpas_mbo_non_pref_chan_attr_body(wpa_s, mbo, start, end); +} + +static void wpas_mbo_non_pref_chan_attrs(struct wpa_supplicant *wpa_s, + struct wpabuf *mbo, int subelement) { u8 i, start = 0; struct wpa_mbo_non_pref_channel *start_pref; - if (!wpa_s->non_pref_chan || !wpa_s->non_pref_chan_num) + if (!wpa_s->non_pref_chan || !wpa_s->non_pref_chan_num) { + if (subelement) + wpas_mbo_non_pref_chan_subelem_hdr(mbo, 4); return; + } start_pref = &wpa_s->non_pref_chan[0]; for (i = 1; i <= wpa_s->non_pref_chan_num; i++) { @@ -89,7 +114,12 @@ static void wpas_mbo_non_pref_chan_attrs(struct wpa_supplicant *wpa_s, non_pref->reason != start_pref->reason || non_pref->reason_detail != start_pref->reason_detail || non_pref->preference != start_pref->preference) { - wpas_mbo_non_pref_chan_attr(wpa_s, mbo, start, i); + if (subelement) + wpas_mbo_non_pref_chan_subelement(wpa_s, mbo, + start, i); + else + wpas_mbo_non_pref_chan_attr(wpa_s, mbo, start, + i); if (!non_pref) return; @@ -116,7 +146,7 @@ int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len) return 0; /* Add non-preferred channels attribute */ - wpas_mbo_non_pref_chan_attrs(wpa_s, mbo); + wpas_mbo_non_pref_chan_attrs(wpa_s, mbo, 0); res = mbo_add_ie(buf, len, wpabuf_head_u8(mbo), wpabuf_len(mbo)); if (!res) @@ -127,6 +157,45 @@ int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len) } +static void wpas_mbo_send_wnm_notification(struct wpa_supplicant *wpa_s) +{ + struct wpabuf *buf; + int res; + + /* + * Send WNM-Notification Request frame only in case of a change in + * non-preferred channels list during association, if the AP supports + * MBO. + */ + if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_bss || + !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE)) + return; + + buf = wpabuf_alloc(512); + if (!buf) + return; + + wpabuf_put_u8(buf, WLAN_ACTION_WNM); + wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ); + wpa_s->mbo_wnm_token++; + if (wpa_s->mbo_wnm_token == 0) + wpa_s->mbo_wnm_token++; + wpabuf_put_u8(buf, wpa_s->mbo_wnm_token); + wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); /* Type */ + + wpas_mbo_non_pref_chan_attrs(wpa_s, buf, 1); + + res = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, + wpa_s->own_addr, wpa_s->bssid, + wpabuf_head(buf), wpabuf_len(buf), 0); + if (res < 0) + wpa_printf(MSG_DEBUG, + "Failed to send WNM-Notification Request frame with non-preferred channel list"); + + wpabuf_free(buf); +} + + static int wpa_non_pref_chan_is_eq(struct wpa_mbo_non_pref_channel *a, struct wpa_mbo_non_pref_channel *b) { @@ -252,6 +321,7 @@ update: os_free(wpa_s->non_pref_chan); wpa_s->non_pref_chan = chans; wpa_s->non_pref_chan_num = num; + wpas_mbo_send_wnm_notification(wpa_s); return 0; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index c14a61a..22efb27 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1027,6 +1027,7 @@ struct wpa_supplicant { u8 preference; } *non_pref_chan; size_t non_pref_chan_num; + u8 mbo_wnm_token; #endif /* CONFIG_MBO */ };