diff mbox

[v2] supplicant: Allow custom probe and assoc req ie.

Message ID 1459810505-27258-1-git-send-email-greearb@candelatech.com
State Superseded
Headers show

Commit Message

Ben Greear April 4, 2016, 10:55 p.m. UTC
From: Ben Greear <greearb@candelatech.com>

This lets user specify additional IEs for probe requests and
association requests.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 wpa_supplicant/config.c            | 49 ++++++++++++++++++++++++++++++--------
 wpa_supplicant/config.h            | 20 ++++++++++++++++
 wpa_supplicant/config_file.c       | 22 +++++++++++++++++
 wpa_supplicant/scan.c              |  8 +++++++
 wpa_supplicant/sme.c               | 14 +++++++++++
 wpa_supplicant/wpa_cli.c           |  3 ++-
 wpa_supplicant/wpa_supplicant.c    | 13 ++++++++++
 wpa_supplicant/wpa_supplicant.conf | 14 +++++++++++
 8 files changed, 132 insertions(+), 11 deletions(-)
diff mbox

Patch

diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 298d910..88bde95 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2282,6 +2282,8 @@  void wpa_config_free(struct wpa_config *config)
 	os_free(config->ext_password_backend);
 	os_free(config->sae_groups);
 	wpabuf_free(config->ap_vendor_elements);
+	wpabuf_free(config->probe_req_ie);
+	wpabuf_free(config->assoc_req_ie);
 	os_free(config->osu_dir);
 	os_free(config->bgscan);
 	os_free(config->wowlan_triggers);
@@ -4094,17 +4096,18 @@  static int wpa_config_process_sae_groups(
 }
 
 
-static int wpa_config_process_ap_vendor_elements(
+static int wpa_config_process_ie_helper(
 	const struct global_parse_data *data,
-	struct wpa_config *config, int line, const char *pos)
+	int line, const char *pos,
+	const char* id, struct wpabuf **buf)
 {
 	struct wpabuf *tmp;
 	int len = os_strlen(pos) / 2;
 	u8 *p;
 
 	if (!len) {
-		wpa_printf(MSG_ERROR, "Line %d: invalid ap_vendor_elements",
-			   line);
+		wpa_printf(MSG_ERROR, "Line %d: invalid %s",
+			   line, id);
 		return -1;
 	}
 
@@ -4113,23 +4116,47 @@  static int wpa_config_process_ap_vendor_elements(
 		p = wpabuf_put(tmp, len);
 
 		if (hexstr2bin(pos, p, len)) {
-			wpa_printf(MSG_ERROR, "Line %d: invalid "
-				   "ap_vendor_elements", line);
+			wpa_printf(MSG_ERROR, "Line %d: invalid %s",
+				   line, id);
 			wpabuf_free(tmp);
 			return -1;
 		}
 
-		wpabuf_free(config->ap_vendor_elements);
-		config->ap_vendor_elements = tmp;
+		wpabuf_free(*buf);
+		*buf = tmp;
 	} else {
-		wpa_printf(MSG_ERROR, "Cannot allocate memory for "
-			   "ap_vendor_elements");
+		wpa_printf(MSG_ERROR, "Cannot allocate memory for %s",
+			   id);
 		return -1;
 	}
 
 	return 0;
 }
 
