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