diff options
Diffstat (limited to 'drivers/net/wireless/rndis_wlan.c')
-rw-r--r-- | drivers/net/wireless/rndis_wlan.c | 86 |
1 files changed, 45 insertions, 41 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 620e3c0e88e0..3802c31fefcd 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -244,6 +244,10 @@ enum ndis_80211_power_mode { | |||
244 | NDIS_80211_POWER_MODE_FAST_PSP, | 244 | NDIS_80211_POWER_MODE_FAST_PSP, |
245 | }; | 245 | }; |
246 | 246 | ||
247 | enum ndis_80211_pmkid_cand_list_flag_bits { | ||
248 | NDIS_80211_PMKID_CAND_PREAUTH = cpu_to_le32(1 << 0) | ||
249 | }; | ||
250 | |||
247 | struct ndis_80211_auth_request { | 251 | struct ndis_80211_auth_request { |
248 | __le32 length; | 252 | __le32 length; |
249 | u8 bssid[6]; | 253 | u8 bssid[6]; |
@@ -387,19 +391,17 @@ struct ndis_80211_capability { | |||
387 | struct ndis_80211_bssid_info { | 391 | struct ndis_80211_bssid_info { |
388 | u8 bssid[6]; | 392 | u8 bssid[6]; |
389 | u8 pmkid[16]; | 393 | u8 pmkid[16]; |
390 | }; | 394 | } __packed; |
391 | 395 | ||
392 | struct ndis_80211_pmkid { | 396 | struct ndis_80211_pmkid { |
393 | __le32 length; | 397 | __le32 length; |
394 | __le32 bssid_info_count; | 398 | __le32 bssid_info_count; |
395 | struct ndis_80211_bssid_info bssid_info[0]; | 399 | struct ndis_80211_bssid_info bssid_info[0]; |
396 | }; | 400 | } __packed; |
397 | 401 | ||
398 | /* | 402 | /* |
399 | * private data | 403 | * private data |
400 | */ | 404 | */ |
401 | #define NET_TYPE_11FB 0 | ||
402 | |||
403 | #define CAP_MODE_80211A 1 | 405 | #define CAP_MODE_80211A 1 |
404 | #define CAP_MODE_80211B 2 | 406 | #define CAP_MODE_80211B 2 |
405 | #define CAP_MODE_80211G 4 | 407 | #define CAP_MODE_80211G 4 |
@@ -1347,6 +1349,32 @@ static int set_channel(struct usbnet *usbdev, int channel) | |||
1347 | return ret; | 1349 | return ret; |
1348 | } | 1350 | } |
1349 | 1351 | ||
1352 | static struct ieee80211_channel *get_current_channel(struct usbnet *usbdev, | ||
1353 | u16 *beacon_interval) | ||
1354 | { | ||
1355 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | ||
1356 | struct ieee80211_channel *channel; | ||
1357 | struct ndis_80211_conf config; | ||
1358 | int len, ret; | ||
1359 | |||
1360 | /* Get channel and beacon interval */ | ||
1361 | len = sizeof(config); | ||
1362 | ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len); | ||
1363 | netdev_dbg(usbdev->net, "%s(): OID_802_11_CONFIGURATION -> %d\n", | ||
1364 | __func__, ret); | ||
1365 | if (ret < 0) | ||
1366 | return NULL; | ||
1367 | |||
1368 | channel = ieee80211_get_channel(priv->wdev.wiphy, | ||
1369 | KHZ_TO_MHZ(le32_to_cpu(config.ds_config))); | ||
1370 | if (!channel) | ||
1371 | return NULL; | ||
1372 | |||
1373 | if (beacon_interval) | ||
1374 | *beacon_interval = le16_to_cpu(config.beacon_period); | ||
1375 | return channel; | ||
1376 | } | ||
1377 | |||
1350 | /* index must be 0 - N, as per NDIS */ | 1378 | /* index must be 0 - N, as per NDIS */ |
1351 | 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, |
1352 | int index) | 1380 | int index) |
@@ -2650,13 +2678,12 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid, | |||
2650 | { | 2678 | { |
2651 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 2679 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
2652 | struct ieee80211_channel *channel; | 2680 | struct ieee80211_channel *channel; |
2653 | struct ndis_80211_conf config; | ||
2654 | struct ndis_80211_ssid ssid; | 2681 | struct ndis_80211_ssid ssid; |
2655 | struct cfg80211_bss *bss; | 2682 | struct cfg80211_bss *bss; |
2656 | s32 signal; | 2683 | s32 signal; |
2657 | u64 timestamp; | 2684 | u64 timestamp; |
2658 | u16 capability; | 2685 | u16 capability; |
2659 | u16 beacon_interval; | 2686 | u16 beacon_interval = 0; |
2660 | __le32 rssi; | 2687 | __le32 rssi; |
2661 | u8 ie_buf[34]; | 2688 | u8 ie_buf[34]; |
2662 | int len, ret, ie_len; | 2689 | int len, ret, ie_len; |
@@ -2681,22 +2708,10 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid, | |||
2681 | } | 2708 | } |
2682 | 2709 | ||
2683 | /* Get channel and beacon interval */ | 2710 | /* Get channel and beacon interval */ |
2684 | len = sizeof(config); | 2711 | channel = get_current_channel(usbdev, &beacon_interval); |
2685 | ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len); | 2712 | if (!channel) { |
2686 | netdev_dbg(usbdev->net, "%s(): OID_802_11_CONFIGURATION -> %d\n", | 2713 | netdev_warn(usbdev->net, "%s(): could not get channel.\n", |
2687 | __func__, ret); | 2714 | __func__); |
2688 | if (ret >= 0) { | ||
2689 | beacon_interval = le16_to_cpu(config.beacon_period); | ||
2690 | channel = ieee80211_get_channel(priv->wdev.wiphy, | ||
2691 | KHZ_TO_MHZ(le32_to_cpu(config.ds_config))); | ||
2692 | if (!channel) { | ||
2693 | netdev_warn(usbdev->net, "%s(): could not get channel." | ||
2694 | "\n", __func__); | ||
2695 | return; | ||
2696 | } | ||
2697 | } else { | ||
2698 | netdev_warn(usbdev->net, "%s(): could not get configuration.\n", | ||
2699 | __func__); | ||
2700 | return; | 2715 | return; |
2701 | } | 2716 | } |
2702 | 2717 | ||
@@ -2841,8 +2856,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
2841 | req_ie_len, resp_ie, | 2856 | req_ie_len, resp_ie, |
2842 | resp_ie_len, 0, GFP_KERNEL); | 2857 | resp_ie_len, 0, GFP_KERNEL); |
2843 | else | 2858 | else |
2844 | cfg80211_roamed(usbdev->net, NULL, bssid, | 2859 | cfg80211_roamed(usbdev->net, |
2845 | req_ie, req_ie_len, | 2860 | get_current_channel(usbdev, NULL), |
2861 | bssid, req_ie, req_ie_len, | ||
2846 | resp_ie, resp_ie_len, GFP_KERNEL); | 2862 | resp_ie, resp_ie_len, GFP_KERNEL); |
2847 | } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) | 2863 | } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) |
2848 | cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); | 2864 | cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); |
@@ -3008,25 +3024,13 @@ static void rndis_wlan_pmkid_cand_list_indication(struct usbnet *usbdev, | |||
3008 | for (i = 0; i < le32_to_cpu(cand_list->num_candidates); i++) { | 3024 | for (i = 0; i < le32_to_cpu(cand_list->num_candidates); i++) { |
3009 | struct ndis_80211_pmkid_candidate *cand = | 3025 | struct ndis_80211_pmkid_candidate *cand = |
3010 | &cand_list->candidate_list[i]; | 3026 | &cand_list->candidate_list[i]; |
3027 | bool preauth = !!(cand->flags & NDIS_80211_PMKID_CAND_PREAUTH); | ||
3011 | 3028 | ||
3012 | netdev_dbg(usbdev->net, "cand[%i]: flags: 0x%08x, bssid: %pM\n", | 3029 | netdev_dbg(usbdev->net, "cand[%i]: flags: 0x%08x, preauth: %d, bssid: %pM\n", |
3013 | i, le32_to_cpu(cand->flags), cand->bssid); | 3030 | i, le32_to_cpu(cand->flags), preauth, cand->bssid); |
3014 | |||
3015 | #if 0 | ||
3016 | struct iw_pmkid_cand pcand; | ||
3017 | union iwreq_data wrqu; | ||
3018 | 3031 | ||
3019 | memset(&pcand, 0, sizeof(pcand)); | 3032 | cfg80211_pmksa_candidate_notify(usbdev->net, i, cand->bssid, |
3020 | if (le32_to_cpu(cand->flags) & 0x01) | 3033 | preauth, GFP_ATOMIC); |
3021 | pcand.flags |= IW_PMKID_CAND_PREAUTH; | ||
3022 | pcand.index = i; | ||
3023 | memcpy(pcand.bssid.sa_data, cand->bssid, ETH_ALEN); | ||
3024 | |||
3025 | memset(&wrqu, 0, sizeof(wrqu)); | ||
3026 | wrqu.data.length = sizeof(pcand); | ||
3027 | wireless_send_event(usbdev->net, IWEVPMKIDCAND, &wrqu, | ||
3028 | (u8 *)&pcand); | ||
3029 | #endif | ||
3030 | } | 3034 | } |
3031 | } | 3035 | } |
3032 | 3036 | ||