TDLS: Set the initiator during tdls_mgmt operations
authorArik Nemtsov <arik@wizery.com>
Mon, 29 Sep 2014 18:47:51 +0000 (20:47 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 3 Oct 2014 08:52:21 +0000 (11:52 +0300)
Some drivers need to know the initiator of a TDLS connection in order
to generate a correct TDLS mgmt packet. It is used to determine
the link identifier IE. Pass this information to the driver.

Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
src/drivers/driver.h
src/drivers/driver_nl80211.c
src/rsn_supp/tdls.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_i.h
wpa_supplicant/driver_i.h
wpa_supplicant/wpas_glue.c

index 501314b..9595b9d 100644 (file)
@@ -2503,6 +2503,7 @@ struct wpa_driver_ops {
         * @dialog_token: Dialog Token to use in the message (if needed)
         * @status_code: Status Code or Reason Code to use (if needed)
         * @peer_capab: TDLS peer capability (TDLS_PEER_* bitfield)
+        * @initiator: Is the current end the TDLS link initiator
         * @buf: TDLS IEs to add to the message
         * @len: Length of buf in octets
         * Returns: 0 on success, negative (<0) on failure
@@ -2512,7 +2513,7 @@ struct wpa_driver_ops {
         */
        int (*send_tdls_mgmt)(void *priv, const u8 *dst, u8 action_code,
                              u8 dialog_token, u16 status_code, u32 peer_capab,
-                             const u8 *buf, size_t len);
+                             int initiator, const u8 *buf, size_t len);
 
        /**
         * tdls_oper - Ask the driver to perform high-level TDLS operations
index 026cb7d..c212a19 100644 (file)
@@ -11605,7 +11605,8 @@ nla_put_failure:
 
 static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
                                  u8 dialog_token, u16 status_code,
-                                 u32 peer_capab, const u8 *buf, size_t len)
+                                 u32 peer_capab, int initiator, const u8 *buf,
+                                 size_t len)
 {
        struct i802_bss *bss = priv;
        struct wpa_driver_nl80211_data *drv = bss->drv;
@@ -11636,6 +11637,8 @@ static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
                 */
                NLA_PUT_U32(msg, NL80211_ATTR_TDLS_PEER_CAPABILITY, peer_capab);
        }
+       if (initiator)
+               NLA_PUT_FLAG(msg, NL80211_ATTR_TDLS_INITIATOR);
        NLA_PUT(msg, NL80211_ATTR_IE, len, buf);
 
        return send_and_recv_msgs(drv, msg, NULL, NULL);
index 93ae143..6803fb6 100644 (file)
@@ -218,26 +218,29 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
 static int wpa_tdls_send_tpk_msg(struct wpa_sm *sm, const u8 *dst,
                                 u8 action_code, u8 dialog_token,
                                 u16 status_code, u32 peer_capab,
-                                const u8 *buf, size_t len)
+                                int initiator, const u8 *buf, size_t len)
 {
        return wpa_sm_send_tdls_mgmt(sm, dst, action_code, dialog_token,
-                                    status_code, peer_capab, buf, len);
+                                    status_code, peer_capab, initiator, buf,
+                                    len);
 }
 
 
 static int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code,
                             u8 dialog_token, u16 status_code, u32 peer_capab,
-                            const u8 *msg, size_t msg_len)
+                            int initiator, const u8 *msg, size_t msg_len)
 {
        struct wpa_tdls_peer *peer;
 
        wpa_printf(MSG_DEBUG, "TDLS: TPK send dest=" MACSTR " action_code=%u "
-                  "dialog_token=%u status_code=%u peer_capab=%u msg_len=%u",
+                  "dialog_token=%u status_code=%u peer_capab=%u initiator=%d "
+                  "msg_len=%u",
                   MAC2STR(dest), action_code, dialog_token, status_code,
-                  peer_capab, (unsigned int) msg_len);
+                  peer_capab, initiator, (unsigned int) msg_len);
 
        if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token,
-                                 status_code, peer_capab, msg, msg_len)) {
+                                 status_code, peer_capab, initiator, msg,
+                                 msg_len)) {
                wpa_printf(MSG_INFO, "TDLS: Failed to send message "
                           "(action_code=%u)", action_code);
                return -1;
@@ -333,6 +336,7 @@ static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx)
                                          peer->sm_tmr.dialog_token,
                                          peer->sm_tmr.status_code,
                                          peer->sm_tmr.peer_capab,
+                                         peer->initiator,
                                          peer->sm_tmr.buf,
                                          peer->sm_tmr.buf_len)) {
                        wpa_printf(MSG_INFO, "TDLS: Failed to retry "
@@ -793,7 +797,7 @@ skip_ies:
 
        /* request driver to send Teardown using this FTIE */
        wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0,
-                         reason_code, 0, rbuf, pos - rbuf);
+                         reason_code, 0, peer->initiator, rbuf, pos - rbuf);
        os_free(rbuf);
 
        return 0;
@@ -968,17 +972,19 @@ skip_ftie:
  *     appropriate status code mentioning reason for error/failure.
  * @dst        - MAC addr of Peer station
  * @tdls_action - TDLS frame type for which error code is sent
+ * @initiator   - was this end the initiator of the connection
  * @status     - status code mentioning reason
  */
 
 static int wpa_tdls_send_error(struct wpa_sm *sm, const u8 *dst,
-                              u8 tdls_action, u8 dialog_token, u16 status)
+                              u8 tdls_action, u8 dialog_token, int initiator,
+                              u16 status)
 {
        wpa_printf(MSG_DEBUG, "TDLS: Sending error to " MACSTR
                   " (action=%u status=%u)",
                   MAC2STR(dst), tdls_action, status);
        return wpa_tdls_tpk_send(sm, dst, tdls_action, dialog_token, status,
-                                0, NULL, 0);
+                                0, initiator, NULL, 0);
 }
 
 
