diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 3319ed18f..eff104382 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -3561,6 +3561,10 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, config->cert_in_cb = DEFAULT_CERT_IN_CB; config->wpa_rsc_relaxation = DEFAULT_WPA_RSC_RELAXATION; +#ifdef CONFIG_MBO + config->mbo_cell_capa = DEFAULT_MBO_CELL_CAPA; +#endif /* CONFIG_MBO */ + if (ctrl_interface) config->ctrl_interface = os_strdup(ctrl_interface); if (driver_param) @@ -4270,6 +4274,8 @@ static const struct global_parse_data global_fields[] = { { STR(sched_scan_plans), CFG_CHANGED_SCHED_SCAN_PLANS }, #ifdef CONFIG_MBO { STR(non_pref_chan), 0 }, + { INT_RANGE(mbo_cell_capa, MBO_CELL_CAPA_AVAILABLE, + MBO_CELL_CAPA_NOT_SUPPORTED), 0 }, #endif /*CONFIG_MBO */ }; diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 27e9b9839..9a13f5ff7 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -40,6 +40,7 @@ #define DEFAULT_CERT_IN_CB 1 #define DEFAULT_P2P_GO_CTWINDOW 0 #define DEFAULT_WPA_RSC_RELAXATION 1 +#define DEFAULT_MBO_CELL_CAPA MBO_CELL_CAPA_NOT_SUPPORTED #include "config_ssid.h" #include "wps/wps.h" @@ -1284,6 +1285,11 @@ struct wpa_config { * Detail is optional. */ char *non_pref_chan; + + /** + * mbo_cell_capa - Cellular capabilities for MBO + */ + enum mbo_cellular_capa mbo_cell_capa; #endif /* CONFIG_MBO */ }; diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 07822ef41..38061f1c1 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1331,6 +1331,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) #ifdef CONFIG_MBO if (config->non_pref_chan) fprintf(f, "non_pref_chan=%s\n", config->non_pref_chan); + if (config->mbo_cell_capa != DEFAULT_MBO_CELL_CAPA) + fprintf(f, "mbo_cell_capa=%u\n", config->mbo_cell_capa); #endif /* CONFIG_MBO */ } diff --git a/wpa_supplicant/mbo.c b/wpa_supplicant/mbo.c index f35a1de5c..d6f2e769a 100644 --- a/wpa_supplicant/mbo.c +++ b/wpa_supplicant/mbo.c @@ -136,8 +136,7 @@ int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len) struct wpabuf *mbo; int res; - if (!wpa_s->non_pref_chan || !wpa_s->non_pref_chan_num || - len < MBO_IE_HEADER + 7) + if (len < MBO_IE_HEADER + 3 + 7) return 0; /* Leave room for the MBO IE header */ @@ -148,6 +147,14 @@ int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len) /* Add non-preferred channels attribute */ wpas_mbo_non_pref_chan_attrs(wpa_s, mbo, 0); + /* + * Send cellular capabilities attribute even if AP does not advertise + * cellular capabilities. + */ + wpabuf_put_u8(mbo, MBO_ATTR_ID_CELL_DATA_CAPA); + wpabuf_put_u8(mbo, 1); + wpabuf_put_u8(mbo, wpa_s->conf->mbo_cell_capa); + res = mbo_add_ie(buf, len, wpabuf_head_u8(mbo), wpabuf_len(mbo)); if (!res) wpa_printf(MSG_ERROR, "Failed to add MBO IE"); @@ -330,3 +337,16 @@ fail: os_free(cmd); return -1; } + + +void wpas_mbo_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ie) +{ + wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); + wpabuf_put_u8(ie, 7); + wpabuf_put_be24(ie, OUI_WFA); + wpabuf_put_u8(ie, MBO_OUI_TYPE); + + wpabuf_put_u8(ie, MBO_ATTR_ID_CELL_DATA_CAPA); + wpabuf_put_u8(ie, 1); + wpabuf_put_u8(ie, wpa_s->conf->mbo_cell_capa); +} diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 30bec2cae..c333e5748 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -490,6 +490,12 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s) wpabuf_put_buf(extra_ie, wpa_s->fst_ies); #endif /* CONFIG_FST */ +#ifdef CONFIG_MBO + /* Send cellular capabilities for potential MBO STAs */ + if (wpabuf_resize(&extra_ie, 9) == 0) + wpas_mbo_scan_ie(wpa_s, extra_ie); +#endif /* CONFIG_MBO */ + return extra_ie; } diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index a6e7bb9e4..e55b380fe 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -649,6 +649,12 @@ fast_reauth=1 # Example: # non_pref_chan="81:5:10:2:0 81:1:0:2:0 81:9:0:2" +# MBO Cellular Data Capabilities +# 1 = Cellular data connection available +# 2 = Cellular data connection not available +# 3 = Not cellular capable (default) +#mbo_cell_capa=3 + # network block # # Each network (usually AP's sharing the same SSID) is configured as a separate diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 22efb27cd..d53bc961e 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1146,6 +1146,7 @@ void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s, int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len); int wpas_mbo_update_non_pref_chan(struct wpa_supplicant *wpa_s, const char *non_pref_chan); +void wpas_mbo_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ie); /** * wpa_supplicant_ctrl_iface_ctrl_rsp_handle - Handle a control response