aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2006-07-17 21:21:47 -0400
committerJohn W. Linville <linville@tuxdriver.com>2006-07-27 16:17:27 -0400
commiteab411f1e850af5acbd6ef278f4e669250f71915 (patch)
treebdaf5b4db188d90743d28db23e9c611b4d74a43c /drivers/net
parent7c0c3afb6e67004648ca589445e073dba4040509 (diff)
[PATCH] prism54: update to WE-19 for WPA support
Add WE-19 capabilities to prism54 fullmac driver so that it supports the necessary Wireless Extensions WPA calls. Convert reporting of WPA/RSN Generic Information Elements to IWEVGENIE rather than pre-WE-19 IWEVCUSTOM as well. Signed-off-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c573
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.h6
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.c4
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.h2
4 files changed, 543 insertions, 42 deletions
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 989599ad33ef..0c30fe7e8f7f 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -35,10 +35,14 @@
35 35
36#include <net/iw_handler.h> /* New driver API */ 36#include <net/iw_handler.h> /* New driver API */
37 37
38#define KEY_SIZE_WEP104 13 /* 104/128-bit WEP keys */
39#define KEY_SIZE_WEP40 5 /* 40/64-bit WEP keys */
40/* KEY_SIZE_TKIP should match isl_oid.h, struct obj_key.key[] size */
41#define KEY_SIZE_TKIP 32 /* TKIP keys */
38 42
39static void prism54_wpa_ie_add(islpci_private *priv, u8 *bssid, 43static void prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
40 u8 *wpa_ie, size_t wpa_ie_len); 44 u8 *wpa_ie, size_t wpa_ie_len);
41static size_t prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie); 45static size_t prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie);
42static int prism54_set_wpa(struct net_device *, struct iw_request_info *, 46static int prism54_set_wpa(struct net_device *, struct iw_request_info *,
43 __u32 *, char *); 47 __u32 *, char *);
44 48
@@ -468,6 +472,9 @@ prism54_get_range(struct net_device *ndev, struct iw_request_info *info,
468 range->event_capa[1] = IW_EVENT_CAPA_K_1; 472 range->event_capa[1] = IW_EVENT_CAPA_K_1;
469 range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM); 473 range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM);
470 474
475 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
476 IW_ENC_CAPA_CIPHER_TKIP;
477
471 if (islpci_get_state(priv) < PRV_STATE_INIT) 478 if (islpci_get_state(priv) < PRV_STATE_INIT)
472 return 0; 479 return 0;
473 480
@@ -567,6 +574,8 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev,
567 struct iw_event iwe; /* Temporary buffer */ 574 struct iw_event iwe; /* Temporary buffer */
568 short cap; 575 short cap;
569 islpci_private *priv = netdev_priv(ndev); 576 islpci_private *priv = netdev_priv(ndev);
577 u8 wpa_ie[MAX_WPA_IE_LEN];
578 size_t wpa_ie_len;
570 579
571 /* The first entry must be the MAC address */ 580 /* The first entry must be the MAC address */
572 memcpy(iwe.u.ap_addr.sa_data, bss->address, 6); 581 memcpy(iwe.u.ap_addr.sa_data, bss->address, 6);
@@ -627,27 +636,13 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev,
627 current_ev = 636 current_ev =
628 iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); 637 iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
629 638
630 if (priv->wpa) { 639 /* Add WPA/RSN Information Element, if any */
631 u8 wpa_ie[MAX_WPA_IE_LEN]; 640 wpa_ie_len = prism54_wpa_bss_ie_get(priv, bss->address, wpa_ie);
632 char *buf, *p; 641 if (wpa_ie_len > 0) {
633 size_t wpa_ie_len; 642 iwe.cmd = IWEVGENIE;
634 int i; 643 iwe.u.data.length = min(wpa_ie_len, (size_t)MAX_WPA_IE_LEN);
635 644 current_ev = iwe_stream_add_point(current_ev, end_buf,
636 wpa_ie_len = prism54_wpa_ie_get(priv, bss->address, wpa_ie); 645 &iwe, wpa_ie);
637 if (wpa_ie_len > 0 &&
638 (buf = kmalloc(wpa_ie_len * 2 + 10, GFP_ATOMIC))) {
639 p = buf;
640 p += sprintf(p, "wpa_ie=");
641 for (i = 0; i < wpa_ie_len; i++) {
642 p += sprintf(p, "%02x", wpa_ie[i]);
643 }
644 memset(&iwe, 0, sizeof (iwe));
645 iwe.cmd = IWEVCUSTOM;
646 iwe.u.data.length = strlen(buf);
647 current_ev = iwe_stream_add_point(current_ev, end_buf,
648 &iwe, buf);
649 kfree(buf);
650 }
651 } 646 }
652 return current_ev; 647 return current_ev;
653} 648}
@@ -1051,12 +1046,24 @@ prism54_set_encode(struct net_device *ndev, struct iw_request_info *info,
1051 current_index = r.u; 1046 current_index = r.u;
1052 /* Verify that the key is not marked as invalid */ 1047 /* Verify that the key is not marked as invalid */
1053 if (!(dwrq->flags & IW_ENCODE_NOKEY)) { 1048 if (!(dwrq->flags & IW_ENCODE_NOKEY)) {
1054 key.length = dwrq->length > sizeof (key.key) ? 1049 if (dwrq->length > KEY_SIZE_TKIP) {
1055 sizeof (key.key) : dwrq->length; 1050 /* User-provided key data too big */
1056 memcpy(key.key, extra, key.length); 1051 return -EINVAL;
1057 if (key.length == 32) 1052 }
1058 /* we want WPA-PSK */ 1053 if (dwrq->length > KEY_SIZE_WEP104) {
1054 /* WPA-PSK TKIP */
1059 key.type = DOT11_PRIV_TKIP; 1055 key.type = DOT11_PRIV_TKIP;
1056 key.length = KEY_SIZE_TKIP;
1057 } else if (dwrq->length > KEY_SIZE_WEP40) {
1058 /* WEP 104/128 */
1059 key.length = KEY_SIZE_WEP104;
1060 } else {
1061 /* WEP 40/64 */
1062 key.length = KEY_SIZE_WEP40;
1063 }
1064 memset(key.key, 0, sizeof (key.key));
1065 memcpy(key.key, extra, dwrq->length);
1066
1060 if ((index < 0) || (index > 3)) 1067 if ((index < 0) || (index > 3))
1061 /* no index provided use the current one */ 1068 /* no index provided use the current one */
1062 index = current_index; 1069 index = current_index;
@@ -1210,6 +1217,489 @@ prism54_set_txpower(struct net_device *ndev, struct iw_request_info *info,
1210 } 1217 }
1211} 1218}
1212 1219
1220static int prism54_set_genie(struct net_device *ndev,
1221 struct iw_request_info *info,
1222 struct iw_point *data, char *extra)
1223{
1224 islpci_private *priv = netdev_priv(ndev);
1225 int alen, ret = 0;
1226 struct obj_attachment *attach;
1227
1228 if (data->length > MAX_WPA_IE_LEN ||
1229 (data->length && extra == NULL))
1230 return -EINVAL;
1231
1232 memcpy(priv->wpa_ie, extra, data->length);
1233 priv->wpa_ie_len = data->length;
1234
1235 alen = sizeof(*attach) + priv->wpa_ie_len;
1236 attach = kzalloc(alen, GFP_KERNEL);
1237 if (attach == NULL)
1238 return -ENOMEM;
1239
1240#define WLAN_FC_TYPE_MGMT 0
1241#define WLAN_FC_STYPE_ASSOC_REQ 0
1242#define WLAN_FC_STYPE_REASSOC_REQ 2
1243
1244 /* Note: endianness is covered by mgt_set_varlen */
1245 attach->type = (WLAN_FC_TYPE_MGMT << 2) |
1246 (WLAN_FC_STYPE_ASSOC_REQ << 4);
1247 attach->id = -1;
1248 attach->size = priv->wpa_ie_len;
1249 memcpy(attach->data, extra, priv->wpa_ie_len);
1250
1251 ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach,
1252 priv->wpa_ie_len);
1253 if (ret == 0) {
1254 attach->type = (WLAN_FC_TYPE_MGMT << 2) |
1255 (WLAN_FC_STYPE_REASSOC_REQ << 4);
1256
1257 ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach,
1258 priv->wpa_ie_len);
1259 if (ret == 0)
1260 printk(KERN_DEBUG "%s: WPA IE Attachment was set\n",
1261 ndev->name);
1262 }
1263
1264 kfree(attach);
1265 return ret;
1266}
1267
1268
1269static int prism54_get_genie(struct net_device *ndev,
1270 struct iw_request_info *info,
1271 struct iw_point *data, char *extra)
1272{
1273 islpci_private *priv = netdev_priv(ndev);
1274 int len = priv->wpa_ie_len;
1275
1276 if (len <= 0) {
1277 data->length = 0;
1278 return 0;
1279 }
1280
1281 if (data->length < len)
1282 return -E2BIG;
1283
1284 data->length = len;
1285 memcpy(extra, priv->wpa_ie, len);
1286
1287 return 0;
1288}
1289
1290static int prism54_set_auth(struct net_device *ndev,
1291 struct iw_request_info *info,
1292 union iwreq_data *wrqu, char *extra)
1293{
1294 islpci_private *priv = netdev_priv(ndev);
1295 struct iw_param *param = &wrqu->param;
1296 u32 mlmelevel = 0, authen = 0, dot1x = 0;
1297 u32 exunencrypt = 0, privinvoked = 0, wpa = 0;
1298 u32 old_wpa;
1299 int ret = 0;
1300 union oid_res_t r;
1301
1302 if (islpci_get_state(priv) < PRV_STATE_INIT)
1303 return 0;
1304
1305 /* first get the flags */
1306 down_write(&priv->mib_sem);
1307 wpa = old_wpa = priv->wpa;
1308 up_write(&priv->mib_sem);
1309 ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r);
1310 authen = r.u;
1311 ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r);
1312 privinvoked = r.u;
1313 ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r);
1314 exunencrypt = r.u;
1315 ret = mgt_get_request(priv, DOT11_OID_DOT1XENABLE, 0, NULL, &r);
1316 dot1x = r.u;
1317 ret = mgt_get_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, NULL, &r);
1318 mlmelevel = r.u;
1319
1320 if (ret < 0)
1321 goto out;
1322
1323 switch (param->flags & IW_AUTH_INDEX) {
1324 case IW_AUTH_CIPHER_PAIRWISE:
1325 case IW_AUTH_CIPHER_GROUP:
1326 case IW_AUTH_KEY_MGMT:
1327 break;
1328
1329 case IW_AUTH_WPA_ENABLED:
1330 /* Do the same thing as IW_AUTH_WPA_VERSION */
1331 if (param->value) {
1332 wpa = 1;
1333 privinvoked = 1; /* For privacy invoked */
1334 exunencrypt = 1; /* Filter out all unencrypted frames */
1335 dot1x = 0x01; /* To enable eap filter */
1336 mlmelevel = DOT11_MLME_EXTENDED;
1337 authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */
1338 } else {
1339 wpa = 0;
1340 privinvoked = 0;
1341 exunencrypt = 0; /* Do not filter un-encrypted data */
1342 dot1x = 0;
1343 mlmelevel = DOT11_MLME_AUTO;
1344 }
1345 break;
1346
1347 case IW_AUTH_WPA_VERSION:
1348 if (param->value & IW_AUTH_WPA_VERSION_DISABLED) {
1349 wpa = 0;
1350 privinvoked = 0;
1351 exunencrypt = 0; /* Do not filter un-encrypted data */
1352 dot1x = 0;
1353 mlmelevel = DOT11_MLME_AUTO;
1354 } else {
1355 if (param->value & IW_AUTH_WPA_VERSION_WPA)
1356 wpa = 1;
1357 else if (param->value & IW_AUTH_WPA_VERSION_WPA2)
1358 wpa = 2;
1359 privinvoked = 1; /* For privacy invoked */
1360 exunencrypt = 1; /* Filter out all unencrypted frames */
1361 dot1x = 0x01; /* To enable eap filter */
1362 mlmelevel = DOT11_MLME_EXTENDED;
1363 authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */
1364 }
1365 break;
1366
1367 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1368 dot1x = param->value ? 1 : 0;
1369 break;
1370
1371 case IW_AUTH_PRIVACY_INVOKED:
1372 privinvoked = param->value ? 1 : 0;
1373
1374 case IW_AUTH_DROP_UNENCRYPTED:
1375 exunencrypt = param->value ? 1 : 0;
1376 break;
1377
1378 case IW_AUTH_80211_AUTH_ALG:
1379 if (param->value & IW_AUTH_ALG_SHARED_KEY) {
1380 /* Only WEP uses _SK and _BOTH */
1381 if (wpa > 0) {
1382 ret = -EINVAL;
1383 goto out;
1384 }
1385 authen = DOT11_AUTH_SK;
1386 } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
1387 authen = DOT11_AUTH_OS;
1388 } else {
1389 ret = -EINVAL;
1390 goto out;
1391 }
1392 break;
1393
1394 default:
1395 return -EOPNOTSUPP;
1396 }
1397
1398 /* Set all the values */
1399 down_write(&priv->mib_sem);
1400 priv->wpa = wpa;
1401 up_write(&priv->mib_sem);
1402 mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen);
1403 mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &privinvoked);
1404 mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, &exunencrypt);
1405 mgt_set_request(priv, DOT11_OID_DOT1XENABLE, 0, &dot1x);
1406 mgt_set_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, &mlmelevel);
1407
1408out:
1409 return ret;
1410}
1411
1412static int prism54_get_auth(struct net_device *ndev,
1413 struct iw_request_info *info,
1414 union iwreq_data *wrqu, char *extra)
1415{
1416 islpci_private *priv = netdev_priv(ndev);
1417 struct iw_param *param = &wrqu->param;
1418 u32 wpa = 0;
1419 int ret = 0;
1420 union oid_res_t r;
1421
1422 if (islpci_get_state(priv) < PRV_STATE_INIT)
1423 return 0;
1424
1425 /* first get the flags */
1426 down_write(&priv->mib_sem);
1427 wpa = priv->wpa;
1428 up_write(&priv->mib_sem);
1429
1430 switch (param->flags & IW_AUTH_INDEX) {
1431 case IW_AUTH_CIPHER_PAIRWISE:
1432 case IW_AUTH_CIPHER_GROUP:
1433 case IW_AUTH_KEY_MGMT:
1434 /*
1435 * wpa_supplicant will control these internally
1436 */
1437 ret = -EOPNOTSUPP;
1438 break;
1439
1440 case IW_AUTH_WPA_VERSION:
1441 switch (wpa) {
1442 case 1:
1443 param->value = IW_AUTH_WPA_VERSION_WPA;
1444 break;
1445 case 2:
1446 param->value = IW_AUTH_WPA_VERSION_WPA2;
1447 break;
1448 case 0:
1449 default:
1450 param->value = IW_AUTH_WPA_VERSION_DISABLED;
1451 break;
1452 }
1453 break;
1454
1455 case IW_AUTH_DROP_UNENCRYPTED:
1456 ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r);
1457 if (ret >= 0)
1458 param->value = r.u > 0 ? 1 : 0;
1459 break;
1460
1461 case IW_AUTH_80211_AUTH_ALG:
1462 ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r);
1463 if (ret >= 0) {
1464 switch (r.u) {
1465 case DOT11_AUTH_OS:
1466 param->value = IW_AUTH_ALG_OPEN_SYSTEM;
1467 break;
1468 case DOT11_AUTH_BOTH:
1469 case DOT11_AUTH_SK:
1470 param->value = IW_AUTH_ALG_SHARED_KEY;
1471 case DOT11_AUTH_NONE:
1472 default:
1473 param->value = 0;
1474 break;
1475 }
1476 }
1477 break;
1478
1479 case IW_AUTH_WPA_ENABLED:
1480 param->value = wpa > 0 ? 1 : 0;
1481 break;
1482
1483 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1484 ret = mgt_get_request(priv, DOT11_OID_DOT1XENABLE, 0, NULL, &r);
1485 if (ret >= 0)
1486 param->value = r.u > 0 ? 1 : 0;
1487 break;
1488
1489 case IW_AUTH_PRIVACY_INVOKED:
1490 ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r);
1491 if (ret >= 0)
1492 param->value = r.u > 0 ? 1 : 0;
1493 break;
1494
1495 default:
1496 return -EOPNOTSUPP;
1497 }
1498 return ret;
1499}
1500
1501static int prism54_set_encodeext(struct net_device *ndev,
1502 struct iw_request_info *info,
1503 union iwreq_data *wrqu,
1504 char *extra)
1505{
1506 islpci_private *priv = netdev_priv(ndev);
1507 struct iw_point *encoding = &wrqu->encoding;
1508 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1509 int idx, alg = ext->alg, set_key = 1;
1510 union oid_res_t r;
1511 int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0;
1512 int ret = 0;
1513
1514 if (islpci_get_state(priv) < PRV_STATE_INIT)
1515 return 0;
1516
1517 /* Determine and validate the key index */
1518 idx = (encoding->flags & IW_ENCODE_INDEX) - 1;
1519 if (idx) {
1520 if (idx < 0 || idx > 3)
1521 return -EINVAL;
1522 } else {
1523 ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r);
1524 if (ret < 0)
1525 goto out;
1526 idx = r.u;
1527 }
1528
1529 if (encoding->flags & IW_ENCODE_DISABLED)
1530 alg = IW_ENCODE_ALG_NONE;
1531
1532 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
1533 /* Only set transmit key index here, actual
1534 * key is set below if needed.
1535 */
1536 ret = mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, &idx);
1537 set_key = ext->key_len > 0 ? 1 : 0;
1538 }
1539
1540 if (set_key) {
1541 struct obj_key key = { DOT11_PRIV_WEP, 0, "" };
1542 switch (alg) {
1543 case IW_ENCODE_ALG_NONE:
1544 break;
1545 case IW_ENCODE_ALG_WEP:
1546 if (ext->key_len > KEY_SIZE_WEP104) {
1547 ret = -EINVAL;
1548 goto out;
1549 }
1550 if (ext->key_len > KEY_SIZE_WEP40)
1551 key.length = KEY_SIZE_WEP104;
1552 else
1553 key.length = KEY_SIZE_WEP40;
1554 break;
1555 case IW_ENCODE_ALG_TKIP:
1556 if (ext->key_len > KEY_SIZE_TKIP) {
1557 ret = -EINVAL;
1558 goto out;
1559 }
1560 key.type = DOT11_PRIV_TKIP;
1561 key.length = KEY_SIZE_TKIP;
1562 default:
1563 return -EINVAL;
1564 }
1565
1566 if (key.length) {
1567 memset(key.key, 0, sizeof(key.key));
1568 memcpy(key.key, ext->key, ext->key_len);
1569 ret = mgt_set_request(priv, DOT11_OID_DEFKEYX, idx,
1570 &key);
1571 if (ret < 0)
1572 goto out;
1573 }
1574 }
1575
1576 /* Read the flags */
1577 if (encoding->flags & IW_ENCODE_DISABLED) {
1578 /* Encoding disabled,
1579 * authen = DOT11_AUTH_OS;
1580 * invoke = 0;
1581 * exunencrypt = 0; */
1582 }
1583 if (encoding->flags & IW_ENCODE_OPEN) {
1584 /* Encode but accept non-encoded packets. No auth */
1585 invoke = 1;
1586 }
1587 if (encoding->flags & IW_ENCODE_RESTRICTED) {
1588 /* Refuse non-encoded packets. Auth */
1589 authen = DOT11_AUTH_BOTH;
1590 invoke = 1;
1591 exunencrypt = 1;
1592 }
1593
1594 /* do the change if requested */
1595 if (encoding->flags & IW_ENCODE_MODE) {
1596 ret = mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0,
1597 &authen);
1598 ret = mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0,
1599 &invoke);
1600 ret = mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0,
1601 &exunencrypt);
1602 }
1603
1604out:
1605 return ret;
1606}
1607
1608
1609static int prism54_get_encodeext(struct net_device *ndev,
1610 struct iw_request_info *info,
1611 union iwreq_data *wrqu,
1612 char *extra)
1613{
1614 islpci_private *priv = netdev_priv(ndev);
1615 struct iw_point *encoding = &wrqu->encoding;
1616 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1617 int idx, max_key_len;
1618 union oid_res_t r;
1619 int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0, wpa = 0;
1620 int ret = 0;
1621
1622 if (islpci_get_state(priv) < PRV_STATE_INIT)
1623 return 0;
1624
1625 /* first get the flags */
1626 ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r);
1627 authen = r.u;
1628 ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r);
1629 invoke = r.u;
1630 ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r);
1631 exunencrypt = r.u;
1632 if (ret < 0)
1633 goto out;
1634
1635 max_key_len = encoding->length - sizeof(*ext);
1636 if (max_key_len < 0)
1637 return -EINVAL;
1638
1639 idx = (encoding->flags & IW_ENCODE_INDEX) - 1;
1640 if (idx) {
1641 if (idx < 0 || idx > 3)
1642 return -EINVAL;
1643 } else {
1644 ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r);
1645 if (ret < 0)
1646 goto out;
1647 idx = r.u;
1648 }
1649
1650 encoding->flags = idx + 1;
1651 memset(ext, 0, sizeof(*ext));
1652
1653 switch (authen) {
1654 case DOT11_AUTH_BOTH:
1655 case DOT11_AUTH_SK:
1656 wrqu->encoding.flags |= IW_ENCODE_RESTRICTED;
1657 case DOT11_AUTH_OS:
1658 default:
1659 wrqu->encoding.flags |= IW_ENCODE_OPEN;
1660 break;
1661 }
1662
1663 down_write(&priv->mib_sem);
1664 wpa = priv->wpa;
1665 up_write(&priv->mib_sem);
1666
1667 if (authen == DOT11_AUTH_OS && !exunencrypt && !invoke && !wpa) {
1668 /* No encryption */
1669 ext->alg = IW_ENCODE_ALG_NONE;
1670 ext->key_len = 0;
1671 wrqu->encoding.flags |= IW_ENCODE_DISABLED;
1672 } else {
1673 struct obj_key *key;
1674
1675 ret = mgt_get_request(priv, DOT11_OID_DEFKEYX, idx, NULL, &r);
1676 if (ret < 0)
1677 goto out;
1678 key = r.ptr;
1679 if (max_key_len < key->length) {
1680 ret = -E2BIG;
1681 goto out;
1682 }
1683 memcpy(ext->key, key->key, key->length);
1684 ext->key_len = key->length;
1685
1686 switch (key->type) {
1687 case DOT11_PRIV_TKIP:
1688 ext->alg = IW_ENCODE_ALG_TKIP;
1689 break;
1690 default:
1691 case DOT11_PRIV_WEP:
1692 ext->alg = IW_ENCODE_ALG_WEP;
1693 break;
1694 }
1695 wrqu->encoding.flags |= IW_ENCODE_ENABLED;
1696 }
1697
1698out:
1699 return ret;
1700}
1701
1702
1213static int 1703static int
1214prism54_reset(struct net_device *ndev, struct iw_request_info *info, 1704prism54_reset(struct net_device *ndev, struct iw_request_info *info,
1215 __u32 * uwrq, char *extra) 1705 __u32 * uwrq, char *extra)
@@ -1591,8 +2081,8 @@ static u8 wpa_oid[4] = { 0x00, 0x50, 0xf2, 1 };
1591#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" 2081#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
1592 2082
1593static void 2083static void
1594prism54_wpa_ie_add(islpci_private *priv, u8 *bssid, 2084prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
1595 u8 *wpa_ie, size_t wpa_ie_len) 2085 u8 *wpa_ie, size_t wpa_ie_len)
1596{ 2086{
1597 struct list_head *ptr; 2087 struct list_head *ptr;
1598 struct islpci_bss_wpa_ie *bss = NULL; 2088 struct islpci_bss_wpa_ie *bss = NULL;
@@ -1658,7 +2148,7 @@ prism54_wpa_ie_add(islpci_private *priv, u8 *bssid,
1658} 2148}
1659 2149
1660static size_t 2150static size_t
1661prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie) 2151prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
1662{ 2152{
1663 struct list_head *ptr; 2153 struct list_head *ptr;
1664 struct islpci_bss_wpa_ie *bss = NULL; 2154 struct islpci_bss_wpa_ie *bss = NULL;
@@ -1683,14 +2173,14 @@ prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
1683} 2173}
1684 2174
1685void 2175void
1686prism54_wpa_ie_init(islpci_private *priv) 2176prism54_wpa_bss_ie_init(islpci_private *priv)
1687{ 2177{
1688 INIT_LIST_HEAD(&priv->bss_wpa_list); 2178 INIT_LIST_HEAD(&priv->bss_wpa_list);
1689 sema_init(&priv->wpa_sem, 1); 2179 sema_init(&priv->wpa_sem, 1);
1690} 2180}
1691 2181
1692void 2182void
1693prism54_wpa_ie_clean(islpci_private *priv) 2183prism54_wpa_bss_ie_clean(islpci_private *priv)
1694{ 2184{
1695 struct list_head *ptr, *n; 2185 struct list_head *ptr, *n;
1696 2186
@@ -1722,7 +2212,7 @@ prism54_process_bss_data(islpci_private *priv, u32 oid, u8 *addr,
1722 } 2212 }
1723 if (pos[0] == WLAN_EID_GENERIC && pos[1] >= 4 && 2213 if (pos[0] == WLAN_EID_GENERIC && pos[1] >= 4 &&
1724 memcmp(pos + 2, wpa_oid, 4) == 0) { 2214 memcmp(pos + 2, wpa_oid, 4) == 0) {
1725 prism54_wpa_ie_add(priv, addr, pos, pos[1] + 2); 2215 prism54_wpa_bss_ie_add(priv, addr, pos, pos[1] + 2);
1726 return; 2216 return;
1727 } 2217 }
1728 pos += 2 + pos[1]; 2218 pos += 2 + pos[1];
@@ -1879,7 +2369,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
1879 send_formatted_event(priv, "Associate request (ex)", mlme, 1); 2369 send_formatted_event(priv, "Associate request (ex)", mlme, 1);
1880 2370
1881 if (priv->iw_mode != IW_MODE_MASTER 2371 if (priv->iw_mode != IW_MODE_MASTER
1882 && mlmeex->state != DOT11_STATE_AUTHING) 2372 && mlmeex->state != DOT11_STATE_ASSOCING)
1883 break; 2373 break;
1884 2374
1885 confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC); 2375 confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC);
@@ -1893,7 +2383,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
1893 confirm->state = 0; /* not used */ 2383 confirm->state = 0; /* not used */
1894 confirm->code = 0; 2384 confirm->code = 0;
1895 2385
1896 wpa_ie_len = prism54_wpa_ie_get(priv, mlmeex->address, wpa_ie); 2386 wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie);
1897 2387
1898 if (!wpa_ie_len) { 2388 if (!wpa_ie_len) {
1899 printk(KERN_DEBUG "No WPA IE found from " 2389 printk(KERN_DEBUG "No WPA IE found from "
@@ -1937,7 +2427,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
1937 confirm->state = 0; /* not used */ 2427 confirm->state = 0; /* not used */
1938 confirm->code = 0; 2428 confirm->code = 0;
1939 2429
1940 wpa_ie_len = prism54_wpa_ie_get(priv, mlmeex->address, wpa_ie); 2430 wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie);
1941 2431
1942 if (!wpa_ie_len) { 2432 if (!wpa_ie_len) {
1943 printk(KERN_DEBUG "No WPA IE found from " 2433 printk(KERN_DEBUG "No WPA IE found from "
@@ -2553,6 +3043,15 @@ static const iw_handler prism54_handler[] = {
2553 (iw_handler) prism54_get_encode, /* SIOCGIWENCODE */ 3043 (iw_handler) prism54_get_encode, /* SIOCGIWENCODE */
2554 (iw_handler) NULL, /* SIOCSIWPOWER */ 3044 (iw_handler) NULL, /* SIOCSIWPOWER */
2555 (iw_handler) NULL, /* SIOCGIWPOWER */ 3045 (iw_handler) NULL, /* SIOCGIWPOWER */
3046 NULL, /* -- hole -- */
3047 NULL, /* -- hole -- */
3048 (iw_handler) prism54_set_genie, /* SIOCSIWGENIE */
3049 (iw_handler) prism54_get_genie, /* SIOCGIWGENIE */
3050 (iw_handler) prism54_set_auth, /* SIOCSIWAUTH */
3051 (iw_handler) prism54_get_auth, /* SIOCGIWAUTH */
3052 (iw_handler) prism54_set_encodeext, /* SIOCSIWENCODEEXT */
3053 (iw_handler) prism54_get_encodeext, /* SIOCGIWENCODEEXT */
3054 NULL, /* SIOCSIWPMKSA */
2556}; 3055};
2557 3056
2558/* The low order bit identify a SET (0) or a GET (1) ioctl. */ 3057/* The low order bit identify a SET (0) or a GET (1) ioctl. */
diff --git a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h
index 46d5cde80c85..65f33acd0a42 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.h
+++ b/drivers/net/wireless/prism54/isl_ioctl.h
@@ -27,7 +27,7 @@
27 27
28#include <net/iw_handler.h> /* New driver API */ 28#include <net/iw_handler.h> /* New driver API */
29 29
30#define SUPPORTED_WIRELESS_EXT 16 30#define SUPPORTED_WIRELESS_EXT 19
31 31
32void prism54_mib_init(islpci_private *); 32void prism54_mib_init(islpci_private *);
33 33
@@ -39,8 +39,8 @@ void prism54_acl_clean(struct islpci_acl *);
39 39
40void prism54_process_trap(void *); 40void prism54_process_trap(void *);
41 41
42void prism54_wpa_ie_init(islpci_private *priv); 42void prism54_wpa_bss_ie_init(islpci_private *priv);
43void prism54_wpa_ie_clean(islpci_private *priv); 43void prism54_wpa_bss_ie_clean(islpci_private *priv);
44 44
45int prism54_set_mac_address(struct net_device *, void *); 45int prism54_set_mac_address(struct net_device *, void *);
46 46
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index 5ddf29599032..ab3c5a27efd9 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -715,7 +715,7 @@ islpci_alloc_memory(islpci_private *priv)
715 } 715 }
716 716
717 prism54_acl_init(&priv->acl); 717 prism54_acl_init(&priv->acl);
718 prism54_wpa_ie_init(priv); 718 prism54_wpa_bss_ie_init(priv);
719 if (mgt_init(priv)) 719 if (mgt_init(priv))
720 goto out_free; 720 goto out_free;
721 721
@@ -774,7 +774,7 @@ islpci_free_memory(islpci_private *priv)
774 774
775 /* Free the acces control list and the WPA list */ 775 /* Free the acces control list and the WPA list */
776 prism54_acl_clean(&priv->acl); 776 prism54_acl_clean(&priv->acl);
777 prism54_wpa_ie_clean(priv); 777 prism54_wpa_bss_ie_clean(priv);
778 mgt_clean(priv); 778 mgt_clean(priv);
779 779
780 return 0; 780 return 0;
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
index 07053165e4c5..5049f37455b1 100644
--- a/drivers/net/wireless/prism54/islpci_dev.h
+++ b/drivers/net/wireless/prism54/islpci_dev.h
@@ -179,6 +179,8 @@ typedef struct {
179 struct list_head bss_wpa_list; 179 struct list_head bss_wpa_list;
180 int num_bss_wpa; 180 int num_bss_wpa;
181 struct semaphore wpa_sem; 181 struct semaphore wpa_sem;
182 u8 wpa_ie[MAX_WPA_IE_LEN];
183 size_t wpa_ie_len;
182 184
183 struct work_struct reset_task; 185 struct work_struct reset_task;
184 int reset_task_pending; 186 int reset_task_pending;