aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ibss.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/ibss.c')
-rw-r--r--net/mac80211/ibss.c347
1 files changed, 165 insertions, 182 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 3201e1f96365..4f7a54518be4 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -59,74 +59,59 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
59 sdata->u.ibss.bssid, 0); 59 sdata->u.ibss.bssid, 0);
60} 60}
61 61
62static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, 62static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
63 const u8 *bssid, const int beacon_int, 63 const u8 *bssid, const int beacon_int,
64 const int freq, 64 struct ieee80211_channel *chan,
65 const size_t supp_rates_len, 65 const size_t supp_rates_len,
66 const u8 *supp_rates, 66 const u8 *supp_rates,
67 const u16 capability, u64 tsf) 67 const u16 capability, u64 tsf)
68{ 68{
69 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 69 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
70 struct ieee80211_local *local = sdata->local; 70 struct ieee80211_local *local = sdata->local;
71 int res = 0, rates, i, j; 71 int rates, i, j;
72 struct sk_buff *skb; 72 struct sk_buff *skb;
73 struct ieee80211_mgmt *mgmt; 73 struct ieee80211_mgmt *mgmt;
74 u8 *pos; 74 u8 *pos;
75 struct ieee80211_supported_band *sband; 75 struct ieee80211_supported_band *sband;
76 union iwreq_data wrqu;
77 76
78 if (local->ops->reset_tsf) { 77 if (local->ops->reset_tsf) {
79 /* Reset own TSF to allow time synchronization work. */ 78 /* Reset own TSF to allow time synchronization work. */
80 local->ops->reset_tsf(local_to_hw(local)); 79 local->ops->reset_tsf(local_to_hw(local));
81 } 80 }
82 81
83 if ((ifibss->flags & IEEE80211_IBSS_PREV_BSSID_SET) && 82 skb = ifibss->skb;
84 memcmp(ifibss->bssid, bssid, ETH_ALEN) == 0) 83 rcu_assign_pointer(ifibss->presp, NULL);
85 return res; 84 synchronize_rcu();
85 skb->data = skb->head;
86 skb->len = 0;
87 skb_reset_tail_pointer(skb);
88 skb_reserve(skb, sdata->local->hw.extra_tx_headroom);
86 89
87 skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); 90 if (memcmp(ifibss->bssid, bssid, ETH_ALEN))
88 if (!skb) { 91 sta_info_flush(sdata->local, sdata);
89 printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
90 "response\n", sdata->dev->name);
91 return -ENOMEM;
92 }
93
94 if (!(ifibss->flags & IEEE80211_IBSS_PREV_BSSID_SET)) {
95 /* Remove possible STA entries from other IBSS networks. */
96 sta_info_flush_delayed(sdata);
97 }
98 92
99 memcpy(ifibss->bssid, bssid, ETH_ALEN); 93 memcpy(ifibss->bssid, bssid, ETH_ALEN);
100 res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID);
101 if (res)
102 return res;
103 94
104 local->hw.conf.beacon_int = beacon_int >= 10 ? beacon_int : 10; 95 local->hw.conf.beacon_int = beacon_int >= 10 ? beacon_int : 10;
105 96
106 sdata->drop_unencrypted = capability & 97 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
107 WLAN_CAPABILITY_PRIVACY ? 1 : 0;
108
109 res = ieee80211_set_freq(sdata, freq);
110 98
111 if (res) 99 ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID);
112 return res;
113 100
114 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 101 local->oper_channel = chan;
102 local->oper_channel_type = NL80211_CHAN_NO_HT;
103 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
104 sband = local->hw.wiphy->bands[chan->band];
115 105
116 /* Build IBSS probe response */ 106 /* Build IBSS probe response */
117 107 mgmt = (void *) skb_put(skb, 24 + sizeof(mgmt->u.beacon));
118 skb_reserve(skb, local->hw.extra_tx_headroom);
119
120 mgmt = (struct ieee80211_mgmt *)
121 skb_put(skb, 24 + sizeof(mgmt->u.beacon));
122 memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); 108 memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
123 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 109 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
124 IEEE80211_STYPE_PROBE_RESP); 110 IEEE80211_STYPE_PROBE_RESP);
125 memset(mgmt->da, 0xff, ETH_ALEN); 111 memset(mgmt->da, 0xff, ETH_ALEN);
126 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 112 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
127 memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); 113 memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN);
128 mgmt->u.beacon.beacon_int = 114 mgmt->u.beacon.beacon_int = cpu_to_le16(local->hw.conf.beacon_int);
129 cpu_to_le16(local->hw.conf.beacon_int);
130 mgmt->u.beacon.timestamp = cpu_to_le64(tsf); 115 mgmt->u.beacon.timestamp = cpu_to_le64(tsf);
131 mgmt->u.beacon.capab_info = cpu_to_le16(capability); 116 mgmt->u.beacon.capab_info = cpu_to_le16(capability);
132 117
@@ -147,7 +132,7 @@ static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
147 pos = skb_put(skb, 2 + 1); 132 pos = skb_put(skb, 2 + 1);
148 *pos++ = WLAN_EID_DS_PARAMS; 133 *pos++ = WLAN_EID_DS_PARAMS;
149 *pos++ = 1; 134 *pos++ = 1;
150 *pos++ = ieee80211_frequency_to_channel(freq); 135 *pos++ = ieee80211_frequency_to_channel(chan->center_freq);
151 } 136 }
152 137
153 pos = skb_put(skb, 2 + 2); 138 pos = skb_put(skb, 2 + 2);
@@ -165,12 +150,15 @@ static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
165 memcpy(pos, &supp_rates[8], rates); 150 memcpy(pos, &supp_rates[8], rates);
166 } 151 }
167 152
168 ifibss->probe_resp = skb; 153 if (ifibss->ie_len)
154 memcpy(skb_put(skb, ifibss->ie_len),
155 ifibss->ie, ifibss->ie_len);
156
157 rcu_assign_pointer(ifibss->presp, skb);
169 158
170 ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | 159 ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON |
171 IEEE80211_IFCC_BEACON_ENABLED); 160 IEEE80211_IFCC_BEACON_ENABLED);
172 161
173
174 rates = 0; 162 rates = 0;
175 for (i = 0; i < supp_rates_len; i++) { 163 for (i = 0; i < supp_rates_len; i++) {
176 int bitrate = (supp_rates[i] & 0x7f) * 5; 164 int bitrate = (supp_rates[i] & 0x7f) * 5;
@@ -181,27 +169,24 @@ static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
181 169
182 ieee80211_sta_def_wmm_params(sdata, supp_rates_len, supp_rates); 170 ieee80211_sta_def_wmm_params(sdata, supp_rates_len, supp_rates);
183 171
184 ifibss->flags |= IEEE80211_IBSS_PREV_BSSID_SET;
185 ifibss->state = IEEE80211_IBSS_MLME_JOINED; 172 ifibss->state = IEEE80211_IBSS_MLME_JOINED;
186 mod_timer(&ifibss->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); 173 mod_timer(&ifibss->timer,
174 round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
187 175
188 memset(&wrqu, 0, sizeof(wrqu)); 176 cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel,
189 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); 177 mgmt, skb->len, 0, GFP_KERNEL);
190 wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); 178 cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
191
192 return res;
193} 179}
194 180
195static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, 181static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
196 struct ieee80211_bss *bss) 182 struct ieee80211_bss *bss)
197{ 183{
198 return __ieee80211_sta_join_ibss(sdata, 184 __ieee80211_sta_join_ibss(sdata, bss->cbss.bssid,
199 bss->cbss.bssid, 185 bss->cbss.beacon_interval,
200 bss->cbss.beacon_interval, 186 bss->cbss.channel,
201 bss->cbss.channel->center_freq, 187 bss->supp_rates_len, bss->supp_rates,
202 bss->supp_rates_len, bss->supp_rates, 188 bss->cbss.capability,
203 bss->cbss.capability, 189 bss->cbss.tsf);
204 bss->cbss.tsf);
205} 190}
206 191
207static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, 192static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
@@ -277,7 +262,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
277 goto put_bss; 262 goto put_bss;
278 263
279 /* we use a fixed BSSID */ 264 /* we use a fixed BSSID */
280 if (sdata->u.ibss.flags & IEEE80211_IBSS_BSSID_SET) 265 if (sdata->u.ibss.bssid)
281 goto put_bss; 266 goto put_bss;
282 267
283 /* not an IBSS */ 268 /* not an IBSS */
@@ -369,13 +354,14 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
369 struct sta_info *sta; 354 struct sta_info *sta;
370 int band = local->hw.conf.channel->band; 355 int band = local->hw.conf.channel->band;
371 356
372 /* TODO: Could consider removing the least recently used entry and 357 /*
373 * allow new one to be added. */ 358 * XXX: Consider removing the least recently used entry and
359 * allow new one to be added.
360 */
374 if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { 361 if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
375 if (net_ratelimit()) { 362 if (net_ratelimit())
376 printk(KERN_DEBUG "%s: No room for a new IBSS STA " 363 printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n",
377 "entry %pM\n", sdata->dev->name, addr); 364 sdata->dev->name, addr);
378 }
379 return NULL; 365 return NULL;
380 } 366 }
381 367
@@ -432,14 +418,15 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
432{ 418{
433 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 419 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
434 420
435 mod_timer(&ifibss->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); 421 mod_timer(&ifibss->timer,
422 round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
436 423
437 ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT); 424 ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT);
425
438 if (ieee80211_sta_active_ibss(sdata)) 426 if (ieee80211_sta_active_ibss(sdata))
439 return; 427 return;
440 428
441 if ((ifibss->flags & IEEE80211_IBSS_BSSID_SET) && 429 if (ifibss->fixed_channel)
442 (!(ifibss->flags & IEEE80211_IBSS_AUTO_CHANNEL_SEL)))
443 return; 430 return;
444 431
445 printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " 432 printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
@@ -455,7 +442,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
455 ieee80211_request_scan(sdata, &sdata->local->int_scan_req); 442 ieee80211_request_scan(sdata, &sdata->local->int_scan_req);
456} 443}
457 444
458static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) 445static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
459{ 446{
460 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 447 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
461 struct ieee80211_local *local = sdata->local; 448 struct ieee80211_local *local = sdata->local;
@@ -466,7 +453,7 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
466 u16 capability; 453 u16 capability;
467 int i; 454 int i;
468 455
469 if (ifibss->flags & IEEE80211_IBSS_BSSID_SET) { 456 if (ifibss->fixed_bssid) {
470 memcpy(bssid, ifibss->bssid, ETH_ALEN); 457 memcpy(bssid, ifibss->bssid, ETH_ALEN);
471 } else { 458 } else {
472 /* Generate random, not broadcast, locally administered BSSID. Mix in 459 /* Generate random, not broadcast, locally administered BSSID. Mix in
@@ -482,7 +469,7 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
482 printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", 469 printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n",
483 sdata->dev->name, bssid); 470 sdata->dev->name, bssid);
484 471
485 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 472 sband = local->hw.wiphy->bands[ifibss->channel->band];
486 473
487 if (local->hw.conf.beacon_int == 0) 474 if (local->hw.conf.beacon_int == 0)
488 local->hw.conf.beacon_int = 100; 475 local->hw.conf.beacon_int = 100;
@@ -500,24 +487,20 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
500 *pos++ = (u8) (rate / 5); 487 *pos++ = (u8) (rate / 5);
501 } 488 }
502 489
503 return __ieee80211_sta_join_ibss(sdata, 490 __ieee80211_sta_join_ibss(sdata, bssid, local->hw.conf.beacon_int,
504 bssid, local->hw.conf.beacon_int, 491 ifibss->channel, sband->n_bitrates,
505 local->hw.conf.channel->center_freq, 492 supp_rates, capability, 0);
506 sband->n_bitrates, supp_rates,
507 capability, 0);
508} 493}
509 494
510static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) 495static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
511{ 496{
512 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 497 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
513 struct ieee80211_local *local = sdata->local; 498 struct ieee80211_local *local = sdata->local;
514 struct ieee80211_bss *bss; 499 struct ieee80211_bss *bss;
500 struct ieee80211_channel *chan = NULL;
515 const u8 *bssid = NULL; 501 const u8 *bssid = NULL;
516 int active_ibss; 502 int active_ibss;
517 503
518 if (ifibss->ssid_len == 0)
519 return -EINVAL;
520
521 active_ibss = ieee80211_sta_active_ibss(sdata); 504 active_ibss = ieee80211_sta_active_ibss(sdata);
522#ifdef CONFIG_MAC80211_IBSS_DEBUG 505#ifdef CONFIG_MAC80211_IBSS_DEBUG
523 printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", 506 printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
@@ -525,11 +508,15 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
525#endif /* CONFIG_MAC80211_IBSS_DEBUG */ 508#endif /* CONFIG_MAC80211_IBSS_DEBUG */
526 509
527 if (active_ibss) 510 if (active_ibss)
528 return 0; 511 return;
529 512
530 if (ifibss->flags & IEEE80211_IBSS_BSSID_SET) 513 if (ifibss->fixed_bssid)
514 bssid = ifibss->bssid;
515 if (ifibss->fixed_channel)
516 chan = ifibss->channel;
517 if (!is_zero_ether_addr(ifibss->bssid))
531 bssid = ifibss->bssid; 518 bssid = ifibss->bssid;
532 bss = (void *)cfg80211_get_bss(local->hw.wiphy, NULL, bssid, 519 bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, bssid,
533 ifibss->ssid, ifibss->ssid_len, 520 ifibss->ssid, ifibss->ssid_len,
534 WLAN_CAPABILITY_IBSS, 521 WLAN_CAPABILITY_IBSS,
535 WLAN_CAPABILITY_IBSS); 522 WLAN_CAPABILITY_IBSS);
@@ -540,18 +527,14 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
540 "%pM\n", bss->cbss.bssid, ifibss->bssid); 527 "%pM\n", bss->cbss.bssid, ifibss->bssid);
541#endif /* CONFIG_MAC80211_IBSS_DEBUG */ 528#endif /* CONFIG_MAC80211_IBSS_DEBUG */
542 529
543 if (bss && 530 if (bss && memcmp(ifibss->bssid, bss->cbss.bssid, ETH_ALEN)) {
544 (!(ifibss->flags & IEEE80211_IBSS_PREV_BSSID_SET) ||
545 memcmp(ifibss->bssid, bss->cbss.bssid, ETH_ALEN))) {
546 int ret;
547
548 printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" 531 printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM"
549 " based on configured SSID\n", 532 " based on configured SSID\n",
550 sdata->dev->name, bss->cbss.bssid); 533 sdata->dev->name, bss->cbss.bssid);
551 534
552 ret = ieee80211_sta_join_ibss(sdata, bss); 535 ieee80211_sta_join_ibss(sdata, bss);
553 ieee80211_rx_bss_put(local, bss); 536 ieee80211_rx_bss_put(local, bss);
554 return ret; 537 return;
555 } else if (bss) 538 } else if (bss)
556 ieee80211_rx_bss_put(local, bss); 539 ieee80211_rx_bss_put(local, bss);
557 540
@@ -562,29 +545,31 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
562 /* Selected IBSS not found in current scan results - try to scan */ 545 /* Selected IBSS not found in current scan results - try to scan */
563 if (ifibss->state == IEEE80211_IBSS_MLME_JOINED && 546 if (ifibss->state == IEEE80211_IBSS_MLME_JOINED &&
564 !ieee80211_sta_active_ibss(sdata)) { 547 !ieee80211_sta_active_ibss(sdata)) {
565 mod_timer(&ifibss->timer, jiffies + 548 mod_timer(&ifibss->timer,
566 IEEE80211_IBSS_MERGE_INTERVAL); 549 round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
567 } else if (time_after(jiffies, local->last_scan_completed + 550 } else if (time_after(jiffies, ifibss->last_scan_completed +
568 IEEE80211_SCAN_INTERVAL)) { 551 IEEE80211_SCAN_INTERVAL)) {
569 printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " 552 printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
570 "join\n", sdata->dev->name); 553 "join\n", sdata->dev->name);
571 554
572 /* XXX maybe racy? */ 555 /* XXX maybe racy? */
573 if (local->scan_req) 556 if (local->scan_req)
574 return -EBUSY; 557 return;
575 558
576 memcpy(local->int_scan_req.ssids[0].ssid, 559 memcpy(local->int_scan_req.ssids[0].ssid,
577 ifibss->ssid, IEEE80211_MAX_SSID_LEN); 560 ifibss->ssid, IEEE80211_MAX_SSID_LEN);
578 local->int_scan_req.ssids[0].ssid_len = ifibss->ssid_len; 561 local->int_scan_req.ssids[0].ssid_len =
579 return ieee80211_request_scan(sdata, &local->int_scan_req); 562 ifibss->ssid_len;
563 ieee80211_request_scan(sdata, &local->int_scan_req);
580 } else if (ifibss->state != IEEE80211_IBSS_MLME_JOINED) { 564 } else if (ifibss->state != IEEE80211_IBSS_MLME_JOINED) {
581 int interval = IEEE80211_SCAN_INTERVAL; 565 int interval = IEEE80211_SCAN_INTERVAL;
582 566
583 if (time_after(jiffies, ifibss->ibss_join_req + 567 if (time_after(jiffies, ifibss->ibss_join_req +
584 IEEE80211_IBSS_JOIN_TIMEOUT)) { 568 IEEE80211_IBSS_JOIN_TIMEOUT)) {
585 if (!(local->oper_channel->flags & 569 if (!(local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS)) {
586 IEEE80211_CHAN_NO_IBSS)) 570 ieee80211_sta_create_ibss(sdata);
587 return ieee80211_sta_create_ibss(sdata); 571 return;
572 }
588 printk(KERN_DEBUG "%s: IBSS not allowed on" 573 printk(KERN_DEBUG "%s: IBSS not allowed on"
589 " %d MHz\n", sdata->dev->name, 574 " %d MHz\n", sdata->dev->name,
590 local->hw.conf.channel->center_freq); 575 local->hw.conf.channel->center_freq);
@@ -595,11 +580,9 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
595 } 580 }
596 581
597 ifibss->state = IEEE80211_IBSS_MLME_SEARCH; 582 ifibss->state = IEEE80211_IBSS_MLME_SEARCH;
598 mod_timer(&ifibss->timer, jiffies + interval); 583 mod_timer(&ifibss->timer,
599 return 0; 584 round_jiffies(jiffies + interval));
600 } 585 }
601
602 return 0;
603} 586}
604 587
605static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, 588static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
@@ -614,7 +597,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
614 u8 *pos, *end; 597 u8 *pos, *end;
615 598
616 if (ifibss->state != IEEE80211_IBSS_MLME_JOINED || 599 if (ifibss->state != IEEE80211_IBSS_MLME_JOINED ||
617 len < 24 + 2 || !ifibss->probe_resp) 600 len < 24 + 2 || !ifibss->presp)
618 return; 601 return;
619 602
620 if (local->ops->tx_last_beacon) 603 if (local->ops->tx_last_beacon)
@@ -649,13 +632,13 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
649 } 632 }
650 if (pos[1] != 0 && 633 if (pos[1] != 0 &&
651 (pos[1] != ifibss->ssid_len || 634 (pos[1] != ifibss->ssid_len ||
652 memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len) != 0)) { 635 !memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len))) {
653 /* Ignore ProbeReq for foreign SSID */ 636 /* Ignore ProbeReq for foreign SSID */
654 return; 637 return;
655 } 638 }
656 639
657 /* Reply with ProbeResp */ 640 /* Reply with ProbeResp */
658 skb = skb_copy(ifibss->probe_resp, GFP_KERNEL); 641 skb = skb_copy(ifibss->presp, GFP_KERNEL);
659 if (!skb) 642 if (!skb)
660 return; 643 return;
661 644
@@ -794,89 +777,21 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
794 setup_timer(&ifibss->timer, ieee80211_ibss_timer, 777 setup_timer(&ifibss->timer, ieee80211_ibss_timer,
795 (unsigned long) sdata); 778 (unsigned long) sdata);
796 skb_queue_head_init(&ifibss->skb_queue); 779 skb_queue_head_init(&ifibss->skb_queue);
797
798 ifibss->flags |= IEEE80211_IBSS_AUTO_BSSID_SEL |
799 IEEE80211_IBSS_AUTO_CHANNEL_SEL;
800}
801
802int ieee80211_ibss_commit(struct ieee80211_sub_if_data *sdata)
803{
804 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
805
806 ifibss->flags &= ~IEEE80211_IBSS_PREV_BSSID_SET;
807
808 if (ifibss->ssid_len)
809 ifibss->flags |= IEEE80211_IBSS_SSID_SET;
810 else
811 ifibss->flags &= ~IEEE80211_IBSS_SSID_SET;
812
813 ifibss->ibss_join_req = jiffies;
814 ifibss->state = IEEE80211_IBSS_MLME_SEARCH;
815 set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
816
817 return 0;
818}
819
820int ieee80211_ibss_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len)
821{
822 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
823
824 if (len > IEEE80211_MAX_SSID_LEN)
825 return -EINVAL;
826
827 if (ifibss->ssid_len != len || memcmp(ifibss->ssid, ssid, len) != 0) {
828 memset(ifibss->ssid, 0, sizeof(ifibss->ssid));
829 memcpy(ifibss->ssid, ssid, len);
830 ifibss->ssid_len = len;
831 }
832
833 return ieee80211_ibss_commit(sdata);
834}
835
836int ieee80211_ibss_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len)
837{
838 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
839
840 memcpy(ssid, ifibss->ssid, ifibss->ssid_len);
841 *len = ifibss->ssid_len;
842
843 return 0;
844}
845
846int ieee80211_ibss_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
847{
848 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
849
850 if (is_valid_ether_addr(bssid)) {
851 memcpy(ifibss->bssid, bssid, ETH_ALEN);
852 ifibss->flags |= IEEE80211_IBSS_BSSID_SET;
853 } else {
854 memset(ifibss->bssid, 0, ETH_ALEN);
855 ifibss->flags &= ~IEEE80211_IBSS_BSSID_SET;
856 }
857
858 if (netif_running(sdata->dev)) {
859 if (ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID)) {
860 printk(KERN_DEBUG "%s: Failed to config new BSSID to "
861 "the low-level driver\n", sdata->dev->name);
862 }
863 }
864
865 return ieee80211_ibss_commit(sdata);
866} 780}
867 781
868/* scan finished notification */ 782/* scan finished notification */
869void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) 783void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
870{ 784{
871 struct ieee80211_sub_if_data *sdata = local->scan_sdata; 785 struct ieee80211_sub_if_data *sdata;
872 struct ieee80211_if_ibss *ifibss;
873 786
874 if (sdata && sdata->vif.type == NL80211_IFTYPE_ADHOC) { 787 rcu_read_lock();
875 ifibss = &sdata->u.ibss; 788 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
876 if ((!(ifibss->flags & IEEE80211_IBSS_PREV_BSSID_SET)) || 789 if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
877 !ieee80211_sta_active_ibss(sdata)) 790 continue;
878 ieee80211_sta_find_ibss(sdata); 791 sdata->u.ibss.last_scan_completed = jiffies;
792 ieee80211_sta_find_ibss(sdata);
879 } 793 }
794 rcu_read_unlock();
880} 795}
881 796
882ieee80211_rx_result 797ieee80211_rx_result
@@ -906,3 +821,71 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
906 821
907 return RX_DROP_MONITOR; 822 return RX_DROP_MONITOR;
908} 823}
824
825int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
826 struct cfg80211_ibss_params *params)
827{
828 struct sk_buff *skb;
829
830 memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN);
831 sdata->u.ibss.ssid_len = params->ssid_len;
832
833 if (params->bssid) {
834 memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN);
835 sdata->u.ibss.fixed_bssid = true;
836 } else
837 sdata->u.ibss.fixed_bssid = false;
838
839 sdata->u.ibss.channel = params->channel;
840 sdata->u.ibss.fixed_channel = params->channel_fixed;
841
842 if (params->ie) {
843 sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len,
844 GFP_KERNEL);
845 if (sdata->u.ibss.ie)
846 sdata->u.ibss.ie_len = params->ie_len;
847 }
848
849 skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
850 36 /* bitrates */ +
851 34 /* SSID */ +
852 3 /* DS params */ +
853 4 /* IBSS params */ +
854 params->ie_len);
855 if (!skb)
856 return -ENOMEM;
857
858 sdata->u.ibss.skb = skb;
859 sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
860 sdata->u.ibss.ibss_join_req = jiffies;
861
862 set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
863 queue_work(sdata->local->hw.workqueue, &sdata->u.ibss.work);
864
865 return 0;
866}
867
868int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
869{
870 struct sk_buff *skb;
871
872 del_timer_sync(&sdata->u.ibss.timer);
873 clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
874 cancel_work_sync(&sdata->u.ibss.work);
875 clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
876
877 sta_info_flush(sdata->local, sdata);
878
879 /* remove beacon */
880 kfree(sdata->u.ibss.ie);
881 skb = sdata->u.ibss.presp;
882 rcu_assign_pointer(sdata->u.ibss.presp, NULL);
883 ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED);
884 synchronize_rcu();
885 kfree_skb(skb);
886
887 skb_queue_purge(&sdata->u.ibss.skb_queue);
888 memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
889
890 return 0;
891}