~ubuntu-branches/ubuntu/natty/linux-backports-modules-2.6.38/natty-proposed

« back to all changes in this revision

Viewing changes to updates/cw-2.6.39/net/wireless/ibss.c

  • Committer: Bazaar Package Importer
  • Author(s): Tim Gardner, Tim Gardner
  • Date: 2011-06-08 10:44:09 UTC
  • Revision ID: james.westby@ubuntu.com-20110608104409-fnl8carkdo15bwsz
Tags: 2.6.38-10.6
[ Tim Gardner ]

Shorten compat-wireless package name to cw to accomodate
CDROM file name length restrictions.

Show diffs side-by-side

added added

removed removed

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