]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WNM: Add option for passing TFS request from external programs
authorJouni Malinen <jouni@qca.qualcomm.com>
Sun, 16 Dec 2012 10:31:16 +0000 (12:31 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 16 Dec 2012 10:31:16 +0000 (12:31 +0200)
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>

wpa_supplicant/ctrl_iface.c
wpa_supplicant/events.c
wpa_supplicant/wnm_sta.c
wpa_supplicant/wnm_sta.h

index b12d349098f1c7d01c35ef0376f43d9c9c8fb157..7a27abdb6345ceb8cf92121331e00b544d63e8dd 100644 (file)
@@ -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 */
index 35ba8e4662360b68cdf5ec561c56167af3cdef8b..492674669fb95773ab6a1fcd8d6b9f519b7055e2 100644 (file)
@@ -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;
        }
 }
index e81ef3134e082e690600d85d411e131e28334541..bcd1d4a8607ba852ec86cd98a8cbfac336e290a2 100644 (file)
@@ -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) {
index 96fe0d9c663ab928b1e47bce865eb9f914cebf8c..3f9d88b714a91d83176be659cb003bad5aa150ef 100644 (file)
@@ -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);