Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[linux-2.6] / drivers / staging / wlan-ng / p80211wext.c
1 /* src/p80211/p80211wext.c
2 *
3 * Glue code to make linux-wlan-ng a happy wireless extension camper.
4 *
5 * original author:  Reyk Floeter <reyk@synack.de>
6 * Completely re-written by Solomon Peachy <solomon@linux-wlan.com>
7 *
8 * Copyright (C) 2002 AbsoluteValue Systems, Inc.  All Rights Reserved.
9 * --------------------------------------------------------------------
10 *
11 * linux-wlan
12 *
13 *   The contents of this file are subject to the Mozilla Public
14 *   License Version 1.1 (the "License"); you may not use this file
15 *   except in compliance with the License. You may obtain a copy of
16 *   the License at http://www.mozilla.org/MPL/
17 *
18 *   Software distributed under the License is distributed on an "AS
19 *   IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
20 *   implied. See the License for the specific language governing
21 *   rights and limitations under the License.
22 *
23 *   Alternatively, the contents of this file may be used under the
24 *   terms of the GNU Public License version 2 (the "GPL"), in which
25 *   case the provisions of the GPL are applicable instead of the
26 *   above.  If you wish to allow the use of your version of this file
27 *   only under the terms of the GPL and not to allow others to use
28 *   your version of this file under the MPL, indicate your decision
29 *   by deleting the provisions above and replace them with the notice
30 *   and other provisions required by the GPL.  If you do not delete
31 *   the provisions above, a recipient may use your version of this
32 *   file under either the MPL or the GPL.
33 *
34 * --------------------------------------------------------------------
35 */
36
37 /*================================================================*/
38 /* System Includes */
39
40
41 #include <linux/version.h>
42
43 #include <linux/kernel.h>
44 #include <linux/sched.h>
45 #include <linux/types.h>
46 #include <linux/slab.h>
47 #include <linux/netdevice.h>
48 #include <linux/etherdevice.h>
49 #include <linux/wireless.h>
50 #if WIRELESS_EXT > 12
51 #include <net/iw_handler.h>
52 #endif
53 #include <linux/if_arp.h>
54 #include <asm/bitops.h>
55 #include <asm/uaccess.h>
56 #include <asm/byteorder.h>
57
58 /*================================================================*/
59 /* Project Includes */
60
61 #include "version.h"
62 #include "wlan_compat.h"
63
64 #include "p80211types.h"
65 #include "p80211hdr.h"
66 #include "p80211conv.h"
67 #include "p80211mgmt.h"
68 #include "p80211msg.h"
69 #include "p80211metastruct.h"
70 #include "p80211metadef.h"
71 #include "p80211netdev.h"
72 #include "p80211ioctl.h"
73 #include "p80211req.h"
74
75 static int p80211wext_giwrate(netdevice_t *dev,
76                               struct iw_request_info *info,
77                               struct iw_param *rrq, char *extra);
78 static int p80211wext_giwessid(netdevice_t *dev,
79                                struct iw_request_info *info,
80                                struct iw_point *data, char *essid);
81 /* compatibility to wireless extensions */
82 #ifdef WIRELESS_EXT
83
84 static UINT8 p80211_mhz_to_channel(UINT16 mhz)
85 {
86         if (mhz >= 5000) {
87                 return ((mhz - 5000) / 5);
88         }
89
90         if (mhz == 2482)
91                 return 14;
92
93         if (mhz >= 2407) {
94                 return ((mhz - 2407) / 5);
95         }
96
97         return 0;
98 }
99
100 static UINT16 p80211_channel_to_mhz(UINT8 ch, int dot11a)
101 {
102
103         if (ch == 0)
104                 return 0;
105         if (ch > 200)
106                 return 0;
107
108         /* 5G */
109
110         if (dot11a) {
111                 return (5000 + (5 * ch));
112         }
113
114         /* 2.4G */
115
116         if (ch == 14)
117                 return 2484;
118
119         if ((ch < 14) && (ch > 0)) {
120                 return (2407 + (5 * ch));
121         }
122
123         return 0;
124 }
125
126 /* taken from orinoco.c ;-) */
127 static const long p80211wext_channel_freq[] = {
128         2412, 2417, 2422, 2427, 2432, 2437, 2442,
129         2447, 2452, 2457, 2462, 2467, 2472, 2484
130 };
131 #define NUM_CHANNELS (sizeof(p80211wext_channel_freq) / sizeof(p80211wext_channel_freq[0]))
132
133 /* steal a spare bit to store the shared/opensystems state. should default to open if not set */
134 #define HOSTWEP_SHAREDKEY BIT3
135
136
137 /** function declarations =============== */
138
139 static int qual_as_percent(int snr ) {
140   if ( snr <= 0 )
141     return 0;
142   if ( snr <= 40 )
143     return snr*5/2;
144   return 100;
145 }
146
147
148
149
150 static int p80211wext_dorequest(wlandevice_t *wlandev, UINT32 did, UINT32 data)
151 {
152         p80211msg_dot11req_mibset_t     msg;
153         p80211item_uint32_t             mibitem;
154         int     result;
155
156         DBFENTER;
157
158         msg.msgcode = DIDmsg_dot11req_mibset;
159         mibitem.did = did;
160         mibitem.data = data;
161         memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
162         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
163
164         DBFEXIT;
165         return result;
166 }
167
168 static int p80211wext_autojoin(wlandevice_t *wlandev)
169 {
170         p80211msg_lnxreq_autojoin_t     msg;
171         struct iw_point                 data;
172         char ssid[IW_ESSID_MAX_SIZE];
173
174         int result;
175         int err = 0;
176
177         DBFENTER;
178
179         /* Get ESSID */
180         result = p80211wext_giwessid(wlandev->netdev, NULL, &data, ssid);
181
182         if (result) {
183                 err = -EFAULT;
184                 goto exit;
185         }
186
187         if ( wlandev->hostwep & HOSTWEP_SHAREDKEY )
188           msg.authtype.data = P80211ENUM_authalg_sharedkey;
189         else
190           msg.authtype.data = P80211ENUM_authalg_opensystem;
191
192         msg.msgcode = DIDmsg_lnxreq_autojoin;
193
194         /* Trim the last '\0' to fit the SSID format */
195
196         if (data.length && ssid[data.length-1] == '\0') {
197                 data.length = data.length - 1;
198         }
199
200         memcpy(msg.ssid.data.data, ssid, data.length);
201         msg.ssid.data.len = data.length;
202
203         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
204
205         if (result) {
206                 err = -EFAULT;
207                 goto exit;
208         }
209
210 exit:
211
212         DBFEXIT;
213         return err;
214
215 }
216
217 /* called by /proc/net/wireless */
218 struct iw_statistics* p80211wext_get_wireless_stats (netdevice_t *dev)
219 {
220         p80211msg_lnxreq_commsquality_t  quality;
221         wlandevice_t *wlandev = dev->ml_priv;
222         struct iw_statistics* wstats = &wlandev->wstats;
223         int retval;
224
225         DBFENTER;
226         /* Check */
227         if ( (wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING) )
228                 return NULL;
229
230         /* XXX Only valid in station mode */
231         wstats->status = 0;
232
233         /* build request message */
234         quality.msgcode = DIDmsg_lnxreq_commsquality;
235         quality.dbm.data = P80211ENUM_truth_true;
236         quality.dbm.status = P80211ENUM_msgitem_status_data_ok;
237
238         /* send message to nsd */
239         if ( wlandev->mlmerequest == NULL )
240                 return NULL;
241
242         retval = wlandev->mlmerequest(wlandev, (p80211msg_t*) &quality);
243
244         wstats->qual.qual = qual_as_percent(quality.link.data);    /* overall link quality */
245         wstats->qual.level = quality.level.data;  /* instant signal level */
246         wstats->qual.noise = quality.noise.data;  /* instant noise level */
247
248 #if WIRELESS_EXT > 18
249         wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
250 #else
251         wstats->qual.updated = 7;
252 #endif
253         wstats->discard.code = wlandev->rx.decrypt_err;
254         wstats->discard.nwid = 0;
255         wstats->discard.misc = 0;
256
257 #if WIRELESS_EXT > 11
258         wstats->discard.fragment = 0;  // incomplete fragments
259         wstats->discard.retries = 0;   // tx retries.
260         wstats->miss.beacon = 0;
261 #endif
262
263         DBFEXIT;
264
265         return wstats;
266 }
267
268 static int p80211wext_giwname(netdevice_t *dev,
269                               struct iw_request_info *info,
270                               char *name, char *extra)
271 {
272         struct iw_param rate;
273         int result;
274         int err = 0;
275
276         DBFENTER;
277
278         result = p80211wext_giwrate(dev, NULL, &rate, NULL);
279
280         if (result) {
281                 err = -EFAULT;
282                 goto exit;
283         }
284
285         switch (rate.value) {
286         case 1000000:
287         case 2000000:
288                 strcpy(name, "IEEE 802.11-DS");
289                 break;
290         case 5500000:
291         case 11000000:
292                 strcpy(name, "IEEE 802.11-b");
293                 break;
294         }
295 exit:
296         DBFEXIT;
297         return err;
298 }
299
300 static int p80211wext_giwfreq(netdevice_t *dev,
301                               struct iw_request_info *info,
302                               struct iw_freq *freq, char *extra)
303 {
304         wlandevice_t *wlandev = dev->ml_priv;
305         p80211item_uint32_t             mibitem;
306         p80211msg_dot11req_mibset_t     msg;
307         int result;
308         int err = 0;
309
310         DBFENTER;
311
312         msg.msgcode = DIDmsg_dot11req_mibget;
313         mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
314         memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
315         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
316
317         if (result) {
318                 err = -EFAULT;
319                 goto exit;
320         }
321
322         memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
323
324         if (mibitem.data > NUM_CHANNELS) {
325                 err = -EFAULT;
326                 goto exit;
327         }
328
329         /* convert into frequency instead of a channel */
330         freq->e = 1;
331         freq->m = p80211_channel_to_mhz(mibitem.data, 0) * 100000;
332
333  exit:
334         DBFEXIT;
335         return err;
336 }
337
338 static int p80211wext_siwfreq(netdevice_t *dev,
339                               struct iw_request_info *info,
340                               struct iw_freq *freq, char *extra)
341 {
342         wlandevice_t *wlandev = dev->ml_priv;
343         p80211item_uint32_t             mibitem;
344         p80211msg_dot11req_mibset_t     msg;
345         int result;
346         int err = 0;
347
348         DBFENTER;
349
350         if (!wlan_wext_write) {
351                 err = (-EOPNOTSUPP);
352                 goto exit;
353         }
354
355         msg.msgcode = DIDmsg_dot11req_mibset;
356         mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
357         mibitem.status = P80211ENUM_msgitem_status_data_ok;
358
359         if ( (freq->e == 0) && (freq->m <= 1000) )
360                 mibitem.data = freq->m;
361         else
362                 mibitem.data = p80211_mhz_to_channel(freq->m);
363
364         memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
365         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
366
367         if (result) {
368                 err = -EFAULT;
369                 goto exit;
370         }
371
372  exit:
373         DBFEXIT;
374         return err;
375 }
376
377 #if WIRELESS_EXT > 8
378
379 static int p80211wext_giwmode(netdevice_t *dev,
380                               struct iw_request_info *info,
381                               __u32 *mode, char *extra)
382 {
383         wlandevice_t *wlandev = dev->ml_priv;
384
385         DBFENTER;
386
387         switch (wlandev->macmode) {
388         case WLAN_MACMODE_IBSS_STA:
389                 *mode = IW_MODE_ADHOC;
390                 break;
391         case WLAN_MACMODE_ESS_STA:
392                 *mode = IW_MODE_INFRA;
393                 break;
394         case WLAN_MACMODE_ESS_AP:
395                 *mode = IW_MODE_MASTER;
396                 break;
397         default:
398                 /* Not set yet. */
399                 *mode = IW_MODE_AUTO;
400         }
401
402         DBFEXIT;
403         return 0;
404 }
405
406 static int p80211wext_siwmode(netdevice_t *dev,
407                               struct iw_request_info *info,
408                               __u32 *mode, char *extra)
409 {
410         wlandevice_t *wlandev = dev->ml_priv;
411         p80211item_uint32_t             mibitem;
412         p80211msg_dot11req_mibset_t     msg;
413         int     result;
414         int     err = 0;
415
416         DBFENTER;
417
418         if (!wlan_wext_write) {
419                 err = (-EOPNOTSUPP);
420                 goto exit;
421         }
422
423         if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA &&
424             *mode != IW_MODE_MASTER) {
425                 err = (-EOPNOTSUPP);
426                 goto exit;
427         }
428
429         /* Operation mode is the same with current mode */
430         if (*mode == wlandev->macmode)
431                 goto exit;
432
433         switch (*mode) {
434         case IW_MODE_ADHOC:
435                 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
436                 break;
437         case IW_MODE_INFRA:
438                 wlandev->macmode = WLAN_MACMODE_ESS_STA;
439                 break;
440         case IW_MODE_MASTER:
441                 wlandev->macmode = WLAN_MACMODE_ESS_AP;
442                 break;
443         default:
444                 /* Not set yet. */
445                 WLAN_LOG_INFO("Operation mode: %d not support\n", *mode);
446                 return -EOPNOTSUPP;
447         }
448
449         /* Set Operation mode to the PORT TYPE RID */
450
451 #warning "get rid of p2mib here"
452
453         msg.msgcode = DIDmsg_dot11req_mibset;
454         mibitem.did = DIDmib_p2_p2Static_p2CnfPortType;
455         mibitem.data = (*mode == IW_MODE_ADHOC) ? 0 : 1;
456         memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
457         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
458
459         if (result)
460                 err = -EFAULT;
461
462  exit:
463         DBFEXIT;
464
465         return err;
466 }
467
468
469 static int p80211wext_giwrange(netdevice_t *dev,
470                                struct iw_request_info *info,
471                                struct iw_point *data, char *extra)
472 {
473         struct iw_range *range = (struct iw_range *) extra;
474         int i, val;
475
476         DBFENTER;
477
478         // for backward compatability set size & zero everything we don't understand
479         data->length = sizeof(*range);
480         memset(range,0,sizeof(*range));
481
482 #if WIRELESS_EXT > 9
483         range->txpower_capa = IW_TXPOW_DBM;
484         // XXX what about min/max_pmp, min/max_pmt, etc.
485 #endif
486
487 #if WIRELESS_EXT > 10
488         range->we_version_compiled = WIRELESS_EXT;
489         range->we_version_source = 13;
490
491         range->retry_capa = IW_RETRY_LIMIT;
492         range->retry_flags = IW_RETRY_LIMIT;
493         range->min_retry = 0;
494         range->max_retry = 255;
495 #endif /* WIRELESS_EXT > 10 */
496
497 #if WIRELESS_EXT > 16
498         range->event_capa[0] = (IW_EVENT_CAPA_K_0 |  //mode/freq/ssid
499                                 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
500                                 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
501         range->event_capa[1] = IW_EVENT_CAPA_K_1;  //encode
502         range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL) |
503                                 IW_EVENT_CAPA_MASK(IWEVCUSTOM) );
504 #endif
505
506         range->num_channels = NUM_CHANNELS;
507
508         /* XXX need to filter against the regulatory domain &| active set */
509         val = 0;
510         for (i = 0; i < NUM_CHANNELS ; i++) {
511                 range->freq[val].i = i + 1;
512                 range->freq[val].m = p80211wext_channel_freq[i] * 100000;
513                 range->freq[val].e = 1;
514                 val++;
515         }
516
517         range->num_frequency = val;
518
519         /* Max of /proc/net/wireless */
520         range->max_qual.qual = 100;
521         range->max_qual.level = 0;
522         range->max_qual.noise = 0;
523         range->sensitivity = 3;
524         // XXX these need to be nsd-specific!
525
526         range->min_rts = 0;
527         range->max_rts = 2347;
528         range->min_frag = 256;
529         range->max_frag = 2346;
530
531         range->max_encoding_tokens = NUM_WEPKEYS;
532         range->num_encoding_sizes = 2;
533         range->encoding_size[0] = 5;
534         range->encoding_size[1] = 13;
535
536         // XXX what about num_bitrates/throughput?
537         range->num_bitrates = 0;
538
539         /* estimated max throughput */
540         // XXX need to cap it if we're running at ~2Mbps..
541         range->throughput = 5500000;
542
543         DBFEXIT;
544         return 0;
545 }
546 #endif
547
548 static int p80211wext_giwap(netdevice_t *dev,
549                             struct iw_request_info *info,
550                             struct sockaddr *ap_addr, char *extra)
551 {
552
553         wlandevice_t *wlandev = dev->ml_priv;
554
555         DBFENTER;
556
557         memcpy(ap_addr->sa_data, wlandev->bssid, WLAN_BSSID_LEN);
558         ap_addr->sa_family = ARPHRD_ETHER;
559
560         DBFEXIT;
561         return 0;
562 }
563
564 #if WIRELESS_EXT > 8
565 static int p80211wext_giwencode(netdevice_t *dev,
566                                 struct iw_request_info *info,
567                                 struct iw_point *erq, char *key)
568 {
569         wlandevice_t *wlandev = dev->ml_priv;
570         int err = 0;
571         int i;
572
573         DBFENTER;
574
575         if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED)
576                 erq->flags = IW_ENCODE_ENABLED;
577         else
578                 erq->flags = IW_ENCODE_DISABLED;
579
580         if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED)
581                 erq->flags |= IW_ENCODE_RESTRICTED;
582         else
583                 erq->flags |= IW_ENCODE_OPEN;
584
585         i = (erq->flags & IW_ENCODE_INDEX) - 1;
586
587         if (i == -1)
588                 i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK;
589
590         if ((i < 0) || (i >= NUM_WEPKEYS)) {
591                 err = -EINVAL;
592                 goto exit;
593         }
594
595         erq->flags |= i + 1;
596
597         /* copy the key from the driver cache as the keys are read-only MIBs */
598         erq->length = wlandev->wep_keylens[i];
599         memcpy(key, wlandev->wep_keys[i], erq->length);
600
601  exit:
602         DBFEXIT;
603         return err;
604 }
605
606 static int p80211wext_siwencode(netdevice_t *dev,
607                                 struct iw_request_info *info,
608                                 struct iw_point *erq, char *key)
609 {
610         wlandevice_t *wlandev = dev->ml_priv;
611         p80211msg_dot11req_mibset_t     msg;
612         p80211item_pstr32_t             pstr;
613
614         int err = 0;
615         int result = 0;
616         int enable = 0;
617         int i;
618
619         DBFENTER;
620         if (!wlan_wext_write) {
621                 err = (-EOPNOTSUPP);
622                 goto exit;
623         }
624
625         /* Check the Key index first. */
626         if((i = (erq->flags & IW_ENCODE_INDEX))) {
627
628                 if ((i < 1) || (i > NUM_WEPKEYS)) {
629                         err = -EINVAL;
630                         goto exit;
631                 }
632                 else
633                         i--;
634
635                 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, i);
636
637                 if (result) {
638                         err = -EFAULT;
639                         goto exit;
640                 }
641                 else {
642                         enable = 1;
643                 }
644
645         }
646         else {
647                 // Do not thing when no Key Index
648         }
649
650         /* Check if there is no key information in the iwconfig request */
651         if((erq->flags & IW_ENCODE_NOKEY) == 0 && enable == 1) {
652
653                 /*------------------------------------------------------------
654                  * If there is WEP Key for setting, check the Key Information
655                  * and then set it to the firmware.
656                  -------------------------------------------------------------*/
657
658                 if (erq->length > 0) {
659
660                         /* copy the key from the driver cache as the keys are read-only MIBs */
661                         wlandev->wep_keylens[i] = erq->length;
662                         memcpy(wlandev->wep_keys[i], key, erq->length);
663
664                         /* Prepare data struture for p80211req_dorequest. */
665                         memcpy(pstr.data.data, key, erq->length);
666                         pstr.data.len = erq->length;
667
668                         switch(i)
669                         {
670                                 case 0:
671                                         pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
672                                         break;
673
674                                 case 1:
675                                         pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
676                                         break;
677
678                                 case 2:
679                                         pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
680                                         break;
681
682                                 case 3:
683                                         pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
684                                         break;
685
686                                 default:
687                                         err = -EINVAL;
688                                         goto exit;
689                         }
690
691                         msg.msgcode = DIDmsg_dot11req_mibset;
692                         memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr));
693                         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
694
695                         if (result) {
696                                 err = -EFAULT;
697                                 goto exit;
698                         }
699                 }
700
701         }
702
703         /* Check the PrivacyInvoked flag */
704         if (erq->flags & IW_ENCODE_DISABLED) {
705                 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false);
706         }
707         else if((erq->flags & IW_ENCODE_ENABLED) || enable == 1) {
708                 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
709         }
710
711         if (result) {
712                 err = -EFAULT;
713                 goto exit;
714         }
715
716         /* Check the ExcludeUnencrypted flag */
717         if (erq->flags & IW_ENCODE_RESTRICTED) {
718                 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true);
719         }
720         else if (erq->flags & IW_ENCODE_OPEN) {
721                 result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false);
722         }
723
724         if (result) {
725                 err = -EFAULT;
726                 goto exit;
727         }
728
729  exit:
730
731         DBFEXIT;
732         return err;
733 }
734
735 static int p80211wext_giwessid(netdevice_t *dev,
736                                struct iw_request_info *info,
737                                struct iw_point *data, char *essid)
738 {
739         wlandevice_t *wlandev = dev->ml_priv;
740
741         DBFENTER;
742
743         if (wlandev->ssid.len) {
744                 data->length = wlandev->ssid.len;
745                 data->flags = 1;
746                 memcpy(essid, wlandev->ssid.data, data->length);
747                 essid[data->length] = 0;
748 #if (WIRELESS_EXT < 21)
749                 data->length++;
750 #endif
751         } else {
752                 memset(essid, 0, sizeof(wlandev->ssid.data));
753                 data->length = 0;
754                 data->flags = 0;
755         }
756
757         DBFEXIT;
758         return 0;
759 }
760
761 static int p80211wext_siwessid(netdevice_t *dev,
762                                struct iw_request_info *info,
763                                struct iw_point *data, char *essid)
764 {
765         wlandevice_t *wlandev = dev->ml_priv;
766         p80211msg_lnxreq_autojoin_t     msg;
767
768         int result;
769         int err = 0;
770         int length = data->length;
771
772         DBFENTER;
773
774         if (!wlan_wext_write) {
775                 err = (-EOPNOTSUPP);
776                 goto exit;
777         }
778
779
780         if ( wlandev->hostwep & HOSTWEP_SHAREDKEY )
781           msg.authtype.data = P80211ENUM_authalg_sharedkey;
782         else
783           msg.authtype.data = P80211ENUM_authalg_opensystem;
784
785         msg.msgcode = DIDmsg_lnxreq_autojoin;
786
787 #if (WIRELESS_EXT < 21)
788         if (length) length--;
789 #endif
790
791         /* Trim the last '\0' to fit the SSID format */
792
793         if (length && essid[length-1] == '\0') {
794           length--;
795         }
796
797         memcpy(msg.ssid.data.data, essid, length);
798         msg.ssid.data.len = length;
799
800         WLAN_LOG_DEBUG(1,"autojoin_ssid for %s \n",essid);
801         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
802         WLAN_LOG_DEBUG(1,"autojoin_ssid %d\n",result);
803
804         if (result) {
805                 err = -EFAULT;
806                 goto exit;
807         }
808
809  exit:
810         DBFEXIT;
811         return err;
812 }
813
814
815 static int p80211wext_siwcommit(netdevice_t *dev,
816                                 struct iw_request_info *info,
817                                 struct iw_point *data, char *essid)
818 {
819         wlandevice_t *wlandev = dev->ml_priv;
820         int err = 0;
821
822         DBFENTER;
823
824         if (!wlan_wext_write) {
825                 err = (-EOPNOTSUPP);
826                 goto exit;
827         }
828
829         /* Auto Join */
830         err = p80211wext_autojoin(wlandev);
831
832  exit:
833         DBFEXIT;
834         return err;
835 }
836
837
838 static int p80211wext_giwrate(netdevice_t *dev,
839                               struct iw_request_info *info,
840                               struct iw_param *rrq, char *extra)
841 {
842         wlandevice_t *wlandev = dev->ml_priv;
843         p80211item_uint32_t             mibitem;
844         p80211msg_dot11req_mibset_t     msg;
845         int result;
846         int err = 0;
847
848         DBFENTER;
849
850         msg.msgcode = DIDmsg_dot11req_mibget;
851         mibitem.did = DIDmib_p2_p2MAC_p2CurrentTxRate;
852         memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
853         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
854
855         if (result) {
856                 err = -EFAULT;
857                 goto exit;
858         }
859
860         memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
861
862         rrq->fixed = 0;   /* can it change? */
863         rrq->disabled = 0;
864         rrq->value = 0;
865
866 #define         HFA384x_RATEBIT_1                       ((UINT16)1)
867 #define         HFA384x_RATEBIT_2                       ((UINT16)2)
868 #define         HFA384x_RATEBIT_5dot5                   ((UINT16)4)
869 #define         HFA384x_RATEBIT_11                      ((UINT16)8)
870
871         switch (mibitem.data) {
872         case HFA384x_RATEBIT_1:
873                 rrq->value = 1000000;
874                 break;
875         case HFA384x_RATEBIT_2:
876                 rrq->value = 2000000;
877                 break;
878         case HFA384x_RATEBIT_5dot5:
879                 rrq->value = 5500000;
880                 break;
881         case HFA384x_RATEBIT_11:
882                 rrq->value = 11000000;
883                 break;
884         default:
885                 err = -EINVAL;
886         }
887  exit:
888         DBFEXIT;
889         return err;
890 }
891
892 static int p80211wext_giwrts(netdevice_t *dev,
893                              struct iw_request_info *info,
894                              struct iw_param *rts, char *extra)
895 {
896         wlandevice_t *wlandev = dev->ml_priv;
897         p80211item_uint32_t             mibitem;
898         p80211msg_dot11req_mibset_t     msg;
899         int result;
900         int err = 0;
901
902         DBFENTER;
903
904         msg.msgcode = DIDmsg_dot11req_mibget;
905         mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
906         memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
907         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
908
909         if (result) {
910                 err = -EFAULT;
911                 goto exit;
912         }
913
914         memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
915
916         rts->value = mibitem.data;
917         rts->disabled = (rts->value == 2347);
918         rts->fixed = 1;
919
920  exit:
921         DBFEXIT;
922         return err;
923 }
924
925
926 static int p80211wext_siwrts(netdevice_t *dev,
927                              struct iw_request_info *info,
928                              struct iw_param *rts, char *extra)
929 {
930         wlandevice_t *wlandev = dev->ml_priv;
931         p80211item_uint32_t             mibitem;
932         p80211msg_dot11req_mibset_t     msg;
933         int result;
934         int err = 0;
935
936         DBFENTER;
937
938         if (!wlan_wext_write) {
939                 err = (-EOPNOTSUPP);
940                 goto exit;
941         }
942
943         msg.msgcode = DIDmsg_dot11req_mibget;
944         mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
945         if (rts->disabled)
946                 mibitem.data = 2347;
947         else
948                 mibitem.data = rts->value;
949
950         memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
951         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
952
953         if (result) {
954                 err = -EFAULT;
955                 goto exit;
956         }
957
958  exit:
959         DBFEXIT;
960         return err;
961 }
962
963 static int p80211wext_giwfrag(netdevice_t *dev,
964                               struct iw_request_info *info,
965                               struct iw_param *frag, char *extra)
966 {
967         wlandevice_t *wlandev = dev->ml_priv;
968         p80211item_uint32_t             mibitem;
969         p80211msg_dot11req_mibset_t     msg;
970         int result;
971         int err = 0;
972
973         DBFENTER;
974
975         msg.msgcode = DIDmsg_dot11req_mibget;
976         mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
977         memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
978         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
979
980         if (result) {
981                 err = -EFAULT;
982                 goto exit;
983         }
984
985         memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
986
987         frag->value = mibitem.data;
988         frag->disabled = (frag->value == 2346);
989         frag->fixed = 1;
990
991  exit:
992         DBFEXIT;
993         return err;
994 }
995
996 static int p80211wext_siwfrag(netdevice_t *dev,
997                               struct iw_request_info *info,
998                               struct iw_param *frag, char *extra)
999 {
1000         wlandevice_t *wlandev = dev->ml_priv;
1001         p80211item_uint32_t             mibitem;
1002         p80211msg_dot11req_mibset_t     msg;
1003         int result;
1004         int err = 0;
1005
1006         DBFENTER;
1007
1008         if (!wlan_wext_write) {
1009                 err = (-EOPNOTSUPP);
1010                 goto exit;
1011         }
1012
1013         msg.msgcode = DIDmsg_dot11req_mibset;
1014         mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
1015
1016         if (frag->disabled)
1017                 mibitem.data = 2346;
1018         else
1019                 mibitem.data = frag->value;
1020
1021         memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1022         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
1023
1024         if (result) {
1025                 err = -EFAULT;
1026                 goto exit;
1027         }
1028
1029  exit:
1030         DBFEXIT;
1031         return err;
1032 }
1033
1034 #endif  /* WIRELESS_EXT > 8 */
1035
1036 #if WIRELESS_EXT > 10
1037
1038 #ifndef IW_RETRY_LONG
1039 #define IW_RETRY_LONG IW_RETRY_MAX
1040 #endif
1041
1042 #ifndef IW_RETRY_SHORT
1043 #define IW_RETRY_SHORT IW_RETRY_MIN
1044 #endif
1045
1046 static int p80211wext_giwretry(netdevice_t *dev,
1047                                struct iw_request_info *info,
1048                                struct iw_param *rrq, char *extra)
1049 {
1050         wlandevice_t *wlandev = dev->ml_priv;
1051         p80211item_uint32_t             mibitem;
1052         p80211msg_dot11req_mibset_t     msg;
1053         int result;
1054         int err = 0;
1055         UINT16 shortretry, longretry, lifetime;
1056
1057         DBFENTER;
1058
1059         msg.msgcode = DIDmsg_dot11req_mibget;
1060         mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
1061
1062         memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1063         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
1064
1065         if (result) {
1066                 err = -EFAULT;
1067                 goto exit;
1068         }
1069
1070         memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1071
1072         shortretry = mibitem.data;
1073
1074         mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
1075
1076         memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1077         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
1078
1079         if (result) {
1080                 err = -EFAULT;
1081                 goto exit;
1082         }
1083
1084         memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1085
1086         longretry = mibitem.data;
1087
1088         mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1089
1090         memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1091         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
1092
1093         if (result) {
1094                 err = -EFAULT;
1095                 goto exit;
1096         }
1097
1098         memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1099
1100         lifetime = mibitem.data;
1101
1102         rrq->disabled = 0;
1103
1104         if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1105                 rrq->flags = IW_RETRY_LIFETIME;
1106                 rrq->value = lifetime * 1024;
1107         } else {
1108                 if (rrq->flags & IW_RETRY_LONG) {
1109                         rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
1110                         rrq->value = longretry;
1111                 } else {
1112                         rrq->flags = IW_RETRY_LIMIT;
1113                         rrq->value = shortretry;
1114                         if (shortretry != longretry)
1115                                 rrq->flags |= IW_RETRY_SHORT;
1116                 }
1117         }
1118
1119  exit:
1120         DBFEXIT;
1121         return err;
1122
1123 }
1124
1125 static int p80211wext_siwretry(netdevice_t *dev,
1126                                struct iw_request_info *info,
1127                                struct iw_param *rrq, char *extra)
1128 {
1129         wlandevice_t *wlandev = dev->ml_priv;
1130         p80211item_uint32_t             mibitem;
1131         p80211msg_dot11req_mibset_t     msg;
1132         int result;
1133         int err = 0;
1134
1135         DBFENTER;
1136
1137         if (!wlan_wext_write) {
1138                 err = (-EOPNOTSUPP);
1139                 goto exit;
1140         }
1141
1142         if (rrq->disabled) {
1143                 err = -EINVAL;
1144                 goto exit;
1145         }
1146
1147         msg.msgcode = DIDmsg_dot11req_mibset;
1148
1149         if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1150                 mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
1151                 mibitem.data =  rrq->value /= 1024;
1152
1153                 memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1154                 result = p80211req_dorequest(wlandev, (UINT8*)&msg);
1155
1156                 if (result) {
1157                         err = -EFAULT;
1158                         goto exit;
1159                 }
1160         } else {
1161                 if (rrq->flags & IW_RETRY_LONG) {
1162                         mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
1163                         mibitem.data = rrq->value;
1164
1165                         memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1166                         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
1167
1168                         if (result) {
1169                                 err = -EFAULT;
1170                                 goto exit;
1171                         }
1172                 }
1173
1174                 if (rrq->flags & IW_RETRY_SHORT) {
1175                         mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
1176                         mibitem.data = rrq->value;
1177
1178                         memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1179                         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
1180
1181                         if (result) {
1182                                 err = -EFAULT;
1183                                 goto exit;
1184                         }
1185                 }
1186         }
1187
1188  exit:
1189         DBFEXIT;
1190         return err;
1191
1192 }
1193
1194 #endif /* WIRELESS_EXT > 10 */
1195
1196 #if WIRELESS_EXT > 9
1197 static int p80211wext_siwtxpow(netdevice_t *dev,
1198                                struct iw_request_info *info,
1199                                struct iw_param *rrq, char *extra)
1200 {
1201         wlandevice_t *wlandev = dev->ml_priv;
1202         p80211item_uint32_t             mibitem;
1203         p80211msg_dot11req_mibset_t     msg;
1204         int result;
1205         int err = 0;
1206
1207         DBFENTER;
1208
1209        if (!wlan_wext_write) {
1210                 err = (-EOPNOTSUPP);
1211                 goto exit;
1212         }
1213
1214         msg.msgcode = DIDmsg_dot11req_mibset;
1215
1216         switch (rrq->value) {
1217
1218           case 1 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel1; break;
1219           case 2 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel2; break;
1220           case 3 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel3; break;
1221           case 4 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel4; break;
1222           case 5 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel5; break;
1223           case 6 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel6; break;
1224           case 7 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel7; break;
1225           case 8 : mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel8; break;
1226           default: mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11TxPowerLevel8; break;
1227         }
1228
1229         memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1230         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
1231
1232         if (result) {
1233                 err = -EFAULT;
1234                 goto exit;
1235         }
1236
1237  exit:
1238         DBFEXIT;
1239         return err;
1240 }
1241
1242 static int p80211wext_giwtxpow(netdevice_t *dev,
1243                                struct iw_request_info *info,
1244                                struct iw_param *rrq, char *extra)
1245 {
1246         wlandevice_t *wlandev = dev->ml_priv;
1247         p80211item_uint32_t             mibitem;
1248         p80211msg_dot11req_mibset_t     msg;
1249         int result;
1250         int err = 0;
1251
1252         DBFENTER;
1253
1254         msg.msgcode = DIDmsg_dot11req_mibget;
1255         mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
1256
1257         memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
1258         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
1259
1260         if (result) {
1261                 err = -EFAULT;
1262                 goto exit;
1263         }
1264
1265         memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem));
1266
1267         // XXX handle OFF by setting disabled = 1;
1268
1269         rrq->flags = 0; // IW_TXPOW_DBM;
1270         rrq->disabled = 0;
1271         rrq->fixed = 0;
1272         rrq->value = mibitem.data;
1273
1274  exit:
1275         DBFEXIT;
1276         return err;
1277 }
1278 #endif /* WIRELESS_EXT > 9 */
1279
1280 static int p80211wext_siwspy(netdevice_t *dev,
1281                              struct iw_request_info *info,
1282                              struct iw_point *srq, char *extra)
1283 {
1284         wlandevice_t *wlandev = dev->ml_priv;
1285         struct sockaddr address[IW_MAX_SPY];
1286         int number = srq->length;
1287         int i;
1288
1289         DBFENTER;
1290
1291         /* Copy the data from the input buffer */
1292         memcpy(address, extra, sizeof(struct sockaddr)*number);
1293
1294         wlandev->spy_number = 0;
1295
1296         if (number > 0) {
1297
1298                 /* extract the addresses */
1299                 for (i = 0; i < number; i++) {
1300
1301                         memcpy(wlandev->spy_address[i], address[i].sa_data, ETH_ALEN);
1302                 }
1303
1304                 /* reset stats */
1305                 memset(wlandev->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY);
1306
1307                 /* set number of addresses */
1308                 wlandev->spy_number = number;
1309         }
1310
1311         DBFEXIT;
1312         return 0;
1313 }
1314
1315 /* jkriegl: from orinoco, modified */
1316 static int p80211wext_giwspy(netdevice_t *dev,
1317                              struct iw_request_info *info,
1318                              struct iw_point *srq, char *extra)
1319 {
1320         wlandevice_t *wlandev = dev->ml_priv;
1321
1322         struct sockaddr address[IW_MAX_SPY];
1323         struct iw_quality spy_stat[IW_MAX_SPY];
1324         int number;
1325         int i;
1326
1327         DBFENTER;
1328
1329         number = wlandev->spy_number;
1330
1331         if (number > 0) {
1332
1333                 /* populate address and spy struct's */
1334                 for (i = 0; i < number; i++) {
1335                         memcpy(address[i].sa_data, wlandev->spy_address[i], ETH_ALEN);
1336                         address[i].sa_family = AF_UNIX;
1337                         memcpy(&spy_stat[i], &wlandev->spy_stat[i], sizeof(struct iw_quality));
1338                 }
1339
1340                 /* reset update flag */
1341                 for (i=0; i < number; i++)
1342                         wlandev->spy_stat[i].updated = 0;
1343         }
1344
1345         /* push stuff to user space */
1346         srq->length = number;
1347         memcpy(extra, address, sizeof(struct sockaddr)*number);
1348         memcpy(extra+sizeof(struct sockaddr)*number, spy_stat, sizeof(struct iw_quality)*number);
1349
1350         DBFEXIT;
1351         return 0;
1352 }
1353
1354 static int prism2_result2err (int prism2_result)
1355 {
1356         int err = 0;
1357
1358         switch (prism2_result) {
1359                 case P80211ENUM_resultcode_invalid_parameters:
1360                         err = -EINVAL;
1361                         break;
1362                 case P80211ENUM_resultcode_implementation_failure:
1363                         err = -EIO;
1364                         break;
1365                 case P80211ENUM_resultcode_not_supported:
1366                         err = -EOPNOTSUPP;
1367                         break;
1368                 default:
1369                         err = 0;
1370                         break;
1371         }
1372
1373         return err;
1374 }
1375
1376 #if WIRELESS_EXT > 13
1377 static int p80211wext_siwscan(netdevice_t *dev,
1378                              struct iw_request_info *info,
1379                              struct iw_point *srq, char *extra)
1380 {
1381         wlandevice_t *wlandev = dev->ml_priv;
1382         p80211msg_dot11req_scan_t       msg;
1383         int result;
1384         int err = 0;
1385         int i = 0;
1386
1387         DBFENTER;
1388
1389         if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
1390                 WLAN_LOG_ERROR("Can't scan in AP mode\n");
1391                 err = (-EOPNOTSUPP);
1392                 goto exit;
1393         }
1394
1395         memset(&msg, 0x00, sizeof(p80211msg_dot11req_scan_t));
1396         msg.msgcode = DIDmsg_dot11req_scan;
1397         msg.bsstype.data = P80211ENUM_bsstype_any;
1398
1399         memset(&(msg.bssid.data), 0xFF, sizeof (p80211item_pstr6_t));
1400         msg.bssid.data.len = 6;
1401
1402         msg.scantype.data = P80211ENUM_scantype_active;
1403         msg.probedelay.data = 0;
1404
1405         for (i = 1; i <= 14; i++)
1406                 msg.channellist.data.data[i-1] = i;
1407         msg.channellist.data.len = 14;
1408
1409         msg.maxchanneltime.data = 250;
1410         msg.minchanneltime.data = 200;
1411
1412         result = p80211req_dorequest(wlandev, (UINT8*)&msg);
1413         if (result)
1414                 err = prism2_result2err (msg.resultcode.data);
1415
1416  exit:
1417         DBFEXIT;
1418         return err;
1419 }
1420
1421
1422 /* Helper to translate scan into Wireless Extensions scan results.
1423  * Inspired by the prism54 code, which was in turn inspired by the
1424  * airo driver code.
1425  */
1426 static char *
1427 wext_translate_bss(struct iw_request_info *info, char *current_ev,
1428                    char *end_buf, p80211msg_dot11req_scan_results_t *bss)
1429 {
1430         struct iw_event iwe;    /* Temporary buffer */
1431
1432         /* The first entry must be the MAC address */
1433         memcpy(iwe.u.ap_addr.sa_data, bss->bssid.data.data, WLAN_BSSID_LEN);
1434         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1435         iwe.cmd = SIOCGIWAP;
1436         current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
1437
1438         /* The following entries will be displayed in the same order we give them */
1439
1440         /* The ESSID. */
1441         if (bss->ssid.data.len > 0) {
1442                 char essid[IW_ESSID_MAX_SIZE + 1];
1443                 int size;
1444
1445                 size = wlan_min(IW_ESSID_MAX_SIZE, bss->ssid.data.len);
1446                 memset(&essid, 0, sizeof (essid));
1447                 memcpy(&essid, bss->ssid.data.data, size);
1448                 WLAN_LOG_DEBUG(1, " essid size = %d\n", size);
1449                 iwe.u.data.length = size;
1450                 iwe.u.data.flags = 1;
1451                 iwe.cmd = SIOCGIWESSID;
1452                 current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, &essid[0]);
1453                 WLAN_LOG_DEBUG(1, " essid size OK.\n");
1454         }
1455
1456         switch (bss->bsstype.data) {
1457                 case P80211ENUM_bsstype_infrastructure:
1458                         iwe.u.mode = IW_MODE_MASTER;
1459                         break;
1460
1461                 case P80211ENUM_bsstype_independent:
1462                         iwe.u.mode = IW_MODE_ADHOC;
1463                         break;
1464
1465                 default:
1466                         iwe.u.mode = 0;
1467                         break;
1468         }
1469         iwe.cmd = SIOCGIWMODE;
1470         if (iwe.u.mode)
1471                 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
1472
1473         /* Encryption capability */
1474         if (bss->privacy.data == P80211ENUM_truth_true)
1475                 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1476         else
1477                 iwe.u.data.flags = IW_ENCODE_DISABLED;
1478         iwe.u.data.length = 0;
1479         iwe.cmd = SIOCGIWENCODE;
1480         current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL);
1481
1482         /* Add frequency. (short) bss->channel is the frequency in MHz */
1483         iwe.u.freq.m = bss->dschannel.data;
1484         iwe.u.freq.e = 0;
1485         iwe.cmd = SIOCGIWFREQ;
1486         current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
1487
1488         /* Add quality statistics */
1489         iwe.u.qual.level = bss->signal.data;
1490         iwe.u.qual.noise = bss->noise.data;
1491         /* do a simple SNR for quality */
1492         iwe.u.qual.qual = qual_as_percent(bss->signal.data - bss->noise.data);
1493         iwe.cmd = IWEVQUAL;
1494         current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
1495
1496         return current_ev;
1497 }
1498
1499
1500 static int p80211wext_giwscan(netdevice_t *dev,
1501                              struct iw_request_info *info,
1502                              struct iw_point *srq, char *extra)
1503 {
1504         wlandevice_t *wlandev = dev->ml_priv;
1505         p80211msg_dot11req_scan_results_t       msg;
1506         int result = 0;
1507         int err = 0;
1508         int i = 0;
1509         int scan_good = 0;
1510         char *current_ev = extra;
1511
1512         DBFENTER;
1513
1514         /* Since wireless tools doesn't really have a way of passing how
1515          * many scan results results there were back here, keep grabbing them
1516          * until we fail.
1517          */
1518         do {
1519                 memset(&msg, 0, sizeof(msg));
1520                 msg.msgcode = DIDmsg_dot11req_scan_results;
1521                 msg.bssindex.data = i;
1522
1523                 result = p80211req_dorequest(wlandev, (UINT8*)&msg);
1524                 if ((result != 0) ||
1525                     (msg.resultcode.data != P80211ENUM_resultcode_success)) {
1526                         break;
1527                 }
1528
1529                 current_ev = wext_translate_bss(info, current_ev, extra + IW_SCAN_MAX_DATA, &msg);
1530                 scan_good = 1;
1531                 i++;
1532         } while (i < IW_MAX_AP);
1533
1534         srq->length = (current_ev - extra);
1535         srq->flags = 0; /* todo */
1536
1537         if (result && !scan_good)
1538                 err = prism2_result2err (msg.resultcode.data);
1539
1540         DBFEXIT;
1541         return err;
1542 }
1543 #endif
1544
1545 /*****************************************************/
1546 //extra wireless extensions stuff to support NetworkManager (I hope)
1547
1548 #if WIRELESS_EXT > 17
1549 /* SIOCSIWENCODEEXT */
1550 static int p80211wext_set_encodeext(struct net_device *dev,
1551                                 struct iw_request_info *info,
1552                                 union iwreq_data *wrqu, char *extra)
1553 {
1554   wlandevice_t *wlandev = dev->ml_priv;
1555   struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1556         p80211msg_dot11req_mibset_t     msg;
1557         p80211item_pstr32_t             *pstr;
1558
1559   int result = 0;
1560   struct iw_point *encoding = &wrqu->encoding;
1561   int idx = encoding->flags & IW_ENCODE_INDEX;
1562
1563   WLAN_LOG_DEBUG(1,"set_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len);
1564
1565
1566   if ( ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY ) {
1567     // set default key ? I'm not sure if this the the correct thing to do here
1568
1569     if ( idx ) {
1570       if (idx < 1 || idx > NUM_WEPKEYS) {
1571         return -EINVAL;
1572       } else
1573         idx--;
1574     }
1575     WLAN_LOG_DEBUG(1,"setting default key (%d)\n",idx);
1576     result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, idx);
1577     if ( result )
1578       return -EFAULT;
1579   }
1580
1581
1582   if ( ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY ) {
1583     if ( ! ext->alg & IW_ENCODE_ALG_WEP) {
1584       WLAN_LOG_DEBUG(1,"asked to set a non wep key :(");
1585       return -EINVAL;
1586     }
1587     if (idx) {
1588       if (idx <1 || idx > NUM_WEPKEYS)
1589         return -EINVAL;
1590       else
1591         idx--;
1592     }
1593     WLAN_LOG_DEBUG(1,"Set WEP key (%d)\n",idx);
1594     wlandev->wep_keylens[idx] = ext->key_len;
1595     memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len);
1596
1597     memset( &msg,0,sizeof(msg));
1598     pstr = (p80211item_pstr32_t*)&msg.mibattribute.data;
1599     memcpy(pstr->data.data, ext->key,ext->key_len);
1600     pstr->data.len = ext->key_len;
1601     switch (idx) {
1602     case 0:
1603       pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0;
1604       break;
1605     case 1:
1606       pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1;
1607       break;
1608     case 2:
1609       pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2;
1610       break;
1611     case 3:
1612       pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3;
1613       break;
1614     default:
1615       break;
1616     }
1617     msg.msgcode = DIDmsg_dot11req_mibset;
1618     result = p80211req_dorequest(wlandev,(UINT8*)&msg);
1619     WLAN_LOG_DEBUG(1,"result (%d)\n",result);
1620   }
1621   return result;
1622 }
1623
1624 /* SIOCGIWENCODEEXT */
1625 static int p80211wext_get_encodeext(struct net_device *dev,
1626                                 struct iw_request_info *info,
1627                                 union iwreq_data *wrqu, char *extra)
1628
1629 {
1630         wlandevice_t *wlandev = dev->ml_priv;
1631         struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1632
1633         struct iw_point *encoding = &wrqu->encoding;
1634         int result = 0;
1635         int max_len;
1636         int idx;
1637
1638         DBFENTER;
1639
1640         WLAN_LOG_DEBUG(1,"get_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len);
1641
1642
1643         max_len = encoding->length - sizeof(*ext);
1644         if ( max_len <= 0) {
1645                 WLAN_LOG_DEBUG(1,"get_encodeext max_len [%d] invalid\n",max_len);
1646                 result = -EINVAL;
1647                 goto exit;
1648         }
1649         idx = encoding->flags & IW_ENCODE_INDEX;
1650
1651         WLAN_LOG_DEBUG(1,"get_encode_ext index [%d]\n",idx);
1652
1653         if (idx) {
1654                 if (idx < 1 || idx > NUM_WEPKEYS ) {
1655                         WLAN_LOG_DEBUG(1,"get_encode_ext invalid key index [%d]\n",idx);
1656                         result = -EINVAL;
1657                         goto exit;
1658                 }
1659                 idx--;
1660         } else {
1661                 /* default key ? not sure what to do */
1662                 /* will just use key[0] for now ! FIX ME */
1663         }
1664
1665         encoding->flags = idx + 1;
1666         memset(ext,0,sizeof(*ext));
1667
1668         ext->alg = IW_ENCODE_ALG_WEP;
1669         ext->key_len = wlandev->wep_keylens[idx];
1670         memcpy( ext->key, wlandev->wep_keys[idx] , ext->key_len );
1671
1672         encoding->flags |= IW_ENCODE_ENABLED;
1673 exit:
1674         DBFEXIT;
1675
1676         return result;
1677 }
1678
1679
1680 /* SIOCSIWAUTH */
1681 static int p80211_wext_set_iwauth (struct net_device *dev,
1682                                    struct iw_request_info *info,
1683                                    union iwreq_data *wrqu, char *extra)
1684 {
1685   wlandevice_t *wlandev = dev->ml_priv;
1686   struct iw_param *param = &wrqu->param;
1687   int result =0;
1688
1689   WLAN_LOG_DEBUG(1,"set_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX );
1690
1691   switch (param->flags & IW_AUTH_INDEX) {
1692   case IW_AUTH_DROP_UNENCRYPTED:
1693     WLAN_LOG_DEBUG(1,"drop_unencrypted %d\n",param->value);
1694     if (param->value)
1695       result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true);
1696     else
1697       result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false);
1698     break;
1699
1700   case IW_AUTH_PRIVACY_INVOKED:
1701     WLAN_LOG_DEBUG(1,"privacy invoked %d\n",param->value);
1702     if ( param->value)
1703       result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true);
1704     else
1705       result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false);
1706
1707     break;
1708
1709   case IW_AUTH_80211_AUTH_ALG:
1710     if ( param->value & IW_AUTH_ALG_OPEN_SYSTEM ) {
1711       WLAN_LOG_DEBUG(1,"set open_system\n");
1712       wlandev->hostwep &= ~HOSTWEP_SHAREDKEY;
1713     } else if ( param->value & IW_AUTH_ALG_SHARED_KEY) {
1714       WLAN_LOG_DEBUG(1,"set shared key\n");
1715       wlandev->hostwep |= HOSTWEP_SHAREDKEY;
1716     } else {
1717       /* don't know what to do know :( */
1718       WLAN_LOG_DEBUG(1,"unknown AUTH_ALG (%d)\n",param->value);
1719       result = -EINVAL;
1720     }
1721     break;
1722
1723   default:
1724     break;
1725   }
1726
1727
1728
1729   return result;
1730 }
1731
1732 /* SIOCSIWAUTH */
1733 static int p80211_wext_get_iwauth (struct net_device *dev,
1734                                    struct iw_request_info *info,
1735                                    union iwreq_data *wrqu, char *extra)
1736 {
1737   wlandevice_t *wlandev = dev->ml_priv;
1738   struct iw_param *param = &wrqu->param;
1739   int result =0;
1740
1741   WLAN_LOG_DEBUG(1,"get_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX );
1742
1743   switch (param->flags & IW_AUTH_INDEX) {
1744   case IW_AUTH_DROP_UNENCRYPTED:
1745     param->value = wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED?1:0;
1746     break;
1747
1748   case IW_AUTH_PRIVACY_INVOKED:
1749     param->value = wlandev->hostwep & HOSTWEP_PRIVACYINVOKED?1:0;
1750     break;
1751
1752   case IW_AUTH_80211_AUTH_ALG:
1753     param->value = wlandev->hostwep & HOSTWEP_SHAREDKEY?IW_AUTH_ALG_SHARED_KEY:IW_AUTH_ALG_OPEN_SYSTEM;
1754     break;
1755
1756
1757   default:
1758     break;
1759   }
1760
1761
1762
1763   return result;
1764 }
1765
1766
1767 #endif
1768
1769
1770
1771
1772
1773
1774 /*****************************************************/
1775
1776
1777
1778
1779
1780 /*
1781 typedef int (*iw_handler)(netdevice_t *dev, struct iw_request_info *info,
1782                           union iwreq_data *wrqu, char *extra);
1783 */
1784
1785 #if WIRELESS_EXT > 12
1786 static iw_handler p80211wext_handlers[] =  {
1787         (iw_handler) p80211wext_siwcommit,              /* SIOCSIWCOMMIT */
1788         (iw_handler) p80211wext_giwname,                /* SIOCGIWNAME */
1789         (iw_handler) NULL,                              /* SIOCSIWNWID */
1790         (iw_handler) NULL,                              /* SIOCGIWNWID */
1791         (iw_handler) p80211wext_siwfreq,                /* SIOCSIWFREQ */
1792         (iw_handler) p80211wext_giwfreq,                /* SIOCGIWFREQ */
1793         (iw_handler) p80211wext_siwmode,                /* SIOCSIWMODE */
1794         (iw_handler) p80211wext_giwmode,                /* SIOCGIWMODE */
1795         (iw_handler) NULL,                              /* SIOCSIWSENS */
1796         (iw_handler) NULL,                              /* SIOCGIWSENS */
1797         (iw_handler) NULL, /* not used */               /* SIOCSIWRANGE */
1798         (iw_handler) p80211wext_giwrange,               /* SIOCGIWRANGE */
1799         (iw_handler) NULL, /* not used */               /* SIOCSIWPRIV */
1800         (iw_handler) NULL, /* kernel code */            /* SIOCGIWPRIV */
1801         (iw_handler) NULL, /* not used */               /* SIOCSIWSTATS */
1802         (iw_handler) NULL, /* kernel code */            /* SIOCGIWSTATS */
1803         (iw_handler) p80211wext_siwspy,                 /* SIOCSIWSPY */
1804         (iw_handler) p80211wext_giwspy,                 /* SIOCGIWSPY */
1805         (iw_handler) NULL,                              /* -- hole -- */
1806         (iw_handler) NULL,                              /* -- hole -- */
1807         (iw_handler) NULL,                              /* SIOCSIWAP */
1808         (iw_handler) p80211wext_giwap,                  /* SIOCGIWAP */
1809         (iw_handler) NULL,                              /* -- hole -- */
1810         (iw_handler) NULL,                              /* SIOCGIWAPLIST */
1811 #if WIRELESS_EXT > 13
1812         (iw_handler) p80211wext_siwscan,                        /* SIOCSIWSCAN */
1813         (iw_handler) p80211wext_giwscan,                        /* SIOCGIWSCAN */
1814 #else /* WIRELESS_EXT > 13 */
1815         (iw_handler) NULL,      /* null */              /* SIOCSIWSCAN */
1816         (iw_handler) NULL,      /* null */              /* SIOCGIWSCAN */
1817 #endif /* WIRELESS_EXT > 13 */
1818         (iw_handler) p80211wext_siwessid,               /* SIOCSIWESSID */
1819         (iw_handler) p80211wext_giwessid,               /* SIOCGIWESSID */
1820         (iw_handler) NULL,                              /* SIOCSIWNICKN */
1821         (iw_handler) p80211wext_giwessid,               /* SIOCGIWNICKN */
1822         (iw_handler) NULL,                              /* -- hole -- */
1823         (iw_handler) NULL,                              /* -- hole -- */
1824         (iw_handler) NULL,                              /* SIOCSIWRATE */
1825         (iw_handler) p80211wext_giwrate,                /* SIOCGIWRATE */
1826         (iw_handler) p80211wext_siwrts,                 /* SIOCSIWRTS */
1827         (iw_handler) p80211wext_giwrts,                 /* SIOCGIWRTS */
1828         (iw_handler) p80211wext_siwfrag,                /* SIOCSIWFRAG */
1829         (iw_handler) p80211wext_giwfrag,                /* SIOCGIWFRAG */
1830         (iw_handler) p80211wext_siwtxpow,               /* SIOCSIWTXPOW */
1831         (iw_handler) p80211wext_giwtxpow,               /* SIOCGIWTXPOW */
1832         (iw_handler) p80211wext_siwretry,               /* SIOCSIWRETRY */
1833         (iw_handler) p80211wext_giwretry,               /* SIOCGIWRETRY */
1834         (iw_handler) p80211wext_siwencode,              /* SIOCSIWENCODE */
1835         (iw_handler) p80211wext_giwencode,              /* SIOCGIWENCODE */
1836         (iw_handler) NULL,                              /* SIOCSIWPOWER */
1837         (iw_handler) NULL,                              /* SIOCGIWPOWER */
1838 #if WIRELESS_EXT > 17
1839 /* WPA operations */
1840
1841         (iw_handler) NULL,                              /* -- hole -- */
1842         (iw_handler) NULL,                              /* -- hole -- */
1843         (iw_handler) NULL, /* SIOCSIWGENIE      set generic IE */
1844         (iw_handler) NULL, /* SIOCGIWGENIE      get generic IE */
1845         (iw_handler) p80211_wext_set_iwauth, /* SIOCSIWAUTH     set authentication mode params */
1846         (iw_handler) p80211_wext_get_iwauth, /* SIOCGIWAUTH     get authentication mode params */
1847
1848         (iw_handler) p80211wext_set_encodeext, /* SIOCSIWENCODEEXT  set encoding token & mode */
1849         (iw_handler) p80211wext_get_encodeext, /* SIOCGIWENCODEEXT  get encoding token & mode */
1850         (iw_handler) NULL, /* SIOCSIWPMKSA      PMKSA cache operation */
1851 #endif
1852 };
1853
1854 struct iw_handler_def p80211wext_handler_def = {
1855         .num_standard = sizeof(p80211wext_handlers) / sizeof(iw_handler),
1856         .num_private = 0,
1857         .num_private_args = 0,
1858         .standard = p80211wext_handlers,
1859         .private = NULL,
1860         .private_args = NULL,
1861 #if WIRELESS_EXT > 16
1862         .get_wireless_stats = p80211wext_get_wireless_stats
1863 #endif
1864 };
1865
1866 #endif
1867
1868 /* wireless extensions' ioctls */
1869 int p80211wext_support_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd)
1870 {
1871         wlandevice_t *wlandev = dev->ml_priv;
1872
1873 #if WIRELESS_EXT < 13
1874         struct iwreq *iwr = (struct iwreq*)ifr;
1875 #endif
1876
1877         p80211item_uint32_t             mibitem;
1878         int err = 0;
1879
1880         DBFENTER;
1881
1882         mibitem.status = P80211ENUM_msgitem_status_data_ok;
1883
1884         if ( wlandev->msdstate != WLAN_MSD_RUNNING ) {
1885                 err = -ENODEV;
1886                 goto exit;
1887         }
1888
1889         WLAN_LOG_DEBUG(1, "Received wireless extension ioctl #%d.\n", cmd);
1890
1891         switch (cmd) {
1892 #if WIRELESS_EXT < 13
1893         case SIOCSIWNAME:  /* unused  */
1894                 err = (-EOPNOTSUPP);
1895                 break;
1896         case SIOCGIWNAME: /* get name == wireless protocol */
1897                 err = p80211wext_giwname(dev, NULL, (char *) &iwr->u, NULL);
1898                 break;
1899         case SIOCSIWNWID:
1900         case SIOCGIWNWID:
1901                 err = (-EOPNOTSUPP);
1902                 break;
1903         case SIOCSIWFREQ: /* set channel */
1904                 err = p80211wext_siwfreq(dev, NULL, &(iwr->u.freq), NULL);
1905                 break;
1906         case SIOCGIWFREQ: /* get channel */
1907                 err = p80211wext_giwfreq(dev, NULL, &(iwr->u.freq), NULL);
1908                 break;
1909         case SIOCSIWRANGE:
1910         case SIOCSIWPRIV:
1911         case SIOCSIWAP: /* set access point MAC addresses (BSSID) */
1912                 err = (-EOPNOTSUPP);
1913                 break;
1914
1915         case SIOCGIWAP: /* get access point MAC addresses (BSSID) */
1916                 err = p80211wext_giwap(dev, NULL, &(iwr->u.ap_addr), NULL);
1917                 break;
1918
1919 #if WIRELESS_EXT > 8
1920         case SIOCSIWMODE: /* set operation mode */
1921         case SIOCSIWESSID: /* set SSID (network name) */
1922         case SIOCSIWRATE: /* set default bit rate (bps) */
1923                 err = (-EOPNOTSUPP);
1924                 break;
1925
1926         case SIOCGIWMODE: /* get operation mode */
1927                 err = p80211wext_giwmode(dev, NULL, &iwr->u.mode, NULL);
1928
1929                 break;
1930         case SIOCGIWNICKN: /* get node name/nickname */
1931         case SIOCGIWESSID: /* get SSID */
1932                 if(iwr->u.essid.pointer) {
1933                         char ssid[IW_ESSID_MAX_SIZE+1];
1934                         memset(ssid, 0, sizeof(ssid));
1935
1936                         err = p80211wext_giwessid(dev, NULL, &iwr->u.essid, ssid);
1937                         if(copy_to_user(iwr->u.essid.pointer, ssid, sizeof(ssid)))
1938                                 err = (-EFAULT);
1939                 }
1940                 break;
1941         case SIOCGIWRATE:
1942                 err = p80211wext_giwrate(dev, NULL, &iwr->u.bitrate, NULL);
1943                 break;
1944         case SIOCGIWRTS:
1945                 err = p80211wext_giwrts(dev, NULL, &iwr->u.rts, NULL);
1946                 break;
1947         case SIOCGIWFRAG:
1948                 err = p80211wext_giwfrag(dev, NULL, &iwr->u.rts, NULL);
1949                 break;
1950         case SIOCGIWENCODE:
1951                 if (!capable(CAP_NET_ADMIN))
1952                         err = -EPERM;
1953                 else if (iwr->u.encoding.pointer) {
1954                         char keybuf[MAX_KEYLEN];
1955                         err = p80211wext_giwencode(dev, NULL,
1956                                                      &iwr->u.encoding, keybuf);
1957                         if (copy_to_user(iwr->u.encoding.pointer, keybuf,
1958                                          iwr->u.encoding.length))
1959                                 err = -EFAULT;
1960                 }
1961                 break;
1962         case SIOCGIWAPLIST:
1963         case SIOCSIWRTS:
1964         case SIOCSIWFRAG:
1965         case SIOCSIWSENS:
1966         case SIOCGIWSENS:
1967         case SIOCSIWNICKN: /* set node name/nickname */
1968         case SIOCSIWENCODE: /* set encoding token & mode */
1969         case SIOCSIWSPY:
1970         case SIOCGIWSPY:
1971         case SIOCSIWPOWER:
1972         case SIOCGIWPOWER:
1973         case SIOCGIWPRIV:
1974                 err = (-EOPNOTSUPP);
1975                 break;
1976         case SIOCGIWRANGE:
1977                 if(iwr->u.data.pointer != NULL) {
1978                         struct iw_range range;
1979                         err = p80211wext_giwrange(dev, NULL, &iwr->u.data,
1980                                                   (char *) &range);
1981                         /* Push that up to the caller */
1982                         if (copy_to_user(iwr->u.data.pointer, &range, sizeof(range)))
1983                                 err = -EFAULT;
1984                 }
1985                 break;
1986 #endif /* WIRELESS_EXT > 8 */
1987 #if WIRELESS_EXT > 9
1988         case SIOCSIWTXPOW:
1989                 err = (-EOPNOTSUPP);
1990                 break;
1991         case SIOCGIWTXPOW:
1992                 err = p80211wext_giwtxpow(dev, NULL, &iwr->u.txpower, NULL);
1993                 break;
1994 #endif /* WIRELESS_EXT > 9 */
1995 #if WIRELESS_EXT > 10
1996         case SIOCSIWRETRY:
1997                 err = (-EOPNOTSUPP);
1998                 break;
1999         case SIOCGIWRETRY:
2000                 err = p80211wext_giwretry(dev, NULL, &iwr->u.retry, NULL);
2001                 break;
2002 #endif /* WIRELESS_EXT > 10 */
2003
2004 #endif /* WIRELESS_EXT <= 12 */
2005
2006         default:
2007                 err = (-EOPNOTSUPP);
2008                 break;
2009         }
2010
2011  exit:
2012         DBFEXIT;
2013         return (err);
2014 }
2015
2016 int p80211wext_event_associated(wlandevice_t *wlandev, int assoc)
2017 {
2018         union iwreq_data data;
2019
2020         DBFENTER;
2021
2022 #if WIRELESS_EXT > 13
2023         /* Send the association state first */
2024         data.ap_addr.sa_family = ARPHRD_ETHER;
2025         if (assoc) {
2026                 memcpy(data.ap_addr.sa_data, wlandev->bssid, WLAN_ADDR_LEN);
2027         } else {
2028                 memset(data.ap_addr.sa_data, 0, WLAN_ADDR_LEN);
2029         }
2030
2031         if (wlan_wext_write)
2032                 wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL);
2033
2034         if (!assoc) goto done;
2035
2036         // XXX send association data, like IEs, etc etc.
2037 #endif
2038  done:
2039         DBFEXIT;
2040         return 0;
2041 }
2042
2043
2044 #endif /* compatibility to wireless extensions */
2045
2046
2047
2048