ibss.c revision 28f333666ea766fdfb25de3783ff56cd2d1c51f0
1/*
2 * Some IBSS support code for cfg80211.
3 *
4 * Copyright 2009	Johannes Berg <johannes@sipsolutions.net>
5 */
6
7#include <linux/etherdevice.h>
8#include <linux/if_arp.h>
9#include <linux/slab.h>
10#include <linux/export.h>
11#include <net/cfg80211.h>
12#include "wext-compat.h"
13#include "nl80211.h"
14
15
16void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
17{
18	struct wireless_dev *wdev = dev->ieee80211_ptr;
19	struct cfg80211_bss *bss;
20#ifdef CONFIG_CFG80211_WEXT
21	union iwreq_data wrqu;
22#endif
23
24	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
25		return;
26
27	if (!wdev->ssid_len)
28		return;
29
30	bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
31			       wdev->ssid, wdev->ssid_len,
32			       WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
33
34	if (WARN_ON(!bss))
35		return;
36
37	if (wdev->current_bss) {
38		cfg80211_unhold_bss(wdev->current_bss);
39		cfg80211_put_bss(&wdev->current_bss->pub);
40	}
41
42	cfg80211_hold_bss(bss_from_pub(bss));
43	wdev->current_bss = bss_from_pub(bss);
44
45	wdev->sme_state = CFG80211_SME_CONNECTED;
46	cfg80211_upload_connect_keys(wdev);
47
48	nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid,
49				GFP_KERNEL);
50#ifdef CONFIG_CFG80211_WEXT
51	memset(&wrqu, 0, sizeof(wrqu));
52	memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
53	wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
54#endif
55}
56
57void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
58{
59	struct wireless_dev *wdev = dev->ieee80211_ptr;
60	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
61	struct cfg80211_event *ev;
62	unsigned long flags;
63
64	CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING);
65
66	ev = kzalloc(sizeof(*ev), gfp);
67	if (!ev)
68		return;
69
70	ev->type = EVENT_IBSS_JOINED;
71	memcpy(ev->cr.bssid, bssid, ETH_ALEN);
72
73	spin_lock_irqsave(&wdev->event_lock, flags);
74	list_add_tail(&ev->list, &wdev->event_list);
75	spin_unlock_irqrestore(&wdev->event_lock, flags);
76	queue_work(cfg80211_wq, &rdev->event_work);
77}
78EXPORT_SYMBOL(cfg80211_ibss_joined);
79
80int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
81			 struct net_device *dev,
82			 struct cfg80211_ibss_params *params,
83			 struct cfg80211_cached_keys *connkeys)
84{
85	struct wireless_dev *wdev = dev->ieee80211_ptr;
86	int err;
87
88	ASSERT_WDEV_LOCK(wdev);
89
90	if (wdev->ssid_len)
91		return -EALREADY;
92
93	if (!params->basic_rates) {
94		/*
95		* If no rates were explicitly configured,
96		* use the mandatory rate set for 11b or
97		* 11a for maximum compatibility.
98		*/
99		struct ieee80211_supported_band *sband =
100			rdev->wiphy.bands[params->channel->band];
101		int j;
102		u32 flag = params->channel->band == IEEE80211_BAND_5GHZ ?
103			IEEE80211_RATE_MANDATORY_A :
104			IEEE80211_RATE_MANDATORY_B;
105
106		for (j = 0; j < sband->n_bitrates; j++) {
107			if (sband->bitrates[j].flags & flag)
108				params->basic_rates |= BIT(j);
109		}
110	}
111
112	if (WARN_ON(wdev->connect_keys))
113		kfree(wdev->connect_keys);
114	wdev->connect_keys = connkeys;
115
116#ifdef CONFIG_CFG80211_WEXT
117	wdev->wext.ibss.channel = params->channel;
118#endif
119	wdev->sme_state = CFG80211_SME_CONNECTING;
120	err = rdev->ops->join_ibss(&rdev->wiphy, dev, params);
121	if (err) {
122		wdev->connect_keys = NULL;
123		wdev->sme_state = CFG80211_SME_IDLE;
124		return err;
125	}
126
127	memcpy(wdev->ssid, params->ssid, params->ssid_len);
128	wdev->ssid_len = params->ssid_len;
129
130	return 0;
131}
132
133int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
134		       struct net_device *dev,
135		       struct cfg80211_ibss_params *params,
136		       struct cfg80211_cached_keys *connkeys)
137{
138	struct wireless_dev *wdev = dev->ieee80211_ptr;
139	int err;
140
141	mutex_lock(&rdev->devlist_mtx);
142	wdev_lock(wdev);
143	err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
144	wdev_unlock(wdev);
145	mutex_unlock(&rdev->devlist_mtx);
146
147	return err;
148}
149
150static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
151{
152	struct wireless_dev *wdev = dev->ieee80211_ptr;
153	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
154	int i;
155
156	ASSERT_WDEV_LOCK(wdev);
157
158	kfree(wdev->connect_keys);
159	wdev->connect_keys = NULL;
160
161	/*
162	 * Delete all the keys ... pairwise keys can't really
163	 * exist any more anyway, but default keys might.
164	 */
165	if (rdev->ops->del_key)
166		for (i = 0; i < 6; i++)
167			rdev->ops->del_key(wdev->wiphy, dev, i, false, NULL);
168
169	if (wdev->current_bss) {
170		cfg80211_unhold_bss(wdev->current_bss);
171		cfg80211_put_bss(&wdev->current_bss->pub);
172	}
173
174	wdev->current_bss = NULL;
175	wdev->sme_state = CFG80211_SME_IDLE;
176	wdev->ssid_len = 0;
177#ifdef CONFIG_CFG80211_WEXT
178	if (!nowext)
179		wdev->wext.ibss.ssid_len = 0;
180#endif
181}
182
183void cfg80211_clear_ibss(struct net_device *dev, bool nowext)
184{
185	struct wireless_dev *wdev = dev->ieee80211_ptr;
186
187	wdev_lock(wdev);
188	__cfg80211_clear_ibss(dev, nowext);
189	wdev_unlock(wdev);
190}
191
192int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
193			  struct net_device *dev, bool nowext)
194{
195	struct wireless_dev *wdev = dev->ieee80211_ptr;
196	int err;
197
198	ASSERT_WDEV_LOCK(wdev);
199
200	if (!wdev->ssid_len)
201		return -ENOLINK;
202
203	err = rdev->ops->leave_ibss(&rdev->wiphy, dev);
204
205	if (err)
206		return err;
207
208	__cfg80211_clear_ibss(dev, nowext);
209
210	return 0;
211}
212
213int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
214			struct net_device *dev, bool nowext)
215{
216	struct wireless_dev *wdev = dev->ieee80211_ptr;
217	int err;
218
219	wdev_lock(wdev);
220	err = __cfg80211_leave_ibss(rdev, dev, nowext);
221	wdev_unlock(wdev);
222
223	return err;
224}
225
226#ifdef CONFIG_CFG80211_WEXT
227int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
228			    struct wireless_dev *wdev)
229{
230	struct cfg80211_cached_keys *ck = NULL;
231	enum ieee80211_band band;
232	int i, err;
233
234	ASSERT_WDEV_LOCK(wdev);
235
236	if (!wdev->wext.ibss.beacon_interval)
237		wdev->wext.ibss.beacon_interval = 100;
238
239	/* try to find an IBSS channel if none requested ... */
240	if (!wdev->wext.ibss.channel) {
241		for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
242			struct ieee80211_supported_band *sband;
243			struct ieee80211_channel *chan;
244
245			sband = rdev->wiphy.bands[band];
246			if (!sband)
247				continue;
248
249			for (i = 0; i < sband->n_channels; i++) {
250				chan = &sband->channels[i];
251				if (chan->flags & IEEE80211_CHAN_NO_IBSS)
252					continue;
253				if (chan->flags & IEEE80211_CHAN_DISABLED)
254					continue;
255				wdev->wext.ibss.channel = chan;
256				break;
257			}
258
259			if (wdev->wext.ibss.channel)
260				break;
261		}
262
263		if (!wdev->wext.ibss.channel)
264			return -EINVAL;
265	}
266
267	/* don't join -- SSID is not there */
268	if (!wdev->wext.ibss.ssid_len)
269		return 0;
270
271	if (!netif_running(wdev->netdev))
272		return 0;
273
274	if (wdev->wext.keys) {
275		wdev->wext.keys->def = wdev->wext.default_key;
276		wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
277	}
278
279	wdev->wext.ibss.privacy = wdev->wext.default_key != -1;
280
281	if (wdev->wext.keys) {
282		ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL);
283		if (!ck)
284			return -ENOMEM;
285		for (i = 0; i < 6; i++)
286			ck->params[i].key = ck->data[i];
287	}
288	err = __cfg80211_join_ibss(rdev, wdev->netdev,
289				   &wdev->wext.ibss, ck);
290	if (err)
291		kfree(ck);
292
293	return err;
294}
295
296int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
297			       struct iw_request_info *info,
298			       struct iw_freq *wextfreq, char *extra)
299{
300	struct wireless_dev *wdev = dev->ieee80211_ptr;
301	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
302	struct ieee80211_channel *chan = NULL;
303	int err, freq;
304
305	/* call only for ibss! */
306	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
307		return -EINVAL;
308
309	if (!rdev->ops->join_ibss)
310		return -EOPNOTSUPP;
311
312	freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
313	if (freq < 0)
314		return freq;
315
316	if (freq) {
317		chan = ieee80211_get_channel(wdev->wiphy, freq);
318		if (!chan)
319			return -EINVAL;
320		if (chan->flags & IEEE80211_CHAN_NO_IBSS ||
321		    chan->flags & IEEE80211_CHAN_DISABLED)
322			return -EINVAL;
323	}
324
325	if (wdev->wext.ibss.channel == chan)
326		return 0;
327
328	wdev_lock(wdev);
329	err = 0;
330	if (wdev->ssid_len)
331		err = __cfg80211_leave_ibss(rdev, dev, true);
332	wdev_unlock(wdev);
333
334	if (err)
335		return err;
336
337	if (chan) {
338		wdev->wext.ibss.channel = chan;
339		wdev->wext.ibss.channel_fixed = true;
340	} else {
341		/* cfg80211_ibss_wext_join will pick one if needed */
342		wdev->wext.ibss.channel_fixed = false;
343	}
344
345	mutex_lock(&rdev->devlist_mtx);
346	wdev_lock(wdev);
347	err = cfg80211_ibss_wext_join(rdev, wdev);
348	wdev_unlock(wdev);
349	mutex_unlock(&rdev->devlist_mtx);
350
351	return err;
352}
353
354int cfg80211_ibss_wext_giwfreq(struct net_device *dev,
355			       struct iw_request_info *info,
356			       struct iw_freq *freq, char *extra)
357{
358	struct wireless_dev *wdev = dev->ieee80211_ptr;
359	struct ieee80211_channel *chan = NULL;
360
361	/* call only for ibss! */
362	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
363		return -EINVAL;
364
365	wdev_lock(wdev);
366	if (wdev->current_bss)
367		chan = wdev->current_bss->pub.channel;
368	else if (wdev->wext.ibss.channel)
369		chan = wdev->wext.ibss.channel;
370	wdev_unlock(wdev);
371
372	if (chan) {
373		freq->m = chan->center_freq;
374		freq->e = 6;
375		return 0;
376	}
377
378	/* no channel if not joining */
379	return -EINVAL;
380}
381
382int cfg80211_ibss_wext_siwessid(struct net_device *dev,
383				struct iw_request_info *info,
384				struct iw_point *data, char *ssid)
385{
386	struct wireless_dev *wdev = dev->ieee80211_ptr;
387	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
388	size_t len = data->length;
389	int err;
390
391	/* call only for ibss! */
392	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
393		return -EINVAL;
394
395	if (!rdev->ops->join_ibss)
396		return -EOPNOTSUPP;
397
398	wdev_lock(wdev);
399	err = 0;
400	if (wdev->ssid_len)
401		err = __cfg80211_leave_ibss(rdev, dev, true);
402	wdev_unlock(wdev);
403
404	if (err)
405		return err;
406
407	/* iwconfig uses nul termination in SSID.. */
408	if (len > 0 && ssid[len - 1] == '\0')
409		len--;
410
411	wdev->wext.ibss.ssid = wdev->ssid;
412	memcpy(wdev->wext.ibss.ssid, ssid, len);
413	wdev->wext.ibss.ssid_len = len;
414
415	mutex_lock(&rdev->devlist_mtx);
416	wdev_lock(wdev);
417	err = cfg80211_ibss_wext_join(rdev, wdev);
418	wdev_unlock(wdev);
419	mutex_unlock(&rdev->devlist_mtx);
420
421	return err;
422}
423
424int cfg80211_ibss_wext_giwessid(struct net_device *dev,
425				struct iw_request_info *info,
426				struct iw_point *data, char *ssid)
427{
428	struct wireless_dev *wdev = dev->ieee80211_ptr;
429
430	/* call only for ibss! */
431	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
432		return -EINVAL;
433
434	data->flags = 0;
435
436	wdev_lock(wdev);
437	if (wdev->ssid_len) {
438		data->flags = 1;
439		data->length = wdev->ssid_len;
440		memcpy(ssid, wdev->ssid, data->length);
441	} else if (wdev->wext.ibss.ssid && wdev->wext.ibss.ssid_len) {
442		data->flags = 1;
443		data->length = wdev->wext.ibss.ssid_len;
444		memcpy(ssid, wdev->wext.ibss.ssid, data->length);
445	}
446	wdev_unlock(wdev);
447
448	return 0;
449}
450
451int cfg80211_ibss_wext_siwap(struct net_device *dev,
452			     struct iw_request_info *info,
453			     struct sockaddr *ap_addr, char *extra)
454{
455	struct wireless_dev *wdev = dev->ieee80211_ptr;
456	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
457	u8 *bssid = ap_addr->sa_data;
458	int err;
459
460	/* call only for ibss! */
461	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
462		return -EINVAL;
463
464	if (!rdev->ops->join_ibss)
465		return -EOPNOTSUPP;
466
467	if (ap_addr->sa_family != ARPHRD_ETHER)
468		return -EINVAL;
469
470	/* automatic mode */
471	if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
472		bssid = NULL;
473
474	/* both automatic */
475	if (!bssid && !wdev->wext.ibss.bssid)
476		return 0;
477
478	/* fixed already - and no change */
479	if (wdev->wext.ibss.bssid && bssid &&
480	    ether_addr_equal(bssid, wdev->wext.ibss.bssid))
481		return 0;
482
483	wdev_lock(wdev);
484	err = 0;
485	if (wdev->ssid_len)
486		err = __cfg80211_leave_ibss(rdev, dev, true);
487	wdev_unlock(wdev);
488
489	if (err)
490		return err;
491
492	if (bssid) {
493		memcpy(wdev->wext.bssid, bssid, ETH_ALEN);
494		wdev->wext.ibss.bssid = wdev->wext.bssid;
495	} else
496		wdev->wext.ibss.bssid = NULL;
497
498	mutex_lock(&rdev->devlist_mtx);
499	wdev_lock(wdev);
500	err = cfg80211_ibss_wext_join(rdev, wdev);
501	wdev_unlock(wdev);
502	mutex_unlock(&rdev->devlist_mtx);
503
504	return err;
505}
506
507int cfg80211_ibss_wext_giwap(struct net_device *dev,
508			     struct iw_request_info *info,
509			     struct sockaddr *ap_addr, char *extra)
510{
511	struct wireless_dev *wdev = dev->ieee80211_ptr;
512
513	/* call only for ibss! */
514	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
515		return -EINVAL;
516
517	ap_addr->sa_family = ARPHRD_ETHER;
518
519	wdev_lock(wdev);
520	if (wdev->current_bss)
521		memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN);
522	else if (wdev->wext.ibss.bssid)
523		memcpy(ap_addr->sa_data, wdev->wext.ibss.bssid, ETH_ALEN);
524	else
525		memset(ap_addr->sa_data, 0, ETH_ALEN);
526
527	wdev_unlock(wdev);
528
529	return 0;
530}
531#endif
532