diff options
Diffstat (limited to 'drivers/net/wireless/rndis_wlan.c')
-rw-r--r-- | drivers/net/wireless/rndis_wlan.c | 61 |
1 files changed, 34 insertions, 27 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index a330c69583d6..d66e2980bc27 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -518,7 +518,7 @@ struct rndis_wlan_private { | |||
518 | __le32 current_command_oid; | 518 | __le32 current_command_oid; |
519 | 519 | ||
520 | /* encryption stuff */ | 520 | /* encryption stuff */ |
521 | int encr_tx_key_index; | 521 | u8 encr_tx_key_index; |
522 | struct rndis_wlan_encr_key encr_keys[RNDIS_WLAN_NUM_KEYS]; | 522 | struct rndis_wlan_encr_key encr_keys[RNDIS_WLAN_NUM_KEYS]; |
523 | int wpa_version; | 523 | int wpa_version; |
524 | 524 | ||
@@ -634,7 +634,7 @@ static u32 get_bcm4320_power_dbm(struct rndis_wlan_private *priv) | |||
634 | } | 634 | } |
635 | } | 635 | } |
636 | 636 | ||
637 | static bool is_wpa_key(struct rndis_wlan_private *priv, int idx) | 637 | static bool is_wpa_key(struct rndis_wlan_private *priv, u8 idx) |
638 | { | 638 | { |
639 | int cipher = priv->encr_keys[idx].cipher; | 639 | int cipher = priv->encr_keys[idx].cipher; |
640 | 640 | ||
@@ -1350,7 +1350,7 @@ static int set_channel(struct usbnet *usbdev, int channel) | |||
1350 | } | 1350 | } |
1351 | 1351 | ||
1352 | static struct ieee80211_channel *get_current_channel(struct usbnet *usbdev, | 1352 | static struct ieee80211_channel *get_current_channel(struct usbnet *usbdev, |
1353 | u16 *beacon_interval) | 1353 | u32 *beacon_period) |
1354 | { | 1354 | { |
1355 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 1355 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
1356 | struct ieee80211_channel *channel; | 1356 | struct ieee80211_channel *channel; |
@@ -1370,14 +1370,14 @@ static struct ieee80211_channel *get_current_channel(struct usbnet *usbdev, | |||
1370 | if (!channel) | 1370 | if (!channel) |
1371 | return NULL; | 1371 | return NULL; |
1372 | 1372 | ||
1373 | if (beacon_interval) | 1373 | if (beacon_period) |
1374 | *beacon_interval = le16_to_cpu(config.beacon_period); | 1374 | *beacon_period = le32_to_cpu(config.beacon_period); |
1375 | return channel; | 1375 | return channel; |
1376 | } | 1376 | } |
1377 | 1377 | ||
1378 | /* index must be 0 - N, as per NDIS */ | 1378 | /* index must be 0 - N, as per NDIS */ |
1379 | static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len, | 1379 | static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len, |
1380 | int index) | 1380 | u8 index) |
1381 | { | 1381 | { |
1382 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 1382 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
1383 | struct ndis_80211_wep_key ndis_key; | 1383 | struct ndis_80211_wep_key ndis_key; |
@@ -1387,13 +1387,15 @@ static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len, | |||
1387 | netdev_dbg(usbdev->net, "%s(idx: %d, len: %d)\n", | 1387 | netdev_dbg(usbdev->net, "%s(idx: %d, len: %d)\n", |
1388 | __func__, index, key_len); | 1388 | __func__, index, key_len); |
1389 | 1389 | ||
1390 | if ((key_len != 5 && key_len != 13) || index < 0 || index > 3) | 1390 | if (index >= RNDIS_WLAN_NUM_KEYS) |
1391 | return -EINVAL; | 1391 | return -EINVAL; |
1392 | 1392 | ||
1393 | if (key_len == 5) | 1393 | if (key_len == 5) |
1394 | cipher = WLAN_CIPHER_SUITE_WEP40; | 1394 | cipher = WLAN_CIPHER_SUITE_WEP40; |
1395 | else | 1395 | else if (key_len == 13) |
1396 | cipher = WLAN_CIPHER_SUITE_WEP104; | 1396 | cipher = WLAN_CIPHER_SUITE_WEP104; |
1397 | else | ||
1398 | return -EINVAL; | ||
1397 | 1399 | ||
1398 | memset(&ndis_key, 0, sizeof(ndis_key)); | 1400 | memset(&ndis_key, 0, sizeof(ndis_key)); |
1399 | 1401 | ||
@@ -1428,7 +1430,7 @@ static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len, | |||
1428 | } | 1430 | } |
1429 | 1431 | ||
1430 | static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, | 1432 | static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, |
1431 | int index, const u8 *addr, const u8 *rx_seq, | 1433 | u8 index, const u8 *addr, const u8 *rx_seq, |
1432 | int seq_len, u32 cipher, __le32 flags) | 1434 | int seq_len, u32 cipher, __le32 flags) |
1433 | { | 1435 | { |
1434 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 1436 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
@@ -1436,7 +1438,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, | |||
1436 | bool is_addr_ok; | 1438 | bool is_addr_ok; |
1437 | int ret; | 1439 | int ret; |
1438 | 1440 | ||
1439 | if (index < 0 || index >= 4) { | 1441 | if (index >= RNDIS_WLAN_NUM_KEYS) { |
1440 | netdev_dbg(usbdev->net, "%s(): index out of range (%i)\n", | 1442 | netdev_dbg(usbdev->net, "%s(): index out of range (%i)\n", |
1441 | __func__, index); | 1443 | __func__, index); |
1442 | return -EINVAL; | 1444 | return -EINVAL; |
@@ -1524,7 +1526,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, | |||
1524 | return 0; | 1526 | return 0; |
1525 | } | 1527 | } |
1526 | 1528 | ||
1527 | static int restore_key(struct usbnet *usbdev, int key_idx) | 1529 | static int restore_key(struct usbnet *usbdev, u8 key_idx) |
1528 | { | 1530 | { |
1529 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 1531 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
1530 | struct rndis_wlan_encr_key key; | 1532 | struct rndis_wlan_encr_key key; |
@@ -1550,13 +1552,13 @@ static void restore_keys(struct usbnet *usbdev) | |||
1550 | restore_key(usbdev, i); | 1552 | restore_key(usbdev, i); |
1551 | } | 1553 | } |
1552 | 1554 | ||
1553 | static void clear_key(struct rndis_wlan_private *priv, int idx) | 1555 | static void clear_key(struct rndis_wlan_private *priv, u8 idx) |
1554 | { | 1556 | { |
1555 | memset(&priv->encr_keys[idx], 0, sizeof(priv->encr_keys[idx])); | 1557 | memset(&priv->encr_keys[idx], 0, sizeof(priv->encr_keys[idx])); |
1556 | } | 1558 | } |
1557 | 1559 | ||
1558 | /* remove_key is for both wep and wpa */ | 1560 | /* remove_key is for both wep and wpa */ |
1559 | static int remove_key(struct usbnet *usbdev, int index, const u8 *bssid) | 1561 | static int remove_key(struct usbnet *usbdev, u8 index, const u8 *bssid) |
1560 | { | 1562 | { |
1561 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 1563 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
1562 | struct ndis_80211_remove_key remove_key; | 1564 | struct ndis_80211_remove_key remove_key; |
@@ -1790,9 +1792,9 @@ static struct ndis_80211_pmkid *remove_pmkid(struct usbnet *usbdev, | |||
1790 | struct cfg80211_pmksa *pmksa, | 1792 | struct cfg80211_pmksa *pmksa, |
1791 | int max_pmkids) | 1793 | int max_pmkids) |
1792 | { | 1794 | { |
1793 | int i, len, count, newlen, err; | 1795 | int i, newlen, err; |
1796 | unsigned int count; | ||
1794 | 1797 | ||
1795 | len = le32_to_cpu(pmkids->length); | ||
1796 | count = le32_to_cpu(pmkids->bssid_info_count); | 1798 | count = le32_to_cpu(pmkids->bssid_info_count); |
1797 | 1799 | ||
1798 | if (count > max_pmkids) | 1800 | if (count > max_pmkids) |
@@ -1831,9 +1833,9 @@ static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev, | |||
1831 | struct cfg80211_pmksa *pmksa, | 1833 | struct cfg80211_pmksa *pmksa, |
1832 | int max_pmkids) | 1834 | int max_pmkids) |
1833 | { | 1835 | { |
1834 | int i, err, len, count, newlen; | 1836 | int i, err, newlen; |
1837 | unsigned int count; | ||
1835 | 1838 | ||
1836 | len = le32_to_cpu(pmkids->length); | ||
1837 | count = le32_to_cpu(pmkids->bssid_info_count); | 1839 | count = le32_to_cpu(pmkids->bssid_info_count); |
1838 | 1840 | ||
1839 | if (count > max_pmkids) | 1841 | if (count > max_pmkids) |
@@ -2683,7 +2685,7 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid, | |||
2683 | s32 signal; | 2685 | s32 signal; |
2684 | u64 timestamp; | 2686 | u64 timestamp; |
2685 | u16 capability; | 2687 | u16 capability; |
2686 | u16 beacon_interval = 0; | 2688 | u32 beacon_period = 0; |
2687 | __le32 rssi; | 2689 | __le32 rssi; |
2688 | u8 ie_buf[34]; | 2690 | u8 ie_buf[34]; |
2689 | int len, ret, ie_len; | 2691 | int len, ret, ie_len; |
@@ -2708,7 +2710,7 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid, | |||
2708 | } | 2710 | } |
2709 | 2711 | ||
2710 | /* Get channel and beacon interval */ | 2712 | /* Get channel and beacon interval */ |
2711 | channel = get_current_channel(usbdev, &beacon_interval); | 2713 | channel = get_current_channel(usbdev, &beacon_period); |
2712 | if (!channel) { | 2714 | if (!channel) { |
2713 | netdev_warn(usbdev->net, "%s(): could not get channel.\n", | 2715 | netdev_warn(usbdev->net, "%s(): could not get channel.\n", |
2714 | __func__); | 2716 | __func__); |
@@ -2738,11 +2740,11 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid, | |||
2738 | netdev_dbg(usbdev->net, "%s(): channel:%d(freq), bssid:[%pM], tsf:%d, " | 2740 | netdev_dbg(usbdev->net, "%s(): channel:%d(freq), bssid:[%pM], tsf:%d, " |
2739 | "capa:%x, beacon int:%d, resp_ie(len:%d, essid:'%.32s'), " | 2741 | "capa:%x, beacon int:%d, resp_ie(len:%d, essid:'%.32s'), " |
2740 | "signal:%d\n", __func__, (channel ? channel->center_freq : -1), | 2742 | "signal:%d\n", __func__, (channel ? channel->center_freq : -1), |
2741 | bssid, (u32)timestamp, capability, beacon_interval, ie_len, | 2743 | bssid, (u32)timestamp, capability, beacon_period, ie_len, |
2742 | ssid.essid, signal); | 2744 | ssid.essid, signal); |
2743 | 2745 | ||
2744 | bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid, | 2746 | bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid, |
2745 | timestamp, capability, beacon_interval, ie_buf, ie_len, | 2747 | timestamp, capability, beacon_period, ie_buf, ie_len, |
2746 | signal, GFP_KERNEL); | 2748 | signal, GFP_KERNEL); |
2747 | cfg80211_put_bss(bss); | 2749 | cfg80211_put_bss(bss); |
2748 | } | 2750 | } |
@@ -2755,9 +2757,10 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
2755 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 2757 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
2756 | struct ndis_80211_assoc_info *info = NULL; | 2758 | struct ndis_80211_assoc_info *info = NULL; |
2757 | u8 bssid[ETH_ALEN]; | 2759 | u8 bssid[ETH_ALEN]; |
2758 | int resp_ie_len, req_ie_len; | 2760 | unsigned int resp_ie_len, req_ie_len; |
2761 | unsigned int offset; | ||
2759 | u8 *req_ie, *resp_ie; | 2762 | u8 *req_ie, *resp_ie; |
2760 | int ret, offset; | 2763 | int ret; |
2761 | bool roamed = false; | 2764 | bool roamed = false; |
2762 | bool match_bss; | 2765 | bool match_bss; |
2763 | 2766 | ||
@@ -2785,7 +2788,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
2785 | ret = get_association_info(usbdev, info, CONTROL_BUFFER_SIZE); | 2788 | ret = get_association_info(usbdev, info, CONTROL_BUFFER_SIZE); |
2786 | if (!ret) { | 2789 | if (!ret) { |
2787 | req_ie_len = le32_to_cpu(info->req_ie_length); | 2790 | req_ie_len = le32_to_cpu(info->req_ie_length); |
2788 | if (req_ie_len > 0) { | 2791 | if (req_ie_len > CONTROL_BUFFER_SIZE) |
2792 | req_ie_len = CONTROL_BUFFER_SIZE; | ||
2793 | if (req_ie_len != 0) { | ||
2789 | offset = le32_to_cpu(info->offset_req_ies); | 2794 | offset = le32_to_cpu(info->offset_req_ies); |
2790 | 2795 | ||
2791 | if (offset > CONTROL_BUFFER_SIZE) | 2796 | if (offset > CONTROL_BUFFER_SIZE) |
@@ -2799,7 +2804,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
2799 | } | 2804 | } |
2800 | 2805 | ||
2801 | resp_ie_len = le32_to_cpu(info->resp_ie_length); | 2806 | resp_ie_len = le32_to_cpu(info->resp_ie_length); |
2802 | if (resp_ie_len > 0) { | 2807 | if (resp_ie_len > CONTROL_BUFFER_SIZE) |
2808 | resp_ie_len = CONTROL_BUFFER_SIZE; | ||
2809 | if (resp_ie_len != 0) { | ||
2803 | offset = le32_to_cpu(info->offset_resp_ies); | 2810 | offset = le32_to_cpu(info->offset_resp_ies); |
2804 | 2811 | ||
2805 | if (offset > CONTROL_BUFFER_SIZE) | 2812 | if (offset > CONTROL_BUFFER_SIZE) |
@@ -3038,7 +3045,7 @@ static void rndis_wlan_media_specific_indication(struct usbnet *usbdev, | |||
3038 | struct rndis_indicate *msg, int buflen) | 3045 | struct rndis_indicate *msg, int buflen) |
3039 | { | 3046 | { |
3040 | struct ndis_80211_status_indication *indication; | 3047 | struct ndis_80211_status_indication *indication; |
3041 | int len, offset; | 3048 | unsigned int len, offset; |
3042 | 3049 | ||
3043 | offset = offsetof(struct rndis_indicate, status) + | 3050 | offset = offsetof(struct rndis_indicate, status) + |
3044 | le32_to_cpu(msg->offset); | 3051 | le32_to_cpu(msg->offset); |
@@ -3050,7 +3057,7 @@ static void rndis_wlan_media_specific_indication(struct usbnet *usbdev, | |||
3050 | return; | 3057 | return; |
3051 | } | 3058 | } |
3052 | 3059 | ||
3053 | if (offset + len > buflen) { | 3060 | if (len > buflen || offset > buflen || offset + len > buflen) { |
3054 | netdev_info(usbdev->net, "media specific indication, too large to fit to buffer (%i > %i)\n", | 3061 | netdev_info(usbdev->net, "media specific indication, too large to fit to buffer (%i > %i)\n", |
3055 | offset + len, buflen); | 3062 | offset + len, buflen); |
3056 | return; | 3063 | return; |