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.c226
1 files changed, 148 insertions, 78 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index e08387cdc8fd..a12afe77bb26 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -34,13 +34,12 @@
34 34
35#define IEEE80211_IBSS_MAX_STA_ENTRIES 128 35#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
36 36
37 37static struct beacon_data *
38static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, 38ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata,
39 const u8 *bssid, const int beacon_int, 39 const int beacon_int, const u32 basic_rates,
40 struct ieee80211_channel *chan, 40 const u16 capability, u64 tsf,
41 const u32 basic_rates, 41 struct cfg80211_chan_def *chandef,
42 const u16 capability, u64 tsf, 42 bool *have_higher_than_11mbit)
43 bool creator)
44{ 43{
45 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 44 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
46 struct ieee80211_local *local = sdata->local; 45 struct ieee80211_local *local = sdata->local;
@@ -48,70 +47,11 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
48 struct ieee80211_mgmt *mgmt; 47 struct ieee80211_mgmt *mgmt;
49 u8 *pos; 48 u8 *pos;
50 struct ieee80211_supported_band *sband; 49 struct ieee80211_supported_band *sband;
51 struct cfg80211_bss *bss; 50 u32 rate_flags, rates = 0, rates_added = 0;
52 u32 bss_change, rate_flags, rates = 0, rates_added = 0;
53 struct cfg80211_chan_def chandef;
54 enum nl80211_bss_scan_width scan_width;
55 bool have_higher_than_11mbit = false;
56 struct beacon_data *presp; 51 struct beacon_data *presp;
57 int frame_len; 52 int frame_len;
58 int shift; 53 int shift;
59 54
60 sdata_assert_lock(sdata);
61
62 /* Reset own TSF to allow time synchronization work. */
63 drv_reset_tsf(local, sdata);
64
65 if (!ether_addr_equal(ifibss->bssid, bssid))
66 sta_info_flush(sdata);
67
68 /* if merging, indicate to driver that we leave the old IBSS */
69 if (sdata->vif.bss_conf.ibss_joined) {
70 sdata->vif.bss_conf.ibss_joined = false;
71 sdata->vif.bss_conf.ibss_creator = false;
72 sdata->vif.bss_conf.enable_beacon = false;
73 netif_carrier_off(sdata->dev);
74 ieee80211_bss_info_change_notify(sdata,
75 BSS_CHANGED_IBSS |
76 BSS_CHANGED_BEACON_ENABLED);
77 }
78
79 presp = rcu_dereference_protected(ifibss->presp,
80 lockdep_is_held(&sdata->wdev.mtx));
81 rcu_assign_pointer(ifibss->presp, NULL);
82 if (presp)
83 kfree_rcu(presp, rcu_head);
84
85 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
86
87 chandef = ifibss->chandef;
88 if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
89 if (chandef.width == NL80211_CHAN_WIDTH_5 ||
90 chandef.width == NL80211_CHAN_WIDTH_10 ||
91 chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
92 chandef.width == NL80211_CHAN_WIDTH_20) {
93 sdata_info(sdata,
94 "Failed to join IBSS, beacons forbidden\n");
95 return;
96 }
97 chandef.width = NL80211_CHAN_WIDTH_20;
98 chandef.center_freq1 = chan->center_freq;
99 }
100
101 ieee80211_vif_release_channel(sdata);
102 if (ieee80211_vif_use_channel(sdata, &chandef,
103 ifibss->fixed_channel ?
104 IEEE80211_CHANCTX_SHARED :
105 IEEE80211_CHANCTX_EXCLUSIVE)) {
106 sdata_info(sdata, "Failed to join IBSS, no channel context\n");
107 return;
108 }
109
110 memcpy(ifibss->bssid, bssid, ETH_ALEN);
111
112 sband = local->hw.wiphy->bands[chan->band];
113 shift = ieee80211_vif_get_shift(&sdata->vif);
114
115 /* Build IBSS probe response */ 55 /* Build IBSS probe response */
116 frame_len = sizeof(struct ieee80211_hdr_3addr) + 56 frame_len = sizeof(struct ieee80211_hdr_3addr) +
117 12 /* struct ieee80211_mgmt.u.beacon */ + 57 12 /* struct ieee80211_mgmt.u.beacon */ +
@@ -125,7 +65,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
125 ifibss->ie_len; 65 ifibss->ie_len;
126 presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL); 66 presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL);
127 if (!presp) 67 if (!presp)
128 return; 68 return NULL;
129 69
130 presp->head = (void *)(presp + 1); 70 presp->head = (void *)(presp + 1);
131 71
@@ -146,12 +86,19 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
146 memcpy(pos, ifibss->ssid, ifibss->ssid_len); 86 memcpy(pos, ifibss->ssid, ifibss->ssid_len);
147 pos += ifibss->ssid_len; 87 pos += ifibss->ssid_len;
148 88
149 rate_flags = ieee80211_chandef_rate_flags(&chandef); 89 sband = local->hw.wiphy->bands[chandef->chan->band];
90 rate_flags = ieee80211_chandef_rate_flags(chandef);
91 shift = ieee80211_chandef_get_shift(chandef);
92 rates_n = 0;
93 if (have_higher_than_11mbit)
94 *have_higher_than_11mbit = false;
95
150 for (i = 0; i < sband->n_bitrates; i++) { 96 for (i = 0; i < sband->n_bitrates; i++) {
151 if ((rate_flags & sband->bitrates[i].flags) != rate_flags) 97 if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
152 continue; 98 continue;
153 if (sband->bitrates[i].bitrate > 110) 99 if (sband->bitrates[i].bitrate > 110 &&
154 have_higher_than_11mbit = true; 100 have_higher_than_11mbit)
101 *have_higher_than_11mbit = true;
155 102
156 rates |= BIT(i); 103 rates |= BIT(i);
157 rates_n++; 104 rates_n++;
@@ -178,7 +125,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
178 if (sband->band == IEEE80211_BAND_2GHZ) { 125 if (sband->band == IEEE80211_BAND_2GHZ) {
179 *pos++ = WLAN_EID_DS_PARAMS; 126 *pos++ = WLAN_EID_DS_PARAMS;
180 *pos++ = 1; 127 *pos++ = 1;
181 *pos++ = ieee80211_frequency_to_channel(chan->center_freq); 128 *pos++ = ieee80211_frequency_to_channel(
129 chandef->chan->center_freq);
182 } 130 }
183 131
184 *pos++ = WLAN_EID_IBSS_PARAMS; 132 *pos++ = WLAN_EID_IBSS_PARAMS;
@@ -210,9 +158,9 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
210 } 158 }
211 159
212 /* add HT capability and information IEs */ 160 /* add HT capability and information IEs */
213 if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT && 161 if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT &&
214 chandef.width != NL80211_CHAN_WIDTH_5 && 162 chandef->width != NL80211_CHAN_WIDTH_5 &&
215 chandef.width != NL80211_CHAN_WIDTH_10 && 163 chandef->width != NL80211_CHAN_WIDTH_10 &&
216 sband->ht_cap.ht_supported) { 164 sband->ht_cap.ht_supported) {
217 struct ieee80211_sta_ht_cap ht_cap; 165 struct ieee80211_sta_ht_cap ht_cap;
218 166
@@ -226,7 +174,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
226 * keep them at 0 174 * keep them at 0
227 */ 175 */
228 pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, 176 pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap,
229 &chandef, 0); 177 chandef, 0);
230 } 178 }
231 179
232 if (local->hw.queues >= IEEE80211_NUM_ACS) { 180 if (local->hw.queues >= IEEE80211_NUM_ACS) {
@@ -243,9 +191,97 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
243 191
244 presp->head_len = pos - presp->head; 192 presp->head_len = pos - presp->head;
245 if (WARN_ON(presp->head_len > frame_len)) 193 if (WARN_ON(presp->head_len > frame_len))
194 goto error;
195
196 return presp;
197error:
198 kfree(presp);
199 return NULL;
200}
201
202static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
203 const u8 *bssid, const int beacon_int,
204 struct cfg80211_chan_def *req_chandef,
205 const u32 basic_rates,
206 const u16 capability, u64 tsf,
207 bool creator)
208{
209 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
210 struct ieee80211_local *local = sdata->local;
211 struct ieee80211_supported_band *sband;
212 struct ieee80211_mgmt *mgmt;
213 struct cfg80211_bss *bss;
214 u32 bss_change;
215 struct cfg80211_chan_def chandef;
216 struct ieee80211_channel *chan;
217 struct beacon_data *presp;
218 enum nl80211_bss_scan_width scan_width;
219 bool have_higher_than_11mbit;
220
221 sdata_assert_lock(sdata);
222
223 /* Reset own TSF to allow time synchronization work. */
224 drv_reset_tsf(local, sdata);
225
226 if (!ether_addr_equal(ifibss->bssid, bssid))
227 sta_info_flush(sdata);
228
229 /* if merging, indicate to driver that we leave the old IBSS */
230 if (sdata->vif.bss_conf.ibss_joined) {
231 sdata->vif.bss_conf.ibss_joined = false;
232 sdata->vif.bss_conf.ibss_creator = false;
233 sdata->vif.bss_conf.enable_beacon = false;
234 netif_carrier_off(sdata->dev);
235 ieee80211_bss_info_change_notify(sdata,
236 BSS_CHANGED_IBSS |
237 BSS_CHANGED_BEACON_ENABLED);
238 }
239
240 presp = rcu_dereference_protected(ifibss->presp,
241 lockdep_is_held(&sdata->wdev.mtx));
242 rcu_assign_pointer(ifibss->presp, NULL);
243 if (presp)
244 kfree_rcu(presp, rcu_head);
245
246 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
247
248 /* make a copy of the chandef, it could be modified below. */
249 chandef = *req_chandef;
250 chan = chandef.chan;
251 if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
252 if (chandef.width == NL80211_CHAN_WIDTH_5 ||
253 chandef.width == NL80211_CHAN_WIDTH_10 ||
254 chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
255 chandef.width == NL80211_CHAN_WIDTH_20) {
256 sdata_info(sdata,
257 "Failed to join IBSS, beacons forbidden\n");
258 return;
259 }
260 chandef.width = NL80211_CHAN_WIDTH_20;
261 chandef.center_freq1 = chan->center_freq;
262 }
263
264 ieee80211_vif_release_channel(sdata);
265 if (ieee80211_vif_use_channel(sdata, &chandef,
266 ifibss->fixed_channel ?
267 IEEE80211_CHANCTX_SHARED :
268 IEEE80211_CHANCTX_EXCLUSIVE)) {
269 sdata_info(sdata, "Failed to join IBSS, no channel context\n");
270 return;
271 }
272
273 memcpy(ifibss->bssid, bssid, ETH_ALEN);
274
275 sband = local->hw.wiphy->bands[chan->band];
276
277 presp = ieee80211_ibss_build_presp(sdata, beacon_int, basic_rates,
278 capability, tsf, &chandef,
279 &have_higher_than_11mbit);
280 if (!presp)
246 return; 281 return;
247 282
248 rcu_assign_pointer(ifibss->presp, presp); 283 rcu_assign_pointer(ifibss->presp, presp);
284 mgmt = (void *)presp->head;
249 285
250 sdata->vif.bss_conf.enable_beacon = true; 286 sdata->vif.bss_conf.enable_beacon = true;
251 sdata->vif.bss_conf.beacon_int = beacon_int; 287 sdata->vif.bss_conf.beacon_int = beacon_int;
@@ -306,10 +342,12 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
306 struct cfg80211_bss *cbss = 342 struct cfg80211_bss *cbss =
307 container_of((void *)bss, struct cfg80211_bss, priv); 343 container_of((void *)bss, struct cfg80211_bss, priv);
308 struct ieee80211_supported_band *sband; 344 struct ieee80211_supported_band *sband;
345 struct cfg80211_chan_def chandef;
309 u32 basic_rates; 346 u32 basic_rates;
310 int i, j; 347 int i, j;
311 u16 beacon_int = cbss->beacon_interval; 348 u16 beacon_int = cbss->beacon_interval;
312 const struct cfg80211_bss_ies *ies; 349 const struct cfg80211_bss_ies *ies;
350 enum nl80211_channel_type chan_type;
313 u64 tsf; 351 u64 tsf;
314 u32 rate_flags; 352 u32 rate_flags;
315 int shift; 353 int shift;
@@ -319,6 +357,26 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
319 if (beacon_int < 10) 357 if (beacon_int < 10)
320 beacon_int = 10; 358 beacon_int = 10;
321 359
360 switch (sdata->u.ibss.chandef.width) {
361 case NL80211_CHAN_WIDTH_20_NOHT:
362 case NL80211_CHAN_WIDTH_20:
363 case NL80211_CHAN_WIDTH_40:
364 chan_type = cfg80211_get_chandef_type(&sdata->u.ibss.chandef);
365 cfg80211_chandef_create(&chandef, cbss->channel, chan_type);
366 break;
367 case NL80211_CHAN_WIDTH_5:
368 case NL80211_CHAN_WIDTH_10:
369 cfg80211_chandef_create(&chandef, cbss->channel,
370 NL80211_CHAN_WIDTH_20_NOHT);
371 chandef.width = sdata->u.ibss.chandef.width;
372 break;
373 default:
374 /* fall back to 20 MHz for unsupported modes */
375 cfg80211_chandef_create(&chandef, cbss->channel,
376 NL80211_CHAN_WIDTH_20_NOHT);
377 break;
378 }
379
322 sband = sdata->local->hw.wiphy->bands[cbss->channel->band]; 380 sband = sdata->local->hw.wiphy->bands[cbss->channel->band];
323 rate_flags = ieee80211_chandef_rate_flags(&sdata->u.ibss.chandef); 381 rate_flags = ieee80211_chandef_rate_flags(&sdata->u.ibss.chandef);
324 shift = ieee80211_vif_get_shift(&sdata->vif); 382 shift = ieee80211_vif_get_shift(&sdata->vif);
@@ -352,7 +410,7 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
352 410
353 __ieee80211_sta_join_ibss(sdata, cbss->bssid, 411 __ieee80211_sta_join_ibss(sdata, cbss->bssid,
354 beacon_int, 412 beacon_int,
355 cbss->channel, 413 &chandef,
356 basic_rates, 414 basic_rates,
357 cbss->capability, 415 cbss->capability,
358 tsf, false); 416 tsf, false);
@@ -834,7 +892,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
834 sdata->drop_unencrypted = 0; 892 sdata->drop_unencrypted = 0;
835 893
836 __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, 894 __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
837 ifibss->chandef.chan, ifibss->basic_rates, 895 &ifibss->chandef, ifibss->basic_rates,
838 capability, 0, true); 896 capability, 0, true);
839} 897}
840 898
@@ -891,6 +949,17 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
891 return; 949 return;
892 } 950 }
893 951
952 /* if a fixed bssid and a fixed freq have been provided create the IBSS
953 * directly and do not waste time scanning
954 */
955 if (ifibss->fixed_bssid && ifibss->fixed_channel) {
956 sdata_info(sdata, "Created IBSS using preconfigured BSSID %pM\n",
957 bssid);
958 ieee80211_sta_create_ibss(sdata);
959 return;
960 }
961
962
894 ibss_dbg(sdata, "sta_find_ibss: did not try to join ibss\n"); 963 ibss_dbg(sdata, "sta_find_ibss: did not try to join ibss\n");
895 964
896 /* Selected IBSS not found in current scan results - try to scan */ 965 /* Selected IBSS not found in current scan results - try to scan */
@@ -1260,6 +1329,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
1260 clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); 1329 clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
1261 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | 1330 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
1262 BSS_CHANGED_IBSS); 1331 BSS_CHANGED_IBSS);
1332 ieee80211_vif_release_channel(sdata);
1263 synchronize_rcu(); 1333 synchronize_rcu();
1264 kfree(presp); 1334 kfree(presp);
1265 1335