aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2011-08-30 14:57:51 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2011-08-31 03:13:00 -0400
commit3c774bbab78435e349de2c88fc6e054716f8f2ea (patch)
treeb323ad5f398ef346951adb4cdd017c286d8e2ece
parent6a7c9badab158086b6162c661a47c4f1a4a68e92 (diff)
ath6kl: Fix AP mode (Re)AssocReq IE processing
Need to use correct length field for association request frame and parse the IEs to find WPA/WPS/RSN IE. In addition, copying of the IE better make sure it fits in into the buffer to avoid buffer overflows. In addition, add the (Re)AssocReq IEs to the cfg80211 new station event for user space. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c57
1 files changed, 49 insertions, 8 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index b64b2a357560..89e29ead254f 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -61,7 +61,8 @@ static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie,
61 61
62 sta = &ar->sta_list[free_slot]; 62 sta = &ar->sta_list[free_slot];
63 memcpy(sta->mac, mac, ETH_ALEN); 63 memcpy(sta->mac, mac, ETH_ALEN);
64 memcpy(sta->wpa_ie, wpaie, ielen); 64 if (ielen <= ATH6KL_MAX_IE)
65 memcpy(sta->wpa_ie, wpaie, ielen);
65 sta->aid = aid; 66 sta->aid = aid;
66 sta->keymgmt = keymgmt; 67 sta->keymgmt = keymgmt;
67 sta->ucipher = ucipher; 68 sta->ucipher = ucipher;
@@ -429,9 +430,11 @@ static void ath6kl_install_static_wep_keys(struct ath6kl *ar)
429 430
430static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid, 431static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid,
431 u16 listen_int, u16 beacon_int, 432 u16 listen_int, u16 beacon_int,
432 u8 assoc_resp_len, u8 *assoc_info) 433 u8 assoc_req_len, u8 *assoc_info)
433{ 434{
434 struct net_device *dev = ar->net_dev; 435 struct net_device *dev = ar->net_dev;
436 u8 *ies = NULL, *wpa_ie = NULL, *pos;
437 size_t ies_len = 0;
435 struct station_info sinfo; 438 struct station_info sinfo;
436 struct ath6kl_req_key *ik; 439 struct ath6kl_req_key *ik;
437 enum crypto_type keyType = NONE_CRYPT; 440 enum crypto_type keyType = NONE_CRYPT;
@@ -473,7 +476,43 @@ skip_key:
473 ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n", 476 ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n",
474 bssid, channel); 477 bssid, channel);
475 478
476 ath6kl_add_new_sta(ar, bssid, channel, assoc_info, assoc_resp_len, 479 if (assoc_req_len > sizeof(struct ieee80211_hdr_3addr)) {
480 struct ieee80211_mgmt *mgmt =
481 (struct ieee80211_mgmt *) assoc_info;
482 if (ieee80211_is_assoc_req(mgmt->frame_control) &&
483 assoc_req_len >= sizeof(struct ieee80211_hdr_3addr) +
484 sizeof(mgmt->u.assoc_req)) {
485 ies = mgmt->u.assoc_req.variable;
486 ies_len = assoc_info + assoc_req_len - ies;
487 } else if (ieee80211_is_reassoc_req(mgmt->frame_control) &&
488 assoc_req_len >= sizeof(struct ieee80211_hdr_3addr)
489 + sizeof(mgmt->u.reassoc_req)) {
490 ies = mgmt->u.reassoc_req.variable;
491 ies_len = assoc_info + assoc_req_len - ies;
492 }
493 }
494
495 pos = ies;
496 while (pos && pos + 1 < ies + ies_len) {
497 if (pos + 2 + pos[1] > ies + ies_len)
498 break;
499 if (pos[0] == WLAN_EID_RSN)
500 wpa_ie = pos; /* RSN IE */
501 else if (pos[0] == WLAN_EID_VENDOR_SPECIFIC &&
502 pos[1] >= 4 &&
503 pos[2] == 0x00 && pos[3] == 0x50 && pos[4] == 0xf2) {
504 if (pos[5] == 0x01)
505 wpa_ie = pos; /* WPA IE */
506 else if (pos[5] == 0x04) {
507 wpa_ie = pos; /* WPS IE */
508 break; /* overrides WPA/RSN IE */
509 }
510 }
511 pos += 2 + pos[1];
512 }
513
514 ath6kl_add_new_sta(ar, bssid, channel, wpa_ie,
515 wpa_ie ? 2 + wpa_ie[1] : 0,
477 listen_int & 0xFF, beacon_int, 516 listen_int & 0xFF, beacon_int,
478 (listen_int >> 8) & 0xFF); 517 (listen_int >> 8) & 0xFF);
479 518
@@ -481,9 +520,11 @@ skip_key:
481 memset(&sinfo, 0, sizeof(sinfo)); 520 memset(&sinfo, 0, sizeof(sinfo));
482 521
483 /* TODO: sinfo.generation */ 522 /* TODO: sinfo.generation */
484 /* TODO: need to deliver (Re)AssocReq IEs somehow.. change in 523
485 * cfg80211 needed, e.g., by adding those into sinfo 524 sinfo.assoc_req_ies = ies;
486 */ 525 sinfo.assoc_req_ies_len = ies_len;
526 sinfo.filled |= STATION_INFO_ASSOC_REQ_IES;
527
487 cfg80211_new_sta(ar->net_dev, bssid, &sinfo, GFP_KERNEL); 528 cfg80211_new_sta(ar->net_dev, bssid, &sinfo, GFP_KERNEL);
488 529
489 netif_wake_queue(ar->net_dev); 530 netif_wake_queue(ar->net_dev);
@@ -895,8 +936,8 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid,
895 936
896 if (ar->nw_type == AP_NETWORK) { 937 if (ar->nw_type == AP_NETWORK) {
897 ath6kl_connect_ap_mode(ar, channel, bssid, listen_int, 938 ath6kl_connect_ap_mode(ar, channel, bssid, listen_int,
898 beacon_int, assoc_resp_len, 939 beacon_int, assoc_req_len,
899 assoc_info); 940 assoc_info + beacon_ie_len);
900 return; 941 return;
901 } 942 }
902 943