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