Merge branches 'upstream/xenfs' and 'upstream/core' of git://git.kernel.org/pub/scm...
[linux-2.6-microblaze.git] / net / mac80211 / mesh_plink.c
index ea13a80..1c91f0f 100644 (file)
@@ -412,7 +412,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
        enum plink_event event;
        enum plink_frame_type ftype;
        size_t baselen;
-       bool deactivated;
+       bool deactivated, matches_local = true;
        u8 ie_len;
        u8 *baseaddr;
        __le16 plid, llid, reason;
@@ -487,6 +487,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
        /* Now we will figure out the appropriate event... */
        event = PLINK_UNDEFINED;
        if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) {
+               matches_local = false;
                switch (ftype) {
                case PLINK_OPEN:
                        event = OPN_RJCT;
@@ -498,7 +499,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
                        /* avoid warning */
                        break;
                }
-               spin_lock_bh(&sta->lock);
+       }
+
+       if (!sta && !matches_local) {
+               rcu_read_unlock();
+               reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
+               llid = 0;
+               mesh_plink_frame_tx(sdata, PLINK_CLOSE, mgmt->sa, llid,
+                                   plid, reason);
+               return;
        } else if (!sta) {
                /* ftype == PLINK_OPEN */
                u32 rates;
@@ -522,7 +531,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
                }
                event = OPN_ACPT;
                spin_lock_bh(&sta->lock);
-       } else {
+       } else if (matches_local) {
                spin_lock_bh(&sta->lock);
                switch (ftype) {
                case PLINK_OPEN:
@@ -564,6 +573,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
                        rcu_read_unlock();
                        return;
                }
+       } else {
+               spin_lock_bh(&sta->lock);
        }
 
        mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n",