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