blob: 83197c3ae5f1a9bb344251c58d6faf471f0ddf18 [file] [log] [blame]
Johannes Berg46900292009-02-15 12:44:28 +01001/*
2 * IBSS mode implementation
3 * Copyright 2003-2008, Jouni Malinen <j@w1.fi>
4 * Copyright 2004, Instant802 Networks, Inc.
5 * Copyright 2005, Devicescape Software, Inc.
6 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
7 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
8 * Copyright 2009, Johannes Berg <johannes@sipsolutions.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/delay.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090016#include <linux/slab.h>
Johannes Berg46900292009-02-15 12:44:28 +010017#include <linux/if_ether.h>
18#include <linux/skbuff.h>
19#include <linux/if_arp.h>
20#include <linux/etherdevice.h>
21#include <linux/rtnetlink.h>
22#include <net/mac80211.h>
Johannes Berg46900292009-02-15 12:44:28 +010023
24#include "ieee80211_i.h"
Johannes Berg24487982009-04-23 18:52:52 +020025#include "driver-ops.h"
Johannes Berg46900292009-02-15 12:44:28 +010026#include "rate.h"
27
28#define IEEE80211_SCAN_INTERVAL (2 * HZ)
Johannes Berg46900292009-02-15 12:44:28 +010029#define IEEE80211_IBSS_JOIN_TIMEOUT (7 * HZ)
30
31#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
32#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)
33
34#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
35
36
Johannes Bergaf8cdcd2009-04-19 21:25:43 +020037static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
38 const u8 *bssid, const int beacon_int,
39 struct ieee80211_channel *chan,
Johannes Bergb59066a2009-05-12 21:18:38 +020040 const u32 basic_rates,
Sujith Manoharanc13a7652012-10-12 17:35:45 +053041 const u16 capability, u64 tsf,
42 bool creator)
Johannes Berg46900292009-02-15 12:44:28 +010043{
44 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
45 struct ieee80211_local *local = sdata->local;
Simon Wunderlich2103dec2013-07-08 16:55:53 +020046 int rates_n = 0, i, ri;
Johannes Berg46900292009-02-15 12:44:28 +010047 struct ieee80211_mgmt *mgmt;
48 u8 *pos;
49 struct ieee80211_supported_band *sband;
Johannes Bergf446d102009-10-28 15:12:32 +010050 struct cfg80211_bss *bss;
Simon Wunderlich2103dec2013-07-08 16:55:53 +020051 u32 bss_change, rate_flags, rates = 0, rates_added = 0;
Johannes Berg683b6d32012-11-08 21:25:48 +010052 struct cfg80211_chan_def chandef;
Simon Wunderlich7ca15a02013-07-08 16:55:56 +020053 enum nl80211_bss_scan_width scan_width;
Simon Wunderlich2ec9c1f2013-07-11 18:07:46 +020054 bool have_higher_than_11mbit = false;
Johannes Bergc3ffeab2013-03-07 20:54:29 +010055 struct beacon_data *presp;
56 int frame_len;
Simon Wunderlich2103dec2013-07-08 16:55:53 +020057 int shift;
Johannes Berg24487982009-04-23 18:52:52 +020058
Johannes Berg8d61ffa2013-05-10 12:32:47 +020059 sdata_assert_lock(sdata);
Johannes Berg7a17a332010-07-21 11:30:27 +020060
Johannes Berg24487982009-04-23 18:52:52 +020061 /* Reset own TSF to allow time synchronization work. */
Eliad Peller37a41b42011-09-21 14:06:11 +030062 drv_reset_tsf(local, sdata);
Johannes Berg46900292009-02-15 12:44:28 +010063
Joe Perchesb203ca32012-05-08 18:56:52 +000064 if (!ether_addr_equal(ifibss->bssid, bssid))
Johannes Bergb998e8b2012-12-13 23:07:46 +010065 sta_info_flush(sdata);
Johannes Berg46900292009-02-15 12:44:28 +010066
Johannes Berg49b5c7f2010-04-29 21:34:01 +020067 /* if merging, indicate to driver that we leave the old IBSS */
68 if (sdata->vif.bss_conf.ibss_joined) {
69 sdata->vif.bss_conf.ibss_joined = false;
Sujith Manoharanc13a7652012-10-12 17:35:45 +053070 sdata->vif.bss_conf.ibss_creator = false;
Johannes Berg1852d402013-03-07 20:22:28 +010071 sdata->vif.bss_conf.enable_beacon = false;
Eliad Peller86a2ea42011-11-08 15:36:59 +020072 netif_carrier_off(sdata->dev);
Johannes Berg1852d402013-03-07 20:22:28 +010073 ieee80211_bss_info_change_notify(sdata,
74 BSS_CHANGED_IBSS |
75 BSS_CHANGED_BEACON_ENABLED);
Johannes Berg49b5c7f2010-04-29 21:34:01 +020076 }
77
Johannes Bergc3ffeab2013-03-07 20:54:29 +010078 presp = rcu_dereference_protected(ifibss->presp,
Johannes Berg8d61ffa2013-05-10 12:32:47 +020079 lockdep_is_held(&sdata->wdev.mtx));
Johannes Bergc3ffeab2013-03-07 20:54:29 +010080 rcu_assign_pointer(ifibss->presp, NULL);
81 if (presp)
82 kfree_rcu(presp, rcu_head);
Johannes Berg1852d402013-03-07 20:22:28 +010083
Johannes Bergaf8cdcd2009-04-19 21:25:43 +020084 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
Johannes Berg46900292009-02-15 12:44:28 +010085
Simon Wunderlich3aede782013-05-16 13:00:36 +020086 chandef = ifibss->chandef;
Johannes Berg4bf88532012-11-09 11:39:59 +010087 if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
Simon Wunderlich4b42aab2013-07-08 16:55:57 +020088 if (chandef.width == NL80211_CHAN_WIDTH_5 ||
89 chandef.width == NL80211_CHAN_WIDTH_10 ||
90 chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
91 chandef.width == NL80211_CHAN_WIDTH_20) {
92 sdata_info(sdata,
93 "Failed to join IBSS, beacons forbidden\n");
94 return;
95 }
Johannes Berg4bf88532012-11-09 11:39:59 +010096 chandef.width = NL80211_CHAN_WIDTH_20;
97 chandef.center_freq1 = chan->center_freq;
98 }
Johannes Berg55de9082012-07-26 17:24:39 +020099
100 ieee80211_vif_release_channel(sdata);
Johannes Berg4bf88532012-11-09 11:39:59 +0100101 if (ieee80211_vif_use_channel(sdata, &chandef,
Johannes Berg55de9082012-07-26 17:24:39 +0200102 ifibss->fixed_channel ?
103 IEEE80211_CHANCTX_SHARED :
104 IEEE80211_CHANCTX_EXCLUSIVE)) {
105 sdata_info(sdata, "Failed to join IBSS, no channel context\n");
106 return;
Alexander Simon13c40c52011-11-30 16:56:34 +0100107 }
Johannes Berg55de9082012-07-26 17:24:39 +0200108
109 memcpy(ifibss->bssid, bssid, ETH_ALEN);
Johannes Berg57c4d7b2009-04-23 16:10:04 +0200110
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200111 sband = local->hw.wiphy->bands[chan->band];
Simon Wunderlich2103dec2013-07-08 16:55:53 +0200112 shift = ieee80211_vif_get_shift(&sdata->vif);
Johannes Berg46900292009-02-15 12:44:28 +0100113
114 /* Build IBSS probe response */
Johannes Bergc3ffeab2013-03-07 20:54:29 +0100115 frame_len = sizeof(struct ieee80211_hdr_3addr) +
116 12 /* struct ieee80211_mgmt.u.beacon */ +
117 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ +
118 2 + 8 /* max Supported Rates */ +
119 3 /* max DS params */ +
120 4 /* IBSS params */ +
121 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
122 2 + sizeof(struct ieee80211_ht_cap) +
123 2 + sizeof(struct ieee80211_ht_operation) +
124 ifibss->ie_len;
125 presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL);
126 if (!presp)
127 return;
128
129 presp->head = (void *)(presp + 1);
130
131 mgmt = (void *) presp->head;
Johannes Berg46900292009-02-15 12:44:28 +0100132 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
133 IEEE80211_STYPE_PROBE_RESP);
Johannes Berge83e6542012-07-13 16:23:07 +0200134 eth_broadcast_addr(mgmt->da);
Johannes Berg47846c92009-11-25 17:46:19 +0100135 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
Johannes Berg46900292009-02-15 12:44:28 +0100136 memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN);
Johannes Berg57c4d7b2009-04-23 16:10:04 +0200137 mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_int);
Sujith707c1b42009-03-03 10:15:10 +0530138 mgmt->u.beacon.timestamp = cpu_to_le64(tsf);
Johannes Berg46900292009-02-15 12:44:28 +0100139 mgmt->u.beacon.capab_info = cpu_to_le16(capability);
140
Johannes Bergc3ffeab2013-03-07 20:54:29 +0100141 pos = (u8 *)mgmt + offsetof(struct ieee80211_mgmt, u.beacon.variable);
142
Johannes Berg46900292009-02-15 12:44:28 +0100143 *pos++ = WLAN_EID_SSID;
144 *pos++ = ifibss->ssid_len;
145 memcpy(pos, ifibss->ssid, ifibss->ssid_len);
Johannes Bergc3ffeab2013-03-07 20:54:29 +0100146 pos += ifibss->ssid_len;
Johannes Berg46900292009-02-15 12:44:28 +0100147
Simon Wunderlich2103dec2013-07-08 16:55:53 +0200148 rate_flags = ieee80211_chandef_rate_flags(&chandef);
149 for (i = 0; i < sband->n_bitrates; i++) {
150 if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
151 continue;
Simon Wunderlich2ec9c1f2013-07-11 18:07:46 +0200152 if (sband->bitrates[i].bitrate > 110)
153 have_higher_than_11mbit = true;
Simon Wunderlich2103dec2013-07-08 16:55:53 +0200154
155 rates |= BIT(i);
156 rates_n++;
157 }
158
Johannes Berg46900292009-02-15 12:44:28 +0100159 *pos++ = WLAN_EID_SUPP_RATES;
Simon Wunderlich2103dec2013-07-08 16:55:53 +0200160 *pos++ = min_t(int, 8, rates_n);
161 for (ri = 0; ri < sband->n_bitrates; ri++) {
162 int rate = DIV_ROUND_UP(sband->bitrates[ri].bitrate,
163 5 * (1 << shift));
Johannes Bergc3ffeab2013-03-07 20:54:29 +0100164 u8 basic = 0;
Simon Wunderlich2103dec2013-07-08 16:55:53 +0200165 if (!(rates & BIT(ri)))
166 continue;
167
168 if (basic_rates & BIT(ri))
Johannes Bergc3ffeab2013-03-07 20:54:29 +0100169 basic = 0x80;
Simon Wunderlich2103dec2013-07-08 16:55:53 +0200170 *pos++ = basic | (u8) rate;
171 if (++rates_added == 8)
172 break;
Johannes Bergc3ffeab2013-03-07 20:54:29 +0100173 }
Johannes Berg46900292009-02-15 12:44:28 +0100174
175 if (sband->band == IEEE80211_BAND_2GHZ) {
Johannes Berg46900292009-02-15 12:44:28 +0100176 *pos++ = WLAN_EID_DS_PARAMS;
177 *pos++ = 1;
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200178 *pos++ = ieee80211_frequency_to_channel(chan->center_freq);
Johannes Berg46900292009-02-15 12:44:28 +0100179 }
180
Johannes Berg46900292009-02-15 12:44:28 +0100181 *pos++ = WLAN_EID_IBSS_PARAMS;
182 *pos++ = 2;
183 /* FIX: set ATIM window based on scan results */
184 *pos++ = 0;
185 *pos++ = 0;
186
Simon Wunderlich2103dec2013-07-08 16:55:53 +0200187 /* put the remaining rates in WLAN_EID_EXT_SUPP_RATES */
188 if (rates_n > 8) {
Johannes Berg46900292009-02-15 12:44:28 +0100189 *pos++ = WLAN_EID_EXT_SUPP_RATES;
Simon Wunderlich2103dec2013-07-08 16:55:53 +0200190 *pos++ = rates_n - 8;
191 for (; ri < sband->n_bitrates; ri++) {
192 int rate = DIV_ROUND_UP(sband->bitrates[ri].bitrate,
193 5 * (1 << shift));
Johannes Bergc3ffeab2013-03-07 20:54:29 +0100194 u8 basic = 0;
Simon Wunderlich2103dec2013-07-08 16:55:53 +0200195 if (!(rates & BIT(ri)))
196 continue;
197
198 if (basic_rates & BIT(ri))
Johannes Bergc3ffeab2013-03-07 20:54:29 +0100199 basic = 0x80;
Simon Wunderlich2103dec2013-07-08 16:55:53 +0200200 *pos++ = basic | (u8) rate;
Johannes Bergc3ffeab2013-03-07 20:54:29 +0100201 }
Johannes Berg46900292009-02-15 12:44:28 +0100202 }
203
Johannes Bergc3ffeab2013-03-07 20:54:29 +0100204 if (ifibss->ie_len) {
205 memcpy(pos, ifibss->ie, ifibss->ie_len);
206 pos += ifibss->ie_len;
207 }
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200208
Alexander Simon13c40c52011-11-30 16:56:34 +0100209 /* add HT capability and information IEs */
Johannes Berg4bf88532012-11-09 11:39:59 +0100210 if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
Simon Wunderlich0418a442013-05-16 13:00:31 +0200211 chandef.width != NL80211_CHAN_WIDTH_5 &&
212 chandef.width != NL80211_CHAN_WIDTH_10 &&
Johannes Berg683b6d32012-11-08 21:25:48 +0100213 sband->ht_cap.ht_supported) {
Simon Wunderlich822854b2013-06-28 10:39:59 +0200214 struct ieee80211_sta_ht_cap ht_cap;
215
216 memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
217 ieee80211_apply_htcap_overrides(sdata, &ht_cap);
218
219 pos = ieee80211_ie_build_ht_cap(pos, &ht_cap, ht_cap.cap);
Ashok Nagarajan0d894ec2012-05-07 21:00:29 -0700220 /*
221 * Note: According to 802.11n-2009 9.13.3.1, HT Protection
222 * field and RIFS Mode are reserved in IBSS mode, therefore
223 * keep them at 0
224 */
Johannes Berg074d46d2012-03-15 19:45:16 +0100225 pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap,
Johannes Berg4bf88532012-11-09 11:39:59 +0100226 &chandef, 0);
Alexander Simon13c40c52011-11-30 16:56:34 +0100227 }
228
Johannes Berg32c50572012-03-28 11:04:29 +0200229 if (local->hw.queues >= IEEE80211_NUM_ACS) {
Bruno Randolf9eba6122010-10-04 11:17:30 +0900230 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
231 *pos++ = 7; /* len */
232 *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
233 *pos++ = 0x50;
234 *pos++ = 0xf2;
235 *pos++ = 2; /* WME */
236 *pos++ = 0; /* WME info */
237 *pos++ = 1; /* WME ver */
238 *pos++ = 0; /* U-APSD no in use */
239 }
240
Johannes Bergc3ffeab2013-03-07 20:54:29 +0100241 presp->head_len = pos - presp->head;
242 if (WARN_ON(presp->head_len > frame_len))
243 return;
244
245 rcu_assign_pointer(ifibss->presp, presp);
Johannes Berg46900292009-02-15 12:44:28 +0100246
Johannes Bergd6a83222012-12-14 14:06:28 +0100247 sdata->vif.bss_conf.enable_beacon = true;
Johannes Berg2d0ddec2009-04-23 16:13:26 +0200248 sdata->vif.bss_conf.beacon_int = beacon_int;
Teemu Paasikivifbd2c8d2010-06-14 12:55:31 +0300249 sdata->vif.bss_conf.basic_rates = basic_rates;
Marek Puzyniak0ca54f62013-04-10 13:19:13 +0200250 sdata->vif.bss_conf.ssid_len = ifibss->ssid_len;
251 memcpy(sdata->vif.bss_conf.ssid, ifibss->ssid, ifibss->ssid_len);
Johannes Berg2d0ddec2009-04-23 16:13:26 +0200252 bss_change = BSS_CHANGED_BEACON_INT;
253 bss_change |= ieee80211_reset_erp_info(sdata);
254 bss_change |= BSS_CHANGED_BSSID;
255 bss_change |= BSS_CHANGED_BEACON;
256 bss_change |= BSS_CHANGED_BEACON_ENABLED;
Teemu Paasikivi392cfdb2010-06-14 12:55:32 +0300257 bss_change |= BSS_CHANGED_BASIC_RATES;
Alexander Simon13c40c52011-11-30 16:56:34 +0100258 bss_change |= BSS_CHANGED_HT;
Johannes Berg8fc214b2010-04-28 17:40:43 +0200259 bss_change |= BSS_CHANGED_IBSS;
Marek Puzyniak0ca54f62013-04-10 13:19:13 +0200260 bss_change |= BSS_CHANGED_SSID;
Simon Wunderlich2f91a962012-12-03 22:21:30 +0100261
262 /*
263 * In 5 GHz/802.11a, we can always use short slot time.
264 * (IEEE 802.11-2012 18.3.8.7)
265 *
266 * In 2.4GHz, we must always use long slots in IBSS for compatibility
267 * reasons.
268 * (IEEE 802.11-2012 19.4.5)
269 *
270 * HT follows these specifications (IEEE 802.11-2012 20.3.18)
271 */
272 sdata->vif.bss_conf.use_short_slot = chan->band == IEEE80211_BAND_5GHZ;
273 bss_change |= BSS_CHANGED_ERP_SLOT;
274
Simon Wunderlich2ec9c1f2013-07-11 18:07:46 +0200275 /* cf. IEEE 802.11 9.2.12 */
276 if (chan->band == IEEE80211_BAND_2GHZ && have_higher_than_11mbit)
277 sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
278 else
279 sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
280
Johannes Berg8fc214b2010-04-28 17:40:43 +0200281 sdata->vif.bss_conf.ibss_joined = true;
Sujith Manoharanc13a7652012-10-12 17:35:45 +0530282 sdata->vif.bss_conf.ibss_creator = creator;
Johannes Berg2d0ddec2009-04-23 16:13:26 +0200283 ieee80211_bss_info_change_notify(sdata, bss_change);
Johannes Berg46900292009-02-15 12:44:28 +0100284
Simon Wunderlich2ec9c1f2013-07-11 18:07:46 +0200285 ieee80211_set_wmm_default(sdata, true);
Johannes Berg46900292009-02-15 12:44:28 +0100286
Johannes Berg46900292009-02-15 12:44:28 +0100287 ifibss->state = IEEE80211_IBSS_MLME_JOINED;
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200288 mod_timer(&ifibss->timer,
289 round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
Johannes Berg46900292009-02-15 12:44:28 +0100290
Simon Wunderlich7ca15a02013-07-08 16:55:56 +0200291 scan_width = cfg80211_chandef_to_scan_width(&chandef);
292 bss = cfg80211_inform_bss_width_frame(local->hw.wiphy, chan,
293 scan_width, mgmt,
294 presp->head_len, 0, GFP_KERNEL);
Johannes Berg5b112d32013-02-01 01:49:58 +0100295 cfg80211_put_bss(local->hw.wiphy, bss);
Eliad Peller86a2ea42011-11-08 15:36:59 +0200296 netif_carrier_on(sdata->dev);
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200297 cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
Johannes Berg46900292009-02-15 12:44:28 +0100298}
299
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200300static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
301 struct ieee80211_bss *bss)
Johannes Berg46900292009-02-15 12:44:28 +0100302{
Johannes Berg0c1ad2c2009-12-23 13:15:39 +0100303 struct cfg80211_bss *cbss =
304 container_of((void *)bss, struct cfg80211_bss, priv);
Johannes Bergb59066a2009-05-12 21:18:38 +0200305 struct ieee80211_supported_band *sband;
306 u32 basic_rates;
307 int i, j;
Johannes Berg0c1ad2c2009-12-23 13:15:39 +0100308 u16 beacon_int = cbss->beacon_interval;
Johannes Berg8cef2c92013-02-05 16:54:31 +0100309 const struct cfg80211_bss_ies *ies;
310 u64 tsf;
Simon Wunderlich2103dec2013-07-08 16:55:53 +0200311 u32 rate_flags;
312 int shift;
Johannes Berg57c4d7b2009-04-23 16:10:04 +0200313
Johannes Berg8d61ffa2013-05-10 12:32:47 +0200314 sdata_assert_lock(sdata);
Johannes Berg7a17a332010-07-21 11:30:27 +0200315
Johannes Berg57c4d7b2009-04-23 16:10:04 +0200316 if (beacon_int < 10)
317 beacon_int = 10;
318
Johannes Berg0c1ad2c2009-12-23 13:15:39 +0100319 sband = sdata->local->hw.wiphy->bands[cbss->channel->band];
Simon Wunderlich2103dec2013-07-08 16:55:53 +0200320 rate_flags = ieee80211_chandef_rate_flags(&sdata->u.ibss.chandef);
321 shift = ieee80211_vif_get_shift(&sdata->vif);
Johannes Bergb59066a2009-05-12 21:18:38 +0200322
323 basic_rates = 0;
324
325 for (i = 0; i < bss->supp_rates_len; i++) {
Simon Wunderlich2103dec2013-07-08 16:55:53 +0200326 int rate = bss->supp_rates[i] & 0x7f;
Johannes Bergb59066a2009-05-12 21:18:38 +0200327 bool is_basic = !!(bss->supp_rates[i] & 0x80);
328
329 for (j = 0; j < sband->n_bitrates; j++) {
Simon Wunderlich2103dec2013-07-08 16:55:53 +0200330 int brate;
331 if ((rate_flags & sband->bitrates[j].flags)
332 != rate_flags)
333 continue;
334
335 brate = DIV_ROUND_UP(sband->bitrates[j].bitrate,
336 5 * (1 << shift));
337 if (brate == rate) {
Johannes Bergb59066a2009-05-12 21:18:38 +0200338 if (is_basic)
339 basic_rates |= BIT(j);
340 break;
341 }
342 }
343 }
344
Johannes Berg8cef2c92013-02-05 16:54:31 +0100345 rcu_read_lock();
346 ies = rcu_dereference(cbss->ies);
347 tsf = ies->tsf;
348 rcu_read_unlock();
349
Johannes Berg0c1ad2c2009-12-23 13:15:39 +0100350 __ieee80211_sta_join_ibss(sdata, cbss->bssid,
Johannes Berg57c4d7b2009-04-23 16:10:04 +0200351 beacon_int,
Johannes Berg0c1ad2c2009-12-23 13:15:39 +0100352 cbss->channel,
Johannes Bergb59066a2009-05-12 21:18:38 +0200353 basic_rates,
Johannes Berg0c1ad2c2009-12-23 13:15:39 +0100354 cbss->capability,
Johannes Berg8cef2c92013-02-05 16:54:31 +0100355 tsf, false);
Johannes Berg46900292009-02-15 12:44:28 +0100356}
357
Antonio Quartulli52874a52013-06-18 14:20:40 +0200358static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta)
Johannes Berg8bf11d82011-12-15 11:17:37 +0100359 __acquires(RCU)
360{
361 struct ieee80211_sub_if_data *sdata = sta->sdata;
362 u8 addr[ETH_ALEN];
363
364 memcpy(addr, sta->sta.addr, ETH_ALEN);
365
Johannes Bergbdcbd8e2012-06-22 11:29:50 +0200366 ibss_dbg(sdata, "Adding new IBSS station %pM\n", addr);
Johannes Berg8bf11d82011-12-15 11:17:37 +0100367
Johannes Berg83d5cc02012-01-12 09:31:10 +0100368 sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
369 sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
Antonio Quartulli267335d2012-01-31 20:25:47 +0100370 /* authorize the station only if the network is not RSN protected. If
371 * not wait for the userspace to authorize it */
372 if (!sta->sdata->u.ibss.control_port)
373 sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
Johannes Berg8bf11d82011-12-15 11:17:37 +0100374
375 rate_control_rate_init(sta);
376
377 /* If it fails, maybe we raced another insertion? */
378 if (sta_info_insert_rcu(sta))
379 return sta_info_get(sdata, addr);
380 return sta;
381}
382
383static struct sta_info *
Antonio Quartulli52874a52013-06-18 14:20:40 +0200384ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid,
385 const u8 *addr, u32 supp_rates)
Johannes Berg8bf11d82011-12-15 11:17:37 +0100386 __acquires(RCU)
387{
388 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
389 struct ieee80211_local *local = sdata->local;
390 struct sta_info *sta;
Johannes Berg55de9082012-07-26 17:24:39 +0200391 struct ieee80211_chanctx_conf *chanctx_conf;
Ashok Nagarajanb422c6c2013-05-10 17:50:51 -0700392 struct ieee80211_supported_band *sband;
Simon Wunderlich74608ac2013-07-08 16:55:54 +0200393 enum nl80211_bss_scan_width scan_width;
Johannes Berg55de9082012-07-26 17:24:39 +0200394 int band;
Johannes Berg8bf11d82011-12-15 11:17:37 +0100395
396 /*
397 * XXX: Consider removing the least recently used entry and
398 * allow new one to be added.
399 */
400 if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
Johannes Bergbdcbd8e2012-06-22 11:29:50 +0200401 net_info_ratelimited("%s: No room for a new IBSS STA entry %pM\n",
Joe Perchese87cc472012-05-13 21:56:26 +0000402 sdata->name, addr);
Johannes Berg8bf11d82011-12-15 11:17:37 +0100403 rcu_read_lock();
404 return NULL;
405 }
406
407 if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH) {
408 rcu_read_lock();
409 return NULL;
410 }
411
Joe Perchesb203ca32012-05-08 18:56:52 +0000412 if (!ether_addr_equal(bssid, sdata->u.ibss.bssid)) {
Johannes Berg8bf11d82011-12-15 11:17:37 +0100413 rcu_read_lock();
414 return NULL;
415 }
416
Johannes Berg55de9082012-07-26 17:24:39 +0200417 rcu_read_lock();
418 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
419 if (WARN_ON_ONCE(!chanctx_conf))
420 return NULL;
Johannes Berg4bf88532012-11-09 11:39:59 +0100421 band = chanctx_conf->def.chan->band;
Simon Wunderlich74608ac2013-07-08 16:55:54 +0200422 scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
Johannes Berg55de9082012-07-26 17:24:39 +0200423 rcu_read_unlock();
424
Johannes Berg8bf11d82011-12-15 11:17:37 +0100425 sta = sta_info_alloc(sdata, addr, GFP_KERNEL);
426 if (!sta) {
427 rcu_read_lock();
428 return NULL;
429 }
430
431 sta->last_rx = jiffies;
432
433 /* make sure mandatory rates are always added */
Ashok Nagarajanb422c6c2013-05-10 17:50:51 -0700434 sband = local->hw.wiphy->bands[band];
Johannes Berg8bf11d82011-12-15 11:17:37 +0100435 sta->sta.supp_rates[band] = supp_rates |
Simon Wunderlich74608ac2013-07-08 16:55:54 +0200436 ieee80211_mandatory_rates(sband, scan_width);
Johannes Berg8bf11d82011-12-15 11:17:37 +0100437
Antonio Quartulli52874a52013-06-18 14:20:40 +0200438 return ieee80211_ibss_finish_sta(sta);
Antonio Quartulli6d810f12012-01-18 00:10:44 +0100439}
440
Antonio Quartulli2cc59e72012-09-07 13:28:53 +0200441static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata,
442 struct ieee80211_mgmt *mgmt,
443 size_t len)
444{
445 u16 reason = le16_to_cpu(mgmt->u.deauth.reason_code);
446
447 if (len < IEEE80211_DEAUTH_FRAME_LEN)
448 return;
449
450 ibss_dbg(sdata, "RX DeAuth SA=%pM DA=%pM BSSID=%pM (reason: %d)\n",
451 mgmt->sa, mgmt->da, mgmt->bssid, reason);
452 sta_info_destroy_addr(sdata, mgmt->sa);
453}
454
Antonio Quartulli6d810f12012-01-18 00:10:44 +0100455static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
456 struct ieee80211_mgmt *mgmt,
457 size_t len)
458{
459 u16 auth_alg, auth_transaction;
460
Johannes Berg8d61ffa2013-05-10 12:32:47 +0200461 sdata_assert_lock(sdata);
Antonio Quartulli6d810f12012-01-18 00:10:44 +0100462
463 if (len < 24 + 6)
464 return;
465
466 auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
467 auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
468
Johannes Bergbdcbd8e2012-06-22 11:29:50 +0200469 ibss_dbg(sdata,
470 "RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n",
471 mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction);
Antonio Quartulli7bed2052012-11-25 23:24:27 +0100472
473 if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1)
474 return;
475
Antonio Quartulli2cc59e72012-09-07 13:28:53 +0200476 /*
Antonio Quartulli6d810f12012-01-18 00:10:44 +0100477 * IEEE 802.11 standard does not require authentication in IBSS
478 * networks and most implementations do not seem to use it.
479 * However, try to reply to authentication attempts if someone
480 * has actually implemented this.
481 */
Jouni Malinen700e8ea2012-09-30 19:29:37 +0300482 ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, 0, NULL, 0,
Johannes Berg1672c0e32013-01-29 15:02:27 +0100483 mgmt->sa, sdata->u.ibss.bssid, NULL, 0, 0, 0);
Johannes Berg8bf11d82011-12-15 11:17:37 +0100484}
485
Johannes Berg46900292009-02-15 12:44:28 +0100486static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
Emmanuel Grumbachd45c4172012-12-10 16:19:13 +0200487 struct ieee80211_mgmt *mgmt, size_t len,
Johannes Berg46900292009-02-15 12:44:28 +0100488 struct ieee80211_rx_status *rx_status,
Emmanuel Grumbachd45c4172012-12-10 16:19:13 +0200489 struct ieee802_11_elems *elems)
Johannes Berg46900292009-02-15 12:44:28 +0100490{
491 struct ieee80211_local *local = sdata->local;
492 int freq;
Johannes Berg0c1ad2c2009-12-23 13:15:39 +0100493 struct cfg80211_bss *cbss;
Johannes Berg46900292009-02-15 12:44:28 +0100494 struct ieee80211_bss *bss;
495 struct sta_info *sta;
496 struct ieee80211_channel *channel;
497 u64 beacon_timestamp, rx_timestamp;
498 u32 supp_rates = 0;
499 enum ieee80211_band band = rx_status->band;
Simon Wunderlich74608ac2013-07-08 16:55:54 +0200500 enum nl80211_bss_scan_width scan_width;
Alexander Simon13c40c52011-11-30 16:56:34 +0100501 struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
502 bool rates_updated = false;
Johannes Berg46900292009-02-15 12:44:28 +0100503
Johannes Berg1cd8e882013-03-27 14:30:12 +0100504 if (elems->ds_params)
Bruno Randolf59eb21a2011-01-17 13:37:28 +0900505 freq = ieee80211_channel_to_frequency(elems->ds_params[0],
506 band);
Johannes Berg46900292009-02-15 12:44:28 +0100507 else
508 freq = rx_status->freq;
509
510 channel = ieee80211_get_channel(local->hw.wiphy, freq);
511
512 if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
513 return;
514
Bruno Randolf9eba6122010-10-04 11:17:30 +0900515 if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
Joe Perchesb203ca32012-05-08 18:56:52 +0000516 ether_addr_equal(mgmt->bssid, sdata->u.ibss.bssid)) {
Johannes Berg46900292009-02-15 12:44:28 +0100517
518 rcu_read_lock();
Johannes Bergabe60632009-11-25 17:46:18 +0100519 sta = sta_info_get(sdata, mgmt->sa);
Johannes Berg46900292009-02-15 12:44:28 +0100520
Bruno Randolf9eba6122010-10-04 11:17:30 +0900521 if (elems->supp_rates) {
Simon Wunderlich2103dec2013-07-08 16:55:53 +0200522 supp_rates = ieee80211_sta_get_rates(sdata, elems,
Ashok Nagarajan9ebb61a2012-04-02 21:21:21 -0700523 band, NULL);
Bruno Randolf9eba6122010-10-04 11:17:30 +0900524 if (sta) {
525 u32 prev_rates;
Johannes Berg46900292009-02-15 12:44:28 +0100526
Bruno Randolf9eba6122010-10-04 11:17:30 +0900527 prev_rates = sta->sta.supp_rates[band];
528 /* make sure mandatory rates are always added */
Simon Wunderlich74608ac2013-07-08 16:55:54 +0200529 scan_width = NL80211_BSS_CHAN_WIDTH_20;
530 if (rx_status->flag & RX_FLAG_5MHZ)
531 scan_width = NL80211_BSS_CHAN_WIDTH_5;
532 if (rx_status->flag & RX_FLAG_10MHZ)
533 scan_width = NL80211_BSS_CHAN_WIDTH_10;
Bruno Randolf9eba6122010-10-04 11:17:30 +0900534
Simon Wunderlich74608ac2013-07-08 16:55:54 +0200535 sta->sta.supp_rates[band] = supp_rates |
536 ieee80211_mandatory_rates(sband,
537 scan_width);
Bruno Randolf9eba6122010-10-04 11:17:30 +0900538 if (sta->sta.supp_rates[band] != prev_rates) {
Johannes Bergbdcbd8e2012-06-22 11:29:50 +0200539 ibss_dbg(sdata,
540 "updated supp_rates set for %pM based on beacon/probe_resp (0x%x -> 0x%x)\n",
541 sta->sta.addr, prev_rates,
542 sta->sta.supp_rates[band]);
Alexander Simon13c40c52011-11-30 16:56:34 +0100543 rates_updated = true;
Bruno Randolf9eba6122010-10-04 11:17:30 +0900544 }
Johannes Berg8bf11d82011-12-15 11:17:37 +0100545 } else {
546 rcu_read_unlock();
Bruno Randolf9eba6122010-10-04 11:17:30 +0900547 sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
Antonio Quartulli52874a52013-06-18 14:20:40 +0200548 mgmt->sa, supp_rates);
Johannes Berg8bf11d82011-12-15 11:17:37 +0100549 }
Johannes Berg34e89502010-02-03 13:59:58 +0100550 }
Bruno Randolf9eba6122010-10-04 11:17:30 +0900551
552 if (sta && elems->wmm_info)
Johannes Bergc2c98fd2011-09-29 16:04:36 +0200553 set_sta_flag(sta, WLAN_STA_WME);
Bruno Randolf9eba6122010-10-04 11:17:30 +0900554
Johannes Berg074d46d2012-03-15 19:45:16 +0100555 if (sta && elems->ht_operation && elems->ht_cap_elem &&
Simon Wunderlich3aede782013-05-16 13:00:36 +0200556 sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
557 sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_5 &&
558 sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_10) {
Alexander Simon13c40c52011-11-30 16:56:34 +0100559 /* we both use HT */
Johannes Berge1a0c6b2013-02-07 11:47:44 +0100560 struct ieee80211_ht_cap htcap_ie;
Johannes Berg4bf88532012-11-09 11:39:59 +0100561 struct cfg80211_chan_def chandef;
562
563 ieee80211_ht_oper_to_chandef(channel,
564 elems->ht_operation,
565 &chandef);
Alexander Simon13c40c52011-11-30 16:56:34 +0100566
Johannes Berge1a0c6b2013-02-07 11:47:44 +0100567 memcpy(&htcap_ie, elems->ht_cap_elem, sizeof(htcap_ie));
Alexander Simon13c40c52011-11-30 16:56:34 +0100568
569 /*
570 * fall back to HT20 if we don't use or use
571 * the other extension channel
572 */
Simon Wunderlich3aede782013-05-16 13:00:36 +0200573 if (chandef.center_freq1 !=
574 sdata->u.ibss.chandef.center_freq1)
Johannes Berge1a0c6b2013-02-07 11:47:44 +0100575 htcap_ie.cap_info &=
576 cpu_to_le16(~IEEE80211_HT_CAP_SUP_WIDTH_20_40);
Alexander Simon13c40c52011-11-30 16:56:34 +0100577
Johannes Berge1a0c6b2013-02-07 11:47:44 +0100578 rates_updated |= ieee80211_ht_cap_ie_to_sta_ht_cap(
579 sdata, sband, &htcap_ie, sta);
Alexander Simon13c40c52011-11-30 16:56:34 +0100580 }
581
Antonio Quartullie687f612012-08-12 18:24:55 +0200582 if (sta && rates_updated) {
583 drv_sta_rc_update(local, sdata, &sta->sta,
584 IEEE80211_RC_SUPP_RATES_CHANGED);
Alexander Simon13c40c52011-11-30 16:56:34 +0100585 rate_control_rate_init(sta);
Antonio Quartullie687f612012-08-12 18:24:55 +0200586 }
Alexander Simon13c40c52011-11-30 16:56:34 +0100587
Bruno Randolf9eba6122010-10-04 11:17:30 +0900588 rcu_read_unlock();
Johannes Berg46900292009-02-15 12:44:28 +0100589 }
590
591 bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems,
Emmanuel Grumbachd45c4172012-12-10 16:19:13 +0200592 channel);
Johannes Berg46900292009-02-15 12:44:28 +0100593 if (!bss)
594 return;
595
Johannes Berg0c1ad2c2009-12-23 13:15:39 +0100596 cbss = container_of((void *)bss, struct cfg80211_bss, priv);
597
Johannes Berg8cef2c92013-02-05 16:54:31 +0100598 /* same for beacon and probe response */
599 beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
Johannes Berg46900292009-02-15 12:44:28 +0100600
601 /* check if we need to merge IBSS */
602
Johannes Berg46900292009-02-15 12:44:28 +0100603 /* we use a fixed BSSID */
Benoit Papillaulta98bfec2010-01-17 22:45:24 +0100604 if (sdata->u.ibss.fixed_bssid)
Johannes Berg46900292009-02-15 12:44:28 +0100605 goto put_bss;
606
607 /* not an IBSS */
Johannes Berg0c1ad2c2009-12-23 13:15:39 +0100608 if (!(cbss->capability & WLAN_CAPABILITY_IBSS))
Johannes Berg46900292009-02-15 12:44:28 +0100609 goto put_bss;
610
611 /* different channel */
Johannes Berg55de9082012-07-26 17:24:39 +0200612 if (sdata->u.ibss.fixed_channel &&
Simon Wunderlich3aede782013-05-16 13:00:36 +0200613 sdata->u.ibss.chandef.chan != cbss->channel)
Johannes Berg46900292009-02-15 12:44:28 +0100614 goto put_bss;
615
616 /* different SSID */
617 if (elems->ssid_len != sdata->u.ibss.ssid_len ||
618 memcmp(elems->ssid, sdata->u.ibss.ssid,
619 sdata->u.ibss.ssid_len))
620 goto put_bss;
621
Alina Friedrichsen34e8f082009-02-22 00:07:28 +0100622 /* same BSSID */
Joe Perchesb203ca32012-05-08 18:56:52 +0000623 if (ether_addr_equal(cbss->bssid, sdata->u.ibss.bssid))
Alina Friedrichsen34e8f082009-02-22 00:07:28 +0100624 goto put_bss;
625
Thomas Pedersenf4bda332012-11-13 10:46:27 -0800626 if (ieee80211_have_rx_timestamp(rx_status)) {
627 /* time when timestamp field was received */
628 rx_timestamp =
629 ieee80211_calculate_rx_timestamp(local, rx_status,
630 len + FCS_LEN, 24);
Johannes Berg24487982009-04-23 18:52:52 +0200631 } else {
632 /*
633 * second best option: get current TSF
634 * (will return -1 if not supported)
635 */
Eliad Peller37a41b42011-09-21 14:06:11 +0300636 rx_timestamp = drv_get_tsf(local, sdata);
Johannes Berg24487982009-04-23 18:52:52 +0200637 }
Johannes Berg46900292009-02-15 12:44:28 +0100638
Johannes Bergbdcbd8e2012-06-22 11:29:50 +0200639 ibss_dbg(sdata,
640 "RX beacon SA=%pM BSSID=%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n",
641 mgmt->sa, mgmt->bssid,
642 (unsigned long long)rx_timestamp,
643 (unsigned long long)beacon_timestamp,
644 (unsigned long long)(rx_timestamp - beacon_timestamp),
645 jiffies);
Johannes Berg46900292009-02-15 12:44:28 +0100646
647 if (beacon_timestamp > rx_timestamp) {
Johannes Bergbdcbd8e2012-06-22 11:29:50 +0200648 ibss_dbg(sdata,
649 "beacon TSF higher than local TSF - IBSS merge with BSSID %pM\n",
650 mgmt->bssid);
Johannes Berg46900292009-02-15 12:44:28 +0100651 ieee80211_sta_join_ibss(sdata, bss);
Simon Wunderlich2103dec2013-07-08 16:55:53 +0200652 supp_rates = ieee80211_sta_get_rates(sdata, elems, band, NULL);
Johannes Berg34e89502010-02-03 13:59:58 +0100653 ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
Antonio Quartulli52874a52013-06-18 14:20:40 +0200654 supp_rates);
Johannes Berg8bf11d82011-12-15 11:17:37 +0100655 rcu_read_unlock();
Johannes Berg46900292009-02-15 12:44:28 +0100656 }
657
658 put_bss:
659 ieee80211_rx_bss_put(local, bss);
660}
661
Johannes Berg8bf11d82011-12-15 11:17:37 +0100662void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
663 const u8 *bssid, const u8 *addr,
664 u32 supp_rates)
Johannes Berg46900292009-02-15 12:44:28 +0100665{
Felix Fietkau2e10d332009-12-20 19:07:09 +0100666 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
Johannes Berg46900292009-02-15 12:44:28 +0100667 struct ieee80211_local *local = sdata->local;
668 struct sta_info *sta;
Johannes Berg55de9082012-07-26 17:24:39 +0200669 struct ieee80211_chanctx_conf *chanctx_conf;
Ashok Nagarajanb422c6c2013-05-10 17:50:51 -0700670 struct ieee80211_supported_band *sband;
Simon Wunderlich74608ac2013-07-08 16:55:54 +0200671 enum nl80211_bss_scan_width scan_width;
Johannes Berg55de9082012-07-26 17:24:39 +0200672 int band;
Johannes Berg46900292009-02-15 12:44:28 +0100673
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200674 /*
675 * XXX: Consider removing the least recently used entry and
676 * allow new one to be added.
677 */
Johannes Berg46900292009-02-15 12:44:28 +0100678 if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
Johannes Bergbdcbd8e2012-06-22 11:29:50 +0200679 net_info_ratelimited("%s: No room for a new IBSS STA entry %pM\n",
Joe Perchese87cc472012-05-13 21:56:26 +0000680 sdata->name, addr);
Johannes Berg8bf11d82011-12-15 11:17:37 +0100681 return;
Johannes Berg46900292009-02-15 12:44:28 +0100682 }
683
Felix Fietkau2e10d332009-12-20 19:07:09 +0100684 if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH)
Johannes Berg8bf11d82011-12-15 11:17:37 +0100685 return;
Felix Fietkau2e10d332009-12-20 19:07:09 +0100686
Joe Perchesb203ca32012-05-08 18:56:52 +0000687 if (!ether_addr_equal(bssid, sdata->u.ibss.bssid))
Johannes Berg8bf11d82011-12-15 11:17:37 +0100688 return;
Johannes Berg46900292009-02-15 12:44:28 +0100689
Johannes Berg55de9082012-07-26 17:24:39 +0200690 rcu_read_lock();
691 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
692 if (WARN_ON_ONCE(!chanctx_conf)) {
693 rcu_read_unlock();
694 return;
695 }
Johannes Berg4bf88532012-11-09 11:39:59 +0100696 band = chanctx_conf->def.chan->band;
Simon Wunderlich74608ac2013-07-08 16:55:54 +0200697 scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
Johannes Berg55de9082012-07-26 17:24:39 +0200698 rcu_read_unlock();
699
Johannes Berg8bf11d82011-12-15 11:17:37 +0100700 sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
Johannes Berg46900292009-02-15 12:44:28 +0100701 if (!sta)
Johannes Berg8bf11d82011-12-15 11:17:37 +0100702 return;
Johannes Berg46900292009-02-15 12:44:28 +0100703
Rajkumar Manoharanc8716d92010-10-23 10:59:57 +0530704 sta->last_rx = jiffies;
Johannes Bergd9a7ddb2011-12-14 12:35:30 +0100705
Johannes Berg46900292009-02-15 12:44:28 +0100706 /* make sure mandatory rates are always added */
Ashok Nagarajanb422c6c2013-05-10 17:50:51 -0700707 sband = local->hw.wiphy->bands[band];
Johannes Berg46900292009-02-15 12:44:28 +0100708 sta->sta.supp_rates[band] = supp_rates |
Simon Wunderlich74608ac2013-07-08 16:55:54 +0200709 ieee80211_mandatory_rates(sband, scan_width);
Johannes Berg46900292009-02-15 12:44:28 +0100710
Johannes Berg8bf11d82011-12-15 11:17:37 +0100711 spin_lock(&ifibss->incomplete_lock);
712 list_add(&sta->list, &ifibss->incomplete_stations);
713 spin_unlock(&ifibss->incomplete_lock);
714 ieee80211_queue_work(&local->hw, &sdata->work);
Johannes Berg46900292009-02-15 12:44:28 +0100715}
716
717static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
718{
719 struct ieee80211_local *local = sdata->local;
720 int active = 0;
721 struct sta_info *sta;
722
Johannes Berg8d61ffa2013-05-10 12:32:47 +0200723 sdata_assert_lock(sdata);
Johannes Berg7a17a332010-07-21 11:30:27 +0200724
Johannes Berg46900292009-02-15 12:44:28 +0100725 rcu_read_lock();
726
727 list_for_each_entry_rcu(sta, &local->sta_list, list) {
728 if (sta->sdata == sdata &&
729 time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
730 jiffies)) {
731 active++;
732 break;
733 }
734 }
735
736 rcu_read_unlock();
737
738 return active;
739}
740
Benoit Papillaultce9058a2010-01-17 22:45:23 +0100741/*
742 * This function is called with state == IEEE80211_IBSS_MLME_JOINED
743 */
Johannes Berg46900292009-02-15 12:44:28 +0100744
745static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
746{
747 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
Simon Wunderlich7ca15a02013-07-08 16:55:56 +0200748 enum nl80211_bss_scan_width scan_width;
Johannes Berg46900292009-02-15 12:44:28 +0100749
Johannes Berg8d61ffa2013-05-10 12:32:47 +0200750 sdata_assert_lock(sdata);
Johannes Berg7a17a332010-07-21 11:30:27 +0200751
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200752 mod_timer(&ifibss->timer,
753 round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
Johannes Berg46900292009-02-15 12:44:28 +0100754
755 ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT);
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200756
Sujith450aae32009-11-02 12:33:23 +0530757 if (time_before(jiffies, ifibss->last_scan_completed +
758 IEEE80211_IBSS_MERGE_INTERVAL))
759 return;
760
Johannes Berg46900292009-02-15 12:44:28 +0100761 if (ieee80211_sta_active_ibss(sdata))
762 return;
763
John W. Linvillec037b832012-01-30 15:28:11 -0500764 if (ifibss->fixed_channel)
Johannes Berg46900292009-02-15 12:44:28 +0100765 return;
766
Johannes Bergbdcbd8e2012-06-22 11:29:50 +0200767 sdata_info(sdata,
768 "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n");
Johannes Berg46900292009-02-15 12:44:28 +0100769
Simon Wunderlich7ca15a02013-07-08 16:55:56 +0200770 scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef);
Stanislaw Gruszka34bcf712012-12-11 10:48:23 +0100771 ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len,
Simon Wunderlich7ca15a02013-07-08 16:55:56 +0200772 NULL, scan_width);
Johannes Berg46900292009-02-15 12:44:28 +0100773}
774
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200775static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
Johannes Berg46900292009-02-15 12:44:28 +0100776{
777 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
Johannes Berg46900292009-02-15 12:44:28 +0100778 u8 bssid[ETH_ALEN];
Johannes Berg46900292009-02-15 12:44:28 +0100779 u16 capability;
780 int i;
781
Johannes Berg8d61ffa2013-05-10 12:32:47 +0200782 sdata_assert_lock(sdata);
Johannes Berg7a17a332010-07-21 11:30:27 +0200783
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200784 if (ifibss->fixed_bssid) {
Johannes Berg46900292009-02-15 12:44:28 +0100785 memcpy(bssid, ifibss->bssid, ETH_ALEN);
786 } else {
787 /* Generate random, not broadcast, locally administered BSSID. Mix in
788 * own MAC address to make sure that devices that do not have proper
789 * random number generator get different BSSID. */
790 get_random_bytes(bssid, ETH_ALEN);
791 for (i = 0; i < ETH_ALEN; i++)
Johannes Berg47846c92009-11-25 17:46:19 +0100792 bssid[i] ^= sdata->vif.addr[i];
Johannes Berg46900292009-02-15 12:44:28 +0100793 bssid[0] &= ~0x01;
794 bssid[0] |= 0x02;
795 }
796
Johannes Bergbdcbd8e2012-06-22 11:29:50 +0200797 sdata_info(sdata, "Creating new IBSS network, BSSID %pM\n", bssid);
Johannes Berg46900292009-02-15 12:44:28 +0100798
Johannes Berg46900292009-02-15 12:44:28 +0100799 capability = WLAN_CAPABILITY_IBSS;
800
Johannes Bergfffd0932009-07-08 14:22:54 +0200801 if (ifibss->privacy)
Johannes Berg46900292009-02-15 12:44:28 +0100802 capability |= WLAN_CAPABILITY_PRIVACY;
803 else
804 sdata->drop_unencrypted = 0;
805
Johannes Berg57c4d7b2009-04-23 16:10:04 +0200806 __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
Simon Wunderlich3aede782013-05-16 13:00:36 +0200807 ifibss->chandef.chan, ifibss->basic_rates,
Sujith Manoharanc13a7652012-10-12 17:35:45 +0530808 capability, 0, true);
Johannes Berg46900292009-02-15 12:44:28 +0100809}
810
Benoit Papillaultce9058a2010-01-17 22:45:23 +0100811/*
812 * This function is called with state == IEEE80211_IBSS_MLME_SEARCH
813 */
814
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200815static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
Johannes Berg46900292009-02-15 12:44:28 +0100816{
817 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
818 struct ieee80211_local *local = sdata->local;
Johannes Berg0c1ad2c2009-12-23 13:15:39 +0100819 struct cfg80211_bss *cbss;
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200820 struct ieee80211_channel *chan = NULL;
Johannes Berg46900292009-02-15 12:44:28 +0100821 const u8 *bssid = NULL;
Simon Wunderlich7ca15a02013-07-08 16:55:56 +0200822 enum nl80211_bss_scan_width scan_width;
Johannes Berg46900292009-02-15 12:44:28 +0100823 int active_ibss;
Johannes Berge0d61882009-05-12 20:47:32 +0200824 u16 capability;
Johannes Berg46900292009-02-15 12:44:28 +0100825
Johannes Berg8d61ffa2013-05-10 12:32:47 +0200826 sdata_assert_lock(sdata);
Johannes Berg7a17a332010-07-21 11:30:27 +0200827
Johannes Berg46900292009-02-15 12:44:28 +0100828 active_ibss = ieee80211_sta_active_ibss(sdata);
Johannes Bergbdcbd8e2012-06-22 11:29:50 +0200829 ibss_dbg(sdata, "sta_find_ibss (active_ibss=%d)\n", active_ibss);
Johannes Berg46900292009-02-15 12:44:28 +0100830
831 if (active_ibss)
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200832 return;
Johannes Berg46900292009-02-15 12:44:28 +0100833
Johannes Berge0d61882009-05-12 20:47:32 +0200834 capability = WLAN_CAPABILITY_IBSS;
Johannes Bergfffd0932009-07-08 14:22:54 +0200835 if (ifibss->privacy)
Johannes Berge0d61882009-05-12 20:47:32 +0200836 capability |= WLAN_CAPABILITY_PRIVACY;
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200837 if (ifibss->fixed_bssid)
Johannes Berg46900292009-02-15 12:44:28 +0100838 bssid = ifibss->bssid;
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200839 if (ifibss->fixed_channel)
Simon Wunderlich3aede782013-05-16 13:00:36 +0200840 chan = ifibss->chandef.chan;
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200841 if (!is_zero_ether_addr(ifibss->bssid))
842 bssid = ifibss->bssid;
Johannes Berg0c1ad2c2009-12-23 13:15:39 +0100843 cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid,
844 ifibss->ssid, ifibss->ssid_len,
845 WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_PRIVACY,
846 capability);
Johannes Berg46900292009-02-15 12:44:28 +0100847
Johannes Berg0c1ad2c2009-12-23 13:15:39 +0100848 if (cbss) {
849 struct ieee80211_bss *bss;
850
851 bss = (void *)cbss->priv;
Johannes Bergbdcbd8e2012-06-22 11:29:50 +0200852 ibss_dbg(sdata,
853 "sta_find_ibss: selected %pM current %pM\n",
854 cbss->bssid, ifibss->bssid);
855 sdata_info(sdata,
856 "Selected IBSS BSSID %pM based on configured SSID\n",
857 cbss->bssid);
Johannes Berg46900292009-02-15 12:44:28 +0100858
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200859 ieee80211_sta_join_ibss(sdata, bss);
Johannes Berg46900292009-02-15 12:44:28 +0100860 ieee80211_rx_bss_put(local, bss);
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200861 return;
Reinette Chatred419b9f2009-10-19 14:55:37 -0700862 }
Johannes Berg46900292009-02-15 12:44:28 +0100863
Johannes Bergbdcbd8e2012-06-22 11:29:50 +0200864 ibss_dbg(sdata, "sta_find_ibss: did not try to join ibss\n");
Johannes Berg46900292009-02-15 12:44:28 +0100865
866 /* Selected IBSS not found in current scan results - try to scan */
Benoit Papillaultce9058a2010-01-17 22:45:23 +0100867 if (time_after(jiffies, ifibss->last_scan_completed +
Johannes Berg46900292009-02-15 12:44:28 +0100868 IEEE80211_SCAN_INTERVAL)) {
Johannes Bergbdcbd8e2012-06-22 11:29:50 +0200869 sdata_info(sdata, "Trigger new scan to find an IBSS to join\n");
Johannes Berg46900292009-02-15 12:44:28 +0100870
Simon Wunderlich7ca15a02013-07-08 16:55:56 +0200871 scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef);
Stanislaw Gruszka34bcf712012-12-11 10:48:23 +0100872 ieee80211_request_ibss_scan(sdata, ifibss->ssid,
Simon Wunderlich7ca15a02013-07-08 16:55:56 +0200873 ifibss->ssid_len, chan,
874 scan_width);
Benoit Papillaultce9058a2010-01-17 22:45:23 +0100875 } else {
Johannes Berg46900292009-02-15 12:44:28 +0100876 int interval = IEEE80211_SCAN_INTERVAL;
877
878 if (time_after(jiffies, ifibss->ibss_join_req +
Johannes Berg55de9082012-07-26 17:24:39 +0200879 IEEE80211_IBSS_JOIN_TIMEOUT))
880 ieee80211_sta_create_ibss(sdata);
Johannes Berg46900292009-02-15 12:44:28 +0100881
Johannes Bergaf8cdcd2009-04-19 21:25:43 +0200882 mod_timer(&ifibss->timer,
883 round_jiffies(jiffies + interval));
Johannes Berg46900292009-02-15 12:44:28 +0100884 }
Johannes Berg46900292009-02-15 12:44:28 +0100885}
886
887static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
Johannes Bergc269a202011-02-14 12:20:22 +0100888 struct sk_buff *req)
Johannes Berg46900292009-02-15 12:44:28 +0100889{
Johannes Bergc269a202011-02-14 12:20:22 +0100890 struct ieee80211_mgmt *mgmt = (void *)req->data;
Johannes Berg46900292009-02-15 12:44:28 +0100891 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
892 struct ieee80211_local *local = sdata->local;
Johannes Bergc269a202011-02-14 12:20:22 +0100893 int tx_last_beacon, len = req->len;
Johannes Berg46900292009-02-15 12:44:28 +0100894 struct sk_buff *skb;
Johannes Bergc3ffeab2013-03-07 20:54:29 +0100895 struct beacon_data *presp;
Johannes Berg46900292009-02-15 12:44:28 +0100896 u8 *pos, *end;
897
Johannes Berg8d61ffa2013-05-10 12:32:47 +0200898 sdata_assert_lock(sdata);
Johannes Berg7a17a332010-07-21 11:30:27 +0200899
Johannes Berg40b275b2011-05-13 14:15:49 +0200900 presp = rcu_dereference_protected(ifibss->presp,
Johannes Berg8d61ffa2013-05-10 12:32:47 +0200901 lockdep_is_held(&sdata->wdev.mtx));
Johannes Berg40b275b2011-05-13 14:15:49 +0200902
Johannes Berg46900292009-02-15 12:44:28 +0100903 if (ifibss->state != IEEE80211_IBSS_MLME_JOINED ||
Johannes Berg40b275b2011-05-13 14:15:49 +0200904 len < 24 + 2 || !presp)
Johannes Berg46900292009-02-15 12:44:28 +0100905 return;
906
Johannes Berg24487982009-04-23 18:52:52 +0200907 tx_last_beacon = drv_tx_last_beacon(local);
Johannes Berg46900292009-02-15 12:44:28 +0100908
Johannes Bergbdcbd8e2012-06-22 11:29:50 +0200909 ibss_dbg(sdata,
910 "RX ProbeReq SA=%pM DA=%pM BSSID=%pM (tx_last_beacon=%d)\n",
911 mgmt->sa, mgmt->da, mgmt->bssid, tx_last_beacon);
Johannes Berg46900292009-02-15 12:44:28 +0100912
Felix Fietkau1ed76482011-03-24 19:46:18 +0100913 if (!tx_last_beacon && is_multicast_ether_addr(mgmt->da))
Johannes Berg46900292009-02-15 12:44:28 +0100914 return;
915
Joe Perchesb203ca32012-05-08 18:56:52 +0000916 if (!ether_addr_equal(mgmt->bssid, ifibss->bssid) &&
Felix Fietkau888d04d2012-03-01 15:22:09 +0100917 !is_broadcast_ether_addr(mgmt->bssid))
Johannes Berg46900292009-02-15 12:44:28 +0100918 return;
919
920 end = ((u8 *) mgmt) + len;
921 pos = mgmt->u.probe_req.variable;
922 if (pos[0] != WLAN_EID_SSID ||
923 pos + 2 + pos[1] > end) {
Johannes Bergbdcbd8e2012-06-22 11:29:50 +0200924 ibss_dbg(sdata, "Invalid SSID IE in ProbeReq from %pM\n",
925 mgmt->sa);
Johannes Berg46900292009-02-15 12:44:28 +0100926 return;
927 }
928 if (pos[1] != 0 &&
929 (pos[1] != ifibss->ssid_len ||
Benoit Papillault0da780c2010-02-05 01:21:03 +0100930 memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len))) {
Johannes Berg46900292009-02-15 12:44:28 +0100931 /* Ignore ProbeReq for foreign SSID */
932 return;
933 }
934
935 /* Reply with ProbeResp */
Johannes Bergc3ffeab2013-03-07 20:54:29 +0100936 skb = dev_alloc_skb(local->tx_headroom + presp->head_len);
Johannes Berg46900292009-02-15 12:44:28 +0100937 if (!skb)
938 return;
939
Johannes Bergc3ffeab2013-03-07 20:54:29 +0100940 skb_reserve(skb, local->tx_headroom);
941 memcpy(skb_put(skb, presp->head_len), presp->head, presp->head_len);
942
943 memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN);
944 ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa);
Johannes Berg62ae67b2009-11-18 18:42:05 +0100945 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
946 ieee80211_tx_skb(sdata, skb);
Johannes Berg46900292009-02-15 12:44:28 +0100947}
948
Emmanuel Grumbachd45c4172012-12-10 16:19:13 +0200949static
950void ieee80211_rx_mgmt_probe_beacon(struct ieee80211_sub_if_data *sdata,
951 struct ieee80211_mgmt *mgmt, size_t len,
952 struct ieee80211_rx_status *rx_status)
Johannes Berg46900292009-02-15 12:44:28 +0100953{
954 size_t baselen;
955 struct ieee802_11_elems elems;
956
Emmanuel Grumbachd45c4172012-12-10 16:19:13 +0200957 BUILD_BUG_ON(offsetof(typeof(mgmt->u.probe_resp), variable) !=
958 offsetof(typeof(mgmt->u.beacon), variable));
959
960 /*
961 * either beacon or probe_resp but the variable field is at the
962 * same offset
963 */
Johannes Berg46900292009-02-15 12:44:28 +0100964 baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
965 if (baselen > len)
966 return;
967
968 ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
Johannes Bergb2e506b2013-03-26 14:54:16 +0100969 false, &elems);
Johannes Berg46900292009-02-15 12:44:28 +0100970
Emmanuel Grumbachd45c4172012-12-10 16:19:13 +0200971 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
Johannes Berg46900292009-02-15 12:44:28 +0100972}
973
Johannes Berg1fa57d02010-06-10 10:21:32 +0200974void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
975 struct sk_buff *skb)
Johannes Berg46900292009-02-15 12:44:28 +0100976{
977 struct ieee80211_rx_status *rx_status;
978 struct ieee80211_mgmt *mgmt;
979 u16 fc;
980
Johannes Bergf1d58c22009-06-17 13:13:00 +0200981 rx_status = IEEE80211_SKB_RXCB(skb);
Johannes Berg46900292009-02-15 12:44:28 +0100982 mgmt = (struct ieee80211_mgmt *) skb->data;
983 fc = le16_to_cpu(mgmt->frame_control);
984
Johannes Berg8d61ffa2013-05-10 12:32:47 +0200985 sdata_lock(sdata);
Johannes Berg7a17a332010-07-21 11:30:27 +0200986
Tim Harveyc926d002010-12-09 10:43:13 -0800987 if (!sdata->u.ibss.ssid_len)
988 goto mgmt_out; /* not ready to merge yet */
989
Johannes Berg46900292009-02-15 12:44:28 +0100990 switch (fc & IEEE80211_FCTL_STYPE) {
991 case IEEE80211_STYPE_PROBE_REQ:
Johannes Bergc269a202011-02-14 12:20:22 +0100992 ieee80211_rx_mgmt_probe_req(sdata, skb);
Johannes Berg46900292009-02-15 12:44:28 +0100993 break;
994 case IEEE80211_STYPE_PROBE_RESP:
Johannes Berg46900292009-02-15 12:44:28 +0100995 case IEEE80211_STYPE_BEACON:
Emmanuel Grumbachd45c4172012-12-10 16:19:13 +0200996 ieee80211_rx_mgmt_probe_beacon(sdata, mgmt, skb->len,
997 rx_status);
Johannes Berg46900292009-02-15 12:44:28 +0100998 break;
999 case IEEE80211_STYPE_AUTH:
1000 ieee80211_rx_mgmt_auth_ibss(sdata, mgmt, skb->len);
1001 break;
Antonio Quartulli2cc59e72012-09-07 13:28:53 +02001002 case IEEE80211_STYPE_DEAUTH:
1003 ieee80211_rx_mgmt_deauth_ibss(sdata, mgmt, skb->len);
1004 break;
Johannes Berg46900292009-02-15 12:44:28 +01001005 }
Johannes Berg7a17a332010-07-21 11:30:27 +02001006
Tim Harveyc926d002010-12-09 10:43:13 -08001007 mgmt_out:
Johannes Berg8d61ffa2013-05-10 12:32:47 +02001008 sdata_unlock(sdata);
Johannes Berg46900292009-02-15 12:44:28 +01001009}
1010
Johannes Berg1fa57d02010-06-10 10:21:32 +02001011void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
Johannes Berg46900292009-02-15 12:44:28 +01001012{
Johannes Berg1fa57d02010-06-10 10:21:32 +02001013 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
Johannes Berg8bf11d82011-12-15 11:17:37 +01001014 struct sta_info *sta;
Johannes Berg46900292009-02-15 12:44:28 +01001015
Johannes Berg8d61ffa2013-05-10 12:32:47 +02001016 sdata_lock(sdata);
Johannes Berg7a17a332010-07-21 11:30:27 +02001017
1018 /*
1019 * Work could be scheduled after scan or similar
1020 * when we aren't even joined (or trying) with a
1021 * network.
1022 */
1023 if (!ifibss->ssid_len)
1024 goto out;
Johannes Berg46900292009-02-15 12:44:28 +01001025
Johannes Berg8bf11d82011-12-15 11:17:37 +01001026 spin_lock_bh(&ifibss->incomplete_lock);
1027 while (!list_empty(&ifibss->incomplete_stations)) {
1028 sta = list_first_entry(&ifibss->incomplete_stations,
1029 struct sta_info, list);
1030 list_del(&sta->list);
1031 spin_unlock_bh(&ifibss->incomplete_lock);
1032
Antonio Quartulli52874a52013-06-18 14:20:40 +02001033 ieee80211_ibss_finish_sta(sta);
Johannes Berg8bf11d82011-12-15 11:17:37 +01001034 rcu_read_unlock();
1035 spin_lock_bh(&ifibss->incomplete_lock);
1036 }
1037 spin_unlock_bh(&ifibss->incomplete_lock);
1038
Johannes Berg46900292009-02-15 12:44:28 +01001039 switch (ifibss->state) {
1040 case IEEE80211_IBSS_MLME_SEARCH:
1041 ieee80211_sta_find_ibss(sdata);
1042 break;
1043 case IEEE80211_IBSS_MLME_JOINED:
1044 ieee80211_sta_merge_ibss(sdata);
1045 break;
1046 default:
1047 WARN_ON(1);
1048 break;
1049 }
Johannes Berg46900292009-02-15 12:44:28 +01001050
Johannes Berg7a17a332010-07-21 11:30:27 +02001051 out:
Johannes Berg8d61ffa2013-05-10 12:32:47 +02001052 sdata_unlock(sdata);
Johannes Berg3a4d4aa2010-05-26 16:41:40 +02001053}
1054
Johannes Berg46900292009-02-15 12:44:28 +01001055static void ieee80211_ibss_timer(unsigned long data)
1056{
1057 struct ieee80211_sub_if_data *sdata =
1058 (struct ieee80211_sub_if_data *) data;
Johannes Berg46900292009-02-15 12:44:28 +01001059
Stanislaw Gruszkaa6182942013-02-28 10:55:28 +01001060 ieee80211_queue_work(&sdata->local->hw, &sdata->work);
Johannes Berg46900292009-02-15 12:44:28 +01001061}
1062
1063void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
1064{
1065 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
1066
Johannes Berg46900292009-02-15 12:44:28 +01001067 setup_timer(&ifibss->timer, ieee80211_ibss_timer,
1068 (unsigned long) sdata);
Johannes Berg8bf11d82011-12-15 11:17:37 +01001069 INIT_LIST_HEAD(&ifibss->incomplete_stations);
1070 spin_lock_init(&ifibss->incomplete_lock);
Johannes Berg46900292009-02-15 12:44:28 +01001071}
1072
1073/* scan finished notification */
1074void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
1075{
Johannes Bergaf8cdcd2009-04-19 21:25:43 +02001076 struct ieee80211_sub_if_data *sdata;
Johannes Berg46900292009-02-15 12:44:28 +01001077
Johannes Berg29b4a4f2009-04-21 00:30:49 +02001078 mutex_lock(&local->iflist_mtx);
1079 list_for_each_entry(sdata, &local->interfaces, list) {
Johannes Berg9607e6b2009-12-23 13:15:31 +01001080 if (!ieee80211_sdata_running(sdata))
Johannes Berg0e41f712009-04-23 11:48:56 +02001081 continue;
Johannes Bergaf8cdcd2009-04-19 21:25:43 +02001082 if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
1083 continue;
1084 sdata->u.ibss.last_scan_completed = jiffies;
Johannes Berg7a17a332010-07-21 11:30:27 +02001085 ieee80211_queue_work(&local->hw, &sdata->work);
Johannes Berg46900292009-02-15 12:44:28 +01001086 }
Johannes Berg29b4a4f2009-04-21 00:30:49 +02001087 mutex_unlock(&local->iflist_mtx);
Johannes Berg46900292009-02-15 12:44:28 +01001088}
1089
Johannes Bergaf8cdcd2009-04-19 21:25:43 +02001090int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
1091 struct cfg80211_ibss_params *params)
1092{
Simon Wunderlichff3cc5f2011-11-30 16:56:33 +01001093 u32 changed = 0;
Simon Wunderlich2103dec2013-07-08 16:55:53 +02001094 u32 rate_flags;
1095 struct ieee80211_supported_band *sband;
1096 int i;
Johannes Bergaf8cdcd2009-04-19 21:25:43 +02001097
Johannes Bergaf8cdcd2009-04-19 21:25:43 +02001098 if (params->bssid) {
1099 memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN);
1100 sdata->u.ibss.fixed_bssid = true;
1101 } else
1102 sdata->u.ibss.fixed_bssid = false;
1103
Johannes Bergfffd0932009-07-08 14:22:54 +02001104 sdata->u.ibss.privacy = params->privacy;
Antonio Quartulli267335d2012-01-31 20:25:47 +01001105 sdata->u.ibss.control_port = params->control_port;
Teemu Paasikivifbd2c8d2010-06-14 12:55:31 +03001106 sdata->u.ibss.basic_rates = params->basic_rates;
Simon Wunderlich2103dec2013-07-08 16:55:53 +02001107
1108 /* fix basic_rates if channel does not support these rates */
1109 rate_flags = ieee80211_chandef_rate_flags(&params->chandef);
1110 sband = sdata->local->hw.wiphy->bands[params->chandef.chan->band];
1111 for (i = 0; i < sband->n_bitrates; i++) {
1112 if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
1113 sdata->u.ibss.basic_rates &= ~BIT(i);
1114 }
Felix Fietkaudd5b4cc2010-11-22 20:58:24 +01001115 memcpy(sdata->vif.bss_conf.mcast_rate, params->mcast_rate,
1116 sizeof(params->mcast_rate));
Johannes Bergfffd0932009-07-08 14:22:54 +02001117
Johannes Berg57c4d7b2009-04-23 16:10:04 +02001118 sdata->vif.bss_conf.beacon_int = params->beacon_interval;
1119
Simon Wunderlich3aede782013-05-16 13:00:36 +02001120 sdata->u.ibss.chandef = params->chandef;
Johannes Bergaf8cdcd2009-04-19 21:25:43 +02001121 sdata->u.ibss.fixed_channel = params->channel_fixed;
1122
1123 if (params->ie) {
1124 sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len,
1125 GFP_KERNEL);
1126 if (sdata->u.ibss.ie)
1127 sdata->u.ibss.ie_len = params->ie_len;
1128 }
1129
Johannes Bergaf8cdcd2009-04-19 21:25:43 +02001130 sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
1131 sdata->u.ibss.ibss_join_req = jiffies;
1132
Antonio Quartullibadecb02012-10-26 18:54:25 +02001133 memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);
Johannes Berg0e41f712009-04-23 11:48:56 +02001134 sdata->u.ibss.ssid_len = params->ssid_len;
1135
Simon Wunderlich822854b2013-06-28 10:39:59 +02001136 memcpy(&sdata->u.ibss.ht_capa, &params->ht_capa,
1137 sizeof(sdata->u.ibss.ht_capa));
1138 memcpy(&sdata->u.ibss.ht_capa_mask, &params->ht_capa_mask,
1139 sizeof(sdata->u.ibss.ht_capa_mask));
1140
Simon Wunderlichff3cc5f2011-11-30 16:56:33 +01001141 /*
1142 * 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is
1143 * reserved, but an HT STA shall protect HT transmissions as though
1144 * the HT Protection field were set to non-HT mixed mode.
1145 *
1146 * In an IBSS, the RIFS Mode field of the HT Operation element is
1147 * also reserved, but an HT STA shall operate as though this field
1148 * were set to 1.
1149 */
1150
1151 sdata->vif.bss_conf.ht_operation_mode |=
1152 IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED
1153 | IEEE80211_HT_PARAM_RIFS_MODE;
1154
1155 changed |= BSS_CHANGED_HT;
1156 ieee80211_bss_info_change_notify(sdata, changed);
1157
Johannes Berg04ecd252012-09-11 14:34:12 +02001158 sdata->smps_mode = IEEE80211_SMPS_OFF;
1159 sdata->needed_rx_chains = sdata->local->rx_chains;
1160
Johannes Berg64592c82010-06-10 10:21:31 +02001161 ieee80211_queue_work(&sdata->local->hw, &sdata->work);
Johannes Bergaf8cdcd2009-04-19 21:25:43 +02001162
1163 return 0;
1164}
1165
1166int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
1167{
Teemu Paasikivi5ea096c2010-06-14 12:55:33 +03001168 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
1169 struct ieee80211_local *local = sdata->local;
1170 struct cfg80211_bss *cbss;
1171 u16 capability;
Johannes Berg7a17a332010-07-21 11:30:27 +02001172 int active_ibss;
Johannes Berg8bf11d82011-12-15 11:17:37 +01001173 struct sta_info *sta;
Johannes Bergc3ffeab2013-03-07 20:54:29 +01001174 struct beacon_data *presp;
Johannes Berg7a17a332010-07-21 11:30:27 +02001175
Teemu Paasikivi5ea096c2010-06-14 12:55:33 +03001176 active_ibss = ieee80211_sta_active_ibss(sdata);
1177
1178 if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) {
1179 capability = WLAN_CAPABILITY_IBSS;
1180
1181 if (ifibss->privacy)
1182 capability |= WLAN_CAPABILITY_PRIVACY;
1183
Simon Wunderlich3aede782013-05-16 13:00:36 +02001184 cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->chandef.chan,
Teemu Paasikivi5ea096c2010-06-14 12:55:33 +03001185 ifibss->bssid, ifibss->ssid,
1186 ifibss->ssid_len, WLAN_CAPABILITY_IBSS |
1187 WLAN_CAPABILITY_PRIVACY,
1188 capability);
1189
1190 if (cbss) {
1191 cfg80211_unlink_bss(local->hw.wiphy, cbss);
Johannes Berg5b112d32013-02-01 01:49:58 +01001192 cfg80211_put_bss(local->hw.wiphy, cbss);
Teemu Paasikivi5ea096c2010-06-14 12:55:33 +03001193 }
1194 }
Johannes Bergaf8cdcd2009-04-19 21:25:43 +02001195
Simon Wunderlichb78a4932012-11-13 18:43:03 +01001196 ifibss->state = IEEE80211_IBSS_MLME_SEARCH;
1197 memset(ifibss->bssid, 0, ETH_ALEN);
1198 ifibss->ssid_len = 0;
1199
Johannes Bergb998e8b2012-12-13 23:07:46 +01001200 sta_info_flush(sdata);
Johannes Berg8bf11d82011-12-15 11:17:37 +01001201
1202 spin_lock_bh(&ifibss->incomplete_lock);
1203 while (!list_empty(&ifibss->incomplete_stations)) {
1204 sta = list_first_entry(&ifibss->incomplete_stations,
1205 struct sta_info, list);
1206 list_del(&sta->list);
1207 spin_unlock_bh(&ifibss->incomplete_lock);
1208
1209 sta_info_free(local, sta);
1210 spin_lock_bh(&ifibss->incomplete_lock);
1211 }
1212 spin_unlock_bh(&ifibss->incomplete_lock);
1213
Eliad Peller86a2ea42011-11-08 15:36:59 +02001214 netif_carrier_off(sdata->dev);
Johannes Bergaf8cdcd2009-04-19 21:25:43 +02001215
1216 /* remove beacon */
1217 kfree(sdata->u.ibss.ie);
Johannes Bergc3ffeab2013-03-07 20:54:29 +01001218 presp = rcu_dereference_protected(ifibss->presp,
Johannes Berg8d61ffa2013-05-10 12:32:47 +02001219 lockdep_is_held(&sdata->wdev.mtx));
Stephen Hemmingera9b3cd72011-08-01 16:19:00 +00001220 RCU_INIT_POINTER(sdata->u.ibss.presp, NULL);
Simon Wunderlich822854b2013-06-28 10:39:59 +02001221
1222 /* on the next join, re-program HT parameters */
1223 memset(&ifibss->ht_capa, 0, sizeof(ifibss->ht_capa));
1224 memset(&ifibss->ht_capa_mask, 0, sizeof(ifibss->ht_capa_mask));
1225
Johannes Berg8fc214b2010-04-28 17:40:43 +02001226 sdata->vif.bss_conf.ibss_joined = false;
Sujith Manoharanc13a7652012-10-12 17:35:45 +05301227 sdata->vif.bss_conf.ibss_creator = false;
Johannes Bergd6a83222012-12-14 14:06:28 +01001228 sdata->vif.bss_conf.enable_beacon = false;
Marek Puzyniak0ca54f62013-04-10 13:19:13 +02001229 sdata->vif.bss_conf.ssid_len = 0;
Johannes Bergd6a83222012-12-14 14:06:28 +01001230 clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
Johannes Berg8fc214b2010-04-28 17:40:43 +02001231 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
1232 BSS_CHANGED_IBSS);
Johannes Bergaf8cdcd2009-04-19 21:25:43 +02001233 synchronize_rcu();
Johannes Bergc3ffeab2013-03-07 20:54:29 +01001234 kfree(presp);
Johannes Bergaf8cdcd2009-04-19 21:25:43 +02001235
Johannes Berg35f20c12010-06-10 10:21:30 +02001236 skb_queue_purge(&sdata->skb_queue);
Johannes Berg5cff20e2009-04-29 12:26:17 +02001237
Johannes Bergbc05d192010-07-21 10:52:40 +02001238 del_timer_sync(&sdata->u.ibss.timer);
Johannes Berg7a17a332010-07-21 11:30:27 +02001239
Johannes Bergaf8cdcd2009-04-19 21:25:43 +02001240 return 0;
1241}