Browse Source

Add station table query to wpa_supplicant AP ctrl_iface

"wpa_cli all_sta" and "wpa_cli sta <addr>" can now be used to fetch
information about stations associated with the
wpa_supplicant-controlled AP.
Jouni Malinen 15 years ago
parent
commit
e653b62275
5 changed files with 123 additions and 0 deletions
  1. 3 0
      wpa_supplicant/Makefile
  2. 31 0
      wpa_supplicant/ap.c
  3. 6 0
      wpa_supplicant/ap.h
  4. 10 0
      wpa_supplicant/ctrl_iface.c
  5. 73 0
      wpa_supplicant/wpa_cli.c

+ 3 - 0
wpa_supplicant/Makefile

@@ -525,6 +525,9 @@ OBJS += ../hostapd/ieee802_1x.o
 OBJS += ../hostapd/eapol_sm.o
 OBJS += ../hostapd/ieee802_11_auth.o
 OBJS += ../hostapd/drv_callbacks.o
+ifdef CONFIG_CTRL_IFACE
+OBJS += ../hostapd/ctrl_iface_ap.o
+endif
 ifdef CONFIG_IEEE80211R
 OBJS += ../hostapd/wpa_ft.o
 endif

+ 31 - 0
wpa_supplicant/ap.c

@@ -22,6 +22,7 @@
 #include "../hostapd/ieee802_11.h"
 #endif /* NEED_AP_MLME */
 #include "../hostapd/wps_hostapd.h"
+#include "../hostapd/ctrl_iface_ap.h"
 #include "eap_common/eap_defs.h"
 #include "eap_server/eap_methods.h"
 #include "eap_common/eap_wsc_common.h"
@@ -551,3 +552,33 @@ int wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
 }
 
 #endif /* CONFIG_WPS */
+
+
+int ap_ctrl_iface_sta_first(struct wpa_supplicant *wpa_s,
+			    char *buf, size_t buflen)
+{
+	if (wpa_s->ap_iface == NULL)
+		return -1;
+	return hostapd_ctrl_iface_sta_first(wpa_s->ap_iface->bss[0],
+					    buf, buflen);
+}
+
+
+int ap_ctrl_iface_sta(struct wpa_supplicant *wpa_s, const char *txtaddr,
+		      char *buf, size_t buflen)
+{
+	if (wpa_s->ap_iface == NULL)
+		return -1;
+	return hostapd_ctrl_iface_sta(wpa_s->ap_iface->bss[0], txtaddr,
+				      buf, buflen);
+}
+
+
+int ap_ctrl_iface_sta_next(struct wpa_supplicant *wpa_s, const char *txtaddr,
+			   char *buf, size_t buflen)
+{
+	if (wpa_s->ap_iface == NULL)
+		return -1;
+	return hostapd_ctrl_iface_sta_next(wpa_s->ap_iface->bss[0], txtaddr,
+					   buf, buflen);
+}

+ 6 - 0
wpa_supplicant/ap.h

@@ -24,5 +24,11 @@ void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
 int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid);
 int wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
 			      const char *pin, char *buf, size_t buflen);
+int ap_ctrl_iface_sta_first(struct wpa_supplicant *wpa_s,
+			    char *buf, size_t buflen);
+int ap_ctrl_iface_sta(struct wpa_supplicant *wpa_s, const char *txtaddr,
+		      char *buf, size_t buflen);
+int ap_ctrl_iface_sta_next(struct wpa_supplicant *wpa_s, const char *txtaddr,
+			   char *buf, size_t buflen);
 
 #endif /* AP_H */

+ 10 - 0
wpa_supplicant/ctrl_iface.c

@@ -1735,6 +1735,16 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
 	} else if (os_strncmp(buf, "BSS ", 4) == 0) {
 		reply_len = wpa_supplicant_ctrl_iface_bss(
 			wpa_s, buf + 4, reply, reply_size);
+#ifdef CONFIG_AP
+	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
+		reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
+	} else if (os_strncmp(buf, "STA ", 4) == 0) {
+		reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
+					      reply_size);
+	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
+		reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
+						   reply_size);
+#endif /* CONFIG_AP */
 	} else {
 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 		reply_len = 16;

+ 73 - 0
wpa_supplicant/wpa_cli.c

@@ -1164,6 +1164,71 @@ static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
 }
 
 
+#ifdef CONFIG_AP
+static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	char buf[64];
+	if (argc != 1) {
+		printf("Invalid 'sta' command - exactly one argument, STA "
+		       "address, is required.\n");
+		return -1;
+	}
+	snprintf(buf, sizeof(buf), "STA %s", argv[0]);
+	return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
+				char *addr, size_t addr_len)
+{
+	char buf[4096], *pos;
+	size_t len;
+	int ret;
+
+	if (ctrl_conn == NULL) {
+		printf("Not connected to hostapd - command dropped.\n");
+		return -1;
+	}
+	len = sizeof(buf) - 1;
+	ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
+			       wpa_cli_msg_cb);
+	if (ret == -2) {
+		printf("'%s' command timed out.\n", cmd);
+		return -2;
+	} else if (ret < 0) {
+		printf("'%s' command failed.\n", cmd);
+		return -1;
+	}
+
+	buf[len] = '\0';
+	if (memcmp(buf, "FAIL", 4) == 0)
+		return -1;
+	printf("%s", buf);
+
+	pos = buf;
+	while (*pos != '\0' && *pos != '\n')
+		pos++;
+	*pos = '\0';
+	os_strlcpy(addr, buf, addr_len);
+	return 0;
+}
+
+
+static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	char addr[32], cmd[64];
+
+	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
+		return 0;
+	do {
+		snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
+	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
+
+	return -1;
+}
+#endif /* CONFIG_AP */
+
+
 enum wpa_cli_cmd_flags {
 	cli_cmd_flag_none		= 0x00,
 	cli_cmd_flag_sensitive		= 0x01
@@ -1335,6 +1400,14 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
 	{ "ibss_rsn", wpa_cli_cmd_ibss_rsn,
 	  cli_cmd_flag_none,
 	  "<addr> = request RSN authentication with <addr> in IBSS" },
+#ifdef CONFIG_AP
+	{ "sta", wpa_cli_cmd_sta,
+	  cli_cmd_flag_none,
+	  "<addr> = get information about an associated station (AP)" },
+	{ "all_sta", wpa_cli_cmd_all_sta,
+	  cli_cmd_flag_none,
+	  "= get information about all associated stations (AP)" },
+#endif /* CONFIG_AP */
 	{ NULL, NULL, cli_cmd_flag_none, NULL }
 };