~ubuntu-branches/ubuntu/lucid/ndiswrapper/lucid

« back to all changes in this revision

Viewing changes to driver/iw_ndis.c

  • Committer: Bazaar Package Importer
  • Author(s): Andres Salomon
  • Date: 2005-01-09 19:40:16 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050109194016-q0wfc6kf43uog0bb
Tags: 0.12+1.0rc2-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
 *  GNU General Public License for more details.
13
13
 *
14
14
 */
 
15
 
 
16
#include <linux/version.h>
15
17
#include <linux/wireless.h>
16
18
#include <linux/netdevice.h>
17
19
#include <linux/etherdevice.h>
18
20
#include <linux/ethtool.h>
19
21
#include <linux/if_arp.h>
 
22
#include <linux/usb.h>
 
23
#include <linux/random.h>
 
24
 
20
25
#include <net/iw_handler.h>
21
26
#include <linux/rtnetlink.h>
22
27
#include <asm/uaccess.h>
23
28
 
24
29
#include "iw_ndis.h"
 
30
#include "wrapper.h"
25
31
 
26
32
static int freq_chan[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
27
33
                           2447, 2452, 2457, 2462, 2467, 2472, 2484 };
28
34
 
29
 
 
30
35
int set_essid(struct ndis_handle *handle, const char *ssid, int ssid_len)
31
36
{
32
 
        unsigned int res, written, needed;
 
37
        unsigned int res;
33
38
        struct ndis_essid req;
34
39
 
35
40
        memset(&req, 0, sizeof(req));
36
41
        
37
42
        if (ssid_len == 0)
38
43
                req.length = 0;
39
 
        else
40
 
        {
 
44
        else {
41
45
                if (ssid_len > (IW_ESSID_MAX_SIZE + 1))
42
46
                        return -EINVAL;
43
47
 
44
48
                req.length = ssid_len;
45
49
                memcpy(&req.essid, ssid, req.length);
46
50
                req.essid[req.length] = 0;
47
 
                DBGTRACE("ssid = '%s'", req.essid);
 
51
                DBGTRACE1("ssid = '%s'", req.essid);
48
52
        }
49
53
        
50
 
        res = dosetinfo(handle, NDIS_OID_ESSID, (char*)&req, sizeof(req),
51
 
                        &written, &needed);
 
54
        res = miniport_set_info(handle, NDIS_OID_ESSID, (char*)&req,
 
55
                                sizeof(req));
52
56
        if (res)
53
57
                WARNING("setting essid failed (%08X)", res); 
54
58
 
67
71
        if (wrqu->essid.flags)
68
72
                wrqu->essid.length--;
69
73
 
70
 
        /* when 'iwconfig iface essid off' is called, we actually set
71
 
         * an impossible essid, which will disassociate without having
72
 
         * to call NDIS_OID_DISASSOCIATE, which also turns off the radio
73
 
         * some cards don't come back when a new essid is given
74
 
         */
75
 
 
76
74
        if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
77
75
                TRACEEXIT1(return -EINVAL);
78
76
 
87
85
                        union iwreq_data *wrqu, char *extra)
88
86
{
89
87
        struct ndis_handle *handle = dev->priv; 
90
 
        unsigned int res, written, needed;
 
88
        unsigned int res;
91
89
        struct ndis_essid req;
92
90
 
93
91
        TRACEENTER1("%s", "");
94
92
        memset(&req, 0, sizeof(req));
95
 
        res = doquery(handle, NDIS_OID_ESSID, (char*)&req, sizeof(req),
96
 
                      &written, &needed);
 
93
        res = miniport_query_info(handle, NDIS_OID_ESSID, (char*)&req,
 
94
                                  sizeof(req));
97
95
        if (res)
98
96
                WARNING("getting essid failed (%08X)", res);
99
97
 
109
107
 
110
108
int set_mode(struct ndis_handle *handle, enum op_mode mode)
111
109
{
112
 
        int res;
 
110
        unsigned int res, i;
113
111
 
114
112
        TRACEENTER1("%s", "");
115
113
 
116
 
        res = set_int(handle, NDIS_OID_MODE, mode);
117
 
        if (res == NDIS_STATUS_INVALID_DATA)
118
 
        {
 
114
        res = miniport_set_int(handle, NDIS_OID_MODE, mode);
 
115
        if (res == NDIS_STATUS_INVALID_DATA) {
119
116
                WARNING("setting operating mode failed (%08X)", res); 
120
117
                TRACEEXIT1(return -EINVAL);
121
118
        }
122
119
 
 
120
        for (i = 0; i < MAX_ENCR_KEYS; i++)
 
121
                handle->encr_info.keys[i].length = 0;
123
122
        handle->op_mode = mode;
124
123
        TRACEEXIT1(return 0);
125
124
}
131
130
        enum op_mode ndis_mode;
132
131
 
133
132
        TRACEENTER1("%s", "");
134
 
        switch (wrqu->mode)
135
 
        {
 
133
        switch (wrqu->mode) {
136
134
        case IW_MODE_ADHOC:
137
135
                ndis_mode = NDIS_MODE_ADHOC;
138
136
                break;  
161
159
        int res;
162
160
 
163
161
        TRACEENTER1("%s", "");
164
 
        res = query_int(handle, NDIS_OID_MODE, &ndis_mode);
165
 
        if (res)
166
 
        {
 
162
        res = miniport_query_int(handle, NDIS_OID_MODE, &ndis_mode);
 
163
        if (res) {
167
164
                WARNING("getting operating mode failed (%08X)", res);
168
165
                TRACEEXIT1(return -EOPNOTSUPP);
169
166
        }
170
167
 
171
 
        switch(ndis_mode)
172
 
        {
 
168
        switch(ndis_mode) {
173
169
        case NDIS_MODE_ADHOC:
174
170
                iw_mode = IW_MODE_ADHOC;
175
171
                break;
206
202
        struct ndis_handle *handle = dev->priv;
207
203
        unsigned int network_type, res;
208
204
        
209
 
        res = query_int(handle, NDIS_OID_NETWORK_TYPE_IN_USE, &network_type);
 
205
        res = miniport_query_int(handle, NDIS_OID_NETWORK_TYPE_IN_USE,
 
206
                                 &network_type);
210
207
        if (res == NDIS_STATUS_INVALID_DATA)
211
208
                network_type = -1;
212
209
 
220
217
                       union iwreq_data *wrqu, char *extra)
221
218
{
222
219
        struct ndis_handle *handle = dev->priv;
223
 
        unsigned int res, written, needed;
 
220
        unsigned int res;
224
221
        struct ndis_configuration req;
225
222
 
226
223
        memset(&req, 0, sizeof(req));
227
 
        res = doquery(handle, NDIS_OID_CONFIGURATION, (char*)&req,
228
 
                      sizeof(req), &written, &needed);
229
 
        if (res == NDIS_STATUS_INVALID_DATA)
230
 
        {
 
224
        res = miniport_query_info(handle, NDIS_OID_CONFIGURATION, (char*)&req,
 
225
                                  sizeof(req));
 
226
        if (res == NDIS_STATUS_INVALID_DATA) {
231
227
                WARNING("getting configuration failed (%08X)", res);
232
 
                TRACEEXIT(return -EOPNOTSUPP);
 
228
                TRACEEXIT2(return -EOPNOTSUPP);
233
229
        }
234
230
 
235
231
        memset(&(wrqu->freq), 0, sizeof(struct iw_freq));
238
234
           definition for an explanation of this if
239
235
           NOTE: 1000000 is due to the kHz
240
236
        */
241
 
        if (req.ds_config > 1000000)
242
 
        {
 
237
        if (req.ds_config > 1000000) {
243
238
                wrqu->freq.m = req.ds_config / 10;
244
239
                wrqu->freq.e = 1;
245
240
        }
256
251
                       union iwreq_data *wrqu, char *extra)
257
252
{
258
253
        struct ndis_handle *handle = dev->priv;
259
 
        unsigned int res, written, needed;
 
254
        unsigned int res;
260
255
        struct ndis_configuration req;
261
256
 
262
257
        memset(&req, 0, sizeof(req));
263
 
        res = doquery(handle, NDIS_OID_CONFIGURATION, (char*)&req,
264
 
                      sizeof(req), &written, &needed);
265
 
        if (res == NDIS_STATUS_INVALID_DATA)
266
 
        {
 
258
        res = miniport_query_info(handle, NDIS_OID_CONFIGURATION, (char*)&req,
 
259
                                  sizeof(req));
 
260
        if (res == NDIS_STATUS_INVALID_DATA) {
267
261
                WARNING("getting configuration failed (%08X)", res);
268
 
                TRACEEXIT(return -EOPNOTSUPP);
 
262
                TRACEEXIT2(return -EOPNOTSUPP);
269
263
        }
270
264
 
271
 
        if (wrqu->freq.m < 1000 && wrqu->freq.e == 0)
272
 
        {
 
265
        if (wrqu->freq.m < 1000 && wrqu->freq.e == 0) {
273
266
                if (wrqu->freq.m >= 1 &&
274
267
                    wrqu->freq.m <= (sizeof(freq_chan)/sizeof(freq_chan[0])))
275
268
                        req.ds_config = freq_chan[wrqu->freq.m - 1] * 1000;
276
269
                else
277
270
                        return -EINVAL;
278
 
        }
279
 
        else
280
 
        {
 
271
        } else {
281
272
                int i;
282
273
                for (req.ds_config = wrqu->freq.m, i = wrqu->freq.e ;
283
274
                     i > 0 ; i--)
285
276
                req.ds_config /= 1000;
286
277
                
287
278
        }
288
 
        res = dosetinfo(handle, NDIS_OID_CONFIGURATION, (char*)&req,
289
 
                        sizeof(req), &written, &needed);
290
 
        if (res == NDIS_STATUS_INVALID_DATA)
291
 
        {
 
279
        res = miniport_set_info(handle, NDIS_OID_CONFIGURATION, (char*)&req,
 
280
                                sizeof(req));
 
281
        if (res == NDIS_STATUS_INVALID_DATA) {
292
282
                WARNING("setting configuration failed (%08X)", res);
293
283
                return -EINVAL;
294
284
        }
301
291
{
302
292
        struct ndis_handle *handle = dev->priv; 
303
293
        unsigned long ndis_power;
304
 
        unsigned int written, needed, res;
 
294
        unsigned int res;
305
295
 
306
 
        res = doquery(handle, NDIS_OID_TX_POWER_LEVEL, (char*)&ndis_power,
307
 
                      sizeof(ndis_power), &written, &needed);
 
296
        res = miniport_query_info(handle, NDIS_OID_TX_POWER_LEVEL,
 
297
                                  (char*)&ndis_power,
 
298
                                  sizeof(ndis_power));
308
299
        /* Centrino driver returns NDIS_STATUS_INVALID_OID (why?) */
309
300
        if (res == NDIS_STATUS_NOT_SUPPORTED || res == NDIS_STATUS_INVALID_OID)
310
301
                return -EOPNOTSUPP;
322
313
{
323
314
        struct ndis_handle *handle = dev->priv; 
324
315
        unsigned long ndis_power;
325
 
        unsigned int written, needed, res;
 
316
        unsigned int res;
326
317
 
327
 
        if (wrqu->txpower.disabled)
328
 
        {
 
318
        if (wrqu->txpower.disabled) {
329
319
                ndis_power = 0;
330
 
                res = dosetinfo(handle, NDIS_OID_TX_POWER_LEVEL,
331
 
                                (char *)&ndis_power,
332
 
                                sizeof(ndis_power), &written, &needed);
 
320
                res = miniport_set_info(handle, NDIS_OID_TX_POWER_LEVEL,
 
321
                                        (char *)&ndis_power,
 
322
                                        sizeof(ndis_power));
333
323
                if (res == NDIS_STATUS_INVALID_DATA)
334
324
                        return -EINVAL;
335
 
                res = set_int(handle, NDIS_OID_DISASSOCIATE, 0);
 
325
                res = miniport_set_int(handle, NDIS_OID_DISASSOCIATE, 0);
336
326
                if (res)
337
327
                        return -EINVAL;
338
328
                return 0;
339
 
        }
340
 
        else 
341
 
        {
 
329
        } else {
342
330
                if (wrqu->txpower.flags == IW_TXPOW_MWATT)
343
331
                        ndis_power = wrqu->txpower.value;
344
 
                else // wrqu->txpower.flags == IW_TXPOW_DBM
345
 
                {
 
332
                else { // wrqu->txpower.flags == IW_TXPOW_DBM
346
333
                        if (wrqu->txpower.value > 20)
347
334
                                ndis_power = 128;
348
335
                        else if (wrqu->txpower.value < -43)
349
336
                                ndis_power = 127;
350
 
                        else
351
 
                        {
 
337
                        else {
352
338
                                signed char tmp;
353
339
                                tmp = wrqu->txpower.value;
354
340
                                tmp = -12 - tmp;
357
343
                        }
358
344
                }
359
345
        }
360
 
        res = dosetinfo(handle, NDIS_OID_TX_POWER_LEVEL, (char*)&ndis_power,
361
 
                      sizeof(ndis_power), &written, &needed);
 
346
        res = miniport_set_info(handle, NDIS_OID_TX_POWER_LEVEL,
 
347
                                (char*)&ndis_power, sizeof(ndis_power));
362
348
        if (res)
363
349
                WARNING("setting tx_power failed (%08X)", res);
364
350
        if (res == NDIS_STATUS_NOT_SUPPORTED)
375
361
        struct ndis_handle *handle = dev->priv; 
376
362
        int ndis_rate;
377
363
 
378
 
        int res = query_int(handle, NDIS_OID_GEN_SPEED, &ndis_rate);
 
364
        int res = miniport_query_int(handle, NDIS_OID_GEN_SPEED, &ndis_rate);
379
365
        if (res)
380
366
                WARNING("getting bitrate failed (%08X)", res);
381
367
 
383
369
        return 0;
384
370
}
385
371
 
 
372
static int iw_set_bitrate(struct net_device *dev, struct iw_request_info *info,
 
373
                          union iwreq_data *wrqu, char *extra)
 
374
{
 
375
        struct ndis_handle *handle = dev->priv; 
 
376
        int i, res;
 
377
        char rates[NDIS_MAX_RATES_EX];
 
378
 
 
379
        if (wrqu->bitrate.fixed == 0)
 
380
                TRACEEXIT1(return 0);
 
381
 
 
382
        res = miniport_query_info(handle, NDIS_OID_SUPPORTED_RATES,
 
383
                                  (char *)&rates, sizeof(rates));
 
384
        if (res == NDIS_STATUS_NOT_SUPPORTED)
 
385
                TRACEEXIT1(return -EOPNOTSUPP);
 
386
        if (res == NDIS_STATUS_INVALID_DATA)
 
387
                TRACEEXIT1(return -EINVAL);
 
388
                
 
389
        for (i = 0 ; i < NDIS_MAX_RATES_EX ; i++) {
 
390
                if (rates[i] & 0x80)
 
391
                        continue;
 
392
                if ((rates[i] & 0x7f) * 500000 > wrqu->bitrate.value) {
 
393
                        DBGTRACE1("setting rate %d to 0",
 
394
                                  (rates[i] & 0x7f) * 500000);
 
395
                        rates[i] = 0;
 
396
                }
 
397
        }
 
398
 
 
399
        res = miniport_query_info(handle, NDIS_OID_DESIRED_RATES,
 
400
                                  (char *)&rates, sizeof(rates));
 
401
        if (res == NDIS_STATUS_NOT_SUPPORTED)
 
402
                TRACEEXIT1(return -EOPNOTSUPP);
 
403
        if (res == NDIS_STATUS_INVALID_DATA)
 
404
                TRACEEXIT1(return -EINVAL);
 
405
 
 
406
        return 0;
 
407
}
 
408
 
386
409
static int iw_set_dummy(struct net_device *dev, struct iw_request_info *info,
387
410
                        union iwreq_data *wrqu, char *extra)
388
411
{
397
420
        struct ndis_handle *handle = dev->priv;
398
421
        int ndis_rts_threshold;
399
422
 
400
 
        int res = query_int(handle, NDIS_OID_RTS_THRESH, &ndis_rts_threshold);
 
423
        int res = miniport_query_int(handle, NDIS_OID_RTS_THRESH,
 
424
                                     &ndis_rts_threshold);
401
425
        if (res == NDIS_STATUS_NOT_SUPPORTED)
402
426
                return -EOPNOTSUPP;
403
427
 
412
436
        struct ndis_handle *handle = dev->priv; 
413
437
        int ndis_frag_threshold;
414
438
 
415
 
        int res = query_int(handle, NDIS_OID_FRAG_THRESH,
416
 
                            &ndis_frag_threshold);
 
439
        int res = miniport_query_int(handle, NDIS_OID_FRAG_THRESH,
 
440
                                     &ndis_frag_threshold);
417
441
        if (res == NDIS_STATUS_NOT_SUPPORTED)
418
442
                return -EOPNOTSUPP;
419
443
 
423
447
 
424
448
int get_ap_address(struct ndis_handle *handle, mac_address ap_addr)
425
449
{
426
 
        unsigned int res, written, needed;
 
450
        unsigned int res;
427
451
 
428
452
        TRACEENTER1("%s", "");
429
453
 
430
 
        res = doquery(handle, NDIS_OID_BSSID, ap_addr, ETH_ALEN,
431
 
                      &written, &needed);
 
454
        res = miniport_query_info(handle, NDIS_OID_BSSID, ap_addr, ETH_ALEN);
432
455
        if (res == NDIS_STATUS_ADAPTER_NOT_READY)
433
456
                memset(ap_addr, 0, ETH_ALEN);
434
457
 
440
463
                             struct iw_request_info *info,
441
464
                             union iwreq_data *wrqu, char *extra)
442
465
{
443
 
    struct ndis_handle *handle = dev->priv;
444
 
    mac_address ap_addr;
445
 
 
446
 
    TRACEENTER1("%s", "");
447
 
    get_ap_address(handle, ap_addr);
448
 
 
449
 
    memcpy(wrqu->ap_addr.sa_data, ap_addr, ETH_ALEN);
450
 
    wrqu->ap_addr.sa_family = ARPHRD_ETHER;
451
 
    TRACEEXIT1(return 0);
 
466
        struct ndis_handle *handle = dev->priv;
 
467
        mac_address ap_addr;
 
468
 
 
469
        TRACEENTER1("%s", "");
 
470
        get_ap_address(handle, ap_addr);
 
471
 
 
472
        memcpy(wrqu->ap_addr.sa_data, ap_addr, ETH_ALEN);
 
473
        wrqu->ap_addr.sa_family = ARPHRD_ETHER;
 
474
        TRACEEXIT1(return 0);
452
475
}
453
476
 
454
477
static int iw_set_ap_address(struct net_device *dev,
456
479
                             union iwreq_data *wrqu, char *extra)
457
480
{
458
481
        struct ndis_handle *handle = dev->priv; 
459
 
        unsigned int res, written, needed;
 
482
        unsigned int res;
460
483
        mac_address ap_addr;
461
484
 
462
485
        memcpy(ap_addr, wrqu->ap_addr.sa_data, ETH_ALEN);
463
486
        DBGTRACE1(MACSTR, MAC2STR(ap_addr));
464
 
        res = dosetinfo(handle, NDIS_OID_BSSID, (char*)&(ap_addr[0]),
465
 
                        ETH_ALEN, &written, &needed);
 
487
        res = miniport_set_info(handle, NDIS_OID_BSSID, (char*)&(ap_addr[0]),
 
488
                                ETH_ALEN);
466
489
 
467
 
        if (res)
468
 
        {
 
490
        if (res) {
469
491
                WARNING("setting AP mac address failed (%08X)", res);
470
492
                TRACEEXIT1(return -EINVAL);
471
493
        }
476
498
int set_auth_mode(struct ndis_handle *handle, int auth_mode)
477
499
{
478
500
        unsigned int res;
479
 
        res = set_int(handle, NDIS_OID_AUTH_MODE, auth_mode);
480
 
        if (res == NDIS_STATUS_INVALID_DATA)
481
 
        {
 
501
        res = miniport_set_int(handle, NDIS_OID_AUTH_MODE, auth_mode);
 
502
        if (res == NDIS_STATUS_INVALID_DATA) {
482
503
                WARNING("setting auth mode failed (%08X)", res);
483
 
                return -EINVAL;
484
 
        }
485
 
        else
486
 
        {
 
504
                TRACEEXIT2(return -EINVAL);
 
505
        } else {
487
506
                handle->auth_mode = auth_mode;
488
 
                return 0;
 
507
                TRACEEXIT2(return 0);
489
508
        }
490
509
}
491
510
 
492
511
int set_encr_mode(struct ndis_handle *handle, int encr_mode)
493
512
{
494
513
        unsigned int res;
495
 
        res = set_int(handle, NDIS_OID_ENCR_STATUS, encr_mode);
 
514
        res = miniport_set_int(handle, NDIS_OID_ENCR_STATUS, encr_mode);
496
515
        if (res == NDIS_STATUS_INVALID_DATA)
497
516
                TRACEEXIT2(return -EINVAL);
498
 
        else
499
 
        {
 
517
        else {
500
518
                handle->encr_mode = encr_mode;
501
519
                TRACEEXIT2(return 0);
502
520
        }
509
527
        int status, res, index;
510
528
        struct encr_info *encr_info = &handle->encr_info;
511
529
 
512
 
        TRACEENTER1("%s", "");
 
530
        TRACEENTER2("handle = %p", handle);
513
531
        wrqu->data.length = 0;
514
532
        extra[0] = 0;
515
533
 
516
 
        index = (wrqu->data.flags & IW_ENCODE_INDEX);
 
534
        index = (wrqu->encoding.flags & IW_ENCODE_INDEX);
517
535
        DBGTRACE2("index = %u", index);
518
 
        if (index && (index <= 0 || index > MAX_ENCR_KEYS))
519
 
        {
 
536
        if (index > 0)
 
537
                index--;
 
538
        else
 
539
                index = encr_info->active;
 
540
 
 
541
        if (index < 0 || index >= MAX_ENCR_KEYS) {
520
542
                WARNING("encryption index out of range (%u)", index);
521
543
                TRACEEXIT1(return -EINVAL);
522
544
        }
523
545
 
524
 
        if (index == 0)
525
 
                index = encr_info->active;
526
 
        else    
527
 
                index--;
528
 
 
529
 
        if (index != encr_info->active)
530
 
        {
531
 
                if (encr_info->keys[index].length > 0)
532
 
                {
 
546
        if (index != encr_info->active) {
 
547
                if (encr_info->keys[index].length > 0) {
533
548
                        wrqu->data.flags |= IW_ENCODE_ENABLED;
534
549
                        wrqu->data.length = encr_info->keys[index].length;
535
550
                        memcpy(extra, encr_info->keys[index].key,
542
557
        }
543
558
        
544
559
        /* active key */
545
 
        res = query_int(handle, NDIS_OID_ENCR_STATUS, &status);
546
 
        if (res == NDIS_STATUS_NOT_SUPPORTED)
547
 
        {
 
560
        res = miniport_query_int(handle, NDIS_OID_ENCR_STATUS, &status);
 
561
        if (res == NDIS_STATUS_NOT_SUPPORTED) {
548
562
                WARNING("getting encryption status failed (%08X)", res);
549
563
                TRACEEXIT1(return -EOPNOTSUPP);
550
564
        }
551
565
 
552
566
        if (status == ENCR_DISABLED || status == ENCR1_NO_SUPPORT)
553
567
                wrqu->data.flags |= IW_ENCODE_DISABLED;
554
 
        else
555
 
        {
 
568
        else {
556
569
                if (status == ENCR1_NOKEY || status == ENCR2_ABSENT ||
557
570
                    status == ENCR3_ABSENT)
558
571
                        wrqu->data.flags |= IW_ENCODE_NOKEY;
559
 
 
560
 
                else
561
 
                {
562
 
                        wrqu->data.flags |= IW_ENCODE_ENABLED | (index+1);
 
572
                else {
 
573
                        wrqu->data.flags |= IW_ENCODE_ENABLED;
 
574
                        wrqu->encoding.flags |= index+1;
563
575
                        wrqu->data.length = encr_info->keys[index].length;
564
576
                        memcpy(extra, encr_info->keys[index].key,
565
577
                               encr_info->keys[index].length);
566
578
                }
567
579
        }
568
 
        res = query_int(handle, NDIS_OID_AUTH_MODE, &status);
569
 
        if (res == NDIS_STATUS_NOT_SUPPORTED)
570
 
        {
 
580
        res = miniport_query_int(handle, NDIS_OID_AUTH_MODE, &status);
 
581
        if (res == NDIS_STATUS_NOT_SUPPORTED) {
571
582
                WARNING("getting authentication mode failed (%08X)", res);
572
583
                TRACEEXIT1(return -EOPNOTSUPP);
573
584
        }
582
593
        TRACEEXIT1(return 0);
583
594
}
584
595
 
 
596
/* index must be 0 - N, as per NDIS  */
 
597
int add_wep_key(struct ndis_handle *handle, char *key, int key_len,
 
598
                int index)
 
599
{
 
600
        struct ndis_encr_key ndis_key;
 
601
        unsigned int res;
 
602
 
 
603
        TRACEENTER2("handle = %p", handle);
 
604
        if (key_len <= 0 || key_len > NDIS_ENCODING_TOKEN_MAX) {
 
605
                WARNING("invalid key length (%d)", key_len);
 
606
                TRACEEXIT2(return -EINVAL);
 
607
        }
 
608
        ndis_key.struct_size = sizeof(ndis_key);
 
609
        ndis_key.length = key_len;
 
610
        memcpy(&ndis_key.key, key, key_len);
 
611
        /* active/transmit key works only if index is 0 */
 
612
        if (index == handle->encr_info.active)
 
613
                ndis_key.index = 0 | (1 << 31);
 
614
        else
 
615
                ndis_key.index = index;
 
616
 
 
617
        res = miniport_set_info(handle, NDIS_OID_ADD_WEP, (char *)&ndis_key,
 
618
                                sizeof(ndis_key));
 
619
        if (res == NDIS_STATUS_INVALID_DATA) {
 
620
                WARNING("adding encryption key %d failed (%08X)",
 
621
                        index+1, res);
 
622
                TRACEEXIT1(return -EINVAL);
 
623
        }
 
624
                
 
625
        /* Atheros driver messes up ndis_key during ADD_WEP, so
 
626
         * don't rely on that; instead use info in key and key_len */
 
627
        handle->encr_info.keys[index].length = key_len;
 
628
        memcpy(&handle->encr_info.keys[index].key, key, key_len);
 
629
 
 
630
        /* active/transmit key is always stored at index 0 */
 
631
        if (index == handle->encr_info.active) {
 
632
                handle->encr_info.keys[0].length = key_len;
 
633
                memcpy(&handle->encr_info.keys[0].key, key, key_len);
 
634
                res = set_encr_mode(handle, ENCR1_ENABLED);
 
635
                if (res)
 
636
                        WARNING("changing encr status failed (%08X)", res);
 
637
        }
 
638
        TRACEEXIT1(return 0);
 
639
}
 
640
 
585
641
static int iw_set_encr(struct net_device *dev, struct iw_request_info *info,
586
642
                       union iwreq_data *wrqu, char *extra)
587
643
{
588
644
        struct ndis_handle *handle = dev->priv;
589
 
        unsigned int res, written, needed, index;
 
645
        unsigned int res, index;
590
646
        struct encr_info *encr_info = &handle->encr_info;
591
 
        struct ndis_encr_key ndis_key;
 
647
        unsigned char *key;
 
648
        int key_len;
592
649
        
593
650
        TRACEENTER1("%s", "");
594
651
        index = (wrqu->encoding.flags & IW_ENCODE_INDEX);
595
652
        DBGTRACE2("index = %u", index);
596
 
        if (index > MAX_ENCR_KEYS)
597
 
        {
 
653
 
 
654
        /* iwconfig gives index as 1 - N */
 
655
        if (index > 0)
 
656
                index--;
 
657
        else
 
658
                index = encr_info->active;
 
659
 
 
660
        if (index < 0 || index >= MAX_ENCR_KEYS) {
598
661
                WARNING("encryption index out of range (%u)", index);
599
662
                TRACEEXIT1(return -EINVAL);
600
663
        }
601
664
 
602
 
        if (index <= 0)
603
 
                index = encr_info->active;
604
 
        else    
605
 
                index--;
606
 
 
607
665
        /* remove key if disabled */
608
 
        if (wrqu->data.flags & IW_ENCODE_DISABLED)
609
 
        {
 
666
        if (wrqu->data.flags & IW_ENCODE_DISABLED) {
610
667
                unsigned long keyindex = index;
611
 
                res = dosetinfo(handle, NDIS_OID_REMOVE_WEP,
612
 
                                (char *)&keyindex, sizeof(keyindex),
613
 
                                &written, &needed);
614
 
                if (res == NDIS_STATUS_INVALID_DATA)
615
 
                {
 
668
                res = miniport_set_info(handle, NDIS_OID_REMOVE_WEP,
 
669
                                        (char *)&keyindex, sizeof(keyindex));
 
670
                if (res == NDIS_STATUS_INVALID_DATA) {
616
671
                        WARNING("removing encryption key %d failed (%08X)",
617
672
                                index, res);
618
673
                        TRACEEXIT1(return -EINVAL);
620
675
                encr_info->keys[index].length = 0;
621
676
                
622
677
                /* if it is active key, disable encryption */
623
 
                if (index == encr_info->active)
624
 
                {
 
678
                if (index == encr_info->active) {
625
679
                        res = set_encr_mode(handle, ENCR_DISABLED);
626
680
                        if (res)
627
681
                                WARNING("changing encr status failed (%08X)",
635
689
                res = set_auth_mode(handle, AUTHMODE_OPEN);
636
690
        else // if (wrqu->data.flags & IW_ENCODE_RESTRICTED)
637
691
                res = set_auth_mode(handle, AUTHMODE_RESTRICTED);
638
 
        if (res)
639
 
        {
 
692
        if (res) {
640
693
                WARNING("setting authentication mode failed (%08X)", res);
641
694
                TRACEEXIT1(return -EINVAL);
642
695
        }
643
696
 
644
 
        ndis_key.struct_size = sizeof(ndis_key);
645
 
        if (wrqu->data.length == 0)
646
 
        {
647
 
                /* should we allow as yet unset tx_key? */
648
 
                if (encr_info->keys[index].length == 0)
649
 
                {
 
697
        if (wrqu->data.length > 0) {
 
698
                key_len = wrqu->data.length;
 
699
                key = extra;
 
700
        } else { // must be set as tx key
 
701
                if (encr_info->keys[index].length == 0) {
650
702
                        WARNING("key %d is not set", index+1);
651
703
                        TRACEEXIT1(return -EINVAL);
652
704
                }
653
 
                ndis_key.length = encr_info->keys[index].length;
654
 
                ndis_key.index = index | (1 << 31);
655
 
                memcpy(ndis_key.key, encr_info->keys[index].key,
656
 
                       ndis_key.length);
657
 
        }
658
 
        else // if (wrqu->data.length > 0)
659
 
        {
660
 
                if (wrqu->data.length > NDIS_ENCODING_TOKEN_MAX)
661
 
                {
662
 
                        WARNING("invalid key length (%d)", wrqu->data.length);
663
 
                        TRACEEXIT(return -EINVAL);
664
 
                }
665
 
                ndis_key.length = wrqu->data.length;
666
 
                ndis_key.index = index;
667
 
                if (index == encr_info->active)
668
 
                        ndis_key.index |= 1 << 31;
669
 
                memcpy(&ndis_key.key, extra, ndis_key.length);
670
 
        }
671
 
 
672
 
        res = dosetinfo(handle, NDIS_OID_ADD_WEP, (char *)&ndis_key,
673
 
                        sizeof(ndis_key), &written, &needed);
674
 
        if (res == NDIS_STATUS_INVALID_DATA)
675
 
        {
676
 
                WARNING("adding encryption key %d failed (%08X)",
677
 
                        index+1, res);
678
 
                TRACEEXIT1(return -EINVAL);
679
 
        }
680
 
 
681
 
        res = set_encr_mode(handle, ENCR1_ENABLED);
682
 
        if (res)
683
 
                WARNING("changing encr status failed (%08X)", res);
684
 
 
685
 
        encr_info->keys[index].length = ndis_key.length;
686
 
        memcpy(&encr_info->keys[index].key, ndis_key.key, ndis_key.length);
687
 
        if (wrqu->data.length == 0)
 
705
                key_len = encr_info->keys[index].length;
 
706
                key = encr_info->keys[index].key;
688
707
                encr_info->active = index;
689
 
 
690
 
        /* ndis drivers want essid to be set after setting encr */
691
 
        set_essid(handle, handle->essid.essid, handle->essid.length);
692
 
 
 
708
        }
 
709
 
 
710
        if (add_wep_key(handle, key, key_len, index))
 
711
                TRACEEXIT2(return -EINVAL);
 
712
 
 
713
        if (index == encr_info->active) {
 
714
                /* ndis drivers want essid to be set after setting encr */
 
715
                set_essid(handle, handle->essid.essid, handle->essid.length);
 
716
        }
693
717
        TRACEEXIT1(return 0);
694
718
}
695
719
        
716
740
}
717
741
 
718
742
static char *ndis_translate_scan(struct net_device *dev, char *event,
719
 
                                 char *end_buf, struct ssid_item *item)
 
743
                                 char *end_buf, struct ndis_ssid_item *item)
720
744
{
721
745
        struct iw_event iwe;
722
746
        char *current_val;
723
 
        int i;
724
 
        char buf[MAX_WPA_IE_LEN * 2 + 30];
 
747
        int i, nrates;
 
748
        unsigned char buf[MAX_WPA_IE_LEN * 2 + 30];
725
749
 
726
750
        TRACEENTER1("%s", "");
727
751
        /* add mac address */
763
787
        memset(&iwe, 0, sizeof(iwe));
764
788
        iwe.cmd = SIOCGIWFREQ;
765
789
        iwe.u.freq.m = item->config.ds_config;
766
 
        if (item->config.ds_config > 1000000)
767
 
        {
 
790
        if (item->config.ds_config > 1000000) {
768
791
                iwe.u.freq.m = item->config.ds_config / 10;
769
792
                iwe.u.freq.e = 1;
770
793
        }
799
822
        memset(&iwe, 0, sizeof(iwe));
800
823
        current_val = event + IW_EV_LCP_LEN;
801
824
        iwe.cmd = SIOCGIWRATE;
802
 
        for (i = 0 ; i < NDIS_MAX_RATES ; i++)
803
 
        {
804
 
                if (item->rates[i] == 0)
805
 
                        break;
806
 
                iwe.u.bitrate.value = ((item->rates[i] & 0x7f) * 500000);
807
 
                current_val = iwe_stream_add_value(event, current_val, end_buf,
808
 
                                                   &iwe, IW_EV_PARAM_LEN);
 
825
        if (item->length > sizeof(struct ndis_ssid_item))
 
826
                nrates = NDIS_MAX_RATES_EX;
 
827
        else
 
828
                nrates = NDIS_MAX_RATES;
 
829
        for (i = 0 ; i < nrates ; i++) {
 
830
                if (item->rates[i] & 0x7f) {
 
831
                        iwe.u.bitrate.value = ((item->rates[i] & 0x7f) *
 
832
                                               500000);
 
833
                        current_val = iwe_stream_add_value(event, current_val,
 
834
                                                           end_buf, &iwe,
 
835
                                                           IW_EV_PARAM_LEN);
 
836
                }
809
837
        }
810
838
 
811
839
        if ((current_val - event) > IW_EV_LCP_LEN)
817
845
        iwe.u.data.length = strlen(buf);
818
846
        event = iwe_stream_add_point(event, end_buf, &iwe, buf);
819
847
        
820
 
        if (item->length > ((char *)&item->rates[NDIS_MAX_RATES] -
821
 
                            (char *)&item->length) &&
822
 
            item->ie_length >= (sizeof(struct fixed_ies) + 2))
823
 
        {
824
 
                struct fixed_ies *fixed_ies = (struct fixed_ies *)item->ies;
825
 
                unsigned char *iep = (unsigned char *)(fixed_ies + 1);
826
 
                int iel = item->ie_length - sizeof(*fixed_ies);
827
 
                
828
 
                DBGTRACE2("%s: adding atim\n", __FUNCTION__);
829
 
                memset(&iwe, 0, sizeof(iwe));
830
 
                iwe.cmd = IWEVCUSTOM;
831
 
                sprintf(buf, "atim=%u", item->config.atim_window);
832
 
                iwe.u.data.length = strlen(buf);
833
 
                event = iwe_stream_add_point(event, end_buf, &iwe, buf);
834
 
                
835
 
                while(iel > 0) {
836
 
                        if(iep[0] == WLAN_EID_GENERIC && iep[1] >= 4 &&
837
 
                           iep[2] == 0x00 && iep[3] == 0x50 &&
838
 
                           iep[4] == 0xf2 && iep[5] == 1)
839
 
                        {
840
 
                                char *p = buf;
841
 
                                
842
 
                                i = iep[1] + 2;
843
 
                                if(i < iel)
844
 
                                        iel = i;
845
 
                                
 
848
        DBGTRACE2("%s: adding atim", __FUNCTION__);
 
849
        memset(&iwe, 0, sizeof(iwe));
 
850
        iwe.cmd = IWEVCUSTOM;
 
851
        sprintf(buf, "atim=%u", item->config.atim_window);
 
852
        iwe.u.data.length = strlen(buf);
 
853
        event = iwe_stream_add_point(event, end_buf, &iwe, buf);
 
854
 
 
855
        if (item->length > sizeof(*item)) {
 
856
                unsigned char *iep = (unsigned char *)item->ies +
 
857
                        sizeof(struct ndis_fixed_ies);
 
858
                unsigned char *end = iep + item->ie_length;
 
859
 
 
860
                while (iep + 1 < end && iep + 2 + iep[1] <= end) {
 
861
                        unsigned char ielen = 2 + iep[1];
 
862
 
 
863
                        if (ielen > SSID_MAX_WPA_IE_LEN) {
 
864
                                iep += ielen;
 
865
                                continue;
 
866
                        }
 
867
 
 
868
                        if (iep[0] == WLAN_EID_GENERIC && iep[1] >= 4 &&
 
869
                            memcmp(iep + 2, "\x00\x50\xf2\x01", 4) == 0) {
 
870
                                unsigned char *p = buf;
 
871
 
846
872
                                p += sprintf(p, "wpa_ie=");
847
 
                                for (i = 0; i < iel; i++)
 
873
                                for (i = 0; i < ielen; i++)
848
874
                                        p += sprintf(p, "%02x", iep[i]);
849
875
                                
850
 
                                DBGTRACE2("adding wpa_ie :%d\n", strlen(buf));
851
 
                                memset(&iwe, 0, sizeof(iwe));
852
 
                                iwe.cmd = IWEVCUSTOM;
853
 
                                iwe.u.data.length = strlen(buf);
854
 
                                event = iwe_stream_add_point(event, end_buf,
855
 
                                                             &iwe, buf);
856
 
                                break;
 
876
                                DBGTRACE2("adding wpa_ie :%ld", strlen(buf));
 
877
                                memset(&iwe, 0, sizeof(iwe));
 
878
                                iwe.cmd = IWEVCUSTOM;
 
879
                                iwe.u.data.length = strlen(buf);
 
880
                                event = iwe_stream_add_point(event, end_buf,
 
881
                                                             &iwe, buf);
 
882
                        } else if (iep[0] == WLAN_EID_RSN) {
 
883
                                unsigned char *p = buf;
 
884
                                for (i = 0; i < ielen; i++)
 
885
                                        p += sprintf(p, "%02x", iep[i]);
 
886
 
 
887
                                DBGTRACE2("adding rsn_ie :%ld\n", strlen(buf));
 
888
                                memset(&iwe, 0, sizeof(iwe));
 
889
                                iwe.cmd = IWEVCUSTOM;
 
890
                                iwe.u.data.length = strlen(buf);
 
891
                                event = iwe_stream_add_point(event, end_buf,
 
892
                                                             &iwe, buf);
857
893
                        }
858
894
 
859
 
                        iel -= iep[1];
860
 
                        iel -= 2;
861
 
                        iep += iep[1];
862
 
                        iep += 2;
 
895
                        iep += ielen;
863
896
                }
864
897
        }
865
898
 
875
908
        unsigned int res = 0;
876
909
 
877
910
        TRACEENTER1("%s", "");
878
 
        res = set_int(handle, NDIS_OID_BSSID_LIST_SCAN, 0);
 
911
        res = miniport_set_int(handle, NDIS_OID_BSSID_LIST_SCAN, 0);
879
912
        if (res == NDIS_STATUS_NOT_SUPPORTED ||
880
 
            res == NDIS_STATUS_INVALID_DATA)
881
 
        {
 
913
            res == NDIS_STATUS_INVALID_DATA) {
882
914
                WARNING("scanning failed (%08X)", res);
883
915
                handle->scan_timestamp = 0;
884
916
                TRACEEXIT1(return -EOPNOTSUPP);
885
 
        }
886
 
        else
887
 
        {
 
917
        } else {
888
918
                handle->scan_timestamp = jiffies;
889
919
                TRACEEXIT1(return 0);
890
920
        }
894
924
                       union iwreq_data *wrqu, char *extra)
895
925
{
896
926
        struct ndis_handle *handle = dev->priv;
897
 
        unsigned int i, res, written, needed, list_len;
898
 
        struct bssid_list *bssid_list;
 
927
        unsigned int i, res, list_len, needed;
 
928
        struct ndis_bssid_list *bssid_list;
899
929
        char *event = extra;
900
 
        struct ssid_item *cur_item ;
 
930
        struct ndis_ssid_item *cur_item ;
901
931
 
902
932
        TRACEENTER1("%s", "");
903
933
        if (!handle->scan_timestamp)
907
937
                return -EAGAIN;
908
938
        
909
939
        /* Try with space for 15 scan items */
910
 
        list_len = sizeof(unsigned long) + sizeof(struct ssid_item) * 15;
 
940
        list_len = sizeof(unsigned long) + sizeof(struct ndis_ssid_item) * 15;
911
941
        bssid_list = kmalloc(list_len, GFP_KERNEL);
912
942
 
913
 
        written = needed = 0;
914
 
        res = doquery(handle, NDIS_OID_BSSID_LIST, (char *)bssid_list,
915
 
                      list_len, &written, &needed);
916
 
        if (res == NDIS_STATUS_INVALID_LENGTH)
917
 
        {
 
943
        res = miniport_query_info_needed(handle, NDIS_OID_BSSID_LIST,
 
944
                                         (char *)bssid_list, list_len,
 
945
                                         &needed);
 
946
        if (res == NDIS_STATUS_INVALID_LENGTH) {
918
947
                /* 15 items not enough; allocate required space */
919
948
                kfree(bssid_list);
920
949
                list_len = needed;
921
950
                bssid_list = kmalloc(list_len, GFP_KERNEL);
922
951
        
923
 
                res = doquery(handle, NDIS_OID_BSSID_LIST, (char*)bssid_list,
924
 
                              list_len, &written, &needed);
 
952
                res = miniport_query_info(handle, NDIS_OID_BSSID_LIST,
 
953
                                          (char*)bssid_list, list_len);
925
954
        }
926
 
        if (res == NDIS_STATUS_INVALID_DATA)
927
 
        {
 
955
 
 
956
        if (res == NDIS_STATUS_INVALID_DATA) {
928
957
                WARNING("getting BSSID list failed (%08X)", res);
929
958
                kfree(bssid_list);
930
959
                TRACEEXIT1(return -EOPNOTSUPP);
931
960
        }
932
961
 
933
962
        for (i = 0, cur_item = &bssid_list->items[0] ;
934
 
             i < bssid_list->num_items ; i++)
935
 
        {
 
963
             i < bssid_list->num_items ; i++) {
936
964
                event = ndis_translate_scan(dev, event,
937
965
                                            extra + IW_SCAN_MAX_DATA,
938
966
                                            cur_item);
939
 
                cur_item = (struct ssid_item *)((char *)cur_item +
 
967
                cur_item = (struct ndis_ssid_item *)((char *)cur_item +
940
968
                                                cur_item->length);
941
969
        }
942
970
        wrqu->data.length = event - extra;
960
988
        else // if (wrqu->power.flags & IW_POWER_MAX)
961
989
                power_mode = NDIS_POWER_MAX;
962
990
 
963
 
        res = set_int(handle, NDIS_OID_POWER_MODE, power_mode);
964
 
        if (res == NDIS_STATUS_INVALID_DATA)
965
 
        {
 
991
        res = miniport_set_int(handle, NDIS_OID_POWER_MODE, power_mode);
 
992
        if (res == NDIS_STATUS_INVALID_DATA) {
966
993
                WARNING("setting power mode failed (%08X)", res);
967
994
                return -EINVAL;
968
995
        }
977
1004
        struct ndis_handle *handle = dev->priv;
978
1005
        int res, power_mode;
979
1006
 
980
 
        res = query_int(handle, NDIS_OID_POWER_MODE, &power_mode);
 
1007
        res = miniport_query_int(handle, NDIS_OID_POWER_MODE, &power_mode);
981
1008
        if (res == NDIS_STATUS_NOT_SUPPORTED)
982
1009
                return -EOPNOTSUPP;
983
1010
 
984
1011
        if (power_mode == NDIS_POWER_OFF)
985
1012
                wrqu->power.disabled = 1;
986
 
        else
987
 
        {
 
1013
        else {
988
1014
                if (wrqu->power.flags != 0)
989
1015
                        return 0;
990
1016
                wrqu->power.flags |= IW_POWER_ALL_R;
1005
1031
                              union iwreq_data *wrqu, char *extra)
1006
1032
{
1007
1033
        struct ndis_handle *handle = dev->priv;
1008
 
        unsigned int res, written, needed;
 
1034
        unsigned int res;
1009
1035
        unsigned long rssi_trigger;
1010
1036
 
1011
 
        res = doquery(handle, NDIS_OID_RSSI_TRIGGER, (char *)&rssi_trigger,
1012
 
                      sizeof(rssi_trigger), &written, &needed);
 
1037
        res = miniport_query_info(handle, NDIS_OID_RSSI_TRIGGER,
 
1038
                                  (char *)&rssi_trigger, sizeof(rssi_trigger));
1013
1039
        if (res)
1014
1040
                return -EOPNOTSUPP;
1015
1041
        wrqu->param.value = rssi_trigger;
1023
1049
                              union iwreq_data *wrqu, char *extra)
1024
1050
{
1025
1051
        struct ndis_handle *handle = dev->priv;
1026
 
        unsigned int res, written, needed;
 
1052
        unsigned int res;
1027
1053
        unsigned long rssi_trigger;
1028
1054
 
1029
1055
        if (wrqu->param.disabled)
1030
1056
                rssi_trigger = 0;
1031
1057
        else
1032
1058
                rssi_trigger = wrqu->param.value;
1033
 
        res = dosetinfo(handle, NDIS_OID_RSSI_TRIGGER, (char *)&rssi_trigger,
1034
 
                        sizeof(rssi_trigger), &written, &needed);
 
1059
        res = miniport_set_info(handle, NDIS_OID_RSSI_TRIGGER,
 
1060
                                (char *)&rssi_trigger, sizeof(rssi_trigger));
1035
1061
        if (res)
1036
1062
                return -EINVAL;
1037
1063
        return 0;
1038
1064
}
1039
1065
 
1040
 
struct iw_statistics *get_wireless_stats(struct net_device *dev)
1041
 
{
1042
 
        struct ndis_handle *handle = dev->priv;
1043
 
        return &handle->wireless_stats;
1044
 
}
1045
 
 
1046
 
 
1047
1066
static int iw_get_ndis_stats(struct net_device *dev,
1048
1067
                             struct iw_request_info *info,
1049
1068
                             union iwreq_data *wrqu, char *extra)
1050
 
 
1051
1069
{
1052
 
        struct iw_statistics *stats = get_wireless_stats(dev);
 
1070
        struct ndis_handle *handle = dev->priv;
 
1071
        struct iw_statistics *stats = &handle->wireless_stats;
1053
1072
        memcpy(&wrqu->qual, &stats->qual, sizeof(stats->qual));
1054
1073
        return 0;
1055
1074
}
1060
1079
        struct iw_range *range = (struct iw_range *)extra;
1061
1080
        struct iw_point *data = &wrqu->data;
1062
1081
        struct ndis_handle *handle = (struct ndis_handle *)dev->priv;
1063
 
        unsigned int i, written, needed;
1064
 
        unsigned char rates[NDIS_MAX_RATES];
 
1082
        unsigned int i, res;
 
1083
        unsigned char rates[NDIS_MAX_RATES_EX];
1065
1084
        unsigned long tx_power;
1066
1085
 
1067
1086
        data->length = sizeof(struct iw_range);
1070
1089
        range->txpower_capa = IW_TXPOW_MWATT;
1071
1090
        range->num_txpower = 0;
1072
1091
 
1073
 
        if (!doquery(handle, NDIS_OID_TX_POWER_LEVEL, (char*)&tx_power,
1074
 
                     sizeof(tx_power), &written, &needed))
1075
 
        {
 
1092
        res = miniport_query_info(handle, NDIS_OID_TX_POWER_LEVEL,
 
1093
                                 (char*)&tx_power, sizeof(tx_power));
 
1094
        if (!res) {
1076
1095
                range->num_txpower = 1;
1077
1096
                range->txpower[0] = tx_power;
1078
1097
        }
1098
1117
        range->encoding_size[1] = 13;
1099
1118
 
1100
1119
        range->num_bitrates = 0;
1101
 
        if (!doquery(handle, NDIS_OID_SUPPORTED_RATES, (char *)&rates,
1102
 
                    sizeof(rates), &written, &needed))
1103
 
        {
1104
 
                for (i = 0 ; i < NDIS_MAX_RATES && rates[i] ; i++)
1105
 
                        if (range->num_bitrates < IW_MAX_BITRATES &&
1106
 
                            rates[i] & 0x80)
1107
 
                        {
 
1120
        res = miniport_query_info(handle, NDIS_OID_SUPPORTED_RATES,
 
1121
                                  (char *)&rates, sizeof(rates));
 
1122
        if (res)
 
1123
                WARNING("getting bit rates failed: %08X", res);
 
1124
        else {
 
1125
                for (i = 0 ; i < NDIS_MAX_RATES_EX &&
 
1126
                             range->num_bitrates < IW_MAX_BITRATES ; i++)
 
1127
                        if (rates[i] & 0x80)
 
1128
                                continue;
 
1129
                        else if (rates[i] & 0x7f) {
1108
1130
                                range->bitrate[range->num_bitrates] =
1109
1131
                                        (rates[i] & 0x7f) * 500000;
1110
1132
                                range->num_bitrates++;
1113
1135
 
1114
1136
        range->num_channels = (sizeof(freq_chan)/sizeof(freq_chan[0]));
1115
1137
 
1116
 
        for(i = 0; i < (sizeof(freq_chan)/sizeof(freq_chan[0])) &&
1117
 
                    i < IW_MAX_FREQUENCIES; i++)
1118
 
        {
 
1138
        for (i = 0; i < (sizeof(freq_chan)/sizeof(freq_chan[0])) &&
 
1139
                    i < IW_MAX_FREQUENCIES; i++) {
1119
1140
                range->freq[i].i = i + 1;
1120
1141
                range->freq[i].m = freq_chan[i] * 100000;
1121
1142
                range->freq[i].e = 1;
1141
1162
        [SIOCGIWTXPOW   - SIOCIWFIRST] = iw_get_tx_power,
1142
1163
        [SIOCSIWTXPOW   - SIOCIWFIRST] = iw_set_tx_power,
1143
1164
        [SIOCGIWRATE    - SIOCIWFIRST] = iw_get_bitrate,
1144
 
        [SIOCSIWRATE    - SIOCIWFIRST] = iw_set_dummy,
 
1165
        [SIOCSIWRATE    - SIOCIWFIRST] = iw_set_bitrate,
1145
1166
        [SIOCGIWRTS     - SIOCIWFIRST] = iw_get_rts_threshold,
1146
1167
        [SIOCGIWFRAG    - SIOCIWFIRST] = iw_get_frag_threshold,
1147
1168
        [SIOCGIWAP      - SIOCIWFIRST] = iw_get_ap_address,
1167
1188
                      union iwreq_data *wrqu, char *extra)
1168
1189
{
1169
1190
        int res;
1170
 
        res = doreset(dev->priv);
1171
 
        if (res)
1172
 
        {
 
1191
        res = miniport_reset(dev->priv);
 
1192
        if (res) {
1173
1193
                WARNING("reset returns %08X", res);
1174
1194
                return -EOPNOTSUPP;
1175
1195
        }
1186
1206
 
1187
1207
        miniport = &handle->driver->miniport_char;
1188
1208
        if (!miniport->pnp_event_notify)
1189
 
                TRACEEXIT(return -EOPNOTSUPP);
 
1209
                TRACEEXIT2(return -EOPNOTSUPP);
1190
1210
 
1191
1211
        /* 1 for AC and 0 for Battery */
1192
1212
        if (wrqu->param.value)
1197
1217
        miniport->pnp_event_notify(handle->adapter_ctx,
1198
1218
                                   NDIS_PNP_PROFILE_CHANGED,
1199
1219
                                   &profile_inf, sizeof(profile_inf));
1200
 
        TRACEEXIT(return 0);
 
1220
        TRACEEXIT2(return 0);
1201
1221
}
1202
1222
 
1203
1223
/* WPA support */
1207
1227
{
1208
1228
        struct ndis_handle *handle = (struct ndis_handle *)dev->priv;
1209
1229
        
1210
 
        TRACEENTER("%s", "");
1211
 
        DBGTRACE("flags = %d,  handle->capa = %ld",
1212
 
                 wrqu->data.flags, handle->capa);
 
1230
        TRACEENTER2("%s", "");
 
1231
        DBGTRACE1("flags = %d,  handle->capa = %ld",
 
1232
                  wrqu->data.flags, handle->capa);
1213
1233
        
 
1234
        if (set_mode(handle, NDIS_MODE_INFRA))
 
1235
                TRACEEXIT2(return -1);
 
1236
 
1214
1237
        if (test_bit(CAPA_WPA, &handle->capa))
1215
 
                TRACEEXIT(return 0);
1216
 
        else
1217
 
        {
 
1238
                TRACEEXIT2(return 0);
 
1239
        else {
1218
1240
                WARNING("%s", "driver is not WPA capable");
1219
 
                TRACEEXIT(return -EINVAL);
1220
 
        }
1221
 
}
1222
 
 
1223
 
static int char_to_hex(int c)
1224
 
{
1225
 
        if (c >= '0' && c <= '9')
1226
 
                return c - '0';
1227
 
        if (c >= 'a' && c <= 'f')
1228
 
                return c - 'a' + 10;
1229
 
        return -1;
1230
 
}
1231
 
 
1232
 
/* convert key in string to hex digits - 2 chars make up one digit */
1233
 
static int key_str_to_hex(const char *str, unsigned char *key, int str_len)
1234
 
{
1235
 
        int i, key_len;
1236
 
 
1237
 
        if (!memcmp(str, "s:", 2))
1238
 
        {
1239
 
                key_len = str_len-2;
1240
 
                if (key_len >= IW_ENCODING_TOKEN_MAX)
1241
 
                        TRACEEXIT(return -1);
1242
 
                memcpy(key, str+2, key_len);
1243
 
        }
1244
 
        else
1245
 
                for (i = key_len = 0; i < str_len-1; i += 2, key_len++)
1246
 
                {
1247
 
                        int c1, c2;
1248
 
 
1249
 
                        if (key_len >= IW_ENCODING_TOKEN_MAX)
1250
 
                                TRACEEXIT(return -1);
1251
 
                        /* sscanf(str, "%1X", &ch) doesn't seem to work */
1252
 
                        c1 = char_to_hex(tolower(str[i]));
1253
 
                        c2 = char_to_hex(tolower(str[i+1]));
1254
 
                        if (c1 < 0 || c2 < 0)
1255
 
                                TRACEEXIT(return -1);
1256
 
                        key[key_len] = c1 << 4 | c2;
1257
 
                }
1258
 
        DBGTRACE("key length = %d", key_len);
1259
 
        if (key_len == 5 || key_len == 13)
1260
 
                TRACEEXIT(return key_len);
1261
 
        else
1262
 
                TRACEEXIT(return -1);
 
1241
                TRACEEXIT2(return -1);
 
1242
        }
1263
1243
}
1264
1244
 
1265
1245
static int wpa_set_key(struct net_device *dev, struct iw_request_info *info,
1266
1246
                       union iwreq_data *wrqu, char *extra)
1267
1247
{
1268
1248
        struct ndis_handle *handle = (struct ndis_handle *)dev->priv;
1269
 
        struct ndis_wpa_key ndis_key;
 
1249
        struct ndis_add_key ndis_key;
1270
1250
        struct wpa_key wpa_key;
1271
 
        int i, res, written, needed;
 
1251
        int i, res;
1272
1252
        u8 addr[ETH_ALEN];
1273
1253
        u8 seq[IW_ENCODING_TOKEN_MAX];
1274
 
        u8 usrkey[IW_ENCODING_TOKEN_MAX];
1275
 
 
1276
 
        copy_from_user(&wpa_key, wrqu->data.pointer, sizeof(wpa_key));
1277
 
        if(wpa_key.addr)
1278
 
                copy_from_user(&addr, wpa_key.addr, ETH_ALEN);
1279
 
 
1280
 
        if(wpa_key.seq)
1281
 
                copy_from_user(&seq, wpa_key.seq, IW_ENCODING_TOKEN_MAX);
1282
 
 
1283
 
        if(wpa_key.key)
1284
 
                copy_from_user(&usrkey, wpa_key.key, IW_ENCODING_TOKEN_MAX);
 
1254
        u8 key[IW_ENCODING_TOKEN_MAX];
 
1255
 
 
1256
        if (copy_from_user(&wpa_key, wrqu->data.pointer, sizeof(wpa_key)))
 
1257
                TRACEEXIT1(return -1);
 
1258
        if (wpa_key.addr && copy_from_user(&addr, wpa_key.addr, ETH_ALEN))
 
1259
                TRACEEXIT1(return -1);
 
1260
 
 
1261
        if (wpa_key.seq &&
 
1262
            copy_from_user(&seq, wpa_key.seq, IW_ENCODING_TOKEN_MAX))
 
1263
                TRACEEXIT1(return -1);
 
1264
 
 
1265
        if (wpa_key.key &&
 
1266
            copy_from_user(&key, wpa_key.key, IW_ENCODING_TOKEN_MAX))
 
1267
                TRACEEXIT1(return -1);
1285
1268
        
1286
 
        TRACEENTER1("alg = %d, key_index = %d",
 
1269
        TRACEENTER2("alg = %d, key_index = %d",
1287
1270
                    wpa_key.alg, wpa_key.key_index);
1288
1271
        
1289
 
        if (wpa_key.alg == WPA_ALG_NONE || wpa_key.key_len == 0)
1290
 
        {
1291
 
                struct ndis_remove_key ndis_remove_key;
1292
 
 
1293
 
                ndis_remove_key.struct_size = sizeof(ndis_remove_key);
1294
 
                ndis_remove_key.index = wpa_key.key_index;
1295
 
                if (wpa_key.addr)
1296
 
                        memcpy(&ndis_remove_key.bssid, addr,
1297
 
                               ETH_ALEN);
1298
 
                else
1299
 
                        memset(&ndis_remove_key.bssid, 0xff, ETH_ALEN);
1300
 
                res = dosetinfo(handle, NDIS_OID_REMOVE_KEY,
1301
 
                                (char *)&ndis_remove_key,
1302
 
                                sizeof(ndis_remove_key), &written, &needed);
1303
 
                if (res == NDIS_STATUS_INVALID_DATA)
1304
 
                {
1305
 
                        DBGTRACE("removing key failed with %08X, %d, %d",
1306
 
                               res, needed, sizeof(ndis_remove_key));
1307
 
                        TRACEEXIT(return -EINVAL);
1308
 
                }
1309
 
                if (wpa_key.key_index >= 0 &&
1310
 
                    wpa_key.key_index < MAX_ENCR_KEYS)
1311
 
                {
1312
 
                        handle->encr_info.keys[wpa_key.key_index].length = 0;
1313
 
                        if (wpa_key.key_index == handle->encr_info.active)
1314
 
                                set_encr_mode(handle, ENCR_DISABLED);
1315
 
                }
1316
 
 
1317
 
                TRACEEXIT(return 0);
1318
 
        }
1319
 
 
1320
 
        if (wpa_key.alg == WPA_ALG_WEP)
1321
 
        {
1322
 
                union iwreq_data encr_req;
1323
 
                unsigned char key[IW_ENCODING_TOKEN_MAX];
1324
 
                int i;
1325
 
 
 
1272
        if (wpa_key.alg == WPA_ALG_WEP) {
1326
1273
                if (test_bit(CAPA_ENCR_NONE, &handle->capa))
1327
 
                        TRACEEXIT(return -EINVAL);
1328
 
 
1329
 
                memset(&encr_req, 0, sizeof(encr_req));
1330
 
                encr_req.data.flags = wpa_key.key_index;
1331
 
                /* auth mode is set with set_auth_alg */
1332
 
                if (handle->auth_mode == AUTHMODE_OPEN)
1333
 
                        encr_req.data.flags |= IW_ENCODE_OPEN;
1334
 
                else
1335
 
                        encr_req.data.flags |= IW_ENCODE_RESTRICTED;
1336
 
                i = key_str_to_hex(usrkey, key, wpa_key.key_len);
1337
 
                if (i < 0)
1338
 
                        TRACEEXIT(return -EINVAL);
1339
 
                encr_req.data.length = i;
1340
 
                encr_req.data.pointer = key;
1341
 
                if (iw_set_encr(dev, info, &encr_req, key))
1342
 
                        TRACEEXIT(return -EINVAL);
1343
 
                else
1344
 
                        TRACEEXIT(return 0);
 
1274
                        TRACEEXIT2(return -1);
 
1275
 
 
1276
                if (wpa_key.set_tx)
 
1277
                        handle->encr_info.active = wpa_key.key_index;
 
1278
 
 
1279
                if (add_wep_key(handle, key, wpa_key.key_len,
 
1280
                                wpa_key.key_index))
 
1281
                        TRACEEXIT2(return -1);
 
1282
                else
 
1283
                        TRACEEXIT2(return 0);
1345
1284
        }
1346
1285
 
1347
1286
        /* alg is either WPA_ALG_TKIP or WPA_ALG_CCMP */
1348
1287
        if (!test_bit(CAPA_WPA, &handle->capa))
1349
 
                TRACEEXIT1(return -EINVAL);
 
1288
                TRACEEXIT2(return -1);
1350
1289
 
1351
 
        if (wpa_key.key_len > sizeof(ndis_key.key))
1352
 
        {
1353
 
                DBGTRACE("incorrect key length (%d)", wpa_key.key_len);
1354
 
                TRACEEXIT1(return -EINVAL);
 
1290
        if (wpa_key.key_len > sizeof(ndis_key.key)) {
 
1291
                DBGTRACE2("incorrect key length (%ld)", wpa_key.key_len);
 
1292
                TRACEEXIT2(return -1);
1355
1293
        }
1356
1294
        
1357
 
        DBGTRACE("adding key %d, %d", wpa_key.key_index, wpa_key.key_len);
 
1295
        if (wpa_key.seq_len > IW_ENCODING_TOKEN_MAX) {
 
1296
                DBGTRACE2("incorrect seq? length = (%ld)", wpa_key.seq_len);
 
1297
                TRACEEXIT2(return -1);
 
1298
        }
 
1299
 
 
1300
        DBGTRACE2("setting key %d, %ld", wpa_key.key_index, wpa_key.key_len);
1358
1301
        memset(&ndis_key, 0, sizeof(ndis_key));
1359
1302
 
1360
 
        if (wpa_key.key_len > IW_ENCODING_TOKEN_MAX)
1361
 
        {
1362
 
                DBGTRACE1("incorrect key? length = (%d)", wpa_key.key_len);
1363
 
                TRACEEXIT1(return -EINVAL);
1364
 
        }
1365
 
        memcpy(&ndis_key.key, usrkey, wpa_key.key_len);
1366
 
 
1367
1303
        ndis_key.struct_size = sizeof(ndis_key);
1368
1304
        ndis_key.length = wpa_key.key_len;
1369
 
 
1370
 
        if (wpa_key.seq_len > IW_ENCODING_TOKEN_MAX)
1371
 
        {
1372
 
                DBGTRACE1("incorrect seq? length = (%d)", wpa_key.seq_len);
1373
 
                TRACEEXIT1(return -EINVAL);
1374
 
        }
1375
 
 
1376
 
        for (i = 0, ndis_key.rsc = 0 ; i < wpa_key.seq_len ; i++)
1377
 
                ndis_key.rsc |= (seq[i] << (i * 8));
1378
 
 
1379
 
        if (wpa_key.key_index == 0) /* pairwise key */
1380
 
                ndis_key.index = (1 << 31) | (1 << 30);
1381
 
        else
1382
 
                ndis_key.index = wpa_key.key_index;
1383
 
 
1384
 
        if (!memcmp(&addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN))
1385
 
        {
1386
 
                mac_address ap_addr;
1387
 
 
1388
 
                get_ap_address(handle, ap_addr);
1389
 
                memcpy(&ndis_key.bssid, &ap_addr, ETH_ALEN);
1390
 
        }
1391
 
        else
 
1305
        ndis_key.index = wpa_key.key_index;
 
1306
 
 
1307
        if (wpa_key.seq && wpa_key.seq_len > 0) {
 
1308
                for (i = 0, ndis_key.rsc = 0 ; i < wpa_key.seq_len ; i++)
 
1309
                        ndis_key.rsc |= (seq[i] << (i * 8));
 
1310
 
 
1311
                ndis_key.index |= 1 << 29;
 
1312
        }
 
1313
 
 
1314
        if (wpa_key.addr == NULL || memcmp(addr, "\xff\xff\xff\xff\xff\xff",
 
1315
                                   ETH_ALEN) == 0) {
 
1316
                /* group key */
 
1317
                get_ap_address(handle, ndis_key.bssid);
 
1318
        } else {
 
1319
                /* pairwise key */
 
1320
                ndis_key.index |= (1 << 30);
1392
1321
                memcpy(&ndis_key.bssid, addr, ETH_ALEN);
1393
 
        DBGTRACE("bssid " MACSTR, MAC2STR(ndis_key.bssid));
1394
 
 
1395
 
        if (wpa_key.alg == WPA_ALG_TKIP && wpa_key.key_len == 32)
1396
 
        {
 
1322
        }
 
1323
                
 
1324
        DBGTRACE2("bssid " MACSTR, MAC2STR(ndis_key.bssid));
 
1325
 
 
1326
        if (wpa_key.set_tx)
 
1327
                ndis_key.index |= (1 << 31);
 
1328
 
 
1329
        if (wpa_key.alg == WPA_ALG_TKIP && wpa_key.key_len == 32) {
1397
1330
                /* wpa_supplicant gives us the Michael MIC RX/TX keys in
1398
1331
                 * different order than NDIS spec, so swap the order here. */
1399
 
                u8 tmp[8];
1400
 
                memcpy(tmp, ndis_key.key + 16, 8);
1401
 
                memcpy(ndis_key.key + 16, ndis_key.key + 24, 8);
1402
 
                memcpy(ndis_key.key + 24, tmp, 8);
1403
 
        }
1404
 
 
1405
 
        res = dosetinfo(handle, NDIS_OID_ADD_KEY, (char *)&ndis_key,
1406
 
                        ndis_key.struct_size, &written, &needed);
1407
 
        if (res == NDIS_STATUS_INVALID_DATA)
1408
 
        {
1409
 
                DBGTRACE("adding key failed (%08X), %d, %d, %lu",
1410
 
                         res, written, needed, ndis_key.struct_size);
1411
 
                TRACEEXIT(return -EINVAL);
1412
 
        }
1413
 
        memcpy(&handle->encr_info.keys[wpa_key.key_index].key, &ndis_key.key,
1414
 
               NDIS_ENCODING_TOKEN_MAX);
1415
 
        handle->encr_info.keys[wpa_key.key_index].length = 
1416
 
                wpa_key.key_len;
1417
 
        TRACEEXIT(return 0);
 
1332
                memcpy(ndis_key.key, key, 16);
 
1333
                memcpy(ndis_key.key + 16, key + 24, 8);
 
1334
                memcpy(ndis_key.key + 24, key + 16, 8);
 
1335
        } else
 
1336
                memcpy(ndis_key.key, key, wpa_key.key_len);
 
1337
 
 
1338
        if (wpa_key.alg == WPA_ALG_NONE || wpa_key.key_len == 0) {
 
1339
                /* TI driver crashes kernel if NDIS_OID_REMOVE_KEY is
 
1340
                 * called; other drivers seem to not require it, so
 
1341
                 * for now, don't remove the key from drvier */
 
1342
                handle->encr_info.keys[wpa_key.key_index].length = 0;
 
1343
                memset(&handle->encr_info.keys[wpa_key.key_index].key, 0,
 
1344
                       wpa_key.key_len);
 
1345
                DBGTRACE2("key %d removed", wpa_key.key_index);
 
1346
        } else {
 
1347
                res = miniport_set_info(handle, NDIS_OID_ADD_KEY,
 
1348
                                        (char *)&ndis_key, sizeof(ndis_key));
 
1349
                if (res == NDIS_STATUS_INVALID_DATA) {
 
1350
                        DBGTRACE2("adding key failed (%08X), %u",
 
1351
                                  res, ndis_key.struct_size);
 
1352
                        TRACEEXIT2(return -1);
 
1353
                }
 
1354
                handle->encr_info.keys[wpa_key.key_index].length = 
 
1355
                        wpa_key.key_len;
 
1356
                memcpy(&handle->encr_info.keys[wpa_key.key_index].key,
 
1357
                       &ndis_key.key, wpa_key.key_len);
 
1358
                DBGTRACE2("key %d added", wpa_key.key_index);
 
1359
        }
 
1360
 
 
1361
        TRACEEXIT2(return 0);
1418
1362
}
1419
1363
 
1420
1364
static int wpa_disassociate(struct net_device *dev,
1423
1367
{
1424
1368
        struct ndis_handle *handle = (struct ndis_handle *)dev->priv;
1425
1369
        mac_address ap_addr;
 
1370
        unsigned char buf[NDIS_ESSID_MAX_SIZE];
 
1371
        int i;
1426
1372
        
1427
 
        TRACEENTER("%s", "");
1428
 
        get_ap_address(handle, ap_addr);
1429
 
        DBGTRACE("bssid " MACSTR, MAC2STR(ap_addr));
1430
 
        /* FIXME: clear keys, essid etc. */
1431
 
        /* calling NDIS_OID_DISASSOCIATE here turns off the radio and further
1432
 
         * communication is not possible */
1433
 
//      if (doreset(handle))
1434
 
//              TRACEEXIT(return -EOPNOTSUPP);
1435
 
 
1436
 
        /* we set an impossible essid to disassociate - see note in
1437
 
         * iw_set_essid; setting an empty essid doesn't disassociate */
1438
 
        set_essid(handle, " ", 1);
1439
 
        get_ap_address(handle, ap_addr);
1440
 
        DBGTRACE("bssid " MACSTR, MAC2STR(ap_addr));
1441
 
        TRACEEXIT(return 0);
 
1373
        TRACEENTER2("%s", "");
 
1374
        get_random_bytes(buf, sizeof(buf));
 
1375
        for (i = 0; i < sizeof(buf); i++)
 
1376
                buf[i] = 'a' + (buf[i] % ('z' - 'a'));
 
1377
        set_essid(handle, buf, sizeof(buf));
 
1378
        get_ap_address(handle, ap_addr);
 
1379
        if (memcmp(ap_addr, "\x00\x00\x00\x00\x00\x00", ETH_ALEN))
 
1380
                TRACEEXIT2(return -1);
 
1381
        else
 
1382
                TRACEEXIT2(return 0);
1442
1383
}
1443
1384
 
1444
1385
static int wpa_associate(struct net_device *dev,
1447
1388
{
1448
1389
        struct ndis_handle *handle = (struct ndis_handle *)dev->priv;
1449
1390
        struct wpa_assoc_info wpa_assoc_info;
1450
 
        char ssid[NDIS_ESSID_MAX_SIZE];
 
1391
        char ssid[NDIS_ESSID_MAX_SIZE], ie;
 
1392
        int auth_mode, encr_mode, wpa2 = 0;
1451
1393
        
1452
 
        TRACEENTER("%s", "");
1453
 
        copy_from_user(&wpa_assoc_info, wrqu->data.pointer,
1454
 
                       sizeof(wpa_assoc_info));
 
1394
        TRACEENTER2("%s", "");
 
1395
        if (copy_from_user(&wpa_assoc_info, wrqu->data.pointer,
 
1396
                           sizeof(wpa_assoc_info)) ||
 
1397
            copy_from_user(&ssid, wpa_assoc_info.ssid, NDIS_ESSID_MAX_SIZE))
 
1398
                TRACEEXIT1(return -1);
1455
1399
 
1456
 
        if(wpa_assoc_info.ssid)
1457
 
                copy_from_user(&ssid, wpa_assoc_info.ssid, NDIS_ESSID_MAX_SIZE);
 
1400
        if (wpa_assoc_info.wpa_ie_len > 0 &&
 
1401
            copy_from_user(&ie, wpa_assoc_info.wpa_ie, 1) == 0 &&
 
1402
            ie == WLAN_EID_RSN) {
 
1403
                wpa2 = 1;
 
1404
        }
1458
1405
        
1459
 
        DBGTRACE("key_mgmt_suite = %d, pairwise_suite = %d, group_suite= %d",
1460
 
                 wpa_assoc_info.key_mgmt_suite,
1461
 
                 wpa_assoc_info.pairwise_suite, wpa_assoc_info.group_suite);
 
1406
        DBGTRACE1("key_mgmt_suite = %d, pairwise_suite = %d, group_suite= %d",
 
1407
                  wpa_assoc_info.key_mgmt_suite,
 
1408
                  wpa_assoc_info.pairwise_suite, wpa_assoc_info.group_suite);
1462
1409
        if (wpa_assoc_info.key_mgmt_suite != KEY_MGMT_PSK &&
 
1410
            wpa_assoc_info.key_mgmt_suite != KEY_MGMT_802_1X &&
1463
1411
            wpa_assoc_info.key_mgmt_suite != KEY_MGMT_NONE)
1464
 
                TRACEEXIT(return -EINVAL);
1465
 
 
1466
 
        switch (wpa_assoc_info.key_mgmt_suite)
1467
 
        {
 
1412
                TRACEEXIT2(return -1);
 
1413
 
 
1414
        switch (wpa_assoc_info.pairwise_suite) {
 
1415
        case CIPHER_CCMP:
 
1416
                if (!test_bit(CAPA_AES, &handle->capa))
 
1417
                        TRACEEXIT2(return -1);
 
1418
                encr_mode = ENCR3_ENABLED;
 
1419
                break;
 
1420
        case CIPHER_TKIP:
 
1421
                if (!test_bit(CAPA_TKIP, &handle->capa))
 
1422
                        TRACEEXIT2(return -1);
 
1423
                encr_mode =  ENCR2_ENABLED;
 
1424
                break;
 
1425
        case CIPHER_WEP104:
 
1426
        case CIPHER_WEP40:
 
1427
                if (test_bit(CAPA_ENCR_NONE, &handle->capa))
 
1428
                        TRACEEXIT2(return -1);
 
1429
                encr_mode = ENCR1_ENABLED;
 
1430
                break;
 
1431
        default:
 
1432
                TRACEEXIT2(return -1);
 
1433
        }
 
1434
 
 
1435
        switch (wpa_assoc_info.key_mgmt_suite) {
1468
1436
        case KEY_MGMT_PSK:
1469
 
                if (set_auth_mode(handle, AUTHMODE_WPAPSK))
1470
 
                        TRACEEXIT(return -EINVAL);
 
1437
                if (!test_bit(CAPA_WPA, &handle->capa))
 
1438
                        TRACEEXIT2(return -1);
 
1439
                auth_mode = wpa2 ? AUTHMODE_WPA2PSK : AUTHMODE_WPAPSK;
 
1440
                break;
 
1441
        case KEY_MGMT_802_1X:
 
1442
                if (!test_bit(CAPA_WPA, &handle->capa))
 
1443
                        TRACEEXIT2(return -1);
 
1444
                auth_mode = wpa2 ? AUTHMODE_WPA2 : AUTHMODE_WPA;
1471
1445
                break;
1472
1446
        case KEY_MGMT_NONE:
1473
1447
                if (wpa_assoc_info.group_suite != CIPHER_WEP104 &&
1474
1448
                    wpa_assoc_info.group_suite != CIPHER_WEP40)
1475
 
                        TRACEEXIT(return -EINVAL);
1476
 
                break;
1477
 
        default:
1478
 
                TRACEEXIT(return -EINVAL);
1479
 
        }
1480
 
 
1481
 
        switch (wpa_assoc_info.group_suite)
1482
 
        {
1483
 
        case CIPHER_CCMP:
1484
 
                if (!test_bit(CAPA_AES, &handle->capa) ||
1485
 
                    set_encr_mode(handle, ENCR3_ENABLED))
1486
 
                        TRACEEXIT(return -EINVAL);
1487
 
                break;
1488
 
        case CIPHER_TKIP:
1489
 
                if (!test_bit(CAPA_WPA, &handle->capa) ||
1490
 
                    set_encr_mode(handle, ENCR2_ENABLED))
1491
 
                        TRACEEXIT(return -EINVAL);
1492
 
                break;
1493
 
        case CIPHER_WEP104:
1494
 
        case CIPHER_WEP40:
1495
 
                if (test_bit(CAPA_ENCR_NONE, &handle->capa))
1496
 
                        TRACEEXIT(return -EINVAL);
1497
 
                break;
1498
 
        default:
1499
 
                TRACEEXIT(return -EINVAL);
1500
 
        }
1501
 
 
 
1449
                        TRACEEXIT2(return -1);
 
1450
                auth_mode = handle->auth_mode;
 
1451
#if 0
 
1452
                if (wpa_assoc_info.auth_alg & AUTH_ALG_SHARED_KEY)
 
1453
                        auth_mode = AUTHMODE_RESTRICTED;
 
1454
                else
 
1455
                        auth_mode = AUTHMODE_OPEN;
 
1456
#endif
 
1457
                break;
 
1458
        default:
 
1459
                TRACEEXIT2(return -1);
 
1460
        }
 
1461
 
 
1462
        if (set_auth_mode(handle, auth_mode))
 
1463
                TRACEEXIT2(return -1);
 
1464
        if (set_encr_mode(handle, encr_mode))
 
1465
                TRACEEXIT2(return -1);
 
1466
 
 
1467
#if 0
 
1468
        /* set channel */
 
1469
        for (i = 0; i < (sizeof(freq_chan)/sizeof(freq_chan[0])); i++) {
 
1470
                if (wpa_assoc_info.freq == freq_chan[i]) {
 
1471
                        union iwreq_data freq_req;
 
1472
 
 
1473
                        memset(&freq_req, 0, sizeof(freq_req));
 
1474
                        freq_req.freq.m = i;
 
1475
                        if (iw_set_freq(dev, NULL, &freq_req, NULL))
 
1476
                                TRACEEXIT2(return -1);
 
1477
                }
 
1478
        }
 
1479
#endif
 
1480
 
 
1481
        /* set ssid */
1502
1482
        if (set_essid(handle, ssid, wpa_assoc_info.ssid_len))
1503
 
                TRACEEXIT(return -EINVAL);
 
1483
                TRACEEXIT2(return -1);
1504
1484
 
1505
 
        TRACEEXIT(return 0);
 
1485
        TRACEEXIT2(return 0);
1506
1486
}
1507
1487
 
1508
1488
static int wpa_set_countermeasures(struct net_device *dev,
1509
1489
                                   struct iw_request_info *info,
1510
1490
                                   union iwreq_data *wrqu, char *extra)
1511
1491
{
1512
 
        TRACEENTER("%s", "");
 
1492
        TRACEENTER2("%s", "");
1513
1493
        return 0;
1514
1494
}
1515
1495
 
1517
1497
                              struct iw_request_info *info,
1518
1498
                              union iwreq_data *wrqu, char *extra)
1519
1499
{
1520
 
        struct ndis_handle *handle = (struct ndis_handle *)dev->priv;
1521
 
        mac_address ap_addr;
 
1500
        int ret;
1522
1501
        
1523
 
        TRACEENTER("%s", "");
1524
 
        get_ap_address(handle, ap_addr);
1525
 
        DBGTRACE("bssid " MACSTR, MAC2STR(ap_addr));
1526
 
        /* FIXME: clear keys, essid etc. */
1527
 
        /* calling NDIS_OID_DISASSOCIATE here turns off the radio and further
1528
 
         * communication is not possible, so do a reset */
1529
 
//      if (doreset(handle))
1530
 
//              TRACEEXIT(return -EOPNOTSUPP);
1531
 
 
1532
 
        /* we set an impossible essid to disassociate - see note in
1533
 
         * iw_set_essid; setting an empty essid doesn't disassociate */
1534
 
        set_essid(handle, " ", 1);
1535
 
        get_ap_address(handle, ap_addr);
1536
 
        DBGTRACE("bssid " MACSTR, MAC2STR(ap_addr));
1537
 
        TRACEEXIT(return 0);
 
1502
        TRACEENTER2("%s", "");
 
1503
        ret = wpa_disassociate(dev, info, wrqu, extra);
 
1504
        TRACEEXIT2(return ret);
1538
1505
}
1539
1506
 
1540
1507
int set_privacy_filter(struct ndis_handle *handle, int flags)
1541
1508
{
1542
1509
        int res;
1543
1510
 
1544
 
        TRACEENTER("filter: %d", flags);
1545
 
        res = set_int(handle, NDIS_OID_PRIVACY_FILTER, flags);
1546
 
        if (res == NDIS_STATUS_INVALID_DATA)
1547
 
        {
 
1511
        TRACEENTER2("filter: %d", flags);
 
1512
        res = miniport_set_int(handle, NDIS_OID_PRIVACY_FILTER, flags);
 
1513
        if (res == NDIS_STATUS_INVALID_DATA) {
1548
1514
                WARNING("setting privacy filter to %d failed (%08X)",
1549
1515
                        flags, res);
1550
 
                TRACEEXIT(return -EINVAL);
 
1516
                TRACEEXIT2(return -EINVAL);
1551
1517
        }
1552
 
        TRACEEXIT(return 0);
 
1518
        TRACEEXIT2(return 0);
1553
1519
}
1554
1520
 
1555
1521
static int wpa_set_privacy_filter(struct net_device *dev,
1559
1525
        struct ndis_handle *handle = (struct ndis_handle *)dev->priv;
1560
1526
        int flags;
1561
1527
 
1562
 
        TRACEENTER("filter: %d", wrqu->param.value);
 
1528
        TRACEENTER2("filter: %d", wrqu->param.value);
1563
1529
        if (wrqu->param.value)
1564
1530
                flags = NDIS_PRIV_WEP;
1565
1531
        else
1566
1532
                flags = NDIS_PRIV_ACCEPT_ALL;
1567
1533
        if (set_privacy_filter(handle, flags))
1568
 
                TRACEEXIT(return -EINVAL);
1569
 
        TRACEEXIT(return 0);
 
1534
                TRACEEXIT2(return -1);
 
1535
        TRACEEXIT2(return 0);
1570
1536
}
1571
1537
 
1572
1538
static int wpa_set_auth_alg(struct net_device *dev,
1576
1542
        struct ndis_handle *handle = (struct ndis_handle *)dev->priv;
1577
1543
        int mode;
1578
1544
        
1579
 
        if (wrqu->param.value == AUTH_ALG_OPEN_SYSTEM)
 
1545
        if (wrqu->param.value & AUTH_ALG_SHARED_KEY)
 
1546
                mode = AUTHMODE_RESTRICTED;
 
1547
        else if (wrqu->param.value & AUTH_ALG_OPEN_SYSTEM)
1580
1548
                mode = AUTHMODE_OPEN;
1581
 
        else if (wrqu->param.value == AUTH_ALG_SHARED_KEY)
1582
 
                mode = AUTHMODE_RESTRICTED;
1583
1549
        else
1584
 
                TRACEEXIT(return -EINVAL);
1585
 
 
1586
 
        /* wpa_supplicant assumes OPEN mode, but it won't work if RESTRCITED
1587
 
         * mode is used, so we try with AUTO mode always hoping the driver
1588
 
         * chooses what is appropriate */
1589
 
        if (set_auth_mode(handle, AUTHMODE_AUTO))
1590
 
                TRACEEXIT(return -EINVAL);
1591
 
        TRACEEXIT(return 0);
 
1550
                TRACEEXIT2(return -1);
 
1551
 
 
1552
        DBGTRACE2("%d", mode);
 
1553
 
 
1554
        if (set_auth_mode(handle, mode))
 
1555
                TRACEEXIT2(return -1);
 
1556
        TRACEEXIT2(return 0);
1592
1557
}
1593
1558
 
1594
1559
static const struct iw_priv_args priv_args[] = {