diff options
author | Dan Williams <dcbw@redhat.com> | 2006-07-17 21:21:47 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2006-07-27 16:17:27 -0400 |
commit | eab411f1e850af5acbd6ef278f4e669250f71915 (patch) | |
tree | bdaf5b4db188d90743d28db23e9c611b4d74a43c /drivers/net | |
parent | 7c0c3afb6e67004648ca589445e073dba4040509 (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.c | 573 | ||||
-rw-r--r-- | drivers/net/wireless/prism54/isl_ioctl.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/prism54/islpci_dev.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/prism54/islpci_dev.h | 2 |
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 | ||
39 | static void prism54_wpa_ie_add(islpci_private *priv, u8 *bssid, | 43 | static 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); |
41 | static size_t prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie); | 45 | static size_t prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie); |
42 | static int prism54_set_wpa(struct net_device *, struct iw_request_info *, | 46 | static 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 | ||
1220 | static 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 | |||
1269 | static 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 | |||
1290 | static 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 | |||
1408 | out: | ||
1409 | return ret; | ||
1410 | } | ||
1411 | |||
1412 | static 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 | |||
1501 | static 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 | |||
1604 | out: | ||
1605 | return ret; | ||
1606 | } | ||
1607 | |||
1608 | |||
1609 | static 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 | |||
1698 | out: | ||
1699 | return ret; | ||
1700 | } | ||
1701 | |||
1702 | |||
1213 | static int | 1703 | static int |
1214 | prism54_reset(struct net_device *ndev, struct iw_request_info *info, | 1704 | prism54_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 | ||
1593 | static void | 2083 | static void |
1594 | prism54_wpa_ie_add(islpci_private *priv, u8 *bssid, | 2084 | prism54_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 | ||
1660 | static size_t | 2150 | static size_t |
1661 | prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie) | 2151 | prism54_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 | ||
1685 | void | 2175 | void |
1686 | prism54_wpa_ie_init(islpci_private *priv) | 2176 | prism54_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 | ||
1692 | void | 2182 | void |
1693 | prism54_wpa_ie_clean(islpci_private *priv) | 2183 | prism54_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 | ||
32 | void prism54_mib_init(islpci_private *); | 32 | void prism54_mib_init(islpci_private *); |
33 | 33 | ||
@@ -39,8 +39,8 @@ void prism54_acl_clean(struct islpci_acl *); | |||
39 | 39 | ||
40 | void prism54_process_trap(void *); | 40 | void prism54_process_trap(void *); |
41 | 41 | ||
42 | void prism54_wpa_ie_init(islpci_private *priv); | 42 | void prism54_wpa_bss_ie_init(islpci_private *priv); |
43 | void prism54_wpa_ie_clean(islpci_private *priv); | 43 | void prism54_wpa_bss_ie_clean(islpci_private *priv); |
44 | 44 | ||
45 | int prism54_set_mac_address(struct net_device *, void *); | 45 | int 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; |