Browse Source

WNM: Add option for passing TFS request from external programs

The optional tfs_req=<hex dump> parameter can be added for the wnm_sleep
command to specify the TFS request element to use in the WNM-Sleep Mode
Request frame.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
Jouni Malinen 12 years ago
parent
commit
cd0ef65784
4 changed files with 61 additions and 14 deletions
  1. 29 1
      wpa_supplicant/ctrl_iface.c
  2. 1 1
      wpa_supplicant/events.c
  3. 30 11
      wpa_supplicant/wnm_sta.c
  4. 1 1
      wpa_supplicant/wnm_sta.h

+ 29 - 1
wpa_supplicant/ctrl_iface.c

@@ -4679,6 +4679,8 @@ static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
 	int enter;
 	int intval = 0;
 	char *pos;
+	int ret;
+	struct wpabuf *tfs_req = NULL;
 
 	if (os_strncmp(cmd, "enter", 5) == 0)
 		enter = 1;
@@ -4691,7 +4693,33 @@ static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
 	if (pos)
 		intval = atoi(pos + 10);
 
-	return ieee802_11_send_wnmsleep_req(wpa_s, enter ? 0 : 1, intval);
+	pos = os_strstr(cmd, " tfs_req=");
+	if (pos) {
+		char *end;
+		size_t len;
+		pos += 9;
+		end = os_strchr(pos, ' ');
+		if (end)
+			len = end - pos;
+		else
+			len = os_strlen(pos);
+		if (len & 1)
+			return -1;
+		len /= 2;
+		tfs_req = wpabuf_alloc(len);
+		if (tfs_req == NULL)
+			return -1;
+		if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) {
+			wpabuf_free(tfs_req);
+			return -1;
+		}
+	}
+
+	ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? 0 : 1, intval,
+					   tfs_req);
+	wpabuf_free(tfs_req);
+
+	return ret;
 }
 
 #endif /* CONFIG_WNM */

+ 1 - 1
wpa_supplicant/events.c

@@ -2150,7 +2150,7 @@ static void wpa_supplicant_event_wnm(struct wpa_supplicant *wpa_s,
 			   "(action=%d, intval=%d)",
 			   data->wnm.sleep_action, data->wnm.sleep_intval);
 		ieee802_11_send_wnmsleep_req(wpa_s, data->wnm.sleep_action,
-					     data->wnm.sleep_intval);
+					     data->wnm.sleep_intval, NULL);
 		break;
 	}
 }

+ 30 - 11
wpa_supplicant/wnm_sta.c

@@ -41,7 +41,7 @@ static int ieee80211_11_set_tfs_ie(struct wpa_supplicant *wpa_s,
 
 /* MLME-SLEEPMODE.request */
 int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s,
-				 u8 action, u16 intval)
+				 u8 action, u16 intval, struct wpabuf *tfs_req)
 {
 	struct ieee80211_mgmt *mgmt;
 	int res;
@@ -53,6 +53,11 @@ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s,
 	enum wnm_oper tfs_oper = action == 0 ? WNM_SLEEP_TFS_REQ_IE_ADD :
 		WNM_SLEEP_TFS_REQ_IE_NONE;
 
+	wpa_printf(MSG_DEBUG, "WNM: Request to send WNM-Sleep Mode Request "
+		   "action=%s to " MACSTR,
+		   action == 0 ? "enter" : "exit",
+		   MAC2STR(wpa_s->bssid));
+
 	/* WNM-Sleep Mode IE */
 	wnmsleep_ie_len = sizeof(struct wnm_sleep_element);
 	wnmsleep_ie = os_zalloc(sizeof(struct wnm_sleep_element));
@@ -63,19 +68,33 @@ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s,
 	wnmsleep_ie->action_type = action;
 	wnmsleep_ie->status = WNM_STATUS_SLEEP_ACCEPT;
 	wnmsleep_ie->intval = host_to_le16(intval);
+	wpa_hexdump(MSG_DEBUG, "WNM: WNM-Sleep Mode element",
+		    (u8 *) wnmsleep_ie, wnmsleep_ie_len);
 
 	/* TFS IE(s) */
-	wnmtfs_ie = os_zalloc(MAX_TFS_IE_LEN);
-	if (wnmtfs_ie == NULL) {
-		os_free(wnmsleep_ie);
-		return -1;
-	}
-	if (ieee80211_11_get_tfs_ie(wpa_s, wnmtfs_ie, &wnmtfs_ie_len,
-				    tfs_oper)) {
-		wnmtfs_ie_len = 0;
-		os_free(wnmtfs_ie);
-		wnmtfs_ie = NULL;
+	if (tfs_req) {
+		wnmtfs_ie_len = wpabuf_len(tfs_req);
+		wnmtfs_ie = os_malloc(wnmtfs_ie_len);
+		if (wnmtfs_ie == NULL) {
+			os_free(wnmsleep_ie);
+			return -1;
+		}
+		os_memcpy(wnmtfs_ie, wpabuf_head(tfs_req), wnmtfs_ie_len);
+	} else {
+		wnmtfs_ie = os_zalloc(MAX_TFS_IE_LEN);
+		if (wnmtfs_ie == NULL) {
+			os_free(wnmsleep_ie);
+			return -1;
+		}
+		if (ieee80211_11_get_tfs_ie(wpa_s, wnmtfs_ie, &wnmtfs_ie_len,
+					    tfs_oper)) {
+			wnmtfs_ie_len = 0;
+			os_free(wnmtfs_ie);
+			wnmtfs_ie = NULL;
+		}
 	}
+	wpa_hexdump(MSG_DEBUG, "WNM: TFS Request element",
+		    (u8 *) wnmtfs_ie, wnmtfs_ie_len);
 
 	mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len + wnmtfs_ie_len);
 	if (mgmt == NULL) {

+ 1 - 1
wpa_supplicant/wnm_sta.h

@@ -13,7 +13,7 @@ struct rx_action;
 struct wpa_supplicant;
 
 int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s,
-				 u8 action, u16 intval);
+				 u8 action, u16 intval, struct wpabuf *tfs_req);
 
 void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
 			      struct rx_action *action);