mac80211: use TDLS initiator in tdls_mgmt operations
authorArik Nemtsov <arik@wizery.com>
Wed, 11 Jun 2014 14:18:22 +0000 (17:18 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 23 Jun 2014 12:24:55 +0000 (14:24 +0200)
The TDLS initiator is set once during link setup. If determines the
address ordering in the link identifier IE.
Use the value from userspace in order to have a correct teardown packet.
With the current code, a teardown from the responder side fails the TDLS
MIC check because of a bad link identifier IE.

Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/tdls.c

index 0b3ca2c..c4a9af3 100644 (file)
@@ -193,13 +193,14 @@ static int
 ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
                                const u8 *peer, u8 action_code,
                                u8 dialog_token, u16 status_code,
-                               u32 peer_capability, const u8 *extra_ies,
-                               size_t extra_ies_len)
+                               u32 peer_capability, bool initiator,
+                               const u8 *extra_ies, size_t extra_ies_len)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb = NULL;
        bool send_direct;
+       const u8 *init_addr, *rsp_addr;
        int ret;
 
        skb = dev_alloc_skb(local->hw.extra_tx_headroom +
@@ -242,27 +243,42 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
        if (extra_ies_len)
                memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
 
-       /* the TDLS link IE is always added last */
+       /* sanity check for initiator */
        switch (action_code) {
        case WLAN_TDLS_SETUP_REQUEST:
        case WLAN_TDLS_SETUP_CONFIRM:
-       case WLAN_TDLS_TEARDOWN:
        case WLAN_TDLS_DISCOVERY_REQUEST:
-               /* we are the initiator */
-               ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer,
-                                          sdata->u.mgd.bssid);
+               if (!initiator) {
+                       ret = -EINVAL;
+                       goto fail;
+               }
                break;
        case WLAN_TDLS_SETUP_RESPONSE:
        case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
-               /* we are the responder */
-               ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr,
-                                          sdata->u.mgd.bssid);
+               if (initiator) {
+                       ret = -EINVAL;
+                       goto fail;
+               }
+               break;
+       case WLAN_TDLS_TEARDOWN:
+               /* any value is ok */
                break;
        default:
                ret = -ENOTSUPP;
                goto fail;
        }
 
+       if (initiator) {
+               init_addr = sdata->vif.addr;
+               rsp_addr = peer;
+       } else {
+               init_addr = peer;
+               rsp_addr = sdata->vif.addr;
+       }
+
+       ieee80211_tdls_add_link_ie(skb, init_addr, rsp_addr,
+                                  sdata->u.mgd.bssid);
+
        if (send_direct) {
                ieee80211_tx_skb(sdata, skb);
                return 0;
@@ -327,8 +343,8 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
 
        ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
                                              dialog_token, status_code,
-                                             peer_capability, extra_ies,
-                                             extra_ies_len);
+                                             peer_capability, initiator,
+                                             extra_ies, extra_ies_len);
        if (ret < 0)
                goto exit;