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