1/****************************************************************************** 2 * 3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 ******************************************************************************/ 15#define _IEEE80211_C 16 17#include <drv_types.h> 18#include <linux/ieee80211.h> 19#include <ieee80211.h> 20#include <wifi.h> 21#include <osdep_service.h> 22#include <wlan_bssdef.h> 23 24u8 RTW_WPA_OUI23A_TYPE[] = { 0x00, 0x50, 0xf2, 1 }; 25u16 RTW_WPA_VERSION23A = 1; 26u8 WPA_AUTH_KEY_MGMT_NONE23A[] = { 0x00, 0x50, 0xf2, 0 }; 27u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X23A[] = { 0x00, 0x50, 0xf2, 1 }; 28u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[] = { 0x00, 0x50, 0xf2, 2 }; 29u8 WPA_CIPHER_SUITE_NONE23A[] = { 0x00, 0x50, 0xf2, 0 }; 30u8 WPA_CIPHER_SUITE_WEP4023A[] = { 0x00, 0x50, 0xf2, 1 }; 31u8 WPA_CIPHER_SUITE_TKIP23A[] = { 0x00, 0x50, 0xf2, 2 }; 32u8 WPA_CIPHER_SUITE_WRAP23A[] = { 0x00, 0x50, 0xf2, 3 }; 33u8 WPA_CIPHER_SUITE_CCMP23A[] = { 0x00, 0x50, 0xf2, 4 }; 34u8 WPA_CIPHER_SUITE_WEP10423A[] = { 0x00, 0x50, 0xf2, 5 }; 35 36u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X23A[] = { 0x00, 0x0f, 0xac, 1 }; 37u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[] = { 0x00, 0x0f, 0xac, 2 }; 38u8 RSN_CIPHER_SUITE_NONE23A[] = { 0x00, 0x0f, 0xac, 0 }; 39u8 RSN_CIPHER_SUITE_WEP4023A[] = { 0x00, 0x0f, 0xac, 1 }; 40u8 RSN_CIPHER_SUITE_TKIP23A[] = { 0x00, 0x0f, 0xac, 2 }; 41u8 RSN_CIPHER_SUITE_WRAP23A[] = { 0x00, 0x0f, 0xac, 3 }; 42u8 RSN_CIPHER_SUITE_CCMP23A[] = { 0x00, 0x0f, 0xac, 4 }; 43u8 RSN_CIPHER_SUITE_WEP10423A[] = { 0x00, 0x0f, 0xac, 5 }; 44/* */ 45/* for adhoc-master to generate ie and provide supported-rate to fw */ 46/* */ 47 48static u8 WIFI_CCKRATES[] = { 49 IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK, 50 IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK, 51 IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK, 52 IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK 53}; 54 55static u8 WIFI_OFDMRATES[] = { 56 IEEE80211_OFDM_RATE_6MB, 57 IEEE80211_OFDM_RATE_9MB, 58 IEEE80211_OFDM_RATE_12MB, 59 IEEE80211_OFDM_RATE_18MB, 60 IEEE80211_OFDM_RATE_24MB, 61 IEEE80211_OFDM_RATE_36MB, 62 IEEE80211_OFDM_RATE_48MB, 63 IEEE80211_OFDM_RATE_54MB 64}; 65 66int rtw_get_bit_value_from_ieee_value23a(u8 val) 67{ 68 unsigned char dot11_rate_table[]= 69 {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 0}; 70 71 int i = 0; 72 while (dot11_rate_table[i] != 0) { 73 if (dot11_rate_table[i] == val) 74 return BIT(i); 75 i++; 76 } 77 return 0; 78} 79 80static bool rtw_is_cckrates_included(u8 *rate) 81{ 82 u32 i = 0; 83 84 while (rate[i]) { 85 if ((rate[i] & 0x7f) == 2 || (rate[i] & 0x7f) == 4 || 86 (rate[i] & 0x7f) == 11 || (rate[i] & 0x7f) == 22) 87 return true; 88 i++; 89 } 90 91 return false; 92} 93 94static bool rtw_is_cckratesonly_included(u8 *rate) 95{ 96 u32 i = 0; 97 98 while (rate[i]) { 99 if ((rate[i] & 0x7f) != 2 && (rate[i] & 0x7f) != 4 && 100 (rate[i] & 0x7f) != 11 && (rate[i] & 0x7f) != 22) 101 return false; 102 103 i++; 104 } 105 106 return true; 107} 108 109int rtw_check_network_type23a(unsigned char *rate, int ratelen, int channel) 110{ 111 if (channel > 14) { 112 if (rtw_is_cckrates_included(rate)) 113 return WIRELESS_INVALID; 114 else 115 return WIRELESS_11A; 116 } else { /* could be pure B, pure G, or B/G */ 117 if (rtw_is_cckratesonly_included(rate)) 118 return WIRELESS_11B; 119 else if (rtw_is_cckrates_included(rate)) 120 return WIRELESS_11BG; 121 else 122 return WIRELESS_11G; 123 } 124} 125 126/* rtw_set_ie23a will update frame length */ 127u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, const u8 *source, uint *frlen) 128{ 129 130 *pbuf = (u8)index; 131 132 *(pbuf + 1) = (u8)len; 133 134 if (len > 0) 135 memcpy((void *)(pbuf + 2), (void *)source, len); 136 137 *frlen = *frlen + (len + 2); 138 139 return pbuf + len + 2; 140} 141 142inline u8 *rtw_set_ie23a_ch_switch (u8 *buf, u32 *buf_len, u8 ch_switch_mode, 143 u8 new_ch, u8 ch_switch_cnt) 144{ 145 u8 ie_data[3]; 146 147 ie_data[0] = ch_switch_mode; 148 ie_data[1] = new_ch; 149 ie_data[2] = ch_switch_cnt; 150 return rtw_set_ie23a(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len); 151} 152 153inline u8 hal_ch_offset_to_secondary_ch_offset23a(u8 ch_offset) 154{ 155 if (ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) 156 return IEEE80211_HT_PARAM_CHA_SEC_BELOW; 157 else if (ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) 158 return IEEE80211_HT_PARAM_CHA_SEC_ABOVE; 159 160 return IEEE80211_HT_PARAM_CHA_SEC_NONE; 161} 162 163inline u8 *rtw_set_ie23a_secondary_ch_offset(u8 *buf, u32 *buf_len, 164 u8 secondary_ch_offset) 165{ 166 return rtw_set_ie23a(buf, WLAN_EID_SECONDARY_CHANNEL_OFFSET, 167 1, &secondary_ch_offset, buf_len); 168} 169 170/*---------------------------------------------------------------------------- 171index: the information element id index, limit is the limit for search 172-----------------------------------------------------------------------------*/ 173u8 *rtw_get_ie23a(u8 *pbuf, int index, int *len, int limit) 174{ 175 int tmp, i; 176 u8 *p; 177 178 if (limit < 1) { 179 180 return NULL; 181 } 182 183 p = pbuf; 184 i = 0; 185 *len = 0; 186 while (1) { 187 if (*p == index) { 188 *len = *(p + 1); 189 return p; 190 } else { 191 tmp = *(p + 1); 192 p += (tmp + 2); 193 i += (tmp + 2); 194 } 195 if (i >= limit) 196 break; 197 } 198 199 return NULL; 200} 201 202/** 203 * rtw_get_ie23a_ex - Search specific IE from a series of IEs 204 * @in_ie: Address of IEs to search 205 * @in_len: Length limit from in_ie 206 * @eid: Element ID to match 207 * @oui: OUI to match 208 * @oui_len: OUI length 209 * @ie: If not NULL and the specific IE is found, the IE will be copied 210 * to the buf starting from the specific IE 211 * @ielen: If not NULL and the specific IE is found, will set to the length 212 * of the entire IE 213 * 214 * Returns: The address of the specific IE found, or NULL 215 */ 216u8 *rtw_get_ie23a_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, 217 u8 *ie, uint *ielen) 218{ 219 uint cnt; 220 u8 *target_ie = NULL; 221 222 if (ielen) 223 *ielen = 0; 224 225 if (!in_ie || in_len <= 0) 226 return target_ie; 227 228 cnt = 0; 229 230 while (cnt < in_len) { 231 if (eid == in_ie[cnt] && 232 (!oui || !memcmp(&in_ie[cnt+2], oui, oui_len))) { 233 target_ie = &in_ie[cnt]; 234 235 if (ie) 236 memcpy(ie, &in_ie[cnt], in_ie[cnt+1]+2); 237 238 if (ielen) 239 *ielen = in_ie[cnt+1]+2; 240 break; 241 } else { 242 cnt += in_ie[cnt + 1] + 2; /* goto next */ 243 } 244 } 245 246 return target_ie; 247} 248 249/** 250 * rtw_ies_remove_ie23a - Find matching IEs and remove 251 * @ies: Address of IEs to search 252 * @ies_len: Pointer of length of ies, will update to new length 253 * @offset: The offset to start search 254 * @eid: Element ID to match 255 * @oui: OUI to match 256 * @oui_len: OUI length 257 * 258 * Returns: _SUCCESS: ies is updated, _FAIL: not updated 259 */ 260int rtw_ies_remove_ie23a(u8 *ies, uint *ies_len, uint offset, u8 eid, 261 u8 *oui, u8 oui_len) 262{ 263 int ret = _FAIL; 264 u8 *target_ie; 265 u32 target_ielen; 266 u8 *start; 267 uint search_len; 268 269 if (!ies || !ies_len || *ies_len <= offset) 270 goto exit; 271 272 start = ies + offset; 273 search_len = *ies_len - offset; 274 275 while (1) { 276 target_ie = rtw_get_ie23a_ex(start, search_len, eid, oui, oui_len, 277 NULL, &target_ielen); 278 if (target_ie && target_ielen) { 279 u8 buf[MAX_IE_SZ] = {0}; 280 u8 *remain_ies = target_ie + target_ielen; 281 uint remain_len = search_len - (remain_ies - start); 282 283 memcpy(buf, remain_ies, remain_len); 284 memcpy(target_ie, buf, remain_len); 285 *ies_len = *ies_len - target_ielen; 286 ret = _SUCCESS; 287 288 start = target_ie; 289 search_len = remain_len; 290 } else { 291 break; 292 } 293 } 294exit: 295 return ret; 296} 297 298void rtw_set_supported_rate23a(u8 *SupportedRates, uint mode) 299{ 300 301 302 memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX); 303 304 switch (mode) 305 { 306 case WIRELESS_11B: 307 memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); 308 break; 309 310 case WIRELESS_11G: 311 case WIRELESS_11A: 312 case WIRELESS_11_5N: 313 case WIRELESS_11A_5N:/* Todo: no basic rate for ofdm ? */ 314 memcpy(SupportedRates, WIFI_OFDMRATES, 315 IEEE80211_NUM_OFDM_RATESLEN); 316 break; 317 318 case WIRELESS_11BG: 319 case WIRELESS_11G_24N: 320 case WIRELESS_11_24N: 321 case WIRELESS_11BG_24N: 322 memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); 323 memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, 324 IEEE80211_NUM_OFDM_RATESLEN); 325 break; 326 } 327 328} 329 330uint rtw_get_rateset_len23a(u8 *rateset) 331{ 332 uint i = 0; 333 334 while(1) { 335 if (rateset[i] == 0) 336 break; 337 338 if (i > 12) 339 break; 340 341 i++; 342 } 343 344 return i; 345} 346 347int rtw_generate_ie23a(struct registry_priv *pregistrypriv) 348{ 349 u8 wireless_mode; 350 int sz = 0, rateLen; 351 struct wlan_bssid_ex* pdev_network = &pregistrypriv->dev_network; 352 u8* ie = pdev_network->IEs; 353 u16 cap; 354 355 pdev_network->tsf = 0; 356 357 cap = WLAN_CAPABILITY_IBSS; 358 359 if (pregistrypriv->preamble == PREAMBLE_SHORT) 360 cap |= WLAN_CAPABILITY_SHORT_PREAMBLE; 361 362 if (pdev_network->Privacy) 363 cap |= WLAN_CAPABILITY_PRIVACY; 364 365 pdev_network->capability = cap; 366 367 /* SSID */ 368 ie = rtw_set_ie23a(ie, WLAN_EID_SSID, pdev_network->Ssid.ssid_len, 369 pdev_network->Ssid.ssid, &sz); 370 371 /* supported rates */ 372 if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) { 373 if (pdev_network->DSConfig > 14) 374 wireless_mode = WIRELESS_11A_5N; 375 else 376 wireless_mode = WIRELESS_11BG_24N; 377 } else { 378 wireless_mode = pregistrypriv->wireless_mode; 379 } 380 381 rtw_set_supported_rate23a(pdev_network->SupportedRates, wireless_mode) ; 382 383 rateLen = rtw_get_rateset_len23a(pdev_network->SupportedRates); 384 385 if (rateLen > 8) { 386 ie = rtw_set_ie23a(ie, WLAN_EID_SUPP_RATES, 8, 387 pdev_network->SupportedRates, &sz); 388 /* ie = rtw_set_ie23a(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */ 389 } else { 390 ie = rtw_set_ie23a(ie, WLAN_EID_SUPP_RATES, rateLen, 391 pdev_network->SupportedRates, &sz); 392 } 393 394 /* DS parameter set */ 395 ie = rtw_set_ie23a(ie, WLAN_EID_DS_PARAMS, 1, 396 (u8 *)&pdev_network->DSConfig, &sz); 397 398 /* IBSS Parameter Set */ 399 400 ie = rtw_set_ie23a(ie, WLAN_EID_IBSS_PARAMS, 2, 401 (u8 *)&pdev_network->ATIMWindow, &sz); 402 403 if (rateLen > 8) { 404 ie = rtw_set_ie23a(ie, WLAN_EID_EXT_SUPP_RATES, (rateLen - 8), 405 (pdev_network->SupportedRates + 8), &sz); 406 } 407 408 409 410 /* return _SUCCESS; */ 411 412 return sz; 413} 414 415static int rtw_get_wpa_cipher_suite(const u8 *s) 416{ 417 if (!memcmp(s, WPA_CIPHER_SUITE_NONE23A, WPA_SELECTOR_LEN)) 418 return WPA_CIPHER_NONE; 419 if (!memcmp(s, WPA_CIPHER_SUITE_WEP4023A, WPA_SELECTOR_LEN)) 420 return WPA_CIPHER_WEP40; 421 if (!memcmp(s, WPA_CIPHER_SUITE_TKIP23A, WPA_SELECTOR_LEN)) 422 return WPA_CIPHER_TKIP; 423 if (!memcmp(s, WPA_CIPHER_SUITE_CCMP23A, WPA_SELECTOR_LEN)) 424 return WPA_CIPHER_CCMP; 425 if (!memcmp(s, WPA_CIPHER_SUITE_WEP10423A, WPA_SELECTOR_LEN)) 426 return WPA_CIPHER_WEP104; 427 428 return 0; 429} 430 431static int rtw_get_wpa2_cipher_suite(const u8 *s) 432{ 433 if (!memcmp(s, RSN_CIPHER_SUITE_NONE23A, RSN_SELECTOR_LEN)) 434 return WPA_CIPHER_NONE; 435 if (!memcmp(s, RSN_CIPHER_SUITE_WEP4023A, RSN_SELECTOR_LEN)) 436 return WPA_CIPHER_WEP40; 437 if (!memcmp(s, RSN_CIPHER_SUITE_TKIP23A, RSN_SELECTOR_LEN)) 438 return WPA_CIPHER_TKIP; 439 if (!memcmp(s, RSN_CIPHER_SUITE_CCMP23A, RSN_SELECTOR_LEN)) 440 return WPA_CIPHER_CCMP; 441 if (!memcmp(s, RSN_CIPHER_SUITE_WEP10423A, RSN_SELECTOR_LEN)) 442 return WPA_CIPHER_WEP104; 443 444 return 0; 445} 446 447int rtw_parse_wpa_ie23a(const u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x) 448{ 449 int i, ret = _SUCCESS; 450 int left, count; 451 const u8 *pos; 452 453 if (wpa_ie_len <= 0) { 454 /* No WPA IE - fail silently */ 455 return _FAIL; 456 } 457 458 if (wpa_ie[1] != (u8)(wpa_ie_len - 2)) 459 return _FAIL; 460 461 pos = wpa_ie; 462 463 pos += 8; 464 left = wpa_ie_len - 8; 465 466 /* group_cipher */ 467 if (left >= WPA_SELECTOR_LEN) { 468 469 *group_cipher = rtw_get_wpa_cipher_suite(pos); 470 471 pos += WPA_SELECTOR_LEN; 472 left -= WPA_SELECTOR_LEN; 473 } else if (left > 0) { 474 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, 475 ("%s: ie length mismatch, %u too much", 476 __func__, left)); 477 478 return _FAIL; 479 } 480 481 /* pairwise_cipher */ 482 if (left >= 2) { 483 /* count = le16_to_cpu(*(u16*)pos); */ 484 count = get_unaligned_le16(pos); 485 pos += 2; 486 left -= 2; 487 488 if (count == 0 || left < count * WPA_SELECTOR_LEN) { 489 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, 490 ("%s: ie count botch (pairwise), " 491 "count %u left %u", __func__, 492 count, left)); 493 return _FAIL; 494 } 495 496 for (i = 0; i < count; i++) { 497 *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos); 498 499 pos += WPA_SELECTOR_LEN; 500 left -= WPA_SELECTOR_LEN; 501 } 502 } else if (left == 1) { 503 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, 504 ("%s: ie too short (for key mgmt)", __func__)); 505 return _FAIL; 506 } 507 508 if (is_8021x) { 509 if (left >= 6) { 510 pos += 2; 511 if (!memcmp(pos, RTW_WPA_OUI23A_TYPE, 4)) { 512 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, 513 ("%s : there has 802.1x auth\n", 514 __func__)); 515 *is_8021x = 1; 516 } 517 } 518 } 519 520 return ret; 521} 522 523int rtw_parse_wpa2_ie23a(const u8 *rsn_ie, int rsn_ie_len, int *group_cipher, 524 int *pairwise_cipher, int *is_8021x) 525{ 526 int i, ret = _SUCCESS; 527 int left, count; 528 const u8 *pos; 529 u8 SUITE_1X[4] = {0x00, 0x0f, 0xac, 0x01}; 530 531 if (rsn_ie_len <= 0) { 532 /* No RSN IE - fail silently */ 533 return _FAIL; 534 } 535 536 if (*rsn_ie != WLAN_EID_RSN || *(rsn_ie+1) != (u8)(rsn_ie_len - 2)) { 537 return _FAIL; 538 } 539 540 pos = rsn_ie; 541 pos += 4; 542 left = rsn_ie_len - 4; 543 544 /* group_cipher */ 545 if (left >= RSN_SELECTOR_LEN) { 546 *group_cipher = rtw_get_wpa2_cipher_suite(pos); 547 548 pos += RSN_SELECTOR_LEN; 549 left -= RSN_SELECTOR_LEN; 550 } else if (left > 0) { 551 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, 552 ("%s: ie length mismatch, %u too much", 553 __func__, left)); 554 return _FAIL; 555 } 556 557 /* pairwise_cipher */ 558 if (left >= 2) { 559 /* count = le16_to_cpu(*(u16*)pos); */ 560 count = get_unaligned_le16(pos); 561 pos += 2; 562 left -= 2; 563 564 if (count == 0 || left < count * RSN_SELECTOR_LEN) { 565 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, 566 ("%s: ie count botch (pairwise), " 567 "count %u left %u", 568 __func__, count, left)); 569 return _FAIL; 570 } 571 572 for (i = 0; i < count; i++) { 573 *pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos); 574 575 pos += RSN_SELECTOR_LEN; 576 left -= RSN_SELECTOR_LEN; 577 } 578 } else if (left == 1) { 579 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, 580 ("%s: ie too short (for key mgmt)", __func__)); 581 582 return _FAIL; 583 } 584 585 if (is_8021x) { 586 if (left >= 6) { 587 pos += 2; 588 if (!memcmp(pos, SUITE_1X, 4)) { 589 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, 590 ("%s (): there has 802.1x auth\n", 591 __func__)); 592 *is_8021x = 1; 593 } 594 } 595 } 596 597 return ret; 598} 599 600/** 601 * rtw_get_wps_attr23a - Search a specific WPS attribute from a given WPS IE 602 * @wps_ie: Address of WPS IE to search 603 * @wps_ielen: Length limit from wps_ie 604 * @target_attr_id: The attribute ID of WPS attribute to search 605 * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute 606 * will be copied to the buf starting from buf_attr 607 * @len_attr: If not NULL and the WPS attribute is found, will set to the 608 * length of the entire WPS attribute 609 * 610 * Returns: the address of the specific WPS attribute found, or NULL 611 */ 612const u8 *rtw_get_wps_attr23a(const u8 *wps_ie, uint wps_ielen, 613 u16 target_attr_id, u8 *buf_attr, u32 *len_attr) 614{ 615 const u8 *attr_ptr = NULL; 616 const u8 *target_attr_ptr = NULL; 617 u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04}; 618 619 if (len_attr) 620 *len_attr = 0; 621 622 if (wps_ie[0] != WLAN_EID_VENDOR_SPECIFIC || 623 memcmp(wps_ie + 2, wps_oui, 4)) { 624 return attr_ptr; 625 } 626 627 /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */ 628 attr_ptr = wps_ie + 6; /* goto first attr */ 629 630 while (attr_ptr - wps_ie < wps_ielen) { 631 /* 4 = 2(Attribute ID) + 2(Length) */ 632 u16 attr_id = get_unaligned_be16(attr_ptr); 633 u16 attr_data_len = get_unaligned_be16(attr_ptr + 2); 634 u16 attr_len = attr_data_len + 4; 635 636 /* DBG_8723A("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len); */ 637 if (attr_id == target_attr_id) { 638 target_attr_ptr = attr_ptr; 639 640 if (buf_attr) 641 memcpy(buf_attr, attr_ptr, attr_len); 642 643 if (len_attr) 644 *len_attr = attr_len; 645 646 break; 647 } else { 648 attr_ptr += attr_len; /* goto next */ 649 } 650 } 651 652 return target_attr_ptr; 653} 654 655/** 656 * rtw_get_wps_attr_content23a - Search a specific WPS attribute content 657 * from a given WPS IE 658 * @wps_ie: Address of WPS IE to search 659 * @wps_ielen: Length limit from wps_ie 660 * @target_attr_id: The attribute ID of WPS attribute to search 661 * @buf_content: If not NULL and the WPS attribute is found, WPS attribute 662 * content will be copied to the buf starting from buf_content 663 * @len_content: If not NULL and the WPS attribute is found, will set to the 664 * length of the WPS attribute content 665 * 666 * Returns: the address of the specific WPS attribute content found, or NULL 667 */ 668const u8 *rtw_get_wps_attr_content23a(const u8 *wps_ie, uint wps_ielen, 669 u16 target_attr_id, u8 *buf_content) 670{ 671 const u8 *attr_ptr; 672 u32 attr_len; 673 674 attr_ptr = rtw_get_wps_attr23a(wps_ie, wps_ielen, target_attr_id, 675 NULL, &attr_len); 676 677 if (attr_ptr && attr_len) { 678 if (buf_content) 679 memcpy(buf_content, attr_ptr + 4, attr_len - 4); 680 681 return attr_ptr + 4; 682 } 683 684 return NULL; 685} 686 687static int rtw_get_cipher_info(struct wlan_network *pnetwork) 688{ 689 const u8 *pbuf; 690 int group_cipher = 0, pairwise_cipher = 0, is8021x = 0; 691 int ret = _FAIL; 692 int r, plen; 693 char *pie; 694 695 pie = pnetwork->network.IEs; 696 plen = pnetwork->network.IELength; 697 698 pbuf = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, 699 WLAN_OUI_TYPE_MICROSOFT_WPA, pie, plen); 700 701 if (pbuf && pbuf[1] > 0) { 702 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, 703 ("rtw_get_cipher_info: wpa_ielen: %d", pbuf[1])); 704 r = rtw_parse_wpa_ie23a(pbuf, pbuf[1] + 2, &group_cipher, 705 &pairwise_cipher, &is8021x); 706 if (r == _SUCCESS) { 707 pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher; 708 pnetwork->BcnInfo.group_cipher = group_cipher; 709 pnetwork->BcnInfo.is_8021x = is8021x; 710 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, 711 ("%s: pnetwork->pairwise_cipher: %d, is_" 712 "8021x is %d", __func__, 713 pnetwork->BcnInfo.pairwise_cipher, 714 pnetwork->BcnInfo.is_8021x)); 715 ret = _SUCCESS; 716 } 717 } else { 718 pbuf = cfg80211_find_ie(WLAN_EID_RSN, pie, plen); 719 720 if (pbuf && pbuf[1] > 0) { 721 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, 722 ("get RSN IE\n")); 723 r = rtw_parse_wpa2_ie23a(pbuf, pbuf[1] + 2, 724 &group_cipher, &pairwise_cipher, 725 &is8021x); 726 if (r == _SUCCESS) { 727 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, 728 ("get RSN IE OK!!!\n")); 729 pnetwork->BcnInfo.pairwise_cipher = 730 pairwise_cipher; 731 pnetwork->BcnInfo.group_cipher = group_cipher; 732 pnetwork->BcnInfo.is_8021x = is8021x; 733 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, 734 ("%s: pnetwork->pairwise_cipher: %d," 735 "pnetwork->group_cipher is %d, " 736 "is_8021x is %d", __func__, 737 pnetwork->BcnInfo.pairwise_cipher, 738 pnetwork->BcnInfo.group_cipher, 739 pnetwork->BcnInfo.is_8021x)); 740 ret = _SUCCESS; 741 } 742 } 743 } 744 745 return ret; 746} 747 748void rtw_get_bcn_info23a(struct wlan_network *pnetwork) 749{ 750 u8 bencrypt = 0; 751 int pie_len; 752 u8 *pie; 753 const u8 *p; 754 755 if (pnetwork->network.capability & WLAN_CAPABILITY_PRIVACY) { 756 bencrypt = 1; 757 pnetwork->network.Privacy = 1; 758 } else 759 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS; 760 761 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, 762 ("%s: ssid =%s\n", __func__, pnetwork->network.Ssid.ssid)); 763 764 pie = pnetwork->network.IEs; 765 pie_len = pnetwork->network.IELength; 766 767 p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len); 768 if (p && p[1]) { 769 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2; 770 } else if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, 771 WLAN_OUI_TYPE_MICROSOFT_WPA, 772 pie, pie_len)) { 773 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA; 774 } else { 775 if (bencrypt) 776 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP; 777 } 778 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, 779 ("%s: pnetwork->encryp_protocol is %x\n", __func__, 780 pnetwork->BcnInfo.encryp_protocol)); 781 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, 782 ("%s: pnetwork->encryp_protocol is %x\n", __func__, 783 pnetwork->BcnInfo.encryp_protocol)); 784 rtw_get_cipher_info(pnetwork); 785 786 /* get bwmode and ch_offset */ 787} 788 789/* show MCS rate, unit: 100Kbps */ 790u16 rtw_mcs_rate23a(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, 791 struct ieee80211_mcs_info *mcs) 792{ 793 u16 max_rate = 0; 794 795 if (rf_type == RF_1T1R) { 796 if (mcs->rx_mask[0] & BIT(7)) 797 max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350): 798 ((short_GI_20)?722:650); 799 else if (mcs->rx_mask[0] & BIT(6)) 800 max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215): 801 ((short_GI_20)?650:585); 802 else if (mcs->rx_mask[0] & BIT(5)) 803 max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080): 804 ((short_GI_20)?578:520); 805 else if (mcs->rx_mask[0] & BIT(4)) 806 max_rate = (bw_40MHz) ? ((short_GI_40)?900:810): 807 ((short_GI_20)?433:390); 808 else if (mcs->rx_mask[0] & BIT(3)) 809 max_rate = (bw_40MHz) ? ((short_GI_40)?600:540): 810 ((short_GI_20)?289:260); 811 else if (mcs->rx_mask[0] & BIT(2)) 812 max_rate = (bw_40MHz) ? ((short_GI_40)?450:405): 813 ((short_GI_20)?217:195); 814 else if (mcs->rx_mask[0] & BIT(1)) 815 max_rate = (bw_40MHz) ? ((short_GI_40)?300:270): 816 ((short_GI_20)?144:130); 817 else if (mcs->rx_mask[0] & BIT(0)) 818 max_rate = (bw_40MHz) ? ((short_GI_40)?150:135): 819 ((short_GI_20)?72:65); 820 } else { 821 if (mcs->rx_mask[1]) { 822 if (mcs->rx_mask[1] & BIT(7)) 823 max_rate = (bw_40MHz) ? ((short_GI_40)?3000:2700):((short_GI_20)?1444:1300); 824 else if (mcs->rx_mask[1] & BIT(6)) 825 max_rate = (bw_40MHz) ? ((short_GI_40)?2700:2430):((short_GI_20)?1300:1170); 826 else if (mcs->rx_mask[1] & BIT(5)) 827 max_rate = (bw_40MHz) ? ((short_GI_40)?2400:2160):((short_GI_20)?1156:1040); 828 else if (mcs->rx_mask[1] & BIT(4)) 829 max_rate = (bw_40MHz) ? ((short_GI_40)?1800:1620):((short_GI_20)?867:780); 830 else if (mcs->rx_mask[1] & BIT(3)) 831 max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520); 832 else if (mcs->rx_mask[1] & BIT(2)) 833 max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390); 834 else if (mcs->rx_mask[1] & BIT(1)) 835 max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260); 836 else if (mcs->rx_mask[1] & BIT(0)) 837 max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130); 838 } else { 839 if (mcs->rx_mask[0] & BIT(7)) 840 max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350):((short_GI_20)?722:650); 841 else if (mcs->rx_mask[0] & BIT(6)) 842 max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215):((short_GI_20)?650:585); 843 else if (mcs->rx_mask[0] & BIT(5)) 844 max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520); 845 else if (mcs->rx_mask[0] & BIT(4)) 846 max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390); 847 else if (mcs->rx_mask[0] & BIT(3)) 848 max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260); 849 else if (mcs->rx_mask[0] & BIT(2)) 850 max_rate = (bw_40MHz) ? ((short_GI_40)?450:405):((short_GI_20)?217:195); 851 else if (mcs->rx_mask[0] & BIT(1)) 852 max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130); 853 else if (mcs->rx_mask[0] & BIT(0)) 854 max_rate = (bw_40MHz) ? ((short_GI_40)?150:135):((short_GI_20)?72:65); 855 } 856 } 857 return max_rate; 858} 859