diff options
-rw-r--r-- | drivers/net/wireless/rndis_wlan.c | 133 |
1 files changed, 103 insertions, 30 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index ffb195dcf4f8..93b504bc2dc5 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -424,7 +424,7 @@ static const u32 rndis_cipher_suites[] = { | |||
424 | 424 | ||
425 | struct rndis_wlan_encr_key { | 425 | struct rndis_wlan_encr_key { |
426 | int len; | 426 | int len; |
427 | int cipher; | 427 | u32 cipher; |
428 | u8 material[32]; | 428 | u8 material[32]; |
429 | u8 bssid[ETH_ALEN]; | 429 | u8 bssid[ETH_ALEN]; |
430 | bool pairwise; | 430 | bool pairwise; |
@@ -520,6 +520,16 @@ static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev); | |||
520 | static int rndis_set_channel(struct wiphy *wiphy, | 520 | static int rndis_set_channel(struct wiphy *wiphy, |
521 | struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); | 521 | struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); |
522 | 522 | ||
523 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, | ||
524 | u8 key_index, const u8 *mac_addr, | ||
525 | struct key_params *params); | ||
526 | |||
527 | static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, | ||
528 | u8 key_index, const u8 *mac_addr); | ||
529 | |||
530 | static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, | ||
531 | u8 key_index); | ||
532 | |||
523 | static struct cfg80211_ops rndis_config_ops = { | 533 | static struct cfg80211_ops rndis_config_ops = { |
524 | .change_virtual_intf = rndis_change_virtual_intf, | 534 | .change_virtual_intf = rndis_change_virtual_intf, |
525 | .scan = rndis_scan, | 535 | .scan = rndis_scan, |
@@ -531,6 +541,9 @@ static struct cfg80211_ops rndis_config_ops = { | |||
531 | .join_ibss = rndis_join_ibss, | 541 | .join_ibss = rndis_join_ibss, |
532 | .leave_ibss = rndis_leave_ibss, | 542 | .leave_ibss = rndis_leave_ibss, |
533 | .set_channel = rndis_set_channel, | 543 | .set_channel = rndis_set_channel, |
544 | .add_key = rndis_add_key, | ||
545 | .del_key = rndis_del_key, | ||
546 | .set_default_key = rndis_set_default_key, | ||
534 | }; | 547 | }; |
535 | 548 | ||
536 | static void *rndis_wiphy_privid = &rndis_wiphy_privid; | 549 | static void *rndis_wiphy_privid = &rndis_wiphy_privid; |
@@ -1258,7 +1271,10 @@ static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len, | |||
1258 | { | 1271 | { |
1259 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 1272 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
1260 | struct ndis_80211_wep_key ndis_key; | 1273 | struct ndis_80211_wep_key ndis_key; |
1261 | int cipher, ret; | 1274 | u32 cipher; |
1275 | int ret; | ||
1276 | |||
1277 | devdbg(usbdev, "add_wep_key(idx: %d, len: %d)", index, key_len); | ||
1262 | 1278 | ||
1263 | if ((key_len != 5 && key_len != 13) || index < 0 || index > 3) | 1279 | if ((key_len != 5 && key_len != 13) || index < 0 || index > 3) |
1264 | return -EINVAL; | 1280 | return -EINVAL; |
@@ -1302,8 +1318,8 @@ static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len, | |||
1302 | 1318 | ||
1303 | 1319 | ||
1304 | static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, | 1320 | static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, |
1305 | int index, const u8 *addr, const u8 *rx_seq, int cipher, | 1321 | int index, const u8 *addr, const u8 *rx_seq, |
1306 | int flags) | 1322 | int seq_len, u32 cipher, int flags) |
1307 | { | 1323 | { |
1308 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 1324 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
1309 | struct ndis_80211_key ndis_key; | 1325 | struct ndis_80211_key ndis_key; |
@@ -1319,10 +1335,18 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, | |||
1319 | key_len); | 1335 | key_len); |
1320 | return -EINVAL; | 1336 | return -EINVAL; |
1321 | } | 1337 | } |
1322 | if ((flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) && !rx_seq) { | 1338 | if (flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) { |
1323 | devdbg(usbdev, "add_wpa_key: recv seq flag without buffer"); | 1339 | if (!rx_seq || seq_len <= 0) { |
1324 | return -EINVAL; | 1340 | devdbg(usbdev, "add_wpa_key: recv seq flag without" |
1341 | "buffer"); | ||
1342 | return -EINVAL; | ||
1343 | } | ||
1344 | if (rx_seq && seq_len > sizeof(ndis_key.rsc)) { | ||
1345 | devdbg(usbdev, "add_wpa_key: too big recv seq buffer"); | ||
1346 | return -EINVAL; | ||
1347 | } | ||
1325 | } | 1348 | } |
1349 | |||
1326 | is_addr_ok = addr && !is_zero_ether_addr(addr) && | 1350 | is_addr_ok = addr && !is_zero_ether_addr(addr) && |
1327 | !is_broadcast_ether_addr(addr); | 1351 | !is_broadcast_ether_addr(addr); |
1328 | if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !is_addr_ok) { | 1352 | if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !is_addr_ok) { |
@@ -1353,7 +1377,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, | |||
1353 | memcpy(ndis_key.material, key, key_len); | 1377 | memcpy(ndis_key.material, key, key_len); |
1354 | 1378 | ||
1355 | if (flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) | 1379 | if (flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) |
1356 | memcpy(ndis_key.rsc, rx_seq, 6); | 1380 | memcpy(ndis_key.rsc, rx_seq, seq_len); |
1357 | 1381 | ||
1358 | if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) { | 1382 | if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) { |
1359 | /* pairwise key */ | 1383 | /* pairwise key */ |
@@ -1392,31 +1416,17 @@ static int restore_key(struct usbnet *usbdev, int key_idx) | |||
1392 | { | 1416 | { |
1393 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 1417 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
1394 | struct rndis_wlan_encr_key key; | 1418 | struct rndis_wlan_encr_key key; |
1395 | int flags; | 1419 | |
1420 | if (is_wpa_key(priv, key_idx)) | ||
1421 | return 0; | ||
1396 | 1422 | ||
1397 | key = priv->encr_keys[key_idx]; | 1423 | key = priv->encr_keys[key_idx]; |
1398 | 1424 | ||
1399 | devdbg(usbdev, "restore_key: %i:%s:%i", key_idx, | 1425 | devdbg(usbdev, "restore_key: %i:%i", key_idx, key.len); |
1400 | is_wpa_key(priv, key_idx) ? "wpa" : "wep", | ||
1401 | key.len); | ||
1402 | 1426 | ||
1403 | if (key.len == 0) | 1427 | if (key.len == 0) |
1404 | return 0; | 1428 | return 0; |
1405 | 1429 | ||
1406 | if (is_wpa_key(priv, key_idx)) { | ||
1407 | flags = 0; | ||
1408 | |||
1409 | /*if (priv->encr_tx_key_index == key_idx) | ||
1410 | flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY;*/ | ||
1411 | |||
1412 | if (!is_zero_ether_addr(key.bssid) && | ||
1413 | !is_broadcast_ether_addr(key.bssid)) | ||
1414 | flags |= NDIS_80211_ADDKEY_PAIRWISE_KEY; | ||
1415 | |||
1416 | return add_wpa_key(usbdev, key.material, key.len, key_idx, | ||
1417 | key.bssid, NULL, key.cipher, flags); | ||
1418 | } | ||
1419 | |||
1420 | return add_wep_key(usbdev, key.material, key.len, key_idx); | 1430 | return add_wep_key(usbdev, key.material, key.len, key_idx); |
1421 | } | 1431 | } |
1422 | 1432 | ||
@@ -1437,7 +1447,7 @@ static void clear_key(struct rndis_wlan_private *priv, int idx) | |||
1437 | 1447 | ||
1438 | 1448 | ||
1439 | /* remove_key is for both wep and wpa */ | 1449 | /* remove_key is for both wep and wpa */ |
1440 | static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN]) | 1450 | static int remove_key(struct usbnet *usbdev, int index, const u8 *bssid) |
1441 | { | 1451 | { |
1442 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 1452 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
1443 | struct ndis_80211_remove_key remove_key; | 1453 | struct ndis_80211_remove_key remove_key; |
@@ -2041,6 +2051,69 @@ static int rndis_set_channel(struct wiphy *wiphy, | |||
2041 | ieee80211_frequency_to_channel(chan->center_freq)); | 2051 | ieee80211_frequency_to_channel(chan->center_freq)); |
2042 | } | 2052 | } |
2043 | 2053 | ||
2054 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, | ||
2055 | u8 key_index, const u8 *mac_addr, | ||
2056 | struct key_params *params) | ||
2057 | { | ||
2058 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | ||
2059 | struct usbnet *usbdev = priv->usbdev; | ||
2060 | int flags; | ||
2061 | |||
2062 | devdbg(usbdev, "rndis_add_key(%i, %pM, %08x)", key_index, mac_addr, | ||
2063 | params->cipher); | ||
2064 | |||
2065 | switch (params->cipher) { | ||
2066 | case WLAN_CIPHER_SUITE_WEP40: | ||
2067 | case WLAN_CIPHER_SUITE_WEP104: | ||
2068 | return add_wep_key(usbdev, params->key, params->key_len, | ||
2069 | key_index); | ||
2070 | case WLAN_CIPHER_SUITE_TKIP: | ||
2071 | case WLAN_CIPHER_SUITE_CCMP: | ||
2072 | flags = 0; | ||
2073 | |||
2074 | if (params->seq && params->seq_len > 0) | ||
2075 | flags |= NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ; | ||
2076 | if (mac_addr) | ||
2077 | flags |= NDIS_80211_ADDKEY_PAIRWISE_KEY | | ||
2078 | NDIS_80211_ADDKEY_TRANSMIT_KEY; | ||
2079 | |||
2080 | return add_wpa_key(usbdev, params->key, params->key_len, | ||
2081 | key_index, mac_addr, params->seq, | ||
2082 | params->seq_len, params->cipher, flags); | ||
2083 | default: | ||
2084 | devdbg(usbdev, "rndis_add_key: unsupported cipher %08x", | ||
2085 | params->cipher); | ||
2086 | return -ENOTSUPP; | ||
2087 | } | ||
2088 | } | ||
2089 | |||
2090 | static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, | ||
2091 | u8 key_index, const u8 *mac_addr) | ||
2092 | { | ||
2093 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | ||
2094 | struct usbnet *usbdev = priv->usbdev; | ||
2095 | |||
2096 | devdbg(usbdev, "rndis_del_key(%i, %pM)", key_index, mac_addr); | ||
2097 | |||
2098 | return remove_key(usbdev, key_index, mac_addr); | ||
2099 | } | ||
2100 | |||
2101 | static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, | ||
2102 | u8 key_index) | ||
2103 | { | ||
2104 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | ||
2105 | struct usbnet *usbdev = priv->usbdev; | ||
2106 | struct rndis_wlan_encr_key key; | ||
2107 | |||
2108 | devdbg(usbdev, "rndis_set_default_key(%i)", key_index); | ||
2109 | |||
2110 | priv->encr_tx_key_index = key_index; | ||
2111 | |||
2112 | key = priv->encr_keys[key_index]; | ||
2113 | |||
2114 | return add_wep_key(usbdev, key.material, key.len, key_index); | ||
2115 | } | ||
2116 | |||
2044 | /* | 2117 | /* |
2045 | * wireless extension handlers | 2118 | * wireless extension handlers |
2046 | */ | 2119 | */ |
@@ -2268,7 +2341,6 @@ static int rndis_iw_get_auth(struct net_device *dev, | |||
2268 | } | 2341 | } |
2269 | return 0; | 2342 | return 0; |
2270 | } | 2343 | } |
2271 | #endif | ||
2272 | 2344 | ||
2273 | 2345 | ||
2274 | static int rndis_iw_set_encode(struct net_device *dev, | 2346 | static int rndis_iw_set_encode(struct net_device *dev, |
@@ -2387,6 +2459,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev, | |||
2387 | (u8 *)&ext->addr.sa_data, ext->rx_seq, cipher, | 2459 | (u8 *)&ext->addr.sa_data, ext->rx_seq, cipher, |
2388 | flags); | 2460 | flags); |
2389 | } | 2461 | } |
2462 | #endif | ||
2390 | 2463 | ||
2391 | 2464 | ||
2392 | static int rndis_iw_get_rate(struct net_device *dev, | 2465 | static int rndis_iw_get_rate(struct net_device *dev, |
@@ -2444,8 +2517,8 @@ static const iw_handler rndis_iw_handler[] = | |||
2444 | IW_IOCTL(SIOCGIWFRAG) = (iw_handler) cfg80211_wext_giwfrag, | 2517 | IW_IOCTL(SIOCGIWFRAG) = (iw_handler) cfg80211_wext_giwfrag, |
2445 | IW_IOCTL(SIOCSIWTXPOW) = (iw_handler) cfg80211_wext_siwtxpower, | 2518 | IW_IOCTL(SIOCSIWTXPOW) = (iw_handler) cfg80211_wext_siwtxpower, |
2446 | IW_IOCTL(SIOCGIWTXPOW) = (iw_handler) cfg80211_wext_giwtxpower, | 2519 | IW_IOCTL(SIOCGIWTXPOW) = (iw_handler) cfg80211_wext_giwtxpower, |
2447 | IW_IOCTL(SIOCSIWENCODE) = rndis_iw_set_encode, | 2520 | IW_IOCTL(SIOCSIWENCODE) = (iw_handler) cfg80211_wext_siwencode, |
2448 | IW_IOCTL(SIOCSIWENCODEEXT) = rndis_iw_set_encode_ext, | 2521 | IW_IOCTL(SIOCSIWENCODEEXT) = (iw_handler) cfg80211_wext_siwencodeext, |
2449 | IW_IOCTL(SIOCSIWAUTH) = (iw_handler) cfg80211_wext_siwauth, | 2522 | IW_IOCTL(SIOCSIWAUTH) = (iw_handler) cfg80211_wext_siwauth, |
2450 | IW_IOCTL(SIOCGIWAUTH) = (iw_handler) cfg80211_wext_giwauth, | 2523 | IW_IOCTL(SIOCGIWAUTH) = (iw_handler) cfg80211_wext_giwauth, |
2451 | IW_IOCTL(SIOCSIWGENIE) = (iw_handler) cfg80211_wext_siwgenie, | 2524 | IW_IOCTL(SIOCSIWGENIE) = (iw_handler) cfg80211_wext_siwgenie, |