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