From: David Spinadel <david.spinadel@xxxxxxxxx> Add WNM notification request in case of a change in np_chan list during connection. Signed-off-by: David Spinadel <david.spinadel@xxxxxxxxx> --- wpa_supplicant/mbo.c | 77 ++++++++++++++++++++++++++++++++++++--- wpa_supplicant/wpa_supplicant_i.h | 1 + 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/wpa_supplicant/mbo.c b/wpa_supplicant/mbo.c index f545034..1cfea44 100644 --- a/wpa_supplicant/mbo.c +++ b/wpa_supplicant/mbo.c @@ -95,15 +95,42 @@ static void wpas_mbo_np_chan_attr(struct wpa_supplicant *wpa_s, } -static void wpas_mbo_np_chan_attrs(struct wpa_supplicant *wpa_s, - struct wpabuf *mbo) +static void wpas_mbo_np_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_NP_CHAN_REPORT); +} + + +static void wpas_mbo_np_chan_subelement(struct wpa_supplicant *wpa_s, + struct wpabuf *mbo, u8 start, u8 end) +{ + size_t size = end - start + 8; + + if (start == end) + return; + + if (size + 2 > wpabuf_tailroom(mbo)) + return; + + wpas_mbo_np_chan_subelem_hdr(mbo, size); + wpas_mbo_np_chan_attr_body(wpa_s, mbo, start, end); +} + +static void wpas_mbo_np_chan_attrs(struct wpa_supplicant *wpa_s, + struct wpabuf *mbo, int subelement) { u8 oper_class = 0, reason = 0, reason_detail = 0, preference = 0; u8 i, start = 0; - if (!wpa_s->np_chan || !wpa_s->np_chan_num) + if (!wpa_s->np_chan || !wpa_s->np_chan_num) { + if (subelement) + wpas_mbo_np_chan_subelem_hdr(mbo, 4); return; + } for (i = 0; i <= wpa_s->np_chan_num; i++) { if (i == wpa_s->np_chan_num || @@ -111,7 +138,11 @@ static void wpas_mbo_np_chan_attrs(struct wpa_supplicant *wpa_s, wpa_s->np_chan[i].reason != reason || wpa_s->np_chan[i].reason_detail != reason_detail || wpa_s->np_chan[i].preference != preference) { - wpas_mbo_np_chan_attr(wpa_s, mbo, start, i); + if (subelement) + wpas_mbo_np_chan_subelement(wpa_s, mbo, start, + i); + else + wpas_mbo_np_chan_attr(wpa_s, mbo, start, i); if (i == wpa_s->np_chan_num) return; @@ -143,7 +174,7 @@ int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len) return 0; /* Add Non-preferred channels attribute */ - wpas_mbo_np_chan_attrs(wpa_s, mbo); + wpas_mbo_np_chan_attrs(wpa_s, mbo, 0); res = mbo_add_ie(buf, len, wpabuf_head_u8(mbo), wpabuf_len(mbo)); if (!res) @@ -154,6 +185,41 @@ 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; + + /* Sending WNM request only in case of a change in non preferred channel + * during connection, if the AP supports MBO. + */ + if (wpa_s->wpa_state != WPA_COMPLETED || + !wpa_bss_get_vendor_ie_subtype(wpa_s->current_bss, OUI_WFA, + MBO_OUI_TYPE)) + return; + + buf = wpabuf_alloc(512); + if (!buf) + return; + + wpabuf_put_u8(buf, WLAN_ACTION_WNM); + wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ); + wpabuf_put_u8(buf, ++wpa_s->mbo_wnm_token); + wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); /* Type */ + + wpas_mbo_np_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 req with non preferred channel list"); + + wpabuf_free(buf); +} + + static int wpa_np_chan_is_eq(struct wpa_mbo_np_channel *a, struct wpa_mbo_np_channel *b) { @@ -263,6 +329,7 @@ update: os_free(wpa_s->np_chan); wpa_s->np_chan = chans; wpa_s->np_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 9519fb6..e03b619 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1027,6 +1027,7 @@ struct wpa_supplicant { u8 preference; } *np_chan; size_t np_chan_num; + u8 mbo_wnm_token; #endif /* CONFIG_MBO */ }; -- 1.9.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap