aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-09-10 18:01:52 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-15 16:48:21 -0400
commit9c6bd79011b14a8bfe58aad0acfb51e4dca05eed (patch)
tree0101b96437b5fb9421e8f291e3a99d0a2bf300a9 /net/mac80211/mlme.c
parent5bc75728fd43bb15b46f16ef465bcf9d487393cf (diff)
mac80211: reorder MLME code more
This way all the utility functions are at the top, then the state machine and externally callable functions are moved to the bottom. Also clean up ieee80211_i.h a bit and add a few comments about which functions are called from where. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
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);