+static int wpa_config_process_ap_vendor_elements(
+	const struct global_parse_data *data,
+	struct wpa_config *config, int line, const char *pos)
+{
+	return wpa_config_process_ie_helper(data, line, pos, "ap_vendor_elements",
+					    &config->ap_vendor_elements);
+}
+
+static int wpa_config_process_probe_req_ie(
+	const struct global_parse_data *data,
+	struct wpa_config *config, int line, const char *pos)
+{
+	return wpa_config_process_ie_helper(data, line, pos, "probe_req_ie",
+					    &config->probe_req_ie);
+}
+
+static int wpa_config_process_assoc_req_ie(
+	const struct global_parse_data *data,
+	struct wpa_config *config, int line, const char *pos)
+{
+	return wpa_config_process_ie_helper(data, line, pos, "assoc_req_ie",
+					    &config->assoc_req_ie);
+}
+
 
 #ifdef CONFIG_CTRL_IFACE
 static int wpa_config_process_no_ctrl_interface(
@@ -4332,6 +4359,8 @@  static const struct global_parse_data global_fields[] = {
 	{ INT(dtim_period), 0 },
 	{ INT(beacon_int), 0 },
 	{ FUNC(ap_vendor_elements), 0 },
+	{ FUNC(probe_req_ie), 0 },
+	{ FUNC(assoc_req_ie), 0 },
 	{ INT_RANGE(ignore_old_scan_res, 0, 1), 0 },
 	{ FUNC(freq_list), 0 },
 	{ INT(scan_cur_freq), 0 },
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index b04f4a5..c2457c6 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -1115,6 +1115,26 @@  struct wpa_config {
 	struct wpabuf *ap_vendor_elements;
 
 	/**
+	 * probe_req_ie: Vendor specific elements for Probe-Req
+	 *
+	 * This parameter can be used to define additional vendor specific
+	 * elements for Probe Requests.
+	 * format for these element(s) is a hexdump of the raw information
+	 * elements (id+len+payload for one or more elements).
+	 */
+	struct wpabuf *probe_req_ie;
+
+	/**
+	 * assoc_req_ie: Vendor specific elements for Assoc-Req
+	 *
+	 * This parameter can be used to define additional vendor specific
+	 * elements for Association Requests.
+	 * format for these element(s) is a hexdump of the raw information
+	 * elements (id+len+payload for one or more elements).
+	 */
+	struct wpabuf *assoc_req_ie;
+
+	/**
 	 * ignore_old_scan_res - Ignore scan results older than request
 	 *
 	 * The driver may have a cache of scan results that makes it return
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 38061f1..cd24cab 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -1242,6 +1242,28 @@  static void wpa_config_write_global(FILE *f, struct wpa_config *config)
 		}
 	}
 
+	if (config->probe_req_ie) {
+		int i, len = wpabuf_len(config->probe_req_ie);
+		const u8 *p = wpabuf_head_u8(config->probe_req_ie);
+		if (len > 0) {
+			fprintf(f, "probe_req_ie=");
+			for (i = 0; i < len; i++)
+				fprintf(f, "%02x", *p++);
+			fprintf(f, "\n");
+		}
+	}
+
+	if (config->assoc_req_ie) {
+		int i, len = wpabuf_len(config->assoc_req_ie);
+		const u8 *p = wpabuf_head_u8(config->assoc_req_ie);
+		if (len > 0) {
+			fprintf(f, "assoc_req_ie=");
+			for (i = 0; i < len; i++)
+				fprintf(f, "%02x", *p++);
+			fprintf(f, "\n");
+		}
+	}
+
 	if (config->ignore_old_scan_res)
 		fprintf(f, "ignore_old_scan_res=%d\n",
 			config->ignore_old_scan_res);
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 619654b..6062fa3 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -512,6 +512,14 @@  static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
 		wpas_mbo_scan_ie(wpa_s, extra_ie);
 #endif /* CONFIG_MBO */
 
+	/* Add user-specified IE */
+	if (wpa_s->conf->probe_req_ie) {
+		int ln = wpabuf_len(wpa_s->conf->probe_req_ie);
+		if (wpabuf_resize(&extra_ie, ln) == 0) {
+			wpabuf_put_buf(extra_ie, wpa_s->conf->probe_req_ie);
+		}
+	}
+
 	return extra_ie;
 }
 
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index a6ace1a..dbd9767 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -464,6 +464,20 @@  static void sme_send_authentication(struct wpa_supplicant *wpa_s,
 		os_memcpy(pos, ext_capab, ext_capab_len);
 	}
 
+	/* Add user-specified IE */
+	if (wpa_s->conf->assoc_req_ie) {
+		int v_ies_len = wpabuf_len(wpa_s->conf->assoc_req_ie);
+
+		if (wpa_s->sme.assoc_req_ie_len + v_ies_len <= sizeof(wpa_s->sme.assoc_req_ie)) {
+			os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
+				  wpabuf_head(wpa_s->conf->assoc_req_ie), v_ies_len);
+			wpa_s->sme.assoc_req_ie_len += v_ies_len;
+			wpa_msg(wpa_s, MSG_INFO, "SME: added user-specified vendor elements, len: %d",
+				v_ies_len);
+		}
+	}
+
+
 #ifdef CONFIG_HS20
 	if (is_hs20_network(wpa_s, ssid, bss)) {
 		struct wpabuf *hs20;
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index eecb1dc..72cbe25 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -678,7 +678,8 @@  static char ** wpa_cli_complete_set(const char *str, int pos)
 		"wps_nfc_dh_privkey", "wps_nfc_dev_pw", "ext_password_backend",
 		"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
 		"sae_groups", "dtim_period", "beacon_int",
-		"ap_vendor_elements", "ignore_old_scan_res", "freq_list",
+		"ap_vendor_elements", "probe_req_ie", "assoc_req_ie",
+		"ignore_old_scan_res", "freq_list",
 		"scan_cur_freq", "sched_scan_interval",
 		"tdls_external_control", "osu_dir", "wowlan_triggers",
 		"p2p_search_delay", "mac_addr", "rand_addr_lifetime",
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 3df1b7d..d6cc099 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2434,6 +2434,19 @@  static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
 	}
 #endif /* CONFIG_MBO */
 
+	/* Add user-specified IE */
+	if (wpa_s->conf->assoc_req_ie) {
+		int v_ies_len = wpabuf_len(wpa_s->conf->assoc_req_ie);
+
+		if (wpa_ie_len + v_ies_len <= sizeof(wpa_ie)) {
+			os_memcpy(wpa_ie + wpa_ie_len,
+				  wpabuf_head(wpa_s->conf->assoc_req_ie), v_ies_len);
+			wpa_ie_len += v_ies_len;
+			wpa_msg(wpa_s, MSG_INFO, "start-assoc-cb, added user-specified vendor elements, len: %d",
+				v_ies_len);
+		}
+	}
+
 	wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
 	use_crypt = 1;
 	cipher_pairwise = wpa_s->pairwise_cipher;
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 2b33242..c2fd650 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -392,6 +392,20 @@  fast_reauth=1
 # one or more elements). This is used in AP and P2P GO modes.
 #ap_vendor_elements=dd0411223301
 
+# Additional vendor specific elements for Probe Request frames
+# This parameter can be used to add additional vendor specific element(s) into
+# the end of the Probe Request frames. The format for these
+# element(s) is a hexdump of the raw information elements (id+len+payload for
+# one or more elements). This is used in Station mode.
+#probe_req_ie=dd0411223301
+
+# Additional vendor specific elements for Assoc Request frames
+# This parameter can be used to add additional vendor specific element(s) into
+# the end of the Assoc Request frames. The format for these
+# element(s) is a hexdump of the raw information elements (id+len+payload for
+# one or more elements). This is used in Station mode.
+#assoc_req_ie=dd0411223301
+
 # Ignore scan results older than request
 #
 # The driver may have a cache of scan results that makes it return