diff mbox series

Introduce DUMP_BEACON command

Message ID 20241009081502.4139823-1-marek.puzyniak@holisticon.pl
State New
Headers show
Series Introduce DUMP_BEACON command | expand

Commit Message

Marek Puzyniak Oct. 9, 2024, 8:15 a.m. UTC
Occasionally, external applications require information about AP
configurations and capabilities.
The optimal source for this is the beacon frame content. To support this need,
a new raw command is being introduced: DUMP_BEACON.

Using wpa_cli or hostapd_cli to execute this command results in a hex
dump of the beacon content.

hostapd_cli -i wlxxx raw DUMP_BEACON
80000000ffffffffffff...
dd180050f2020101010003a4000027a4000042435e0062322f007f080000000000000040

Signed-off-by: Marek Puzyniak <marek.puzyniak@holisticon.pl>
---
 hostapd/ctrl_iface.c | 72 ++++++++++++++++++++++++++++++++++++++++++++
 src/ap/hostapd.c     |  4 +--
 src/ap/hostapd.h     |  2 ++
 3 files changed, 76 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 1fcefb355..371e3f2c5 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -1354,6 +1354,75 @@  static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
 }
 
 
+static int hostapd_ctrl_iface_dump_beacon(struct hostapd_data *hapd,
+					  char *buf, size_t buflen)
+{
+	struct ieee80211_mgmt *mgmt;
+	struct beacon_data beacon;
+	size_t ies_len, req_buf;
+	char *pos, *end;
+	u8 *ies_start;
+	int ret;
+
+	pos = buf;
+	end = buf + buflen;
+
+	ret = hostapd_build_beacon_data(hapd, &beacon);
+	if (ret)
+		return -1;
+
+	/* calculate required buffer size to store beacon hex dump */
+	/* beacon ies, first part */
+	mgmt = (struct ieee80211_mgmt*)beacon.head;
+	ies_start = &mgmt->u.beacon.variable[0];
+	ies_len = beacon.head_len - (ies_start - beacon.head);
+
+	req_buf = 2 * (beacon.head_len + ies_len + beacon.tail_len + beacon.beacon_ies_len) + 1;
+
+	if (req_buf > buflen) {
+		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
+			       HOSTAPD_LEVEL_WARNING,
+			       "Get beacon failed, required bufer %zu > %zu buffer",
+			       req_buf, buflen);
+		ret = -1;
+		goto error_return;
+	}
+
+	/* beacon head, management frame */
+	ret = wpa_snprintf_hex(pos, end - pos, beacon.head, beacon.head_len);
+	pos += ret;
+
+	/* beacon ies, first part */
+	ret = wpa_snprintf_hex(pos, end - pos, ies_start, ies_len);
+	pos += ret;
+
+	/* beacon tail, ie continuation */
+	ret = wpa_snprintf_hex(pos, end - pos, beacon.tail, beacon.tail_len);
+	pos += ret;
+
+	/* beacon extra ie */
+	ret = wpa_snprintf_hex(pos, end - pos, beacon.beacon_ies, beacon.beacon_ies_len);
+	pos += ret;
+
+	ret = os_snprintf(pos, end - pos, "\n");
+	if (os_snprintf_error(end - pos, ret)) {
+		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
+			       HOSTAPD_LEVEL_WARNING,
+			       "Get beacon failed, used:%lu of %zu", 
+			       end - pos, buflen);
+		ret = -1;
+		goto error_return;
+	}
+	pos += ret;
+
+	ret = pos - buf;
+error_return:
+	free_beacon_data(&beacon);
+
+	return ret;
+}
+
+
 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
 				  char *buf, size_t buflen)
 {
@@ -4370,6 +4439,9 @@  static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
 	} else if (os_strncmp(buf, "REQ_BEACON ", 11) == 0) {
 		reply_len = hostapd_ctrl_iface_req_beacon(hapd, buf + 11,
 							  reply, reply_size);
+	} else if (os_strcmp(buf, "DUMP_BEACON") == 0) {
+		reply_len = hostapd_ctrl_iface_dump_beacon(hapd, reply,
+							   reply_size);
 	} else if (os_strncmp(buf, "REQ_LINK_MEASUREMENT ", 21) == 0) {
 		reply_len = hostapd_ctrl_iface_req_link_measurement(
 			hapd, buf + 21, reply, reply_size);
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 5ba2cab2c..01a228c43 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -4200,8 +4200,8 @@  void free_beacon_data(struct beacon_data *beacon)
 }
 
 
-static int hostapd_build_beacon_data(struct hostapd_data *hapd,
-				     struct beacon_data *beacon)
+int hostapd_build_beacon_data(struct hostapd_data *hapd,
+			      struct beacon_data *beacon)
 {
 	struct wpabuf *beacon_extra, *proberesp_extra, *assocresp_extra;
 	struct wpa_driver_ap_params params;
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 7e72863af..6cc25e474 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -859,6 +859,8 @@  int hostapd_mld_add_link(struct hostapd_data *hapd);
 int hostapd_mld_remove_link(struct hostapd_data *hapd);
 struct hostapd_data * hostapd_mld_get_first_bss(struct hostapd_data *hapd);
 
+int hostapd_build_beacon_data(struct hostapd_data *hapd,
+			      struct beacon_data *beacon);
 void free_beacon_data(struct beacon_data *beacon);
 int hostapd_fill_cca_settings(struct hostapd_data *hapd,
 			      struct cca_settings *settings);