1// SPDX-License-Identifier: GPL-2.0 2/****************************************************************************** 3 * 4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. 5 * 6 ******************************************************************************/ 7 8#include <drv_types.h> 9#include <rtw_debug.h> 10 11u8 rtw_validate_bssid(u8 *bssid) 12{ 13 u8 ret = true; 14 15 if (is_zero_mac_addr(bssid) 16 || is_broadcast_mac_addr(bssid) 17 || is_multicast_mac_addr(bssid) 18 ) { 19 ret = false; 20 } 21 22 return ret; 23} 24 25u8 rtw_validate_ssid(struct ndis_802_11_ssid *ssid) 26{ 27 u8 ret = true; 28 29 if (ssid->ssid_length > 32) { 30 ret = false; 31 goto exit; 32 } 33 34exit: 35 return ret; 36} 37 38u8 rtw_do_join(struct adapter *padapter) 39{ 40 struct list_head *plist, *phead; 41 u8 *pibss = NULL; 42 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 43 struct __queue *queue = &(pmlmepriv->scanned_queue); 44 u8 ret = _SUCCESS; 45 46 spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 47 phead = get_list_head(queue); 48 plist = get_next(phead); 49 50 pmlmepriv->cur_network.join_res = -2; 51 52 set_fwstate(pmlmepriv, _FW_UNDER_LINKING); 53 54 pmlmepriv->pscanned = plist; 55 56 pmlmepriv->to_join = true; 57 58 if (list_empty(&queue->queue)) { 59 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 60 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); 61 62 /* when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty */ 63 /* we try to issue sitesurvey firstly */ 64 65 if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false 66 || rtw_to_roam(padapter) > 0 67 ) { 68 /* submit site_survey_cmd */ 69 ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0); 70 if (ret != _SUCCESS) 71 pmlmepriv->to_join = false; 72 73 } else { 74 pmlmepriv->to_join = false; 75 ret = _FAIL; 76 } 77 78 goto exit; 79 } else { 80 int select_ret; 81 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.mac_address; 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 134exit: 135 return ret; 136} 137 138u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid) 139{ 140 u8 status = _SUCCESS; 141 142 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 143 struct wlan_network *pnetwork = &pmlmepriv->cur_network; 144 145 netdev_dbg(padapter->pnetdev, "set ssid [%s] fw_state = 0x%08x\n", 146 ssid->ssid, get_fwstate(pmlmepriv)); 147 148 if (padapter->hw_init_completed == false) { 149 status = _FAIL; 150 goto exit; 151 } 152 153 spin_lock_bh(&pmlmepriv->lock); 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 ((pmlmepriv->assoc_ssid.ssid_length == ssid->ssid_length) && 162 (!memcmp(&pmlmepriv->assoc_ssid.ssid, ssid->ssid, ssid->ssid_length))) { 163 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false) { 164 if (rtw_is_same_ibss(padapter, pnetwork) == false) { 165 /* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */ 166 rtw_disassoc_cmd(padapter, 0, true); 167 168 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) 169 rtw_indicate_disconnect(padapter); 170 171 rtw_free_assoc_resources(padapter, 1); 172 173 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) { 174 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); 175 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); 176 } 177 } else { 178 goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */ 179 } 180 } else { 181 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1); 182 } 183 } else { 184 rtw_disassoc_cmd(padapter, 0, true); 185 186 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) 187 rtw_indicate_disconnect(padapter); 188 189 rtw_free_assoc_resources(padapter, 1); 190 191 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) { 192 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); 193 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); 194 } 195 } 196 } 197 198handle_tkip_countermeasure: 199 if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) { 200 status = _FAIL; 201 goto release_mlme_lock; 202 } 203 204 if (rtw_validate_ssid(ssid) == false) { 205 status = _FAIL; 206 goto release_mlme_lock; 207 } 208 209 memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid)); 210 pmlmepriv->assoc_by_bssid = false; 211 212 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) 213 pmlmepriv->to_join = true; 214 else 215 status = rtw_do_join(padapter); 216 217release_mlme_lock: 218 spin_unlock_bh(&pmlmepriv->lock); 219 220exit: 221 222 return status; 223} 224 225u8 rtw_set_802_11_connect(struct adapter *padapter, u8 *bssid, struct ndis_802_11_ssid *ssid) 226{ 227 u8 status = _SUCCESS; 228 bool bssid_valid = true; 229 bool ssid_valid = true; 230 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 231 232 if (!ssid || rtw_validate_ssid(ssid) == false) 233 ssid_valid = false; 234 235 if (!bssid || rtw_validate_bssid(bssid) == false) 236 bssid_valid = false; 237 238 if (!ssid_valid && !bssid_valid) { 239 status = _FAIL; 240 goto exit; 241 } 242 243 if (padapter->hw_init_completed == false) { 244 status = _FAIL; 245 goto exit; 246 } 247 248 spin_lock_bh(&pmlmepriv->lock); 249 250 netdev_dbg(padapter->pnetdev, FUNC_ADPT_FMT " fw_state = 0x%08x\n", 251 FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv)); 252 253 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) 254 goto handle_tkip_countermeasure; 255 else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) 256 goto release_mlme_lock; 257 258handle_tkip_countermeasure: 259 if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) { 260 status = _FAIL; 261 goto release_mlme_lock; 262 } 263 264 if (ssid && ssid_valid) 265 memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid)); 266 else 267 memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid)); 268 269 if (bssid && bssid_valid) { 270 memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN); 271 pmlmepriv->assoc_by_bssid = true; 272 } else { 273 pmlmepriv->assoc_by_bssid = false; 274 } 275 276 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) 277 pmlmepriv->to_join = true; 278 else 279 status = rtw_do_join(padapter); 280 281release_mlme_lock: 282 spin_unlock_bh(&pmlmepriv->lock); 283 284exit: 285 return status; 286} 287 288u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter, 289 enum ndis_802_11_network_infrastructure networktype) 290{ 291 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 292 struct wlan_network *cur_network = &pmlmepriv->cur_network; 293 enum ndis_802_11_network_infrastructure *pold_state = &(cur_network->network.infrastructure_mode); 294 295 if (*pold_state != networktype) { 296 if (*pold_state == Ndis802_11APMode) { 297 /* change to other mode from Ndis802_11APMode */ 298 cur_network->join_res = -1; 299 300 stop_ap_mode(padapter); 301 } 302 303 spin_lock_bh(&pmlmepriv->lock); 304 305 if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) || (*pold_state == Ndis802_11IBSS)) 306 rtw_disassoc_cmd(padapter, 0, true); 307 308 if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) || 309 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) 310 rtw_free_assoc_resources(padapter, 1); 311 312 if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) { 313 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) 314 rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have checked whether issue dis-assoc_cmd or not */ 315 } 316 317 *pold_state = networktype; 318 319 _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE); 320 321 switch (networktype) { 322 case Ndis802_11IBSS: 323 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); 324 break; 325 326 case Ndis802_11Infrastructure: 327 set_fwstate(pmlmepriv, WIFI_STATION_STATE); 328 break; 329 330 case Ndis802_11APMode: 331 set_fwstate(pmlmepriv, WIFI_AP_STATE); 332 start_ap_mode(padapter); 333 /* rtw_indicate_connect(padapter); */ 334 335 break; 336 337 case Ndis802_11AutoUnknown: 338 case Ndis802_11InfrastructureMax: 339 break; 340 } 341 342 /* SecClearAllKeys(adapter); */ 343 344 spin_unlock_bh(&pmlmepriv->lock); 345 } 346 return true; 347} 348 349 350u8 rtw_set_802_11_disassociate(struct adapter *padapter) 351{ 352 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 353 354 spin_lock_bh(&pmlmepriv->lock); 355 356 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { 357 rtw_disassoc_cmd(padapter, 0, true); 358 rtw_indicate_disconnect(padapter); 359 /* modify for CONFIG_IEEE80211W, none 11w can use it */ 360 rtw_free_assoc_resources_cmd(padapter); 361 rtw_pwr_wakeup(padapter); 362 } 363 364 spin_unlock_bh(&pmlmepriv->lock); 365 366 return true; 367} 368 369u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_ssid *pssid, int ssid_max_num) 370{ 371 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 372 u8 res = true; 373 374 if (!padapter) { 375 res = false; 376 goto exit; 377 } 378 if (padapter->hw_init_completed == false) { 379 res = false; 380 goto exit; 381 } 382 383 if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) || 384 (pmlmepriv->LinkDetectInfo.bBusyTraffic == true)) { 385 /* Scan or linking is in progress, do nothing. */ 386 res = true; 387 388 } else { 389 if (rtw_is_scan_deny(padapter)) 390 return _SUCCESS; 391 392 spin_lock_bh(&pmlmepriv->lock); 393 394 res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num, NULL, 0); 395 396 spin_unlock_bh(&pmlmepriv->lock); 397 } 398exit: 399 400 return res; 401} 402 403u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum ndis_802_11_authentication_mode authmode) 404{ 405 struct security_priv *psecuritypriv = &padapter->securitypriv; 406 int res; 407 u8 ret; 408 409 psecuritypriv->ndisauthtype = authmode; 410 411 if (psecuritypriv->ndisauthtype > 3) 412 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; 413 414 res = rtw_set_auth(padapter, psecuritypriv); 415 416 if (res == _SUCCESS) 417 ret = true; 418 else 419 ret = false; 420 421 return ret; 422} 423 424u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep) 425{ 426 427 signed int keyid, res; 428 struct security_priv *psecuritypriv = &(padapter->securitypriv); 429 u8 ret = _SUCCESS; 430 431 keyid = wep->key_index & 0x3fffffff; 432 433 if (keyid >= 4) { 434 ret = false; 435 goto exit; 436 } 437 438 switch (wep->key_length) { 439 case 5: 440 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_; 441 break; 442 case 13: 443 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_; 444 break; 445 default: 446 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_; 447 break; 448 } 449 450 memcpy(&(psecuritypriv->dot11DefKey[keyid].skey[0]), &(wep->key_material), wep->key_length); 451 452 psecuritypriv->dot11DefKeylen[keyid] = wep->key_length; 453 454 psecuritypriv->dot11PrivacyKeyIndex = keyid; 455 456 res = rtw_set_key(padapter, psecuritypriv, keyid, 1, true); 457 458 if (res == _FAIL) 459 ret = false; 460exit: 461 462 return ret; 463} 464 465/* 466 * rtw_get_cur_max_rate - 467 * @adapter: pointer to struct adapter structure 468 * 469 * Return 0 or 100Kbps 470 */ 471u16 rtw_get_cur_max_rate(struct adapter *adapter) 472{ 473 int i = 0; 474 u16 rate = 0, max_rate = 0; 475 struct mlme_priv *pmlmepriv = &adapter->mlmepriv; 476 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; 477 struct sta_info *psta = NULL; 478 u8 short_GI = 0; 479 480 if ((check_fwstate(pmlmepriv, _FW_LINKED) != true) 481 && (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != true)) 482 return 0; 483 484 psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(pmlmepriv)); 485 if (!psta) 486 return 0; 487 488 short_GI = query_ra_short_GI(psta); 489 490 if (is_supported_ht(psta->wireless_mode)) { 491 max_rate = rtw_mcs_rate(psta->bw_mode == CHANNEL_WIDTH_40 ? 1 : 0, 492 short_GI, 493 psta->htpriv.ht_cap.mcs.rx_mask); 494 } else { 495 while ((pcur_bss->supported_rates[i] != 0) && (pcur_bss->supported_rates[i] != 0xFF)) { 496 rate = pcur_bss->supported_rates[i]&0x7F; 497 if (rate > max_rate) 498 max_rate = rate; 499 i++; 500 } 501 502 max_rate = max_rate*10/2; 503 } 504 505 return max_rate; 506} 507