diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 17 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 347 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 35 | ||||
-rw-r--r-- | net/mac80211/iface.c | 12 | ||||
-rw-r--r-- | net/mac80211/main.c | 2 | ||||
-rw-r--r-- | net/mac80211/scan.c | 2 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 71 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 3 | ||||
-rw-r--r-- | net/mac80211/tx.c | 6 | ||||
-rw-r--r-- | net/mac80211/wext.c | 63 |
10 files changed, 228 insertions, 330 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index daf75287e92a..14013dc64474 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1283,6 +1283,21 @@ static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev, | |||
1283 | return ieee80211_sta_disassociate(sdata, req->reason_code); | 1283 | return ieee80211_sta_disassociate(sdata, req->reason_code); |
1284 | } | 1284 | } |
1285 | 1285 | ||
1286 | static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, | ||
1287 | struct cfg80211_ibss_params *params) | ||
1288 | { | ||
1289 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1290 | |||
1291 | return ieee80211_ibss_join(sdata, params); | ||
1292 | } | ||
1293 | |||
1294 | static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) | ||
1295 | { | ||
1296 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1297 | |||
1298 | return ieee80211_ibss_leave(sdata); | ||
1299 | } | ||
1300 | |||
1286 | struct cfg80211_ops mac80211_config_ops = { | 1301 | struct cfg80211_ops mac80211_config_ops = { |
1287 | .add_virtual_intf = ieee80211_add_iface, | 1302 | .add_virtual_intf = ieee80211_add_iface, |
1288 | .del_virtual_intf = ieee80211_del_iface, | 1303 | .del_virtual_intf = ieee80211_del_iface, |
@@ -1319,4 +1334,6 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1319 | .assoc = ieee80211_assoc, | 1334 | .assoc = ieee80211_assoc, |
1320 | .deauth = ieee80211_deauth, | 1335 | .deauth = ieee80211_deauth, |
1321 | .disassoc = ieee80211_disassoc, | 1336 | .disassoc = ieee80211_disassoc, |
1337 | .join_ibss = ieee80211_join_ibss, | ||
1338 | .leave_ibss = ieee80211_leave_ibss, | ||
1322 | }; | 1339 | }; |
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 | ||
62 | static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 62 | static 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 | ||
195 | static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 181 | static 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 | ||
207 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | 192 | static 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 | ||
458 | static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | 445 | static 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 | ||
510 | static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | 495 | static 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 | ||
605 | static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | 588 | static 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 | |||
802 | int 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 | |||
820 | int 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 | |||
836 | int 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 | |||
846 | int 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 */ |
869 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) | 783 | void 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 | ||
882 | ieee80211_rx_result | 797 | ieee80211_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 | |||
825 | int 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 | |||
868 | int 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 | } | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 38c980612518..e770c1e8e08c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -323,14 +323,6 @@ struct ieee80211_if_managed { | |||
323 | size_t sme_auth_ie_len; | 323 | size_t sme_auth_ie_len; |
324 | }; | 324 | }; |
325 | 325 | ||
326 | enum ieee80211_ibss_flags { | ||
327 | IEEE80211_IBSS_AUTO_CHANNEL_SEL = BIT(0), | ||
328 | IEEE80211_IBSS_AUTO_BSSID_SEL = BIT(1), | ||
329 | IEEE80211_IBSS_BSSID_SET = BIT(2), | ||
330 | IEEE80211_IBSS_PREV_BSSID_SET = BIT(3), | ||
331 | IEEE80211_IBSS_SSID_SET = BIT(4), | ||
332 | }; | ||
333 | |||
334 | enum ieee80211_ibss_request { | 326 | enum ieee80211_ibss_request { |
335 | IEEE80211_IBSS_REQ_RUN = 0, | 327 | IEEE80211_IBSS_REQ_RUN = 0, |
336 | }; | 328 | }; |
@@ -341,17 +333,20 @@ struct ieee80211_if_ibss { | |||
341 | 333 | ||
342 | struct sk_buff_head skb_queue; | 334 | struct sk_buff_head skb_queue; |
343 | 335 | ||
344 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 336 | unsigned long request; |
345 | u8 ssid_len; | 337 | unsigned long last_scan_completed; |
346 | 338 | bool fixed_bssid; | |
347 | u32 flags; | 339 | bool fixed_channel; |
348 | 340 | ||
349 | u8 bssid[ETH_ALEN]; | 341 | u8 bssid[ETH_ALEN]; |
350 | 342 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | |
351 | unsigned long request; | 343 | u8 ssid_len, ie_len; |
344 | u8 *ie; | ||
345 | struct ieee80211_channel *channel; | ||
352 | 346 | ||
353 | unsigned long ibss_join_req; | 347 | unsigned long ibss_join_req; |
354 | struct sk_buff *probe_resp; /* ProbeResp template for IBSS */ | 348 | /* probe response/beacon for IBSS */ |
349 | struct sk_buff *presp, *skb; | ||
355 | 350 | ||
356 | enum { | 351 | enum { |
357 | IEEE80211_IBSS_MLME_SEARCH, | 352 | IEEE80211_IBSS_MLME_SEARCH, |
@@ -630,8 +625,6 @@ struct ieee80211_local { | |||
630 | spinlock_t sta_lock; | 625 | spinlock_t sta_lock; |
631 | unsigned long num_sta; | 626 | unsigned long num_sta; |
632 | struct list_head sta_list; | 627 | struct list_head sta_list; |
633 | struct list_head sta_flush_list; | ||
634 | struct work_struct sta_flush_work; | ||
635 | struct sta_info *sta_hash[STA_HASH_SIZE]; | 628 | struct sta_info *sta_hash[STA_HASH_SIZE]; |
636 | struct timer_list sta_cleanup; | 629 | struct timer_list sta_cleanup; |
637 | 630 | ||
@@ -681,7 +674,6 @@ struct ieee80211_local { | |||
681 | int scan_ies_len; | 674 | int scan_ies_len; |
682 | 675 | ||
683 | enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; | 676 | enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; |
684 | unsigned long last_scan_completed; | ||
685 | struct delayed_work scan_work; | 677 | struct delayed_work scan_work; |
686 | struct ieee80211_sub_if_data *scan_sdata; | 678 | struct ieee80211_sub_if_data *scan_sdata; |
687 | enum nl80211_channel_type oper_channel_type; | 679 | enum nl80211_channel_type oper_channel_type; |
@@ -946,10 +938,6 @@ int ieee80211_max_network_latency(struct notifier_block *nb, | |||
946 | unsigned long data, void *dummy); | 938 | unsigned long data, void *dummy); |
947 | 939 | ||
948 | /* IBSS code */ | 940 | /* IBSS code */ |
949 | int ieee80211_ibss_commit(struct ieee80211_sub_if_data *sdata); | ||
950 | int ieee80211_ibss_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len); | ||
951 | int ieee80211_ibss_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len); | ||
952 | int ieee80211_ibss_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid); | ||
953 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); | 941 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); |
954 | void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); | 942 | void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); |
955 | ieee80211_rx_result | 943 | ieee80211_rx_result |
@@ -957,6 +945,9 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | |||
957 | struct ieee80211_rx_status *rx_status); | 945 | struct ieee80211_rx_status *rx_status); |
958 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 946 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
959 | u8 *bssid, u8 *addr, u32 supp_rates); | 947 | u8 *bssid, u8 *addr, u32 supp_rates); |
948 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | ||
949 | struct cfg80211_ibss_params *params); | ||
950 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); | ||
960 | 951 | ||
961 | /* scan/BSS handling */ | 952 | /* scan/BSS handling */ |
962 | void ieee80211_scan_work(struct work_struct *work); | 953 | void ieee80211_scan_work(struct work_struct *work); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 5d60deb219d3..52425975bbbe 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -235,11 +235,7 @@ static int ieee80211_open(struct net_device *dev) | |||
235 | netif_addr_unlock_bh(local->mdev); | 235 | netif_addr_unlock_bh(local->mdev); |
236 | break; | 236 | break; |
237 | case NL80211_IFTYPE_STATION: | 237 | case NL80211_IFTYPE_STATION: |
238 | case NL80211_IFTYPE_ADHOC: | 238 | sdata->u.mgd.flags &= ~IEEE80211_STA_PREV_BSSID_SET; |
239 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
240 | sdata->u.mgd.flags &= ~IEEE80211_STA_PREV_BSSID_SET; | ||
241 | else | ||
242 | sdata->u.ibss.flags &= ~IEEE80211_IBSS_PREV_BSSID_SET; | ||
243 | /* fall through */ | 239 | /* fall through */ |
244 | default: | 240 | default: |
245 | conf.vif = &sdata->vif; | 241 | conf.vif = &sdata->vif; |
@@ -327,8 +323,6 @@ static int ieee80211_open(struct net_device *dev) | |||
327 | */ | 323 | */ |
328 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 324 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
329 | queue_work(local->hw.workqueue, &sdata->u.mgd.work); | 325 | queue_work(local->hw.workqueue, &sdata->u.mgd.work); |
330 | else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
331 | queue_work(local->hw.workqueue, &sdata->u.ibss.work); | ||
332 | 326 | ||
333 | netif_tx_start_all_queues(dev); | 327 | netif_tx_start_all_queues(dev); |
334 | 328 | ||
@@ -499,7 +493,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
499 | /* fall through */ | 493 | /* fall through */ |
500 | case NL80211_IFTYPE_ADHOC: | 494 | case NL80211_IFTYPE_ADHOC: |
501 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 495 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
502 | memset(sdata->u.ibss.bssid, 0, ETH_ALEN); | ||
503 | del_timer_sync(&sdata->u.ibss.timer); | 496 | del_timer_sync(&sdata->u.ibss.timer); |
504 | cancel_work_sync(&sdata->u.ibss.work); | 497 | cancel_work_sync(&sdata->u.ibss.work); |
505 | synchronize_rcu(); | 498 | synchronize_rcu(); |
@@ -653,7 +646,8 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
653 | mesh_rmc_free(sdata); | 646 | mesh_rmc_free(sdata); |
654 | break; | 647 | break; |
655 | case NL80211_IFTYPE_ADHOC: | 648 | case NL80211_IFTYPE_ADHOC: |
656 | kfree_skb(sdata->u.ibss.probe_resp); | 649 | if (WARN_ON(sdata->u.ibss.presp)) |
650 | kfree_skb(sdata->u.ibss.presp); | ||
657 | break; | 651 | break; |
658 | case NL80211_IFTYPE_STATION: | 652 | case NL80211_IFTYPE_STATION: |
659 | kfree(sdata->u.mgd.extra_ie); | 653 | kfree(sdata->u.mgd.extra_ie); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 049ce8639806..d26fc399285e 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -209,7 +209,7 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) | |||
209 | !!rcu_dereference(sdata->u.ap.beacon); | 209 | !!rcu_dereference(sdata->u.ap.beacon); |
210 | break; | 210 | break; |
211 | case NL80211_IFTYPE_ADHOC: | 211 | case NL80211_IFTYPE_ADHOC: |
212 | conf.enable_beacon = !!sdata->u.ibss.probe_resp; | 212 | conf.enable_beacon = !!sdata->u.ibss.presp; |
213 | break; | 213 | break; |
214 | case NL80211_IFTYPE_MESH_POINT: | 214 | case NL80211_IFTYPE_MESH_POINT: |
215 | conf.enable_beacon = true; | 215 | conf.enable_beacon = true; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 20df861c6c4c..f25b07feabf9 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -295,8 +295,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
295 | cfg80211_scan_done(local->scan_req, aborted); | 295 | cfg80211_scan_done(local->scan_req, aborted); |
296 | local->scan_req = NULL; | 296 | local->scan_req = NULL; |
297 | 297 | ||
298 | local->last_scan_completed = jiffies; | ||
299 | |||
300 | if (local->hw_scanning) { | 298 | if (local->hw_scanning) { |
301 | local->hw_scanning = false; | 299 | local->hw_scanning = false; |
302 | /* | 300 | /* |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index c5f14e6bbde2..654a8e963ccb 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -686,41 +686,10 @@ static void sta_info_debugfs_add_work(struct work_struct *work) | |||
686 | } | 686 | } |
687 | #endif | 687 | #endif |
688 | 688 | ||
689 | static void __ieee80211_run_pending_flush(struct ieee80211_local *local) | ||
690 | { | ||
691 | struct sta_info *sta; | ||
692 | unsigned long flags; | ||
693 | |||
694 | ASSERT_RTNL(); | ||
695 | |||
696 | spin_lock_irqsave(&local->sta_lock, flags); | ||
697 | while (!list_empty(&local->sta_flush_list)) { | ||
698 | sta = list_first_entry(&local->sta_flush_list, | ||
699 | struct sta_info, list); | ||
700 | list_del(&sta->list); | ||
701 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
702 | sta_info_destroy(sta); | ||
703 | spin_lock_irqsave(&local->sta_lock, flags); | ||
704 | } | ||
705 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
706 | } | ||
707 | |||
708 | static void ieee80211_sta_flush_work(struct work_struct *work) | ||
709 | { | ||
710 | struct ieee80211_local *local = | ||
711 | container_of(work, struct ieee80211_local, sta_flush_work); | ||
712 | |||
713 | rtnl_lock(); | ||
714 | __ieee80211_run_pending_flush(local); | ||
715 | rtnl_unlock(); | ||
716 | } | ||
717 | |||
718 | void sta_info_init(struct ieee80211_local *local) | 689 | void sta_info_init(struct ieee80211_local *local) |
719 | { | 690 | { |
720 | spin_lock_init(&local->sta_lock); | 691 | spin_lock_init(&local->sta_lock); |
721 | INIT_LIST_HEAD(&local->sta_list); | 692 | INIT_LIST_HEAD(&local->sta_list); |
722 | INIT_LIST_HEAD(&local->sta_flush_list); | ||
723 | INIT_WORK(&local->sta_flush_work, ieee80211_sta_flush_work); | ||
724 | 693 | ||
725 | setup_timer(&local->sta_cleanup, sta_info_cleanup, | 694 | setup_timer(&local->sta_cleanup, sta_info_cleanup, |
726 | (unsigned long)local); | 695 | (unsigned long)local); |
@@ -741,7 +710,6 @@ int sta_info_start(struct ieee80211_local *local) | |||
741 | void sta_info_stop(struct ieee80211_local *local) | 710 | void sta_info_stop(struct ieee80211_local *local) |
742 | { | 711 | { |
743 | del_timer(&local->sta_cleanup); | 712 | del_timer(&local->sta_cleanup); |
744 | cancel_work_sync(&local->sta_flush_work); | ||
745 | #ifdef CONFIG_MAC80211_DEBUGFS | 713 | #ifdef CONFIG_MAC80211_DEBUGFS |
746 | /* | 714 | /* |
747 | * Make sure the debugfs adding work isn't pending after this | 715 | * Make sure the debugfs adding work isn't pending after this |
@@ -752,10 +720,7 @@ void sta_info_stop(struct ieee80211_local *local) | |||
752 | cancel_work_sync(&local->sta_debugfs_add); | 720 | cancel_work_sync(&local->sta_debugfs_add); |
753 | #endif | 721 | #endif |
754 | 722 | ||
755 | rtnl_lock(); | ||
756 | sta_info_flush(local, NULL); | 723 | sta_info_flush(local, NULL); |
757 | __ieee80211_run_pending_flush(local); | ||
758 | rtnl_unlock(); | ||
759 | } | 724 | } |
760 | 725 | ||
761 | /** | 726 | /** |
@@ -767,7 +732,7 @@ void sta_info_stop(struct ieee80211_local *local) | |||
767 | * @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs | 732 | * @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs |
768 | */ | 733 | */ |
769 | int sta_info_flush(struct ieee80211_local *local, | 734 | int sta_info_flush(struct ieee80211_local *local, |
770 | struct ieee80211_sub_if_data *sdata) | 735 | struct ieee80211_sub_if_data *sdata) |
771 | { | 736 | { |
772 | struct sta_info *sta, *tmp; | 737 | struct sta_info *sta, *tmp; |
773 | LIST_HEAD(tmp_list); | 738 | LIST_HEAD(tmp_list); |
@@ -775,7 +740,6 @@ int sta_info_flush(struct ieee80211_local *local, | |||
775 | unsigned long flags; | 740 | unsigned long flags; |
776 | 741 | ||
777 | might_sleep(); | 742 | might_sleep(); |
778 | ASSERT_RTNL(); | ||
779 | 743 | ||
780 | spin_lock_irqsave(&local->sta_lock, flags); | 744 | spin_lock_irqsave(&local->sta_lock, flags); |
781 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { | 745 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { |
@@ -795,39 +759,6 @@ int sta_info_flush(struct ieee80211_local *local, | |||
795 | return ret; | 759 | return ret; |
796 | } | 760 | } |
797 | 761 | ||
798 | /** | ||
799 | * sta_info_flush_delayed - flush matching STA entries from the STA table | ||
800 | * | ||
801 | * This function unlinks all stations for a given interface and queues | ||
802 | * them for freeing. Note that the workqueue function scheduled here has | ||
803 | * to run before any new keys can be added to the system to avoid set_key() | ||
804 | * callback ordering issues. | ||
805 | * | ||
806 | * @sdata: the interface | ||
807 | */ | ||
808 | void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata) | ||
809 | { | ||
810 | struct ieee80211_local *local = sdata->local; | ||
811 | struct sta_info *sta, *tmp; | ||
812 | unsigned long flags; | ||
813 | bool work = false; | ||
814 | |||
815 | spin_lock_irqsave(&local->sta_lock, flags); | ||
816 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { | ||
817 | if (sdata == sta->sdata) { | ||
818 | __sta_info_unlink(&sta); | ||
819 | if (sta) { | ||
820 | list_add_tail(&sta->list, | ||
821 | &local->sta_flush_list); | ||
822 | work = true; | ||
823 | } | ||
824 | } | ||
825 | } | ||
826 | if (work) | ||
827 | schedule_work(&local->sta_flush_work); | ||
828 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
829 | } | ||
830 | |||
831 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | 762 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, |
832 | unsigned long exp_time) | 763 | unsigned long exp_time) |
833 | { | 764 | { |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 5534d489f506..31a8990ce401 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -442,8 +442,7 @@ void sta_info_init(struct ieee80211_local *local); | |||
442 | int sta_info_start(struct ieee80211_local *local); | 442 | int sta_info_start(struct ieee80211_local *local); |
443 | void sta_info_stop(struct ieee80211_local *local); | 443 | void sta_info_stop(struct ieee80211_local *local); |
444 | int sta_info_flush(struct ieee80211_local *local, | 444 | int sta_info_flush(struct ieee80211_local *local, |
445 | struct ieee80211_sub_if_data *sdata); | 445 | struct ieee80211_sub_if_data *sdata); |
446 | void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata); | ||
447 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | 446 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, |
448 | unsigned long exp_time); | 447 | unsigned long exp_time); |
449 | 448 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index f336cc731df6..c53d77db3e4f 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -2102,18 +2102,18 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
2102 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 2102 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
2103 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 2103 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
2104 | struct ieee80211_hdr *hdr; | 2104 | struct ieee80211_hdr *hdr; |
2105 | struct sk_buff *presp = rcu_dereference(ifibss->presp); | ||
2105 | 2106 | ||
2106 | if (!ifibss->probe_resp) | 2107 | if (!presp) |
2107 | goto out; | 2108 | goto out; |
2108 | 2109 | ||
2109 | skb = skb_copy(ifibss->probe_resp, GFP_ATOMIC); | 2110 | skb = skb_copy(presp, GFP_ATOMIC); |
2110 | if (!skb) | 2111 | if (!skb) |
2111 | goto out; | 2112 | goto out; |
2112 | 2113 | ||
2113 | hdr = (struct ieee80211_hdr *) skb->data; | 2114 | hdr = (struct ieee80211_hdr *) skb->data; |
2114 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 2115 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
2115 | IEEE80211_STYPE_BEACON); | 2116 | IEEE80211_STYPE_BEACON); |
2116 | |||
2117 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 2117 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
2118 | struct ieee80211_mgmt *mgmt; | 2118 | struct ieee80211_mgmt *mgmt; |
2119 | u8 *pos; | 2119 | u8 *pos; |
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 896704cf94e1..eb63fc148019 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -149,17 +149,14 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, | |||
149 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 149 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
150 | 150 | ||
151 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 151 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
152 | sdata->u.ibss.flags &= ~IEEE80211_IBSS_AUTO_CHANNEL_SEL; | 152 | return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); |
153 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | 153 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
154 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL; | 154 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL; |
155 | 155 | ||
156 | /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ | 156 | /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ |
157 | if (freq->e == 0) { | 157 | if (freq->e == 0) { |
158 | if (freq->m < 0) { | 158 | if (freq->m < 0) { |
159 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 159 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
160 | sdata->u.ibss.flags |= | ||
161 | IEEE80211_IBSS_AUTO_CHANNEL_SEL; | ||
162 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
163 | sdata->u.mgd.flags |= | 160 | sdata->u.mgd.flags |= |
164 | IEEE80211_STA_AUTO_CHANNEL_SEL; | 161 | IEEE80211_STA_AUTO_CHANNEL_SEL; |
165 | return 0; | 162 | return 0; |
@@ -183,6 +180,10 @@ static int ieee80211_ioctl_giwfreq(struct net_device *dev, | |||
183 | struct iw_freq *freq, char *extra) | 180 | struct iw_freq *freq, char *extra) |
184 | { | 181 | { |
185 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 182 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
183 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
184 | |||
185 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
186 | return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); | ||
186 | 187 | ||
187 | freq->m = local->hw.conf.channel->center_freq; | 188 | freq->m = local->hw.conf.channel->center_freq; |
188 | freq->e = 6; | 189 | freq->e = 6; |
@@ -195,15 +196,17 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, | |||
195 | struct iw_request_info *info, | 196 | struct iw_request_info *info, |
196 | struct iw_point *data, char *ssid) | 197 | struct iw_point *data, char *ssid) |
197 | { | 198 | { |
198 | struct ieee80211_sub_if_data *sdata; | 199 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
199 | size_t len = data->length; | 200 | size_t len = data->length; |
200 | int ret; | 201 | int ret; |
201 | 202 | ||
203 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
204 | return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); | ||
205 | |||
202 | /* iwconfig uses nul termination in SSID.. */ | 206 | /* iwconfig uses nul termination in SSID.. */ |
203 | if (len > 0 && ssid[len - 1] == '\0') | 207 | if (len > 0 && ssid[len - 1] == '\0') |
204 | len--; | 208 | len--; |
205 | 209 | ||
206 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
207 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 210 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
208 | if (data->flags) | 211 | if (data->flags) |
209 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; | 212 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; |
@@ -217,8 +220,7 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, | |||
217 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; | 220 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; |
218 | ieee80211_sta_req_auth(sdata); | 221 | ieee80211_sta_req_auth(sdata); |
219 | return 0; | 222 | return 0; |
220 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 223 | } |
221 | return ieee80211_ibss_set_ssid(sdata, ssid, len); | ||
222 | 224 | ||
223 | return -EOPNOTSUPP; | 225 | return -EOPNOTSUPP; |
224 | } | 226 | } |
@@ -229,9 +231,13 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, | |||
229 | struct iw_point *data, char *ssid) | 231 | struct iw_point *data, char *ssid) |
230 | { | 232 | { |
231 | size_t len; | 233 | size_t len; |
232 | |||
233 | struct ieee80211_sub_if_data *sdata; | 234 | struct ieee80211_sub_if_data *sdata; |
235 | |||
234 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 236 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
237 | |||
238 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
239 | return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); | ||
240 | |||
235 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 241 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
236 | int res = ieee80211_sta_get_ssid(sdata, ssid, &len); | 242 | int res = ieee80211_sta_get_ssid(sdata, ssid, &len); |
237 | if (res == 0) { | 243 | if (res == 0) { |
@@ -240,14 +246,6 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, | |||
240 | } else | 246 | } else |
241 | data->flags = 0; | 247 | data->flags = 0; |
242 | return res; | 248 | return res; |
243 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
244 | int res = ieee80211_ibss_get_ssid(sdata, ssid, &len); | ||
245 | if (res == 0) { | ||
246 | data->length = len; | ||
247 | data->flags = 1; | ||
248 | } else | ||
249 | data->flags = 0; | ||
250 | return res; | ||
251 | } | 249 | } |
252 | 250 | ||
253 | return -EOPNOTSUPP; | 251 | return -EOPNOTSUPP; |
@@ -258,9 +256,11 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, | |||
258 | struct iw_request_info *info, | 256 | struct iw_request_info *info, |
259 | struct sockaddr *ap_addr, char *extra) | 257 | struct sockaddr *ap_addr, char *extra) |
260 | { | 258 | { |
261 | struct ieee80211_sub_if_data *sdata; | 259 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
260 | |||
261 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
262 | return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); | ||
262 | 263 | ||
263 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
264 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 264 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
265 | int ret; | 265 | int ret; |
266 | 266 | ||
@@ -277,16 +277,6 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, | |||
277 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; | 277 | sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; |
278 | ieee80211_sta_req_auth(sdata); | 278 | ieee80211_sta_req_auth(sdata); |
279 | return 0; | 279 | return 0; |
280 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
281 | if (is_zero_ether_addr((u8 *) &ap_addr->sa_data)) | ||
282 | sdata->u.ibss.flags |= IEEE80211_IBSS_AUTO_BSSID_SEL | | ||
283 | IEEE80211_IBSS_AUTO_CHANNEL_SEL; | ||
284 | else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data)) | ||
285 | sdata->u.ibss.flags |= IEEE80211_IBSS_AUTO_BSSID_SEL; | ||
286 | else | ||
287 | sdata->u.ibss.flags &= ~IEEE80211_IBSS_AUTO_BSSID_SEL; | ||
288 | |||
289 | return ieee80211_ibss_set_bssid(sdata, (u8 *) &ap_addr->sa_data); | ||
290 | } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { | 280 | } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { |
291 | /* | 281 | /* |
292 | * If it is necessary to update the WDS peer address | 282 | * If it is necessary to update the WDS peer address |
@@ -312,9 +302,11 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, | |||
312 | struct iw_request_info *info, | 302 | struct iw_request_info *info, |
313 | struct sockaddr *ap_addr, char *extra) | 303 | struct sockaddr *ap_addr, char *extra) |
314 | { | 304 | { |
315 | struct ieee80211_sub_if_data *sdata; | 305 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
306 | |||
307 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
308 | return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); | ||
316 | 309 | ||
317 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
318 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 310 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
319 | if (sdata->u.mgd.state == IEEE80211_STA_MLME_ASSOCIATED) { | 311 | if (sdata->u.mgd.state == IEEE80211_STA_MLME_ASSOCIATED) { |
320 | ap_addr->sa_family = ARPHRD_ETHER; | 312 | ap_addr->sa_family = ARPHRD_ETHER; |
@@ -322,13 +314,6 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, | |||
322 | } else | 314 | } else |
323 | memset(&ap_addr->sa_data, 0, ETH_ALEN); | 315 | memset(&ap_addr->sa_data, 0, ETH_ALEN); |
324 | return 0; | 316 | return 0; |
325 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
326 | if (sdata->u.ibss.state == IEEE80211_IBSS_MLME_JOINED) { | ||
327 | ap_addr->sa_family = ARPHRD_ETHER; | ||
328 | memcpy(&ap_addr->sa_data, sdata->u.ibss.bssid, ETH_ALEN); | ||
329 | } else | ||
330 | memset(&ap_addr->sa_data, 0, ETH_ALEN); | ||
331 | return 0; | ||
332 | } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { | 317 | } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { |
333 | ap_addr->sa_family = ARPHRD_ETHER; | 318 | ap_addr->sa_family = ARPHRD_ETHER; |
334 | memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN); | 319 | memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN); |