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>
This commit is contained in:
Jouni Malinen 2012-12-16 12:31:16 +02:00 committed by Jouni Malinen
parent 61c54976f5
commit cd0ef65784
4 changed files with 61 additions and 14 deletions

View file

@ -4679,6 +4679,8 @@ static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
int enter; int enter;
int intval = 0; int intval = 0;
char *pos; char *pos;
int ret;
struct wpabuf *tfs_req = NULL;
if (os_strncmp(cmd, "enter", 5) == 0) if (os_strncmp(cmd, "enter", 5) == 0)
enter = 1; enter = 1;
@ -4691,7 +4693,33 @@ static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd)
if (pos) if (pos)
intval = atoi(pos + 10); 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 */ #endif /* CONFIG_WNM */

View file

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

View file

@ -41,7 +41,7 @@ static int ieee80211_11_set_tfs_ie(struct wpa_supplicant *wpa_s,
/* MLME-SLEEPMODE.request */ /* MLME-SLEEPMODE.request */
int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s, 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; struct ieee80211_mgmt *mgmt;
int res; 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 : enum wnm_oper tfs_oper = action == 0 ? WNM_SLEEP_TFS_REQ_IE_ADD :
WNM_SLEEP_TFS_REQ_IE_NONE; 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 */ /* WNM-Sleep Mode IE */
wnmsleep_ie_len = sizeof(struct wnm_sleep_element); wnmsleep_ie_len = sizeof(struct wnm_sleep_element);
wnmsleep_ie = os_zalloc(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->action_type = action;
wnmsleep_ie->status = WNM_STATUS_SLEEP_ACCEPT; wnmsleep_ie->status = WNM_STATUS_SLEEP_ACCEPT;
wnmsleep_ie->intval = host_to_le16(intval); 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) */ /* TFS IE(s) */
wnmtfs_ie = os_zalloc(MAX_TFS_IE_LEN); if (tfs_req) {
if (wnmtfs_ie == NULL) { wnmtfs_ie_len = wpabuf_len(tfs_req);
os_free(wnmsleep_ie); wnmtfs_ie = os_malloc(wnmtfs_ie_len);
return -1; if (wnmtfs_ie == NULL) {
} os_free(wnmsleep_ie);
if (ieee80211_11_get_tfs_ie(wpa_s, wnmtfs_ie, &wnmtfs_ie_len, return -1;
tfs_oper)) { }
wnmtfs_ie_len = 0; os_memcpy(wnmtfs_ie, wpabuf_head(tfs_req), wnmtfs_ie_len);
os_free(wnmtfs_ie); } else {
wnmtfs_ie = NULL; 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); mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len + wnmtfs_ie_len);
if (mgmt == NULL) { if (mgmt == NULL) {

View file

@ -13,7 +13,7 @@ struct rx_action;
struct wpa_supplicant; struct wpa_supplicant;
int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s, 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, void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
struct rx_action *action); struct rx_action *action);