1 // SPDX-License-Identifier: GPL-2.0 2 /****************************************************************************** 3 * 4 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. 5 * 6 ******************************************************************************/ 7 #define _IEEE80211_C 8 9 #include <drv_types.h> 10 #include <rtw_debug.h> 11 #include <linux/of.h> 12 #include <asm/unaligned.h> 13 14 u8 RTW_WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 }; 15 u16 RTW_WPA_VERSION = 1; 16 u8 WPA_AUTH_KEY_MGMT_NONE[] = { 0x00, 0x50, 0xf2, 0 }; 17 u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 }; 18 u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 }; 19 u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 }; 20 u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 }; 21 u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 }; 22 u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 }; 23 u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 }; 24 u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 }; 25 26 u16 RSN_VERSION_BSD = 1; 27 u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x0f, 0xac, 1 }; 28 u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x0f, 0xac, 2 }; 29 u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 }; 30 u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 }; 31 u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 }; 32 u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 }; 33 u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 }; 34 u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 }; 35 /* */ 36 /* for adhoc-master to generate ie and provide supported-rate to fw */ 37 /* */ 38 39 static u8 WIFI_CCKRATES[] = { 40 (IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK), 41 (IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK), 42 (IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK), 43 (IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK) 44 }; 45 46 static u8 WIFI_OFDMRATES[] = { 47 (IEEE80211_OFDM_RATE_6MB), 48 (IEEE80211_OFDM_RATE_9MB), 49 (IEEE80211_OFDM_RATE_12MB), 50 (IEEE80211_OFDM_RATE_18MB), 51 (IEEE80211_OFDM_RATE_24MB), 52 IEEE80211_OFDM_RATE_36MB, 53 IEEE80211_OFDM_RATE_48MB, 54 IEEE80211_OFDM_RATE_54MB 55 }; 56 57 int rtw_get_bit_value_from_ieee_value(u8 val) 58 { 59 unsigned char dot11_rate_table[] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 0}; /* last element must be zero!! */ 60 int i = 0; 61 62 while (dot11_rate_table[i] != 0) { 63 if (dot11_rate_table[i] == val) 64 return BIT(i); 65 i++; 66 } 67 return 0; 68 } 69 70 bool rtw_is_cckrates_included(u8 *rate) 71 { 72 while (*rate) { 73 u8 r = *rate & 0x7f; 74 75 if (r == 2 || r == 4 || r == 11 || r == 22) 76 return true; 77 rate++; 78 } 79 80 return false; 81 } 82 83 bool rtw_is_cckratesonly_included(u8 *rate) 84 { 85 while (*rate) { 86 u8 r = *rate & 0x7f; 87 88 if (r != 2 && r != 4 && r != 11 && r != 22) 89 return false; 90 rate++; 91 } 92 93 return true; 94 } 95 96 int rtw_check_network_type(unsigned char *rate, int ratelen, int channel) 97 { 98 if (channel > 14) { 99 if (rtw_is_cckrates_included(rate)) 100 return WIRELESS_INVALID; 101 else 102 return WIRELESS_11A; 103 } else { /* could be pure B, pure G, or B/G */ 104 if (rtw_is_cckratesonly_included(rate)) 105 return WIRELESS_11B; 106 else if (rtw_is_cckrates_included(rate)) 107 return WIRELESS_11BG; 108 else 109 return WIRELESS_11G; 110 } 111 } 112 113 u8 *rtw_set_fixed_ie(unsigned char *pbuf, unsigned int len, unsigned char *source, 114 unsigned int *frlen) 115 { 116 memcpy((void *)pbuf, (void *)source, len); 117 *frlen = *frlen + len; 118 return pbuf + len; 119 } 120 121 /* rtw_set_ie will update frame length */ 122 u8 *rtw_set_ie(u8 *pbuf, 123 sint index, 124 uint len, 125 u8 *source, 126 uint *frlen) /* frame length */ 127 { 128 *pbuf = (u8)index; 129 130 *(pbuf + 1) = (u8)len; 131 132 if (len > 0) 133 memcpy((void *)(pbuf + 2), (void *)source, len); 134 135 *frlen = *frlen + (len + 2); 136 137 return pbuf + len + 2; 138 } 139 140 /*---------------------------------------------------------------------------- 141 index: the information element id index, limit is the limit for search 142 -----------------------------------------------------------------------------*/ 143 u8 *rtw_get_ie(u8 *pbuf, sint index, sint *len, sint limit) 144 { 145 sint tmp, i; 146 u8 *p; 147 148 if (limit < 1) 149 return NULL; 150 151 p = pbuf; 152 i = 0; 153 *len = 0; 154 while (1) { 155 if (*p == index) { 156 *len = *(p + 1); 157 return p; 158 } else { 159 tmp = *(p + 1); 160 p += (tmp + 2); 161 i += (tmp + 2); 162 } 163 if (i >= limit) 164 break; 165 } 166 return NULL; 167 } 168 169 /** 170 * rtw_get_ie_ex - Search specific IE from a series of IEs 171 * @in_ie: Address of IEs to search 172 * @in_len: Length limit from in_ie 173 * @eid: Element ID to match 174 * @oui: OUI to match 175 * @oui_len: OUI length 176 * @ie: If not NULL and the specific IE is found, the IE will be copied to the buf starting from the specific IE 177 * @ielen: If not NULL and the specific IE is found, will set to the length of the entire IE 178 * 179 * Returns: The address of the specific IE found, or NULL 180 */ 181 u8 *rtw_get_ie_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, u8 *ie, uint *ielen) 182 { 183 uint cnt; 184 u8 *target_ie = NULL; 185 186 if (ielen) 187 *ielen = 0; 188 189 if (!in_ie || in_len <= 0) 190 return target_ie; 191 192 cnt = 0; 193 194 while (cnt < in_len) { 195 if (eid == in_ie[cnt] 196 && (!oui || !memcmp(&in_ie[cnt+2], oui, oui_len))) { 197 target_ie = &in_ie[cnt]; 198 199 if (ie) 200 memcpy(ie, &in_ie[cnt], in_ie[cnt+1]+2); 201 202 if (ielen) 203 *ielen = in_ie[cnt+1]+2; 204 205 break; 206 } else { 207 cnt += in_ie[cnt+1]+2; /* goto next */ 208 } 209 } 210 211 return target_ie; 212 } 213 214 /** 215 * rtw_ies_remove_ie - Find matching IEs and remove 216 * @ies: Address of IEs to search 217 * @ies_len: Pointer of length of ies, will update to new length 218 * @offset: The offset to start search 219 * @eid: Element ID to match 220 * @oui: OUI to match 221 * @oui_len: OUI length 222 * 223 * Returns: _SUCCESS: ies is updated, _FAIL: not updated 224 */ 225 int rtw_ies_remove_ie(u8 *ies, uint *ies_len, uint offset, u8 eid, u8 *oui, u8 oui_len) 226 { 227 int ret = _FAIL; 228 u8 *target_ie; 229 u32 target_ielen; 230 u8 *start; 231 uint search_len; 232 233 if (!ies || !ies_len || *ies_len <= offset) 234 goto exit; 235 236 start = ies + offset; 237 search_len = *ies_len - offset; 238 239 while (1) { 240 target_ie = rtw_get_ie_ex(start, search_len, eid, oui, oui_len, NULL, &target_ielen); 241 if (target_ie && target_ielen) { 242 u8 buf[MAX_IE_SZ] = {0}; 243 u8 *remain_ies = target_ie + target_ielen; 244 uint remain_len = search_len - (remain_ies - start); 245 246 memcpy(buf, remain_ies, remain_len); 247 memcpy(target_ie, buf, remain_len); 248 *ies_len = *ies_len - target_ielen; 249 ret = _SUCCESS; 250 251 start = target_ie; 252 search_len = remain_len; 253 } else { 254 break; 255 } 256 } 257 exit: 258 return ret; 259 } 260 261 void rtw_set_supported_rate(u8 *SupportedRates, uint mode) 262 { 263 memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX); 264 265 switch (mode) { 266 case WIRELESS_11B: 267 memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); 268 break; 269 270 case WIRELESS_11G: 271 case WIRELESS_11A: 272 case WIRELESS_11_5N: 273 case WIRELESS_11A_5N:/* Todo: no basic rate for ofdm ? */ 274 case WIRELESS_11_5AC: 275 memcpy(SupportedRates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN); 276 break; 277 278 case WIRELESS_11BG: 279 case WIRELESS_11G_24N: 280 case WIRELESS_11_24N: 281 case WIRELESS_11BG_24N: 282 memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); 283 memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN); 284 break; 285 } 286 } 287 288 uint rtw_get_rateset_len(u8 *rateset) 289 { 290 uint i; 291 292 for (i = 0; i < 13; i++) 293 if (rateset[i] == 0) 294 break; 295 return i; 296 } 297 298 int rtw_generate_ie(struct registry_priv *pregistrypriv) 299 { 300 u8 wireless_mode; 301 int sz = 0, rateLen; 302 struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network; 303 u8 *ie = pdev_network->IEs; 304 305 /* timestamp will be inserted by hardware */ 306 sz += 8; 307 ie += sz; 308 309 /* beacon interval : 2bytes */ 310 *(__le16 *)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);/* BCN_INTERVAL; */ 311 sz += 2; 312 ie += 2; 313 314 /* capability info */ 315 *(u16 *)ie = 0; 316 317 *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_IBSS); 318 319 if (pregistrypriv->preamble == PREAMBLE_SHORT) 320 *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); 321 322 if (pdev_network->Privacy) 323 *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); 324 325 sz += 2; 326 ie += 2; 327 328 /* SSID */ 329 ie = rtw_set_ie(ie, WLAN_EID_SSID, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz); 330 331 /* supported rates */ 332 if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) { 333 if (pdev_network->Configuration.DSConfig > 14) 334 wireless_mode = WIRELESS_11A_5N; 335 else 336 wireless_mode = WIRELESS_11BG_24N; 337 } else { 338 wireless_mode = pregistrypriv->wireless_mode; 339 } 340 341 rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode); 342 343 rateLen = rtw_get_rateset_len(pdev_network->SupportedRates); 344 345 if (rateLen > 8) { 346 ie = rtw_set_ie(ie, WLAN_EID_SUPP_RATES, 8, pdev_network->SupportedRates, &sz); 347 /* ie = rtw_set_ie(ie, WLAN_EID_EXT_SUPP_RATES, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */ 348 } else { 349 ie = rtw_set_ie(ie, WLAN_EID_SUPP_RATES, rateLen, pdev_network->SupportedRates, &sz); 350 } 351 352 /* DS parameter set */ 353 ie = rtw_set_ie(ie, WLAN_EID_DS_PARAMS, 1, (u8 *)&(pdev_network->Configuration.DSConfig), &sz); 354 355 /* IBSS Parameter Set */ 356 357 ie = rtw_set_ie(ie, WLAN_EID_IBSS_PARAMS, 2, (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz); 358 359 if (rateLen > 8) { 360 ie = rtw_set_ie(ie, WLAN_EID_EXT_SUPP_RATES, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); 361 } 362 363 /* HT Cap. */ 364 if (((pregistrypriv->wireless_mode&WIRELESS_11_5N) || (pregistrypriv->wireless_mode&WIRELESS_11_24N)) 365 && (pregistrypriv->ht_enable == true)) { 366 /* todo: */ 367 } 368 369 /* pdev_network->IELength = sz; update IELength */ 370 371 /* return _SUCCESS; */ 372 373 return sz; 374 } 375 376 unsigned char *rtw_get_wpa_ie(unsigned char *pie, int *wpa_ie_len, int limit) 377 { 378 int len; 379 u16 val16; 380 unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01}; 381 u8 *pbuf = pie; 382 int limit_new = limit; 383 __le16 le_tmp; 384 385 while (1) { 386 pbuf = rtw_get_ie(pbuf, WLAN_EID_VENDOR_SPECIFIC, &len, limit_new); 387 388 if (pbuf) { 389 /* check if oui matches... */ 390 if (memcmp((pbuf + 2), wpa_oui_type, sizeof(wpa_oui_type))) { 391 goto check_next_ie; 392 } 393 394 /* check version... */ 395 memcpy((u8 *)&le_tmp, (pbuf + 6), sizeof(val16)); 396 397 val16 = le16_to_cpu(le_tmp); 398 if (val16 != 0x0001) 399 goto check_next_ie; 400 401 *wpa_ie_len = *(pbuf + 1); 402 403 return pbuf; 404 405 } else { 406 *wpa_ie_len = 0; 407 return NULL; 408 } 409 410 check_next_ie: 411 412 limit_new = limit - (pbuf - pie) - 2 - len; 413 414 if (limit_new <= 0) 415 break; 416 417 pbuf += (2 + len); 418 } 419 420 *wpa_ie_len = 0; 421 422 return NULL; 423 } 424 425 unsigned char *rtw_get_wpa2_ie(unsigned char *pie, int *rsn_ie_len, int limit) 426 { 427 return rtw_get_ie(pie, WLAN_EID_RSN, rsn_ie_len, limit); 428 } 429 430 int rtw_get_wpa_cipher_suite(u8 *s) 431 { 432 if (!memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN)) 433 return WPA_CIPHER_NONE; 434 if (!memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN)) 435 return WPA_CIPHER_WEP40; 436 if (!memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN)) 437 return WPA_CIPHER_TKIP; 438 if (!memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN)) 439 return WPA_CIPHER_CCMP; 440 if (!memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN)) 441 return WPA_CIPHER_WEP104; 442 443 return 0; 444 } 445 446 int rtw_get_wpa2_cipher_suite(u8 *s) 447 { 448 if (!memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN)) 449 return WPA_CIPHER_NONE; 450 if (!memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN)) 451 return WPA_CIPHER_WEP40; 452 if (!memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN)) 453 return WPA_CIPHER_TKIP; 454 if (!memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN)) 455 return WPA_CIPHER_CCMP; 456 if (!memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN)) 457 return WPA_CIPHER_WEP104; 458 459 return 0; 460 } 461 462 int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x) 463 { 464 int i, ret = _SUCCESS; 465 int left, count; 466 u8 *pos; 467 u8 SUITE_1X[4] = {0x00, 0x50, 0xf2, 1}; 468 469 if (wpa_ie_len <= 0) { 470 /* No WPA IE - fail silently */ 471 return _FAIL; 472 } 473 474 if ((*wpa_ie != WLAN_EID_VENDOR_SPECIFIC) || (*(wpa_ie+1) != (u8)(wpa_ie_len - 2)) || 475 (memcmp(wpa_ie+2, RTW_WPA_OUI_TYPE, WPA_SELECTOR_LEN))) { 476 return _FAIL; 477 } 478 479 pos = wpa_ie; 480 481 pos += 8; 482 left = wpa_ie_len - 8; 483 484 /* group_cipher */ 485 if (left >= WPA_SELECTOR_LEN) { 486 *group_cipher = rtw_get_wpa_cipher_suite(pos); 487 488 pos += WPA_SELECTOR_LEN; 489 left -= WPA_SELECTOR_LEN; 490 491 } else if (left > 0) { 492 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie length mismatch, %u too much", __func__, left)); 493 494 return _FAIL; 495 } 496 497 /* pairwise_cipher */ 498 if (left >= 2) { 499 /* count = le16_to_cpu(*(u16*)pos); */ 500 count = get_unaligned_le16(pos); 501 pos += 2; 502 left -= 2; 503 504 if (count == 0 || left < count * WPA_SELECTOR_LEN) { 505 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie count botch (pairwise), " 506 "count %u left %u", __func__, count, left)); 507 return _FAIL; 508 } 509 510 for (i = 0; i < count; i++) { 511 *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos); 512 513 pos += WPA_SELECTOR_LEN; 514 left -= WPA_SELECTOR_LEN; 515 } 516 517 } else if (left == 1) { 518 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie too short (for key mgmt)", __func__)); 519 return _FAIL; 520 } 521 522 if (is_8021x) { 523 if (left >= 6) { 524 pos += 2; 525 if (!memcmp(pos, SUITE_1X, 4)) { 526 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s : there has 802.1x auth\n", __func__)); 527 *is_8021x = 1; 528 } 529 } 530 } 531 532 return ret; 533 } 534 535 int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x) 536 { 537 int i, ret = _SUCCESS; 538 int left, count; 539 u8 *pos; 540 u8 SUITE_1X[4] = {0x00, 0x0f, 0xac, 0x01}; 541 542 if (rsn_ie_len <= 0) { 543 /* No RSN IE - fail silently */ 544 return _FAIL; 545 } 546 547 if ((*rsn_ie != WLAN_EID_RSN) || (*(rsn_ie+1) != (u8)(rsn_ie_len - 2))) { 548 return _FAIL; 549 } 550 551 pos = rsn_ie; 552 pos += 4; 553 left = rsn_ie_len - 4; 554 555 /* group_cipher */ 556 if (left >= RSN_SELECTOR_LEN) { 557 *group_cipher = rtw_get_wpa2_cipher_suite(pos); 558 559 pos += RSN_SELECTOR_LEN; 560 left -= RSN_SELECTOR_LEN; 561 562 } else if (left > 0) { 563 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie length mismatch, %u too much", __func__, left)); 564 return _FAIL; 565 } 566 567 /* pairwise_cipher */ 568 if (left >= 2) { 569 /* count = le16_to_cpu(*(u16*)pos); */ 570 count = get_unaligned_le16(pos); 571 pos += 2; 572 left -= 2; 573 574 if (count == 0 || left < count * RSN_SELECTOR_LEN) { 575 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie count botch (pairwise), " 576 "count %u left %u", __func__, count, left)); 577 return _FAIL; 578 } 579 580 for (i = 0; i < count; i++) { 581 *pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos); 582 583 pos += RSN_SELECTOR_LEN; 584 left -= RSN_SELECTOR_LEN; 585 } 586 587 } else if (left == 1) { 588 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie too short (for key mgmt)", __func__)); 589 590 return _FAIL; 591 } 592 593 if (is_8021x) { 594 if (left >= 6) { 595 pos += 2; 596 if (!memcmp(pos, SUITE_1X, 4)) { 597 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s (): there has 802.1x auth\n", __func__)); 598 *is_8021x = 1; 599 } 600 } 601 } 602 603 return ret; 604 } 605 606 /* ifdef CONFIG_WAPI_SUPPORT */ 607 int rtw_get_wapi_ie(u8 *in_ie, uint in_len, u8 *wapi_ie, u16 *wapi_len) 608 { 609 int len = 0; 610 u8 authmode, i; 611 uint cnt; 612 u8 wapi_oui1[4] = {0x0, 0x14, 0x72, 0x01}; 613 u8 wapi_oui2[4] = {0x0, 0x14, 0x72, 0x02}; 614 615 if (wapi_len) 616 *wapi_len = 0; 617 618 if (!in_ie || in_len <= 0) 619 return len; 620 621 cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_); 622 623 while (cnt < in_len) { 624 authmode = in_ie[cnt]; 625 626 /* if (authmode == WLAN_EID_BSS_AC_ACCESS_DELAY) */ 627 if (authmode == WLAN_EID_BSS_AC_ACCESS_DELAY && (!memcmp(&in_ie[cnt+6], wapi_oui1, 4) || 628 !memcmp(&in_ie[cnt+6], wapi_oui2, 4))) { 629 if (wapi_ie) { 630 memcpy(wapi_ie, &in_ie[cnt], in_ie[cnt+1]+2); 631 632 for (i = 0; i < (in_ie[cnt+1]+2); i = i+8) { 633 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n", 634 wapi_ie[i], wapi_ie[i+1], wapi_ie[i+2], wapi_ie[i+3], wapi_ie[i+4], 635 wapi_ie[i+5], wapi_ie[i+6], wapi_ie[i+7])); 636 } 637 } 638 639 if (wapi_len) 640 *wapi_len = in_ie[cnt+1]+2; 641 642 cnt += in_ie[cnt+1]+2; /* get next */ 643 } else { 644 cnt += in_ie[cnt+1]+2; /* get next */ 645 } 646 } 647 648 if (wapi_len) 649 len = *wapi_len; 650 651 return len; 652 } 653 /* endif */ 654 655 void rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie, u16 *wpa_len) 656 { 657 u8 authmode, sec_idx, i; 658 u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01}; 659 uint cnt; 660 661 /* Search required WPA or WPA2 IE and copy to sec_ie[ ] */ 662 663 cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_); 664 665 sec_idx = 0; 666 667 while (cnt < in_len) { 668 authmode = in_ie[cnt]; 669 670 if ((authmode == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&in_ie[cnt+2], &wpa_oui[0], 4))) { 671 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\n rtw_get_wpa_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n", sec_idx, in_ie[cnt+1]+2)); 672 673 if (wpa_ie) { 674 memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt+1]+2); 675 676 for (i = 0; i < (in_ie[cnt+1]+2); i = i+8) { 677 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n", 678 wpa_ie[i], wpa_ie[i+1], wpa_ie[i+2], wpa_ie[i+3], wpa_ie[i+4], 679 wpa_ie[i+5], wpa_ie[i+6], wpa_ie[i+7])); 680 } 681 } 682 683 *wpa_len = in_ie[cnt+1]+2; 684 cnt += in_ie[cnt+1]+2; /* get next */ 685 } else { 686 if (authmode == WLAN_EID_RSN) { 687 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\n get_rsn_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n", sec_idx, in_ie[cnt+1]+2)); 688 689 if (rsn_ie) { 690 memcpy(rsn_ie, &in_ie[cnt], in_ie[cnt+1]+2); 691 692 for (i = 0; i < (in_ie[cnt+1]+2); i = i+8) { 693 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n", 694 rsn_ie[i], rsn_ie[i+1], rsn_ie[i+2], rsn_ie[i+3], rsn_ie[i+4], 695 rsn_ie[i+5], rsn_ie[i+6], rsn_ie[i+7])); 696 } 697 } 698 699 *rsn_len = in_ie[cnt+1]+2; 700 cnt += in_ie[cnt+1]+2; /* get next */ 701 } else { 702 cnt += in_ie[cnt+1]+2; /* get next */ 703 } 704 } 705 } 706 } 707 708 u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen) 709 { 710 u8 match = false; 711 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04}; 712 713 if (!ie_ptr) 714 return match; 715 716 eid = ie_ptr[0]; 717 718 if ((eid == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&ie_ptr[2], wps_oui, 4))) { 719 /* DBG_8192C("==> found WPS_IE.....\n"); */ 720 *wps_ielen = ie_ptr[1]+2; 721 match = true; 722 } 723 return match; 724 } 725 726 /** 727 * rtw_get_wps_ie - Search WPS IE from a series of IEs 728 * @in_ie: Address of IEs to search 729 * @in_len: Length limit from in_ie 730 * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the buf starting from wps_ie 731 * @wps_ielen: If not NULL and WPS IE is found, will set to the length of the entire WPS IE 732 * 733 * Returns: The address of the WPS IE found, or NULL 734 */ 735 u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen) 736 { 737 uint cnt; 738 u8 *wpsie_ptr = NULL; 739 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04}; 740 741 if (wps_ielen) 742 *wps_ielen = 0; 743 744 if (!in_ie || in_len <= 0) 745 return wpsie_ptr; 746 747 cnt = 0; 748 749 while (cnt < in_len) { 750 eid = in_ie[cnt]; 751 752 if ((eid == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&in_ie[cnt+2], wps_oui, 4))) { 753 wpsie_ptr = &in_ie[cnt]; 754 755 if (wps_ie) 756 memcpy(wps_ie, &in_ie[cnt], in_ie[cnt+1]+2); 757 758 if (wps_ielen) 759 *wps_ielen = in_ie[cnt+1]+2; 760 761 cnt += in_ie[cnt+1]+2; 762 763 break; 764 } else { 765 cnt += in_ie[cnt+1]+2; /* goto next */ 766 } 767 } 768 769 return wpsie_ptr; 770 } 771 772 /** 773 * rtw_get_wps_attr - Search a specific WPS attribute from a given WPS IE 774 * @wps_ie: Address of WPS IE to search 775 * @wps_ielen: Length limit from wps_ie 776 * @target_attr_id: The attribute ID of WPS attribute to search 777 * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute will be copied to the buf starting from buf_attr 778 * @len_attr: If not NULL and the WPS attribute is found, will set to the length of the entire WPS attribute 779 * 780 * Returns: the address of the specific WPS attribute found, or NULL 781 */ 782 u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_attr, u32 *len_attr) 783 { 784 u8 *attr_ptr = NULL; 785 u8 *target_attr_ptr = NULL; 786 u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04}; 787 788 if (len_attr) 789 *len_attr = 0; 790 791 if ((wps_ie[0] != WLAN_EID_VENDOR_SPECIFIC) || 792 (memcmp(wps_ie + 2, wps_oui, 4))) { 793 return attr_ptr; 794 } 795 796 /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */ 797 attr_ptr = wps_ie + 6; /* goto first attr */ 798 799 while (attr_ptr - wps_ie < wps_ielen) { 800 /* 4 = 2(Attribute ID) + 2(Length) */ 801 u16 attr_id = get_unaligned_be16(attr_ptr); 802 u16 attr_data_len = get_unaligned_be16(attr_ptr + 2); 803 u16 attr_len = attr_data_len + 4; 804 805 /* DBG_871X("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len); */ 806 if (attr_id == target_attr_id) { 807 target_attr_ptr = attr_ptr; 808 809 if (buf_attr) 810 memcpy(buf_attr, attr_ptr, attr_len); 811 812 if (len_attr) 813 *len_attr = attr_len; 814 815 break; 816 } else { 817 attr_ptr += attr_len; /* goto next */ 818 } 819 } 820 821 return target_attr_ptr; 822 } 823 824 /** 825 * rtw_get_wps_attr_content - Search a specific WPS attribute content from a given WPS IE 826 * @wps_ie: Address of WPS IE to search 827 * @wps_ielen: Length limit from wps_ie 828 * @target_attr_id: The attribute ID of WPS attribute to search 829 * @buf_content: If not NULL and the WPS attribute is found, WPS attribute content will be copied to the buf starting from buf_content 830 * @len_content: If not NULL and the WPS attribute is found, will set to the length of the WPS attribute content 831 * 832 * Returns: the address of the specific WPS attribute content found, or NULL 833 */ 834 u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_content, uint *len_content) 835 { 836 u8 *attr_ptr; 837 u32 attr_len; 838 839 if (len_content) 840 *len_content = 0; 841 842 attr_ptr = rtw_get_wps_attr(wps_ie, wps_ielen, target_attr_id, NULL, &attr_len); 843 844 if (attr_ptr && attr_len) { 845 if (buf_content) 846 memcpy(buf_content, attr_ptr+4, attr_len-4); 847 848 if (len_content) 849 *len_content = attr_len-4; 850 851 return attr_ptr+4; 852 } 853 854 return NULL; 855 } 856 857 static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen, 858 struct rtw_ieee802_11_elems *elems, 859 int show_errors) 860 { 861 unsigned int oui; 862 863 /* first 3 bytes in vendor specific information element are the IEEE 864 * OUI of the vendor. The following byte is used a vendor specific 865 * sub-type. */ 866 if (elen < 4) { 867 if (show_errors) { 868 DBG_871X("short vendor specific " 869 "information element ignored (len =%lu)\n", 870 (unsigned long) elen); 871 } 872 return -1; 873 } 874 875 oui = get_unaligned_be24(pos); 876 switch (oui) { 877 case OUI_MICROSOFT: 878 /* Microsoft/Wi-Fi information elements are further typed and 879 * subtyped */ 880 switch (pos[3]) { 881 case 1: 882 /* Microsoft OUI (00:50:F2) with OUI Type 1: 883 * real WPA information element */ 884 elems->wpa_ie = pos; 885 elems->wpa_ie_len = elen; 886 break; 887 case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */ 888 if (elen < 5) { 889 DBG_871X("short WME " 890 "information element ignored " 891 "(len =%lu)\n", 892 (unsigned long) elen); 893 return -1; 894 } 895 switch (pos[4]) { 896 case WME_OUI_SUBTYPE_INFORMATION_ELEMENT: 897 case WME_OUI_SUBTYPE_PARAMETER_ELEMENT: 898 elems->wme = pos; 899 elems->wme_len = elen; 900 break; 901 case WME_OUI_SUBTYPE_TSPEC_ELEMENT: 902 elems->wme_tspec = pos; 903 elems->wme_tspec_len = elen; 904 break; 905 default: 906 DBG_871X("unknown WME " 907 "information element ignored " 908 "(subtype =%d len =%lu)\n", 909 pos[4], (unsigned long) elen); 910 return -1; 911 } 912 break; 913 case 4: 914 /* Wi-Fi Protected Setup (WPS) IE */ 915 elems->wps_ie = pos; 916 elems->wps_ie_len = elen; 917 break; 918 default: 919 DBG_871X("Unknown Microsoft " 920 "information element ignored " 921 "(type =%d len =%lu)\n", 922 pos[3], (unsigned long) elen); 923 return -1; 924 } 925 break; 926 927 case OUI_BROADCOM: 928 switch (pos[3]) { 929 case VENDOR_HT_CAPAB_OUI_TYPE: 930 elems->vendor_ht_cap = pos; 931 elems->vendor_ht_cap_len = elen; 932 break; 933 default: 934 DBG_871X("Unknown Broadcom " 935 "information element ignored " 936 "(type =%d len =%lu)\n", 937 pos[3], (unsigned long) elen); 938 return -1; 939 } 940 break; 941 942 default: 943 DBG_871X("unknown vendor specific information " 944 "element ignored (vendor OUI %02x:%02x:%02x " 945 "len =%lu)\n", 946 pos[0], pos[1], pos[2], (unsigned long) elen); 947 return -1; 948 } 949 950 return 0; 951 } 952 953 /** 954 * ieee802_11_parse_elems - Parse information elements in management frames 955 * @start: Pointer to the start of IEs 956 * @len: Length of IE buffer in octets 957 * @elems: Data structure for parsed elements 958 * @show_errors: Whether to show parsing errors in debug log 959 * Returns: Parsing result 960 */ 961 ParseRes rtw_ieee802_11_parse_elems(u8 *start, uint len, 962 struct rtw_ieee802_11_elems *elems, 963 int show_errors) 964 { 965 uint left = len; 966 u8 *pos = start; 967 int unknown = 0; 968 969 memset(elems, 0, sizeof(*elems)); 970 971 while (left >= 2) { 972 u8 id, elen; 973 974 id = *pos++; 975 elen = *pos++; 976 left -= 2; 977 978 if (elen > left) { 979 if (show_errors) { 980 DBG_871X("IEEE 802.11 element " 981 "parse failed (id =%d elen =%d " 982 "left =%lu)\n", 983 id, elen, (unsigned long) left); 984 } 985 return ParseFailed; 986 } 987 988 switch (id) { 989 case WLAN_EID_SSID: 990 elems->ssid = pos; 991 elems->ssid_len = elen; 992 break; 993 case WLAN_EID_SUPP_RATES: 994 elems->supp_rates = pos; 995 elems->supp_rates_len = elen; 996 break; 997 case WLAN_EID_FH_PARAMS: 998 elems->fh_params = pos; 999 elems->fh_params_len = elen; 1000 break; 1001 case WLAN_EID_DS_PARAMS: 1002 elems->ds_params = pos; 1003 elems->ds_params_len = elen; 1004 break; 1005 case WLAN_EID_CF_PARAMS: 1006 elems->cf_params = pos; 1007 elems->cf_params_len = elen; 1008 break; 1009 case WLAN_EID_TIM: 1010 elems->tim = pos; 1011 elems->tim_len = elen; 1012 break; 1013 case WLAN_EID_IBSS_PARAMS: 1014 elems->ibss_params = pos; 1015 elems->ibss_params_len = elen; 1016 break; 1017 case WLAN_EID_CHALLENGE: 1018 elems->challenge = pos; 1019 elems->challenge_len = elen; 1020 break; 1021 case WLAN_EID_ERP_INFO: 1022 elems->erp_info = pos; 1023 elems->erp_info_len = elen; 1024 break; 1025 case WLAN_EID_EXT_SUPP_RATES: 1026 elems->ext_supp_rates = pos; 1027 elems->ext_supp_rates_len = elen; 1028 break; 1029 case WLAN_EID_VENDOR_SPECIFIC: 1030 if (rtw_ieee802_11_parse_vendor_specific(pos, elen, 1031 elems, 1032 show_errors)) 1033 unknown++; 1034 break; 1035 case WLAN_EID_RSN: 1036 elems->rsn_ie = pos; 1037 elems->rsn_ie_len = elen; 1038 break; 1039 case WLAN_EID_PWR_CAPABILITY: 1040 elems->power_cap = pos; 1041 elems->power_cap_len = elen; 1042 break; 1043 case WLAN_EID_SUPPORTED_CHANNELS: 1044 elems->supp_channels = pos; 1045 elems->supp_channels_len = elen; 1046 break; 1047 case WLAN_EID_MOBILITY_DOMAIN: 1048 elems->mdie = pos; 1049 elems->mdie_len = elen; 1050 break; 1051 case WLAN_EID_FAST_BSS_TRANSITION: 1052 elems->ftie = pos; 1053 elems->ftie_len = elen; 1054 break; 1055 case WLAN_EID_TIMEOUT_INTERVAL: 1056 elems->timeout_int = pos; 1057 elems->timeout_int_len = elen; 1058 break; 1059 case WLAN_EID_HT_CAPABILITY: 1060 elems->ht_capabilities = pos; 1061 elems->ht_capabilities_len = elen; 1062 break; 1063 case WLAN_EID_HT_OPERATION: 1064 elems->ht_operation = pos; 1065 elems->ht_operation_len = elen; 1066 break; 1067 case WLAN_EID_VHT_CAPABILITY: 1068 elems->vht_capabilities = pos; 1069 elems->vht_capabilities_len = elen; 1070 break; 1071 case WLAN_EID_VHT_OPERATION: 1072 elems->vht_operation = pos; 1073 elems->vht_operation_len = elen; 1074 break; 1075 case WLAN_EID_OPMODE_NOTIF: 1076 elems->vht_op_mode_notify = pos; 1077 elems->vht_op_mode_notify_len = elen; 1078 break; 1079 default: 1080 unknown++; 1081 if (!show_errors) 1082 break; 1083 DBG_871X("IEEE 802.11 element parse " 1084 "ignored unknown element (id =%d elen =%d)\n", 1085 id, elen); 1086 break; 1087 } 1088 1089 left -= elen; 1090 pos += elen; 1091 } 1092 1093 if (left) 1094 return ParseFailed; 1095 1096 return unknown ? ParseUnknown : ParseOK; 1097 } 1098 1099 void rtw_macaddr_cfg(struct device *dev, u8 *mac_addr) 1100 { 1101 u8 mac[ETH_ALEN]; 1102 struct device_node *np = dev->of_node; 1103 const unsigned char *addr; 1104 int len; 1105 1106 if (!mac_addr) 1107 return; 1108 1109 if (rtw_initmac && mac_pton(rtw_initmac, mac)) { 1110 /* Users specify the mac address */ 1111 ether_addr_copy(mac_addr, mac); 1112 } else { 1113 /* Use the mac address stored in the Efuse */ 1114 ether_addr_copy(mac, mac_addr); 1115 } 1116 1117 if (is_broadcast_ether_addr(mac) || is_zero_ether_addr(mac)) { 1118 if ((addr = of_get_property(np, "local-mac-address", &len)) && 1119 len == ETH_ALEN) { 1120 ether_addr_copy(mac_addr, addr); 1121 } else { 1122 eth_random_addr(mac_addr); 1123 DBG_871X("MAC Address from efuse error, assign random one !!!\n"); 1124 } 1125 } 1126 1127 DBG_871X("rtw_macaddr_cfg MAC Address = %pM\n", MAC_ARG(mac_addr)); 1128 } 1129 1130 static int rtw_get_cipher_info(struct wlan_network *pnetwork) 1131 { 1132 u32 wpa_ielen; 1133 unsigned char *pbuf; 1134 int group_cipher = 0, pairwise_cipher = 0, is8021x = 0; 1135 int ret = _FAIL; 1136 1137 pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12); 1138 1139 if (pbuf && (wpa_ielen > 0)) { 1140 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_cipher_info: wpa_ielen: %d", wpa_ielen)); 1141 if (_SUCCESS == rtw_parse_wpa_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is8021x)) { 1142 pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher; 1143 pnetwork->BcnInfo.group_cipher = group_cipher; 1144 pnetwork->BcnInfo.is_8021x = is8021x; 1145 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->pairwise_cipher: %d, is_8021x is %d", 1146 __func__, pnetwork->BcnInfo.pairwise_cipher, pnetwork->BcnInfo.is_8021x)); 1147 ret = _SUCCESS; 1148 } 1149 } else { 1150 pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12); 1151 1152 if (pbuf && (wpa_ielen > 0)) { 1153 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("get RSN IE\n")); 1154 if (_SUCCESS == rtw_parse_wpa2_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is8021x)) { 1155 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("get RSN IE OK!!!\n")); 1156 pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher; 1157 pnetwork->BcnInfo.group_cipher = group_cipher; 1158 pnetwork->BcnInfo.is_8021x = is8021x; 1159 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->pairwise_cipher: %d," 1160 "pnetwork->group_cipher is %d, is_8021x is %d", __func__, pnetwork->BcnInfo.pairwise_cipher, 1161 pnetwork->BcnInfo.group_cipher, pnetwork->BcnInfo.is_8021x)); 1162 ret = _SUCCESS; 1163 } 1164 } 1165 } 1166 1167 return ret; 1168 } 1169 1170 void rtw_get_bcn_info(struct wlan_network *pnetwork) 1171 { 1172 unsigned short cap = 0; 1173 u8 bencrypt = 0; 1174 /* u8 wpa_ie[255], rsn_ie[255]; */ 1175 u16 wpa_len = 0, rsn_len = 0; 1176 struct HT_info_element *pht_info = NULL; 1177 struct ieee80211_ht_cap *pht_cap = NULL; 1178 unsigned int len; 1179 unsigned char *p; 1180 __le16 le_cap; 1181 1182 memcpy((u8 *)&le_cap, rtw_get_capability_from_ie(pnetwork->network.IEs), 2); 1183 cap = le16_to_cpu(le_cap); 1184 if (cap & WLAN_CAPABILITY_PRIVACY) { 1185 bencrypt = 1; 1186 pnetwork->network.Privacy = 1; 1187 } else { 1188 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS; 1189 } 1190 rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &rsn_len, NULL, &wpa_len); 1191 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: ssid =%s\n", pnetwork->network.Ssid.Ssid)); 1192 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len)); 1193 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: ssid =%s\n", pnetwork->network.Ssid.Ssid)); 1194 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len)); 1195 1196 if (rsn_len > 0) { 1197 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2; 1198 } else if (wpa_len > 0) { 1199 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA; 1200 } else { 1201 if (bencrypt) 1202 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP; 1203 } 1204 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n", 1205 pnetwork->BcnInfo.encryp_protocol)); 1206 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n", 1207 pnetwork->BcnInfo.encryp_protocol)); 1208 rtw_get_cipher_info(pnetwork); 1209 1210 /* get bwmode and ch_offset */ 1211 /* parsing HT_CAP_IE */ 1212 p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_); 1213 if (p && len > 0) { 1214 pht_cap = (struct ieee80211_ht_cap *)(p + 2); 1215 pnetwork->BcnInfo.ht_cap_info = le16_to_cpu(pht_cap->cap_info); 1216 } else { 1217 pnetwork->BcnInfo.ht_cap_info = 0; 1218 } 1219 /* parsing HT_INFO_IE */ 1220 p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_OPERATION, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_); 1221 if (p && len > 0) { 1222 pht_info = (struct HT_info_element *)(p + 2); 1223 pnetwork->BcnInfo.ht_info_infos_0 = pht_info->infos[0]; 1224 } else { 1225 pnetwork->BcnInfo.ht_info_infos_0 = 0; 1226 } 1227 } 1228 1229 /* show MCS rate, unit: 100Kbps */ 1230 u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI, unsigned char *MCS_rate) 1231 { 1232 u16 max_rate = 0; 1233 1234 if (rf_type == RF_1T1R) { 1235 if (MCS_rate[0] & BIT(7)) 1236 max_rate = (bw_40MHz) ? ((short_GI)?1500:1350):((short_GI)?722:650); 1237 else if (MCS_rate[0] & BIT(6)) 1238 max_rate = (bw_40MHz) ? ((short_GI)?1350:1215):((short_GI)?650:585); 1239 else if (MCS_rate[0] & BIT(5)) 1240 max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520); 1241 else if (MCS_rate[0] & BIT(4)) 1242 max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390); 1243 else if (MCS_rate[0] & BIT(3)) 1244 max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260); 1245 else if (MCS_rate[0] & BIT(2)) 1246 max_rate = (bw_40MHz) ? ((short_GI)?450:405):((short_GI)?217:195); 1247 else if (MCS_rate[0] & BIT(1)) 1248 max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130); 1249 else if (MCS_rate[0] & BIT(0)) 1250 max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65); 1251 } else { 1252 if (MCS_rate[1]) { 1253 if (MCS_rate[1] & BIT(7)) 1254 max_rate = (bw_40MHz) ? ((short_GI)?3000:2700):((short_GI)?1444:1300); 1255 else if (MCS_rate[1] & BIT(6)) 1256 max_rate = (bw_40MHz) ? ((short_GI)?2700:2430):((short_GI)?1300:1170); 1257 else if (MCS_rate[1] & BIT(5)) 1258 max_rate = (bw_40MHz) ? ((short_GI)?2400:2160):((short_GI)?1156:1040); 1259 else if (MCS_rate[1] & BIT(4)) 1260 max_rate = (bw_40MHz) ? ((short_GI)?1800:1620):((short_GI)?867:780); 1261 else if (MCS_rate[1] & BIT(3)) 1262 max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520); 1263 else if (MCS_rate[1] & BIT(2)) 1264 max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390); 1265 else if (MCS_rate[1] & BIT(1)) 1266 max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260); 1267 else if (MCS_rate[1] & BIT(0)) 1268 max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130); 1269 } else { 1270 if (MCS_rate[0] & BIT(7)) 1271 max_rate = (bw_40MHz) ? ((short_GI)?1500:1350):((short_GI)?722:650); 1272 else if (MCS_rate[0] & BIT(6)) 1273 max_rate = (bw_40MHz) ? ((short_GI)?1350:1215):((short_GI)?650:585); 1274 else if (MCS_rate[0] & BIT(5)) 1275 max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520); 1276 else if (MCS_rate[0] & BIT(4)) 1277 max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390); 1278 else if (MCS_rate[0] & BIT(3)) 1279 max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260); 1280 else if (MCS_rate[0] & BIT(2)) 1281 max_rate = (bw_40MHz) ? ((short_GI)?450:405):((short_GI)?217:195); 1282 else if (MCS_rate[0] & BIT(1)) 1283 max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130); 1284 else if (MCS_rate[0] & BIT(0)) 1285 max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65); 1286 } 1287 } 1288 return max_rate; 1289 } 1290 1291 int rtw_action_frame_parse(const u8 *frame, u32 frame_len, u8 *category, u8 *action) 1292 { 1293 const u8 *frame_body = frame + sizeof(struct ieee80211_hdr_3addr); 1294 u16 fc; 1295 u8 c; 1296 u8 a = ACT_PUBLIC_MAX; 1297 1298 fc = le16_to_cpu(((struct ieee80211_hdr_3addr *)frame)->frame_control); 1299 1300 if ((fc & (IEEE80211_FCTL_FTYPE|IEEE80211_FCTL_STYPE)) 1301 != (IEEE80211_FTYPE_MGMT|IEEE80211_STYPE_ACTION) 1302 ) { 1303 return false; 1304 } 1305 1306 c = frame_body[0]; 1307 1308 switch (c) { 1309 case RTW_WLAN_CATEGORY_P2P: /* vendor-specific */ 1310 break; 1311 default: 1312 a = frame_body[1]; 1313 } 1314 1315 if (category) 1316 *category = c; 1317 if (action) 1318 *action = a; 1319 1320 return true; 1321 } 1322 1323 static const char *_action_public_str[] = { 1324 "ACT_PUB_BSSCOEXIST", 1325 "ACT_PUB_DSE_ENABLE", 1326 "ACT_PUB_DSE_DEENABLE", 1327 "ACT_PUB_DSE_REG_LOCATION", 1328 "ACT_PUB_EXT_CHL_SWITCH", 1329 "ACT_PUB_DSE_MSR_REQ", 1330 "ACT_PUB_DSE_MSR_RPRT", 1331 "ACT_PUB_MP", 1332 "ACT_PUB_DSE_PWR_CONSTRAINT", 1333 "ACT_PUB_VENDOR", 1334 "ACT_PUB_GAS_INITIAL_REQ", 1335 "ACT_PUB_GAS_INITIAL_RSP", 1336 "ACT_PUB_GAS_COMEBACK_REQ", 1337 "ACT_PUB_GAS_COMEBACK_RSP", 1338 "ACT_PUB_TDLS_DISCOVERY_RSP", 1339 "ACT_PUB_LOCATION_TRACK", 1340 "ACT_PUB_RSVD", 1341 }; 1342 1343 const char *action_public_str(u8 action) 1344 { 1345 action = (action >= ACT_PUBLIC_MAX) ? ACT_PUBLIC_MAX : action; 1346 return _action_public_str[action]; 1347 } 1348