1 // SPDX-License-Identifier: GPL-2.0 2 /****************************************************************************** 3 * 4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. 5 * 6 ******************************************************************************/ 7 #define _RTW_IOCTL_SET_C_ 8 9 #include <drv_types.h> 10 #include <rtw_debug.h> 11 12 u8 rtw_validate_bssid(u8 *bssid) 13 { 14 u8 ret = true; 15 16 if (is_zero_mac_addr(bssid) 17 || is_broadcast_mac_addr(bssid) 18 || is_multicast_mac_addr(bssid) 19 ) { 20 ret = false; 21 } 22 23 return ret; 24 } 25 26 u8 rtw_validate_ssid(struct ndis_802_11_ssid *ssid) 27 { 28 u8 ret = true; 29 30 if (ssid->SsidLength > 32) { 31 ret = false; 32 goto exit; 33 } 34 35 exit: 36 return ret; 37 } 38 39 u8 rtw_do_join(struct adapter *padapter) 40 { 41 struct list_head *plist, *phead; 42 u8 *pibss = NULL; 43 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 44 struct __queue *queue = &(pmlmepriv->scanned_queue); 45 u8 ret = _SUCCESS; 46 47 spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 48 phead = get_list_head(queue); 49 plist = get_next(phead); 50 51 pmlmepriv->cur_network.join_res = -2; 52 53 set_fwstate(pmlmepriv, _FW_UNDER_LINKING); 54 55 pmlmepriv->pscanned = plist; 56 57 pmlmepriv->to_join = true; 58 59 if (list_empty(&queue->queue)) { 60 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 61 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); 62 63 /* when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty */ 64 /* we try to issue sitesurvey firstly */ 65 66 if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false 67 || rtw_to_roam(padapter) > 0 68 ) { 69 /* submit site_survey_cmd */ 70 ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0); 71 if (ret != _SUCCESS) 72 pmlmepriv->to_join = false; 73 74 } else { 75 pmlmepriv->to_join = false; 76 ret = _FAIL; 77 } 78 79 goto exit; 80 } else { 81 int select_ret; 82 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 83 select_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv); 84 if (select_ret == _SUCCESS) { 85 pmlmepriv->to_join = false; 86 _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT); 87 } else { 88 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) { 89 /* submit createbss_cmd to change to a ADHOC_MASTER */ 90 91 /* pmlmepriv->lock has been acquired by caller... */ 92 struct wlan_bssid_ex *pdev_network = &(padapter->registrypriv.dev_network); 93 94 pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE; 95 96 pibss = padapter->registrypriv.dev_network.MacAddress; 97 98 memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid)); 99 100 rtw_update_registrypriv_dev_network(padapter); 101 102 rtw_generate_random_ibss(pibss); 103 104 if (rtw_createbss_cmd(padapter) != _SUCCESS) { 105 ret = false; 106 goto exit; 107 } 108 109 pmlmepriv->to_join = false; 110 111 } else { 112 /* can't associate ; reset under-linking */ 113 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); 114 115 /* when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue */ 116 /* we try to issue sitesurvey firstly */ 117 if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false 118 || rtw_to_roam(padapter) > 0 119 ) { 120 ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0); 121 if (ret != _SUCCESS) 122 pmlmepriv->to_join = false; 123 124 } else { 125 ret = _FAIL; 126 pmlmepriv->to_join = false; 127 } 128 } 129 130 } 131 132 } 133 134 exit: 135 return ret; 136 } 137 138 u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid) 139 { 140 u8 status = _SUCCESS; 141 142 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 143 144 netdev_dbg(padapter->pnetdev, "set bssid:%pM\n", bssid); 145 146 if ((bssid[0] == 0x00 && bssid[1] == 0x00 && bssid[2] == 0x00 && bssid[3] == 0x00 && bssid[4] == 0x00 && bssid[5] == 0x00) || 147 (bssid[0] == 0xFF && bssid[1] == 0xFF && bssid[2] == 0xFF && bssid[3] == 0xFF && bssid[4] == 0xFF && bssid[5] == 0xFF)) { 148 status = _FAIL; 149 goto exit; 150 } 151 152 spin_lock_bh(&pmlmepriv->lock); 153 154 155 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) 156 goto handle_tkip_countermeasure; 157 else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) 158 goto release_mlme_lock; 159 160 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) { 161 if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN)) { 162 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false) 163 goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */ 164 } else { 165 rtw_disassoc_cmd(padapter, 0, true); 166 167 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) 168 rtw_indicate_disconnect(padapter); 169 170 rtw_free_assoc_resources(padapter, 1); 171 172 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) { 173 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); 174 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); 175 } 176 } 177 } 178 179 handle_tkip_countermeasure: 180 if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) { 181 status = _FAIL; 182 goto release_mlme_lock; 183 } 184 185 memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid)); 186 memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN); 187 pmlmepriv->assoc_by_bssid = true; 188 189 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) 190 pmlmepriv->to_join = true; 191 else 192 status = rtw_do_join(padapter); 193 194 release_mlme_lock: 195 spin_unlock_bh(&pmlmepriv->lock); 196 197 exit: 198 199 return status; 200 } 201 202 u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid) 203 { 204 u8 status = _SUCCESS; 205 206 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 207 struct wlan_network *pnetwork = &pmlmepriv->cur_network; 208 209 netdev_dbg(padapter->pnetdev, "set ssid [%s] fw_state = 0x%08x\n", 210 ssid->Ssid, get_fwstate(pmlmepriv)); 211 212 if (padapter->hw_init_completed == false) { 213 status = _FAIL; 214 goto exit; 215 } 216 217 spin_lock_bh(&pmlmepriv->lock); 218 219 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) 220 goto handle_tkip_countermeasure; 221 else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) 222 goto release_mlme_lock; 223 224 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) { 225 if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) && 226 (!memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength))) { 227 if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false)) { 228 if (rtw_is_same_ibss(padapter, pnetwork) == false) { 229 /* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */ 230 rtw_disassoc_cmd(padapter, 0, true); 231 232 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) 233 rtw_indicate_disconnect(padapter); 234 235 rtw_free_assoc_resources(padapter, 1); 236 237 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) { 238 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); 239 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); 240 } 241 } else { 242 goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */ 243 } 244 } else { 245 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1); 246 } 247 } else { 248 rtw_disassoc_cmd(padapter, 0, true); 249 250 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) 251 rtw_indicate_disconnect(padapter); 252 253 rtw_free_assoc_resources(padapter, 1); 254 255 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) { 256 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); 257 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); 258 } 259 } 260 } 261 262 handle_tkip_countermeasure: 263 if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) { 264 status = _FAIL; 265 goto release_mlme_lock; 266 } 267 268 if (rtw_validate_ssid(ssid) == false) { 269 status = _FAIL; 270 goto release_mlme_lock; 271 } 272 273 memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid)); 274 pmlmepriv->assoc_by_bssid = false; 275 276 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) 277 pmlmepriv->to_join = true; 278 else 279 status = rtw_do_join(padapter); 280 281 release_mlme_lock: 282 spin_unlock_bh(&pmlmepriv->lock); 283 284 exit: 285 286 return status; 287 } 288 289 u8 rtw_set_802_11_connect(struct adapter *padapter, u8 *bssid, struct ndis_802_11_ssid *ssid) 290 { 291 u8 status = _SUCCESS; 292 bool bssid_valid = true; 293 bool ssid_valid = true; 294 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 295 296 if (!ssid || rtw_validate_ssid(ssid) == false) 297 ssid_valid = false; 298 299 if (!bssid || rtw_validate_bssid(bssid) == false) 300 bssid_valid = false; 301 302 if (!ssid_valid && !bssid_valid) { 303 status = _FAIL; 304 goto exit; 305 } 306 307 if (padapter->hw_init_completed == false) { 308 status = _FAIL; 309 goto exit; 310 } 311 312 spin_lock_bh(&pmlmepriv->lock); 313 314 netdev_dbg(padapter->pnetdev, FUNC_ADPT_FMT " fw_state = 0x%08x\n", 315 FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv)); 316 317 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) 318 goto handle_tkip_countermeasure; 319 else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) 320 goto release_mlme_lock; 321 322 handle_tkip_countermeasure: 323 if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) { 324 status = _FAIL; 325 goto release_mlme_lock; 326 } 327 328 if (ssid && ssid_valid) 329 memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid)); 330 else 331 memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid)); 332 333 if (bssid && bssid_valid) { 334 memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN); 335 pmlmepriv->assoc_by_bssid = true; 336 } else { 337 pmlmepriv->assoc_by_bssid = false; 338 } 339 340 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) 341 pmlmepriv->to_join = true; 342 else 343 status = rtw_do_join(padapter); 344 345 release_mlme_lock: 346 spin_unlock_bh(&pmlmepriv->lock); 347 348 exit: 349 return status; 350 } 351 352 u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter, 353 enum ndis_802_11_network_infrastructure networktype) 354 { 355 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 356 struct wlan_network *cur_network = &pmlmepriv->cur_network; 357 enum ndis_802_11_network_infrastructure *pold_state = &(cur_network->network.InfrastructureMode); 358 359 if (*pold_state != networktype) { 360 if (*pold_state == Ndis802_11APMode) { 361 /* change to other mode from Ndis802_11APMode */ 362 cur_network->join_res = -1; 363 364 stop_ap_mode(padapter); 365 } 366 367 spin_lock_bh(&pmlmepriv->lock); 368 369 if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) || (*pold_state == Ndis802_11IBSS)) 370 rtw_disassoc_cmd(padapter, 0, true); 371 372 if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) || 373 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) 374 rtw_free_assoc_resources(padapter, 1); 375 376 if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) { 377 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) 378 rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have checked whether issue dis-assoc_cmd or not */ 379 } 380 381 *pold_state = networktype; 382 383 _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE); 384 385 switch (networktype) { 386 case Ndis802_11IBSS: 387 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); 388 break; 389 390 case Ndis802_11Infrastructure: 391 set_fwstate(pmlmepriv, WIFI_STATION_STATE); 392 break; 393 394 case Ndis802_11APMode: 395 set_fwstate(pmlmepriv, WIFI_AP_STATE); 396 start_ap_mode(padapter); 397 /* rtw_indicate_connect(padapter); */ 398 399 break; 400 401 case Ndis802_11AutoUnknown: 402 case Ndis802_11InfrastructureMax: 403 break; 404 } 405 406 /* SecClearAllKeys(adapter); */ 407 408 spin_unlock_bh(&pmlmepriv->lock); 409 } 410 return true; 411 } 412 413 414 u8 rtw_set_802_11_disassociate(struct adapter *padapter) 415 { 416 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 417 418 spin_lock_bh(&pmlmepriv->lock); 419 420 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { 421 rtw_disassoc_cmd(padapter, 0, true); 422 rtw_indicate_disconnect(padapter); 423 /* modify for CONFIG_IEEE80211W, none 11w can use it */ 424 rtw_free_assoc_resources_cmd(padapter); 425 rtw_pwr_wakeup(padapter); 426 } 427 428 spin_unlock_bh(&pmlmepriv->lock); 429 430 return true; 431 } 432 433 u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_ssid *pssid, int ssid_max_num) 434 { 435 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 436 u8 res = true; 437 438 if (padapter == NULL) { 439 res = false; 440 goto exit; 441 } 442 if (padapter->hw_init_completed == false) { 443 res = false; 444 goto exit; 445 } 446 447 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) || 448 (pmlmepriv->LinkDetectInfo.bBusyTraffic == true)) { 449 /* Scan or linking is in progress, do nothing. */ 450 res = true; 451 452 } else { 453 if (rtw_is_scan_deny(padapter)) { 454 indicate_wx_scan_complete_event(padapter); 455 return _SUCCESS; 456 } 457 458 spin_lock_bh(&pmlmepriv->lock); 459 460 res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num, NULL, 0); 461 462 spin_unlock_bh(&pmlmepriv->lock); 463 } 464 exit: 465 466 return res; 467 } 468 469 u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum ndis_802_11_authentication_mode authmode) 470 { 471 struct security_priv *psecuritypriv = &padapter->securitypriv; 472 int res; 473 u8 ret; 474 475 psecuritypriv->ndisauthtype = authmode; 476 477 if (psecuritypriv->ndisauthtype > 3) 478 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; 479 480 res = rtw_set_auth(padapter, psecuritypriv); 481 482 if (res == _SUCCESS) 483 ret = true; 484 else 485 ret = false; 486 487 return ret; 488 } 489 490 u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep) 491 { 492 493 signed int keyid, res; 494 struct security_priv *psecuritypriv = &(padapter->securitypriv); 495 u8 ret = _SUCCESS; 496 497 keyid = wep->KeyIndex & 0x3fffffff; 498 499 if (keyid >= 4) { 500 ret = false; 501 goto exit; 502 } 503 504 switch (wep->KeyLength) { 505 case 5: 506 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_; 507 break; 508 case 13: 509 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_; 510 break; 511 default: 512 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_; 513 break; 514 } 515 516 memcpy(&(psecuritypriv->dot11DefKey[keyid].skey[0]), &(wep->KeyMaterial), wep->KeyLength); 517 518 psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength; 519 520 psecuritypriv->dot11PrivacyKeyIndex = keyid; 521 522 res = rtw_set_key(padapter, psecuritypriv, keyid, 1, true); 523 524 if (res == _FAIL) 525 ret = false; 526 exit: 527 528 return ret; 529 } 530 531 /* 532 * rtw_get_cur_max_rate - 533 * @adapter: pointer to struct adapter structure 534 * 535 * Return 0 or 100Kbps 536 */ 537 u16 rtw_get_cur_max_rate(struct adapter *adapter) 538 { 539 int i = 0; 540 u16 rate = 0, max_rate = 0; 541 struct mlme_priv *pmlmepriv = &adapter->mlmepriv; 542 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; 543 struct sta_info *psta = NULL; 544 u8 short_GI = 0; 545 u8 rf_type = 0; 546 547 if ((check_fwstate(pmlmepriv, _FW_LINKED) != true) 548 && (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != true)) 549 return 0; 550 551 psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(pmlmepriv)); 552 if (psta == NULL) 553 return 0; 554 555 short_GI = query_ra_short_GI(psta); 556 557 if (IsSupportedHT(psta->wireless_mode)) { 558 rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); 559 560 max_rate = rtw_mcs_rate(rf_type, 561 ((psta->bw_mode == CHANNEL_WIDTH_40)?1:0), 562 short_GI, 563 psta->htpriv.ht_cap.mcs.rx_mask); 564 } else { 565 while ((pcur_bss->SupportedRates[i] != 0) && (pcur_bss->SupportedRates[i] != 0xFF)) { 566 rate = pcur_bss->SupportedRates[i]&0x7F; 567 if (rate > max_rate) 568 max_rate = rate; 569 i++; 570 } 571 572 max_rate = max_rate*10/2; 573 } 574 575 return max_rate; 576 } 577