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 signed int 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, signed int index, signed int *len, signed int limit) 144 { 145 signed int 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 return _FAIL; 493 494 /* pairwise_cipher */ 495 if (left >= 2) { 496 /* count = le16_to_cpu(*(u16*)pos); */ 497 count = get_unaligned_le16(pos); 498 pos += 2; 499 left -= 2; 500 501 if (count == 0 || left < count * WPA_SELECTOR_LEN) 502 return _FAIL; 503 504 for (i = 0; i < count; i++) { 505 *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos); 506 507 pos += WPA_SELECTOR_LEN; 508 left -= WPA_SELECTOR_LEN; 509 } 510 511 } else if (left == 1) 512 return _FAIL; 513 514 if (is_8021x) { 515 if (left >= 6) { 516 pos += 2; 517 if (!memcmp(pos, SUITE_1X, 4)) { 518 *is_8021x = 1; 519 } 520 } 521 } 522 523 return ret; 524 } 525 526 int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x) 527 { 528 int i, ret = _SUCCESS; 529 int left, count; 530 u8 *pos; 531 u8 SUITE_1X[4] = {0x00, 0x0f, 0xac, 0x01}; 532 533 if (rsn_ie_len <= 0) { 534 /* No RSN IE - fail silently */ 535 return _FAIL; 536 } 537 538 if ((*rsn_ie != WLAN_EID_RSN) || (*(rsn_ie+1) != (u8)(rsn_ie_len - 2))) { 539 return _FAIL; 540 } 541 542 pos = rsn_ie; 543 pos += 4; 544 left = rsn_ie_len - 4; 545 546 /* group_cipher */ 547 if (left >= RSN_SELECTOR_LEN) { 548 *group_cipher = rtw_get_wpa2_cipher_suite(pos); 549 550 pos += RSN_SELECTOR_LEN; 551 left -= RSN_SELECTOR_LEN; 552 553 } else if (left > 0) 554 return _FAIL; 555 556 /* pairwise_cipher */ 557 if (left >= 2) { 558 /* count = le16_to_cpu(*(u16*)pos); */ 559 count = get_unaligned_le16(pos); 560 pos += 2; 561 left -= 2; 562 563 if (count == 0 || left < count * RSN_SELECTOR_LEN) 564 return _FAIL; 565 566 for (i = 0; i < count; i++) { 567 *pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos); 568 569 pos += RSN_SELECTOR_LEN; 570 left -= RSN_SELECTOR_LEN; 571 } 572 573 } else if (left == 1) 574 return _FAIL; 575 576 if (is_8021x) { 577 if (left >= 6) { 578 pos += 2; 579 if (!memcmp(pos, SUITE_1X, 4)) 580 *is_8021x = 1; 581 } 582 } 583 584 return ret; 585 } 586 587 /* ifdef CONFIG_WAPI_SUPPORT */ 588 int rtw_get_wapi_ie(u8 *in_ie, uint in_len, u8 *wapi_ie, u16 *wapi_len) 589 { 590 int len = 0; 591 u8 authmode; 592 uint cnt; 593 u8 wapi_oui1[4] = {0x0, 0x14, 0x72, 0x01}; 594 u8 wapi_oui2[4] = {0x0, 0x14, 0x72, 0x02}; 595 596 if (wapi_len) 597 *wapi_len = 0; 598 599 if (!in_ie || in_len <= 0) 600 return len; 601 602 cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_); 603 604 while (cnt < in_len) { 605 authmode = in_ie[cnt]; 606 607 /* if (authmode == WLAN_EID_BSS_AC_ACCESS_DELAY) */ 608 if (authmode == WLAN_EID_BSS_AC_ACCESS_DELAY && (!memcmp(&in_ie[cnt+6], wapi_oui1, 4) || 609 !memcmp(&in_ie[cnt+6], wapi_oui2, 4))) { 610 if (wapi_ie) 611 memcpy(wapi_ie, &in_ie[cnt], in_ie[cnt+1]+2); 612 613 if (wapi_len) 614 *wapi_len = in_ie[cnt+1]+2; 615 616 cnt += in_ie[cnt+1]+2; /* get next */ 617 } else { 618 cnt += in_ie[cnt+1]+2; /* get next */ 619 } 620 } 621 622 if (wapi_len) 623 len = *wapi_len; 624 625 return len; 626 } 627 /* endif */ 628 629 void rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie, u16 *wpa_len) 630 { 631 u8 authmode; 632 u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01}; 633 uint cnt; 634 635 /* Search required WPA or WPA2 IE and copy to sec_ie[ ] */ 636 637 cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_); 638 639 while (cnt < in_len) { 640 authmode = in_ie[cnt]; 641 642 if ((authmode == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&in_ie[cnt+2], &wpa_oui[0], 4))) { 643 if (wpa_ie) 644 memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt+1]+2); 645 646 *wpa_len = in_ie[cnt + 1] + 2; 647 cnt += in_ie[cnt + 1] + 2; /* get next */ 648 } else { 649 if (authmode == WLAN_EID_RSN) { 650 if (rsn_ie) 651 memcpy(rsn_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); 652 653 *rsn_len = in_ie[cnt+1]+2; 654 cnt += in_ie[cnt+1]+2; /* get next */ 655 } else { 656 cnt += in_ie[cnt+1]+2; /* get next */ 657 } 658 } 659 } 660 } 661 662 u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen) 663 { 664 u8 match = false; 665 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04}; 666 667 if (!ie_ptr) 668 return match; 669 670 eid = ie_ptr[0]; 671 672 if ((eid == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&ie_ptr[2], wps_oui, 4))) { 673 *wps_ielen = ie_ptr[1]+2; 674 match = true; 675 } 676 return match; 677 } 678 679 /** 680 * rtw_get_wps_ie - Search WPS IE from a series of IEs 681 * @in_ie: Address of IEs to search 682 * @in_len: Length limit from in_ie 683 * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the buf starting from wps_ie 684 * @wps_ielen: If not NULL and WPS IE is found, will set to the length of the entire WPS IE 685 * 686 * Returns: The address of the WPS IE found, or NULL 687 */ 688 u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen) 689 { 690 uint cnt; 691 u8 *wpsie_ptr = NULL; 692 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04}; 693 694 if (wps_ielen) 695 *wps_ielen = 0; 696 697 if (!in_ie || in_len <= 0) 698 return wpsie_ptr; 699 700 cnt = 0; 701 702 while (cnt < in_len) { 703 eid = in_ie[cnt]; 704 705 if ((eid == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&in_ie[cnt+2], wps_oui, 4))) { 706 wpsie_ptr = &in_ie[cnt]; 707 708 if (wps_ie) 709 memcpy(wps_ie, &in_ie[cnt], in_ie[cnt+1]+2); 710 711 if (wps_ielen) 712 *wps_ielen = in_ie[cnt+1]+2; 713 714 cnt += in_ie[cnt+1]+2; 715 716 break; 717 } else { 718 cnt += in_ie[cnt+1]+2; /* goto next */ 719 } 720 } 721 722 return wpsie_ptr; 723 } 724 725 /** 726 * rtw_get_wps_attr - Search a specific WPS attribute from a given WPS IE 727 * @wps_ie: Address of WPS IE to search 728 * @wps_ielen: Length limit from wps_ie 729 * @target_attr_id: The attribute ID of WPS attribute to search 730 * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute will be copied to the buf starting from buf_attr 731 * @len_attr: If not NULL and the WPS attribute is found, will set to the length of the entire WPS attribute 732 * 733 * Returns: the address of the specific WPS attribute found, or NULL 734 */ 735 u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_attr, u32 *len_attr) 736 { 737 u8 *attr_ptr = NULL; 738 u8 *target_attr_ptr = NULL; 739 u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04}; 740 741 if (len_attr) 742 *len_attr = 0; 743 744 if ((wps_ie[0] != WLAN_EID_VENDOR_SPECIFIC) || 745 (memcmp(wps_ie + 2, wps_oui, 4))) { 746 return attr_ptr; 747 } 748 749 /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */ 750 attr_ptr = wps_ie + 6; /* goto first attr */ 751 752 while (attr_ptr - wps_ie < wps_ielen) { 753 /* 4 = 2(Attribute ID) + 2(Length) */ 754 u16 attr_id = get_unaligned_be16(attr_ptr); 755 u16 attr_data_len = get_unaligned_be16(attr_ptr + 2); 756 u16 attr_len = attr_data_len + 4; 757 758 if (attr_id == target_attr_id) { 759 target_attr_ptr = attr_ptr; 760 761 if (buf_attr) 762 memcpy(buf_attr, attr_ptr, attr_len); 763 764 if (len_attr) 765 *len_attr = attr_len; 766 767 break; 768 } else { 769 attr_ptr += attr_len; /* goto next */ 770 } 771 } 772 773 return target_attr_ptr; 774 } 775 776 /** 777 * rtw_get_wps_attr_content - Search a specific WPS attribute content from a given WPS IE 778 * @wps_ie: Address of WPS IE to search 779 * @wps_ielen: Length limit from wps_ie 780 * @target_attr_id: The attribute ID of WPS attribute to search 781 * @buf_content: If not NULL and the WPS attribute is found, WPS attribute content will be copied to the buf starting from buf_content 782 * @len_content: If not NULL and the WPS attribute is found, will set to the length of the WPS attribute content 783 * 784 * Returns: the address of the specific WPS attribute content found, or NULL 785 */ 786 u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_content, uint *len_content) 787 { 788 u8 *attr_ptr; 789 u32 attr_len; 790 791 if (len_content) 792 *len_content = 0; 793 794 attr_ptr = rtw_get_wps_attr(wps_ie, wps_ielen, target_attr_id, NULL, &attr_len); 795 796 if (attr_ptr && attr_len) { 797 if (buf_content) 798 memcpy(buf_content, attr_ptr+4, attr_len-4); 799 800 if (len_content) 801 *len_content = attr_len-4; 802 803 return attr_ptr+4; 804 } 805 806 return NULL; 807 } 808 809 static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen, 810 struct rtw_ieee802_11_elems *elems, 811 int show_errors) 812 { 813 unsigned int oui; 814 815 /* first 3 bytes in vendor specific information element are the IEEE 816 * OUI of the vendor. The following byte is used a vendor specific 817 * sub-type. */ 818 if (elen < 4) 819 return -1; 820 821 oui = get_unaligned_be24(pos); 822 switch (oui) { 823 case OUI_MICROSOFT: 824 /* Microsoft/Wi-Fi information elements are further typed and 825 * subtyped */ 826 switch (pos[3]) { 827 case 1: 828 /* Microsoft OUI (00:50:F2) with OUI Type 1: 829 * real WPA information element */ 830 elems->wpa_ie = pos; 831 elems->wpa_ie_len = elen; 832 break; 833 case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */ 834 if (elen < 5) 835 return -1; 836 837 switch (pos[4]) { 838 case WME_OUI_SUBTYPE_INFORMATION_ELEMENT: 839 case WME_OUI_SUBTYPE_PARAMETER_ELEMENT: 840 elems->wme = pos; 841 elems->wme_len = elen; 842 break; 843 case WME_OUI_SUBTYPE_TSPEC_ELEMENT: 844 elems->wme_tspec = pos; 845 elems->wme_tspec_len = elen; 846 break; 847 default: 848 return -1; 849 } 850 break; 851 case 4: 852 /* Wi-Fi Protected Setup (WPS) IE */ 853 elems->wps_ie = pos; 854 elems->wps_ie_len = elen; 855 break; 856 default: 857 return -1; 858 } 859 break; 860 861 case OUI_BROADCOM: 862 switch (pos[3]) { 863 case VENDOR_HT_CAPAB_OUI_TYPE: 864 elems->vendor_ht_cap = pos; 865 elems->vendor_ht_cap_len = elen; 866 break; 867 default: 868 return -1; 869 } 870 break; 871 872 default: 873 return -1; 874 } 875 876 return 0; 877 } 878 879 /** 880 * ieee802_11_parse_elems - Parse information elements in management frames 881 * @start: Pointer to the start of IEs 882 * @len: Length of IE buffer in octets 883 * @elems: Data structure for parsed elements 884 * @show_errors: Whether to show parsing errors in debug log 885 * Returns: Parsing result 886 */ 887 enum ParseRes rtw_ieee802_11_parse_elems(u8 *start, uint len, 888 struct rtw_ieee802_11_elems *elems, 889 int show_errors) 890 { 891 uint left = len; 892 u8 *pos = start; 893 int unknown = 0; 894 895 memset(elems, 0, sizeof(*elems)); 896 897 while (left >= 2) { 898 u8 id, elen; 899 900 id = *pos++; 901 elen = *pos++; 902 left -= 2; 903 904 if (elen > left) 905 return ParseFailed; 906 907 switch (id) { 908 case WLAN_EID_SSID: 909 elems->ssid = pos; 910 elems->ssid_len = elen; 911 break; 912 case WLAN_EID_SUPP_RATES: 913 elems->supp_rates = pos; 914 elems->supp_rates_len = elen; 915 break; 916 case WLAN_EID_FH_PARAMS: 917 elems->fh_params = pos; 918 elems->fh_params_len = elen; 919 break; 920 case WLAN_EID_DS_PARAMS: 921 elems->ds_params = pos; 922 elems->ds_params_len = elen; 923 break; 924 case WLAN_EID_CF_PARAMS: 925 elems->cf_params = pos; 926 elems->cf_params_len = elen; 927 break; 928 case WLAN_EID_TIM: 929 elems->tim = pos; 930 elems->tim_len = elen; 931 break; 932 case WLAN_EID_IBSS_PARAMS: 933 elems->ibss_params = pos; 934 elems->ibss_params_len = elen; 935 break; 936 case WLAN_EID_CHALLENGE: 937 elems->challenge = pos; 938 elems->challenge_len = elen; 939 break; 940 case WLAN_EID_ERP_INFO: 941 elems->erp_info = pos; 942 elems->erp_info_len = elen; 943 break; 944 case WLAN_EID_EXT_SUPP_RATES: 945 elems->ext_supp_rates = pos; 946 elems->ext_supp_rates_len = elen; 947 break; 948 case WLAN_EID_VENDOR_SPECIFIC: 949 if (rtw_ieee802_11_parse_vendor_specific(pos, elen, 950 elems, 951 show_errors)) 952 unknown++; 953 break; 954 case WLAN_EID_RSN: 955 elems->rsn_ie = pos; 956 elems->rsn_ie_len = elen; 957 break; 958 case WLAN_EID_PWR_CAPABILITY: 959 elems->power_cap = pos; 960 elems->power_cap_len = elen; 961 break; 962 case WLAN_EID_SUPPORTED_CHANNELS: 963 elems->supp_channels = pos; 964 elems->supp_channels_len = elen; 965 break; 966 case WLAN_EID_MOBILITY_DOMAIN: 967 elems->mdie = pos; 968 elems->mdie_len = elen; 969 break; 970 case WLAN_EID_FAST_BSS_TRANSITION: 971 elems->ftie = pos; 972 elems->ftie_len = elen; 973 break; 974 case WLAN_EID_TIMEOUT_INTERVAL: 975 elems->timeout_int = pos; 976 elems->timeout_int_len = elen; 977 break; 978 case WLAN_EID_HT_CAPABILITY: 979 elems->ht_capabilities = pos; 980 elems->ht_capabilities_len = elen; 981 break; 982 case WLAN_EID_HT_OPERATION: 983 elems->ht_operation = pos; 984 elems->ht_operation_len = elen; 985 break; 986 case WLAN_EID_VHT_CAPABILITY: 987 elems->vht_capabilities = pos; 988 elems->vht_capabilities_len = elen; 989 break; 990 case WLAN_EID_VHT_OPERATION: 991 elems->vht_operation = pos; 992 elems->vht_operation_len = elen; 993 break; 994 case WLAN_EID_OPMODE_NOTIF: 995 elems->vht_op_mode_notify = pos; 996 elems->vht_op_mode_notify_len = elen; 997 break; 998 default: 999 unknown++; 1000 break; 1001 } 1002 1003 left -= elen; 1004 pos += elen; 1005 } 1006 1007 if (left) 1008 return ParseFailed; 1009 1010 return unknown ? ParseUnknown : ParseOK; 1011 } 1012 1013 void rtw_macaddr_cfg(struct device *dev, u8 *mac_addr) 1014 { 1015 u8 mac[ETH_ALEN]; 1016 struct device_node *np = dev->of_node; 1017 const unsigned char *addr; 1018 int len; 1019 1020 if (!mac_addr) 1021 return; 1022 1023 if (rtw_initmac && mac_pton(rtw_initmac, mac)) { 1024 /* Users specify the mac address */ 1025 ether_addr_copy(mac_addr, mac); 1026 } else { 1027 /* Use the mac address stored in the Efuse */ 1028 ether_addr_copy(mac, mac_addr); 1029 } 1030 1031 if (is_broadcast_ether_addr(mac) || is_zero_ether_addr(mac)) { 1032 addr = of_get_property(np, "local-mac-address", &len); 1033 1034 if (addr && len == ETH_ALEN) { 1035 ether_addr_copy(mac_addr, addr); 1036 } else { 1037 eth_random_addr(mac_addr); 1038 } 1039 } 1040 } 1041 1042 static int rtw_get_cipher_info(struct wlan_network *pnetwork) 1043 { 1044 u32 wpa_ielen; 1045 unsigned char *pbuf; 1046 int group_cipher = 0, pairwise_cipher = 0, is8021x = 0; 1047 int ret = _FAIL; 1048 1049 pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12); 1050 1051 if (pbuf && (wpa_ielen > 0)) { 1052 if (_SUCCESS == rtw_parse_wpa_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is8021x)) { 1053 pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher; 1054 pnetwork->BcnInfo.group_cipher = group_cipher; 1055 pnetwork->BcnInfo.is_8021x = is8021x; 1056 ret = _SUCCESS; 1057 } 1058 } else { 1059 pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12); 1060 1061 if (pbuf && (wpa_ielen > 0)) { 1062 if (_SUCCESS == rtw_parse_wpa2_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is8021x)) { 1063 pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher; 1064 pnetwork->BcnInfo.group_cipher = group_cipher; 1065 pnetwork->BcnInfo.is_8021x = is8021x; 1066 ret = _SUCCESS; 1067 } 1068 } 1069 } 1070 1071 return ret; 1072 } 1073 1074 void rtw_get_bcn_info(struct wlan_network *pnetwork) 1075 { 1076 unsigned short cap = 0; 1077 u8 bencrypt = 0; 1078 /* u8 wpa_ie[255], rsn_ie[255]; */ 1079 u16 wpa_len = 0, rsn_len = 0; 1080 struct HT_info_element *pht_info = NULL; 1081 struct ieee80211_ht_cap *pht_cap = NULL; 1082 unsigned int len; 1083 unsigned char *p; 1084 __le16 le_cap; 1085 1086 memcpy((u8 *)&le_cap, rtw_get_capability_from_ie(pnetwork->network.IEs), 2); 1087 cap = le16_to_cpu(le_cap); 1088 if (cap & WLAN_CAPABILITY_PRIVACY) { 1089 bencrypt = 1; 1090 pnetwork->network.Privacy = 1; 1091 } else { 1092 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS; 1093 } 1094 rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &rsn_len, NULL, &wpa_len); 1095 1096 if (rsn_len > 0) { 1097 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2; 1098 } else if (wpa_len > 0) { 1099 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA; 1100 } else { 1101 if (bencrypt) 1102 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP; 1103 } 1104 rtw_get_cipher_info(pnetwork); 1105 1106 /* get bwmode and ch_offset */ 1107 /* parsing HT_CAP_IE */ 1108 p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_); 1109 if (p && len > 0) { 1110 pht_cap = (struct ieee80211_ht_cap *)(p + 2); 1111 pnetwork->BcnInfo.ht_cap_info = le16_to_cpu(pht_cap->cap_info); 1112 } else { 1113 pnetwork->BcnInfo.ht_cap_info = 0; 1114 } 1115 /* parsing HT_INFO_IE */ 1116 p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_OPERATION, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_); 1117 if (p && len > 0) { 1118 pht_info = (struct HT_info_element *)(p + 2); 1119 pnetwork->BcnInfo.ht_info_infos_0 = pht_info->infos[0]; 1120 } else { 1121 pnetwork->BcnInfo.ht_info_infos_0 = 0; 1122 } 1123 } 1124 1125 /* show MCS rate, unit: 100Kbps */ 1126 u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI, unsigned char *MCS_rate) 1127 { 1128 u16 max_rate = 0; 1129 1130 if (rf_type == RF_1T1R) { 1131 if (MCS_rate[0] & BIT(7)) 1132 max_rate = (bw_40MHz) ? ((short_GI)?1500:1350):((short_GI)?722:650); 1133 else if (MCS_rate[0] & BIT(6)) 1134 max_rate = (bw_40MHz) ? ((short_GI)?1350:1215):((short_GI)?650:585); 1135 else if (MCS_rate[0] & BIT(5)) 1136 max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520); 1137 else if (MCS_rate[0] & BIT(4)) 1138 max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390); 1139 else if (MCS_rate[0] & BIT(3)) 1140 max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260); 1141 else if (MCS_rate[0] & BIT(2)) 1142 max_rate = (bw_40MHz) ? ((short_GI)?450:405):((short_GI)?217:195); 1143 else if (MCS_rate[0] & BIT(1)) 1144 max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130); 1145 else if (MCS_rate[0] & BIT(0)) 1146 max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65); 1147 } else { 1148 if (MCS_rate[1]) { 1149 if (MCS_rate[1] & BIT(7)) 1150 max_rate = (bw_40MHz) ? ((short_GI)?3000:2700):((short_GI)?1444:1300); 1151 else if (MCS_rate[1] & BIT(6)) 1152 max_rate = (bw_40MHz) ? ((short_GI)?2700:2430):((short_GI)?1300:1170); 1153 else if (MCS_rate[1] & BIT(5)) 1154 max_rate = (bw_40MHz) ? ((short_GI)?2400:2160):((short_GI)?1156:1040); 1155 else if (MCS_rate[1] & BIT(4)) 1156 max_rate = (bw_40MHz) ? ((short_GI)?1800:1620):((short_GI)?867:780); 1157 else if (MCS_rate[1] & BIT(3)) 1158 max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520); 1159 else if (MCS_rate[1] & BIT(2)) 1160 max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390); 1161 else if (MCS_rate[1] & BIT(1)) 1162 max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260); 1163 else if (MCS_rate[1] & BIT(0)) 1164 max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130); 1165 } else { 1166 if (MCS_rate[0] & BIT(7)) 1167 max_rate = (bw_40MHz) ? ((short_GI)?1500:1350):((short_GI)?722:650); 1168 else if (MCS_rate[0] & BIT(6)) 1169 max_rate = (bw_40MHz) ? ((short_GI)?1350:1215):((short_GI)?650:585); 1170 else if (MCS_rate[0] & BIT(5)) 1171 max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520); 1172 else if (MCS_rate[0] & BIT(4)) 1173 max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390); 1174 else if (MCS_rate[0] & BIT(3)) 1175 max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260); 1176 else if (MCS_rate[0] & BIT(2)) 1177 max_rate = (bw_40MHz) ? ((short_GI)?450:405):((short_GI)?217:195); 1178 else if (MCS_rate[0] & BIT(1)) 1179 max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130); 1180 else if (MCS_rate[0] & BIT(0)) 1181 max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65); 1182 } 1183 } 1184 return max_rate; 1185 } 1186 1187 int rtw_action_frame_parse(const u8 *frame, u32 frame_len, u8 *category, u8 *action) 1188 { 1189 const u8 *frame_body = frame + sizeof(struct ieee80211_hdr_3addr); 1190 u16 fc; 1191 u8 c; 1192 u8 a = ACT_PUBLIC_MAX; 1193 1194 fc = le16_to_cpu(((struct ieee80211_hdr_3addr *)frame)->frame_control); 1195 1196 if ((fc & (IEEE80211_FCTL_FTYPE|IEEE80211_FCTL_STYPE)) 1197 != (IEEE80211_FTYPE_MGMT|IEEE80211_STYPE_ACTION) 1198 ) { 1199 return false; 1200 } 1201 1202 c = frame_body[0]; 1203 1204 switch (c) { 1205 case RTW_WLAN_CATEGORY_P2P: /* vendor-specific */ 1206 break; 1207 default: 1208 a = frame_body[1]; 1209 } 1210 1211 if (category) 1212 *category = c; 1213 if (action) 1214 *action = a; 1215 1216 return true; 1217 } 1218 1219 static const char *_action_public_str[] = { 1220 "ACT_PUB_BSSCOEXIST", 1221 "ACT_PUB_DSE_ENABLE", 1222 "ACT_PUB_DSE_DEENABLE", 1223 "ACT_PUB_DSE_REG_LOCATION", 1224 "ACT_PUB_EXT_CHL_SWITCH", 1225 "ACT_PUB_DSE_MSR_REQ", 1226 "ACT_PUB_DSE_MSR_RPRT", 1227 "ACT_PUB_MP", 1228 "ACT_PUB_DSE_PWR_CONSTRAINT", 1229 "ACT_PUB_VENDOR", 1230 "ACT_PUB_GAS_INITIAL_REQ", 1231 "ACT_PUB_GAS_INITIAL_RSP", 1232 "ACT_PUB_GAS_COMEBACK_REQ", 1233 "ACT_PUB_GAS_COMEBACK_RSP", 1234 "ACT_PUB_TDLS_DISCOVERY_RSP", 1235 "ACT_PUB_LOCATION_TRACK", 1236 "ACT_PUB_RSVD", 1237 }; 1238 1239 const char *action_public_str(u8 action) 1240 { 1241 action = (action >= ACT_PUBLIC_MAX) ? ACT_PUBLIC_MAX : action; 1242 return _action_public_str[action]; 1243 } 1244