aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--wpa_supplicant/config.c6
-rw-r--r--wpa_supplicant/config.h6
-rw-r--r--wpa_supplicant/config_file.c2
-rw-r--r--wpa_supplicant/mbo.c24
-rw-r--r--wpa_supplicant/scan.c6
-rw-r--r--wpa_supplicant/wpa_supplicant.conf6
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h1
7 files changed, 49 insertions, 2 deletions
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 3319ed1..eff1043 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 27e9b98..9a13f5f 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 07822ef..38061f1 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 f35a1de..d6f2e76 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 30bec2c..c333e57 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 a6e7bb9..e55b380 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 22efb27..d53bc96 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