]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/mac80211/mlme.c
mac80211: allow drivers to support NL80211_SCAN_FLAG_RANDOM_ADDR
[mirror_ubuntu-artful-kernel.git] / net / mac80211 / mlme.c
index c078cd344ca46b963f8c10890c4251b22631adc2..d29589a090658436427e7d153879df7978c534e9 100644 (file)
@@ -775,11 +775,30 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
                        WLAN_EID_QOS_CAPA,
                        WLAN_EID_RRM_ENABLED_CAPABILITIES,
                        WLAN_EID_MOBILITY_DOMAIN,
+                       WLAN_EID_FAST_BSS_TRANSITION,   /* reassoc only */
+                       WLAN_EID_RIC_DATA,              /* reassoc only */
                        WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
                };
-               noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
-                                            before_ht, ARRAY_SIZE(before_ht),
-                                            offset);
+               static const u8 after_ric[] = {
+                       WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
+                       WLAN_EID_HT_CAPABILITY,
+                       WLAN_EID_BSS_COEX_2040,
+                       WLAN_EID_EXT_CAPABILITY,
+                       WLAN_EID_QOS_TRAFFIC_CAPA,
+                       WLAN_EID_TIM_BCAST_REQ,
+                       WLAN_EID_INTERWORKING,
+                       /* 60GHz doesn't happen right now */
+                       WLAN_EID_VHT_CAPABILITY,
+                       WLAN_EID_OPMODE_NOTIF,
+               };
+
+               noffset = ieee80211_ie_split_ric(assoc_data->ie,
+                                                assoc_data->ie_len,
+                                                before_ht,
+                                                ARRAY_SIZE(before_ht),
+                                                after_ric,
+                                                ARRAY_SIZE(after_ric),
+                                                offset);
                pos = skb_put(skb, noffset - offset);
                memcpy(pos, assoc_data->ie + offset, noffset - offset);
                offset = noffset;
@@ -813,6 +832,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
                        WLAN_EID_TIM_BCAST_REQ,
                        WLAN_EID_INTERWORKING,
                };
+
+               /* RIC already taken above, so no need to handle here anymore */
                noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
                                             before_vht, ARRAY_SIZE(before_vht),
                                             offset);
@@ -1028,6 +1049,8 @@ static void ieee80211_chswitch_post_beacon(struct ieee80211_sub_if_data *sdata)
                sdata->csa_block_tx = false;
        }
 
+       cfg80211_ch_switch_notify(sdata->dev, &sdata->reserved_chandef);
+
        sdata->vif.csa_active = false;
        ifmgd->csa_waiting_bcn = false;
 
@@ -1184,6 +1207,9 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
                                          IEEE80211_QUEUE_STOP_REASON_CSA);
        mutex_unlock(&local->mtx);
 
+       cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef,
+                                         csa_ie.count);
+
        if (local->ops->channel_switch) {
                /* use driver's channel switch callback */
                drv_channel_switch(local, sdata, &ch_switch);
@@ -2199,7 +2225,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
                else
                        ssid_len = ssid[1];
 
-               ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL,
+               ieee80211_send_probe_req(sdata, sdata->vif.addr, NULL,
+                                        ssid + 2, ssid_len, NULL,
                                         0, (u32) -1, true, 0,
                                         ifmgd->associated->channel, false);
                rcu_read_unlock();
@@ -2302,7 +2329,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
        else
                ssid_len = ssid[1];
 
-       skb = ieee80211_build_probe_req(sdata, cbss->bssid,
+       skb = ieee80211_build_probe_req(sdata, sdata->vif.addr, cbss->bssid,
                                        (u32) -1, cbss->channel,
                                        ssid + 2, ssid_len,
                                        NULL, 0, true);
@@ -2776,6 +2803,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
        }
 
        ifmgd->aid = aid;
+       ifmgd->tdls_chan_switch_prohibited =
+               elems.ext_capab && elems.ext_capab_len >= 5 &&
+               (elems.ext_capab[4] & WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED);
 
        /*
         * Some APs are erroneously not including some information in their
@@ -3620,7 +3650,8 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
                 * Direct probe is sent to broadcast address as some APs
                 * will not answer to direct packet in unassociated state.
                 */
-               ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],
+               ieee80211_send_probe_req(sdata, sdata->vif.addr, NULL,
+                                        ssidie + 2, ssidie[1],
                                         NULL, 0, (u32) -1, true, 0,
                                         auth_data->bss->channel, false);
                rcu_read_unlock();
@@ -3977,6 +4008,11 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
                ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC;
        else
                ifmgd->req_smps = IEEE80211_SMPS_OFF;
+
+       /* Setup TDLS data */
+       spin_lock_init(&ifmgd->teardown_lock);
+       ifmgd->teardown_skb = NULL;
+       ifmgd->orig_teardown_skb = NULL;
 }
 
 /* scan finished notification */
@@ -4839,6 +4875,13 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
        }
        if (ifmgd->auth_data)
                ieee80211_destroy_auth_data(sdata, false);
+       spin_lock_bh(&ifmgd->teardown_lock);
+       if (ifmgd->teardown_skb) {
+               kfree_skb(ifmgd->teardown_skb);
+               ifmgd->teardown_skb = NULL;
+               ifmgd->orig_teardown_skb = NULL;
+       }
+       spin_unlock_bh(&ifmgd->teardown_lock);
        del_timer_sync(&ifmgd->timer);
        sdata_unlock(sdata);
 }