@@ -1184,7 +1190,7 @@ skip_ies:
                   MAC2STR(peer->addr));
 
        status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST,
-                                  1, 0, 0, rbuf, pos - rbuf);
+                                  1, 0, 0, peer->initiator, rbuf, pos - rbuf);
        os_free(rbuf);
 
        return status;
@@ -1274,7 +1280,8 @@ static int wpa_tdls_send_tpk_m2(struct wpa_sm *sm,
 
 skip_ies:
        status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE,
-                                  dtoken, 0, 0, rbuf, pos - rbuf);
+                                  dtoken, 0, 0, peer->initiator, rbuf,
+                                  pos - rbuf);
        os_free(rbuf);
 
        return status;
@@ -1371,7 +1378,8 @@ skip_ies:
                peer_capab |= TDLS_PEER_WMM;
 
        status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM,
-                                  dtoken, 0, peer_capab, rbuf, pos - rbuf);
+                                  dtoken, 0, peer_capab, peer->initiator,
+                                  rbuf, pos - rbuf);
        os_free(rbuf);
 
        return status;
@@ -1457,7 +1465,7 @@ skip_rsn_ies:
        wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime);
 skip_ies:
        status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE,
-                                  dialog_token, 0, 0,  rbuf, pos - rbuf);
+                                  dialog_token, 0, 0, 0, rbuf, pos - rbuf);
        os_free(rbuf);
 
        return status;
@@ -1528,7 +1536,7 @@ int wpa_tdls_send_discovery_request(struct wpa_sm *sm, const u8 *addr)
        wpa_printf(MSG_DEBUG, "TDLS: Sending Discovery Request to peer "
                   MACSTR, MAC2STR(addr));
        return wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_DISCOVERY_REQUEST,
-                                1, 0, 0, NULL, 0);
+                                1, 0, 0, 1, NULL, 0);
 }
 
 
@@ -2051,7 +2059,7 @@ skip_rsn_check:
        return 0;
 
 error:
-       wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken,
+       wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, 0,
                            status);
        if (peer)
                wpa_tdls_peer_free(sm, peer);
@@ -2362,7 +2370,7 @@ skip_rsn:
        return ret;
 
 error:
-       wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken,
+       wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, 1,
                            status);
        wpa_tdls_disable_peer_link(sm, peer);
        return -1;
index 07a7bf9..e7c5569 100644 (file)
@@ -55,7 +55,7 @@ struct wpa_sm_ctx {
        int (*send_tdls_mgmt)(void *ctx, const u8 *dst,
                              u8 action_code, u8 dialog_token,
                              u16 status_code, u32 peer_capab,
-                             const u8 *buf, size_t len);
+                             int initiator, const u8 *buf, size_t len);
        int (*tdls_oper)(void *ctx, int oper, const u8 *peer);
        int (*tdls_peer_addset)(void *ctx, const u8 *addr, int add, u16 aid,
                                u16 capability, const u8 *supp_rates,
index e20e9da..845a1b6 100644 (file)
@@ -268,12 +268,14 @@ static inline int wpa_sm_tdls_get_capa(struct wpa_sm *sm,
 static inline int wpa_sm_send_tdls_mgmt(struct wpa_sm *sm, const u8 *dst,
                                        u8 action_code, u8 dialog_token,
                                        u16 status_code, u32 peer_capab,
-                                       const u8 *buf, size_t len)
+                                       int initiator, const u8 *buf,
+                                       size_t len)
 {
        if (sm->ctx->send_tdls_mgmt)
                return sm->ctx->send_tdls_mgmt(sm->ctx->ctx, dst, action_code,
                                               dialog_token, status_code,
-                                              peer_capab, buf, len);
+                                              peer_capab, initiator, buf,
+                                              len);
        return -1;
 }
 
index cba32a9..649de9b 100644 (file)
@@ -532,14 +532,14 @@ static inline int wpa_drv_ampdu(struct wpa_supplicant *wpa_s, int ampdu)
 static inline int wpa_drv_send_tdls_mgmt(struct wpa_supplicant *wpa_s,
                                         const u8 *dst, u8 action_code,
                                         u8 dialog_token, u16 status_code,
-                                        u32 peer_capab, const u8 *buf,
-                                        size_t len)
+                                        u32 peer_capab, int initiator,
+                                        const u8 *buf, size_t len)
 {
        if (wpa_s->driver->send_tdls_mgmt) {
                return wpa_s->driver->send_tdls_mgmt(wpa_s->drv_priv, dst,
                                                     action_code, dialog_token,
                                                     status_code, peer_capab,
-                                                    buf, len);
+                                                    initiator, buf, len);
        }
        return -1;
 }
index 09b5961..896c256 100644 (file)
@@ -580,11 +580,13 @@ static int wpa_supplicant_tdls_get_capa(void *ctx, int *tdls_supported,
 static int wpa_supplicant_send_tdls_mgmt(void *ctx, const u8 *dst,
                                         u8 action_code, u8 dialog_token,
                                         u16 status_code, u32 peer_capab,
-                                        const u8 *buf, size_t len)
+                                        int initiator, const u8 *buf,
+                                        size_t len)
 {
        struct wpa_supplicant *wpa_s = ctx;
        return wpa_drv_send_tdls_mgmt(wpa_s, dst, action_code, dialog_token,
-                                     status_code, peer_capab, buf, len);
+                                     status_code, peer_capab, initiator, buf,
+                                     len);
 }