aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c624
1 files changed, 325 insertions, 299 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 19c7f21e49d1..e14830106526 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -93,44 +93,46 @@ static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss,
93 return count; 93 return count;
94} 94}
95 95
96/* frame sending functions */ 96/* also used by mesh code */
97static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, 97u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
98 struct ieee80211_if_sta *ifsta, 98 struct ieee802_11_elems *elems,
99 int transaction, u8 *extra, size_t extra_len, 99 enum ieee80211_band band)
100 int encrypt)
101{ 100{
102 struct ieee80211_local *local = sdata->local; 101 struct ieee80211_supported_band *sband;
103 struct sk_buff *skb; 102 struct ieee80211_rate *bitrates;
104 struct ieee80211_mgmt *mgmt; 103 size_t num_rates;
104 u64 supp_rates;
105 int i, j;
106 sband = local->hw.wiphy->bands[band];
105 107
106 skb = dev_alloc_skb(local->hw.extra_tx_headroom + 108 if (!sband) {
107 sizeof(*mgmt) + 6 + extra_len); 109 WARN_ON(1);
108 if (!skb) { 110 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
109 printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
110 "frame\n", sdata->dev->name);
111 return;
112 } 111 }
113 skb_reserve(skb, local->hw.extra_tx_headroom);
114 112
115 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); 113 bitrates = sband->bitrates;
116 memset(mgmt, 0, 24 + 6); 114 num_rates = sband->n_bitrates;
117 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 115 supp_rates = 0;
118 IEEE80211_STYPE_AUTH); 116 for (i = 0; i < elems->supp_rates_len +
119 if (encrypt) 117 elems->ext_supp_rates_len; i++) {
120 mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); 118 u8 rate = 0;
121 memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); 119 int own_rate;
122 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 120 if (i < elems->supp_rates_len)
123 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); 121 rate = elems->supp_rates[i];
124 mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg); 122 else if (elems->ext_supp_rates)
125 mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); 123 rate = elems->ext_supp_rates
126 ifsta->auth_transaction = transaction + 1; 124 [i - elems->supp_rates_len];
127 mgmt->u.auth.status_code = cpu_to_le16(0); 125 own_rate = 5 * (rate & 0x7f);
128 if (extra) 126 for (j = 0; j < num_rates; j++)
129 memcpy(skb_put(skb, extra_len), extra, extra_len); 127 if (bitrates[j].bitrate == own_rate)
130 128 supp_rates |= BIT(j);
131 ieee80211_tx_skb(sdata, skb, encrypt); 129 }
130 return supp_rates;
132} 131}
133 132
133/* frame sending functions */
134
135/* also used by scanning code */
134void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, 136void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
135 u8 *ssid, size_t ssid_len) 137 u8 *ssid, size_t ssid_len)
136{ 138{
@@ -191,6 +193,43 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
191 ieee80211_tx_skb(sdata, skb, 0); 193 ieee80211_tx_skb(sdata, skb, 0);
192} 194}
193 195
196static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
197 struct ieee80211_if_sta *ifsta,
198 int transaction, u8 *extra, size_t extra_len,
199 int encrypt)
200{
201 struct ieee80211_local *local = sdata->local;
202 struct sk_buff *skb;
203 struct ieee80211_mgmt *mgmt;
204
205 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
206 sizeof(*mgmt) + 6 + extra_len);
207 if (!skb) {
208 printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
209 "frame\n", sdata->dev->name);
210 return;
211 }
212 skb_reserve(skb, local->hw.extra_tx_headroom);
213
214 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
215 memset(mgmt, 0, 24 + 6);
216 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
217 IEEE80211_STYPE_AUTH);
218 if (encrypt)
219 mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
220 memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
221 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
222 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
223 mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg);
224 mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
225 ifsta->auth_transaction = transaction + 1;
226 mgmt->u.auth.status_code = cpu_to_le16(0);
227 if (extra)
228 memcpy(skb_put(skb, extra_len), extra, extra_len);
229
230 ieee80211_tx_skb(sdata, skb, encrypt);
231}
232
194static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, 233static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
195 struct ieee80211_if_sta *ifsta) 234 struct ieee80211_if_sta *ifsta)
196{ 235{
@@ -1414,42 +1453,6 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
1414 return res; 1453 return res;
1415} 1454}
1416 1455
1417u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
1418 struct ieee802_11_elems *elems,
1419 enum ieee80211_band band)
1420{
1421 struct ieee80211_supported_band *sband;
1422 struct ieee80211_rate *bitrates;
1423 size_t num_rates;
1424 u64 supp_rates;
1425 int i, j;
1426 sband = local->hw.wiphy->bands[band];
1427
1428 if (!sband) {
1429 WARN_ON(1);
1430 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1431 }
1432
1433 bitrates = sband->bitrates;
1434 num_rates = sband->n_bitrates;
1435 supp_rates = 0;
1436 for (i = 0; i < elems->supp_rates_len +
1437 elems->ext_supp_rates_len; i++) {
1438 u8 rate = 0;
1439 int own_rate;
1440 if (i < elems->supp_rates_len)
1441 rate = elems->supp_rates[i];
1442 else if (elems->ext_supp_rates)
1443 rate = elems->ext_supp_rates
1444 [i - elems->supp_rates_len];
1445 own_rate = 5 * (rate & 0x7f);
1446 for (j = 0; j < num_rates; j++)
1447 if (bitrates[j].bitrate == own_rate)
1448 supp_rates |= BIT(j);
1449 }
1450 return supp_rates;
1451}
1452
1453static u64 ieee80211_sta_get_mandatory_rates(struct ieee80211_local *local, 1456static u64 ieee80211_sta_get_mandatory_rates(struct ieee80211_local *local,
1454 enum ieee80211_band band) 1457 enum ieee80211_band band)
1455{ 1458{
@@ -1894,7 +1897,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata,
1894} 1897}
1895 1898
1896 1899
1897void ieee80211_sta_timer(unsigned long data) 1900static void ieee80211_sta_timer(unsigned long data)
1898{ 1901{
1899 struct ieee80211_sub_if_data *sdata = 1902 struct ieee80211_sub_if_data *sdata =
1900 (struct ieee80211_sub_if_data *) data; 1903 (struct ieee80211_sub_if_data *) data;
@@ -1937,28 +1940,6 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata,
1937} 1940}
1938 1941
1939 1942
1940void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata,
1941 struct ieee80211_if_sta *ifsta)
1942{
1943 struct ieee80211_local *local = sdata->local;
1944
1945 if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
1946 return;
1947
1948 if ((ifsta->flags & (IEEE80211_STA_BSSID_SET |
1949 IEEE80211_STA_AUTO_BSSID_SEL)) &&
1950 (ifsta->flags & (IEEE80211_STA_SSID_SET |
1951 IEEE80211_STA_AUTO_SSID_SEL))) {
1952
1953 if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED)
1954 ieee80211_set_disassoc(sdata, ifsta, true, true,
1955 WLAN_REASON_DEAUTH_LEAVING);
1956
1957 set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
1958 queue_work(local->hw.workqueue, &ifsta->work);
1959 }
1960}
1961
1962static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta, 1943static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
1963 const char *ssid, int ssid_len) 1944 const char *ssid, int ssid_len)
1964{ 1945{
@@ -2160,159 +2141,6 @@ dont_join:
2160} 2141}
2161 2142
2162 2143
2163int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len)
2164{
2165 struct ieee80211_if_sta *ifsta;
2166 int res;
2167
2168 if (len > IEEE80211_MAX_SSID_LEN)
2169 return -EINVAL;
2170
2171 ifsta = &sdata->u.sta;
2172
2173 if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) {
2174 memset(ifsta->ssid, 0, sizeof(ifsta->ssid));
2175 memcpy(ifsta->ssid, ssid, len);
2176 ifsta->ssid_len = len;
2177 ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
2178
2179 res = 0;
2180 /*
2181 * Hack! MLME code needs to be cleaned up to have different
2182 * entry points for configuration and internal selection change
2183 */
2184 if (netif_running(sdata->dev))
2185 res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID);
2186 if (res) {
2187 printk(KERN_DEBUG "%s: Failed to config new SSID to "
2188 "the low-level driver\n", sdata->dev->name);
2189 return res;
2190 }
2191 }
2192
2193 if (len)
2194 ifsta->flags |= IEEE80211_STA_SSID_SET;
2195 else
2196 ifsta->flags &= ~IEEE80211_STA_SSID_SET;
2197
2198 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
2199 !(ifsta->flags & IEEE80211_STA_BSSID_SET)) {
2200 ifsta->ibss_join_req = jiffies;
2201 ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH;
2202 return ieee80211_sta_find_ibss(sdata, ifsta);
2203 }
2204
2205 return 0;
2206}
2207
2208
2209int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len)
2210{
2211 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
2212 memcpy(ssid, ifsta->ssid, ifsta->ssid_len);
2213 *len = ifsta->ssid_len;
2214 return 0;
2215}
2216
2217
2218int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
2219{
2220 struct ieee80211_if_sta *ifsta;
2221 int res;
2222
2223 ifsta = &sdata->u.sta;
2224
2225 if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
2226 memcpy(ifsta->bssid, bssid, ETH_ALEN);
2227 res = 0;
2228 /*
2229 * Hack! See also ieee80211_sta_set_ssid.
2230 */
2231 if (netif_running(sdata->dev))
2232 res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID);
2233 if (res) {
2234 printk(KERN_DEBUG "%s: Failed to config new BSSID to "
2235 "the low-level driver\n", sdata->dev->name);
2236 return res;
2237 }
2238 }
2239
2240 if (is_valid_ether_addr(bssid))
2241 ifsta->flags |= IEEE80211_STA_BSSID_SET;
2242 else
2243 ifsta->flags &= ~IEEE80211_STA_BSSID_SET;
2244
2245 return 0;
2246}
2247
2248
2249int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len)
2250{
2251 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
2252
2253 kfree(ifsta->extra_ie);
2254 if (len == 0) {
2255 ifsta->extra_ie = NULL;
2256 ifsta->extra_ie_len = 0;
2257 return 0;
2258 }
2259 ifsta->extra_ie = kmalloc(len, GFP_KERNEL);
2260 if (!ifsta->extra_ie) {
2261 ifsta->extra_ie_len = 0;
2262 return -ENOMEM;
2263 }
2264 memcpy(ifsta->extra_ie, ie, len);
2265 ifsta->extra_ie_len = len;
2266 return 0;
2267}
2268
2269
2270struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
2271 struct sk_buff *skb, u8 *bssid,
2272 u8 *addr, u64 supp_rates)
2273{
2274 struct ieee80211_local *local = sdata->local;
2275 struct sta_info *sta;
2276 DECLARE_MAC_BUF(mac);
2277 int band = local->hw.conf.channel->band;
2278
2279 /* TODO: Could consider removing the least recently used entry and
2280 * allow new one to be added. */
2281 if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
2282 if (net_ratelimit()) {
2283 printk(KERN_DEBUG "%s: No room for a new IBSS STA "
2284 "entry %s\n", sdata->dev->name, print_mac(mac, addr));
2285 }
2286 return NULL;
2287 }
2288
2289 if (compare_ether_addr(bssid, sdata->u.sta.bssid))
2290 return NULL;
2291
2292#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
2293 printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n",
2294 wiphy_name(local->hw.wiphy), print_mac(mac, addr), sdata->dev->name);
2295#endif
2296
2297 sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
2298 if (!sta)
2299 return NULL;
2300
2301 set_sta_flags(sta, WLAN_STA_AUTHORIZED);
2302
2303 /* make sure mandatory rates are always added */
2304 sta->supp_rates[band] = supp_rates |
2305 ieee80211_sta_get_mandatory_rates(local, band);
2306
2307 rate_control_rate_init(sta, local);
2308
2309 if (sta_info_insert(sta))
2310 return NULL;
2311
2312 return sta;
2313}
2314
2315
2316static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, 2144static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata,
2317 struct ieee80211_if_sta *ifsta) 2145 struct ieee80211_if_sta *ifsta)
2318{ 2146{
@@ -2392,61 +2220,7 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata,
2392} 2220}
2393 2221
2394 2222
2395int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason) 2223static void ieee80211_sta_work(struct work_struct *work)
2396{
2397 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
2398
2399 printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n",
2400 sdata->dev->name, reason);
2401
2402 if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
2403 sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
2404 return -EINVAL;
2405
2406 ieee80211_set_disassoc(sdata, ifsta, true, true, reason);
2407 return 0;
2408}
2409
2410
2411int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason)
2412{
2413 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
2414
2415 printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n",
2416 sdata->dev->name, reason);
2417
2418 if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
2419 return -EINVAL;
2420
2421 if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED))
2422 return -1;
2423
2424 ieee80211_set_disassoc(sdata, ifsta, false, true, reason);
2425 return 0;
2426}
2427
2428void ieee80211_notify_mac(struct ieee80211_hw *hw,
2429 enum ieee80211_notification_types notif_type)
2430{
2431 struct ieee80211_local *local = hw_to_local(hw);
2432 struct ieee80211_sub_if_data *sdata;
2433
2434 switch (notif_type) {
2435 case IEEE80211_NOTIFY_RE_ASSOC:
2436 rcu_read_lock();
2437 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
2438 if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
2439 continue;
2440
2441 ieee80211_sta_req_auth(sdata, &sdata->u.sta);
2442 }
2443 rcu_read_unlock();
2444 break;
2445 }
2446}
2447EXPORT_SYMBOL(ieee80211_notify_mac);
2448
2449void ieee80211_sta_work(struct work_struct *work)
2450{ 2224{
2451 struct ieee80211_sub_if_data *sdata = 2225 struct ieee80211_sub_if_data *sdata =
2452 container_of(work, struct ieee80211_sub_if_data, u.sta.work); 2226 container_of(work, struct ieee80211_sub_if_data, u.sta.work);
@@ -2525,6 +2299,236 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
2525 &sdata->u.sta.work); 2299 &sdata->u.sta.work);
2526} 2300}
2527 2301
2302/* interface setup */
2303void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
2304{
2305 struct ieee80211_if_sta *ifsta;
2306
2307 ifsta = &sdata->u.sta;
2308 INIT_WORK(&ifsta->work, ieee80211_sta_work);
2309 setup_timer(&ifsta->timer, ieee80211_sta_timer,
2310 (unsigned long) sdata);
2311 skb_queue_head_init(&ifsta->skb_queue);
2312
2313 ifsta->capab = WLAN_CAPABILITY_ESS;
2314 ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
2315 IEEE80211_AUTH_ALG_SHARED_KEY;
2316 ifsta->flags |= IEEE80211_STA_CREATE_IBSS |
2317 IEEE80211_STA_AUTO_BSSID_SEL |
2318 IEEE80211_STA_AUTO_CHANNEL_SEL;
2319 if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4)
2320 ifsta->flags |= IEEE80211_STA_WMM_ENABLED;
2321}
2322
2323/*
2324 * Add a new IBSS station, will also be called by the RX code when,
2325 * in IBSS mode, receiving a frame from a yet-unknown station, hence
2326 * must be callable in atomic context.
2327 */
2328struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
2329 struct sk_buff *skb, u8 *bssid,
2330 u8 *addr, u64 supp_rates)
2331{
2332 struct ieee80211_local *local = sdata->local;
2333 struct sta_info *sta;
2334 DECLARE_MAC_BUF(mac);
2335 int band = local->hw.conf.channel->band;
2336
2337 /* TODO: Could consider removing the least recently used entry and
2338 * allow new one to be added. */
2339 if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
2340 if (net_ratelimit()) {
2341 printk(KERN_DEBUG "%s: No room for a new IBSS STA "
2342 "entry %s\n", sdata->dev->name, print_mac(mac, addr));
2343 }
2344 return NULL;
2345 }
2346
2347 if (compare_ether_addr(bssid, sdata->u.sta.bssid))
2348 return NULL;
2349
2350#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
2351 printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n",
2352 wiphy_name(local->hw.wiphy), print_mac(mac, addr), sdata->dev->name);
2353#endif
2354
2355 sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
2356 if (!sta)
2357 return NULL;
2358
2359 set_sta_flags(sta, WLAN_STA_AUTHORIZED);
2360
2361 /* make sure mandatory rates are always added */
2362 sta->supp_rates[band] = supp_rates |
2363 ieee80211_sta_get_mandatory_rates(local, band);
2364
2365 rate_control_rate_init(sta, local);
2366
2367 if (sta_info_insert(sta))
2368 return NULL;
2369
2370 return sta;
2371}
2372
2373/* configuration hooks */
2374void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata,
2375 struct ieee80211_if_sta *ifsta)
2376{
2377 struct ieee80211_local *local = sdata->local;
2378
2379 if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
2380 return;
2381
2382 if ((ifsta->flags & (IEEE80211_STA_BSSID_SET |
2383 IEEE80211_STA_AUTO_BSSID_SEL)) &&
2384 (ifsta->flags & (IEEE80211_STA_SSID_SET |
2385 IEEE80211_STA_AUTO_SSID_SEL))) {
2386
2387 if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED)
2388 ieee80211_set_disassoc(sdata, ifsta, true, true,
2389 WLAN_REASON_DEAUTH_LEAVING);
2390
2391 set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
2392 queue_work(local->hw.workqueue, &ifsta->work);
2393 }
2394}
2395
2396int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len)
2397{
2398 struct ieee80211_if_sta *ifsta;
2399 int res;
2400
2401 if (len > IEEE80211_MAX_SSID_LEN)
2402 return -EINVAL;
2403
2404 ifsta = &sdata->u.sta;
2405
2406 if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) {
2407 memset(ifsta->ssid, 0, sizeof(ifsta->ssid));
2408 memcpy(ifsta->ssid, ssid, len);
2409 ifsta->ssid_len = len;
2410 ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
2411
2412 res = 0;
2413 /*
2414 * Hack! MLME code needs to be cleaned up to have different
2415 * entry points for configuration and internal selection change
2416 */
2417 if (netif_running(sdata->dev))
2418 res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID);
2419 if (res) {
2420 printk(KERN_DEBUG "%s: Failed to config new SSID to "
2421 "the low-level driver\n", sdata->dev->name);
2422 return res;
2423 }
2424 }
2425
2426 if (len)
2427 ifsta->flags |= IEEE80211_STA_SSID_SET;
2428 else
2429 ifsta->flags &= ~IEEE80211_STA_SSID_SET;
2430
2431 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
2432 !(ifsta->flags & IEEE80211_STA_BSSID_SET)) {
2433 ifsta->ibss_join_req = jiffies;
2434 ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH;
2435 return ieee80211_sta_find_ibss(sdata, ifsta);
2436 }
2437
2438 return 0;
2439}
2440
2441int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len)
2442{
2443 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
2444 memcpy(ssid, ifsta->ssid, ifsta->ssid_len);
2445 *len = ifsta->ssid_len;
2446 return 0;
2447}
2448
2449int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
2450{
2451 struct ieee80211_if_sta *ifsta;
2452 int res;
2453
2454 ifsta = &sdata->u.sta;
2455
2456 if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
2457 memcpy(ifsta->bssid, bssid, ETH_ALEN);
2458 res = 0;
2459 /*
2460 * Hack! See also ieee80211_sta_set_ssid.
2461 */
2462 if (netif_running(sdata->dev))
2463 res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID);
2464 if (res) {
2465 printk(KERN_DEBUG "%s: Failed to config new BSSID to "
2466 "the low-level driver\n", sdata->dev->name);
2467 return res;
2468 }
2469 }
2470
2471 if (is_valid_ether_addr(bssid))
2472 ifsta->flags |= IEEE80211_STA_BSSID_SET;
2473 else
2474 ifsta->flags &= ~IEEE80211_STA_BSSID_SET;
2475
2476 return 0;
2477}
2478
2479int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len)
2480{
2481 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
2482
2483 kfree(ifsta->extra_ie);
2484 if (len == 0) {
2485 ifsta->extra_ie = NULL;
2486 ifsta->extra_ie_len = 0;
2487 return 0;
2488 }
2489 ifsta->extra_ie = kmalloc(len, GFP_KERNEL);
2490 if (!ifsta->extra_ie) {
2491 ifsta->extra_ie_len = 0;
2492 return -ENOMEM;
2493 }
2494 memcpy(ifsta->extra_ie, ie, len);
2495 ifsta->extra_ie_len = len;
2496 return 0;
2497}
2498
2499int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason)
2500{
2501 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
2502
2503 printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n",
2504 sdata->dev->name, reason);
2505
2506 if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
2507 sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
2508 return -EINVAL;
2509
2510 ieee80211_set_disassoc(sdata, ifsta, true, true, reason);
2511 return 0;
2512}
2513
2514int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason)
2515{
2516 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
2517
2518 printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n",
2519 sdata->dev->name, reason);
2520
2521 if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
2522 return -EINVAL;
2523
2524 if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED))
2525 return -1;
2526
2527 ieee80211_set_disassoc(sdata, ifsta, false, true, reason);
2528 return 0;
2529}
2530
2531/* scan finished notification */
2528void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) 2532void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
2529{ 2533{
2530 struct ieee80211_sub_if_data *sdata = local->scan_sdata; 2534 struct ieee80211_sub_if_data *sdata = local->scan_sdata;
@@ -2544,3 +2548,25 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
2544 ieee80211_restart_sta_timer(sdata); 2548 ieee80211_restart_sta_timer(sdata);
2545 rcu_read_unlock(); 2549 rcu_read_unlock();
2546} 2550}
2551
2552/* driver notification call */
2553void ieee80211_notify_mac(struct ieee80211_hw *hw,
2554 enum ieee80211_notification_types notif_type)
2555{
2556 struct ieee80211_local *local = hw_to_local(hw);
2557 struct ieee80211_sub_if_data *sdata;
2558
2559 switch (notif_type) {
2560 case IEEE80211_NOTIFY_RE_ASSOC:
2561 rcu_read_lock();
2562 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
2563 if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
2564 continue;
2565
2566 ieee80211_sta_req_auth(sdata, &sdata->u.sta);
2567 }
2568 rcu_read_unlock();
2569 break;
2570 }
2571}
2572EXPORT_SYMBOL(ieee80211_notify_mac);