1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2012 Realtek Corporation. */
3 
4 #define _RTW_IOCTL_SET_C_
5 
6 #include "../include/osdep_service.h"
7 #include "../include/drv_types.h"
8 #include "../include/rtw_ioctl_set.h"
9 #include "../include/hal_intf.h"
10 
11 #include "../include/usb_osintf.h"
12 #include "../include/usb_ops.h"
13 
rtw_do_join(struct adapter * padapter)14 u8 rtw_do_join(struct adapter *padapter)
15 {
16 	struct list_head *plist, *phead;
17 	u8 *pibss = NULL;
18 	struct	mlme_priv	*pmlmepriv = &padapter->mlmepriv;
19 	struct __queue *queue	= &pmlmepriv->scanned_queue;
20 	u8 ret = _SUCCESS;
21 
22 	spin_lock_bh(&pmlmepriv->scanned_queue.lock);
23 	phead = get_list_head(queue);
24 	plist = phead->next;
25 
26 	pmlmepriv->cur_network.join_res = -2;
27 
28 	set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
29 
30 	pmlmepriv->pscanned = plist;
31 
32 	pmlmepriv->to_join = true;
33 
34 	if (list_empty(&queue->queue)) {
35 		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
36 		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
37 
38 		/* when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty */
39 		/* we try to issue sitesurvey firstly */
40 
41 		if (!pmlmepriv->LinkDetectInfo.bBusyTraffic ||
42 		    pmlmepriv->to_roaming > 0) {
43 			/*  submit site_survey_cmd */
44 			ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1);
45 			if (ret != _SUCCESS)
46 				pmlmepriv->to_join = false;
47 		} else {
48 			pmlmepriv->to_join = false;
49 			ret = _FAIL;
50 		}
51 
52 		return ret;
53 	} else {
54 		int select_ret;
55 
56 		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
57 		select_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
58 		if (select_ret == _SUCCESS) {
59 			pmlmepriv->to_join = false;
60 			_set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
61 		} else {
62 			if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
63 				/*  submit createbss_cmd to change to a ADHOC_MASTER */
64 
65 				/* pmlmepriv->lock has been acquired by caller... */
66 				struct wlan_bssid_ex    *pdev_network = &padapter->registrypriv.dev_network;
67 
68 				pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
69 
70 				pibss = padapter->registrypriv.dev_network.MacAddress;
71 
72 				memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
73 
74 				rtw_update_registrypriv_dev_network(padapter);
75 
76 				rtw_generate_random_ibss(pibss);
77 
78 				if (rtw_createbss_cmd(padapter) != _SUCCESS)
79 					return false;
80 
81 				pmlmepriv->to_join = false;
82 			} else {
83 				/*  can't associate ; reset under-linking */
84 				_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
85 
86 				/* when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue */
87 				/* we try to issue sitesurvey firstly */
88 				if (!pmlmepriv->LinkDetectInfo.bBusyTraffic ||
89 				    pmlmepriv->to_roaming > 0) {
90 					ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1);
91 					if (ret != _SUCCESS)
92 						pmlmepriv->to_join = false;
93 				} else {
94 					ret = _FAIL;
95 					pmlmepriv->to_join = false;
96 				}
97 			}
98 		}
99 	}
100 
101 	return ret;
102 }
103 
rtw_set_802_11_bssid(struct adapter * padapter,u8 * bssid)104 u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid)
105 {
106 	u8 status = _SUCCESS;
107 	u32 cur_time = 0;
108 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
109 
110 	if ((bssid[0] == 0x00 && bssid[1] == 0x00 && bssid[2] == 0x00 &&
111 	     bssid[3] == 0x00 && bssid[4] == 0x00 && bssid[5] == 0x00) ||
112 	    (bssid[0] == 0xFF && bssid[1] == 0xFF && bssid[2] == 0xFF &&
113 	     bssid[3] == 0xFF && bssid[4] == 0xFF && bssid[5] == 0xFF)) {
114 		status = _FAIL;
115 		goto exit;
116 	}
117 
118 	spin_lock_bh(&pmlmepriv->lock);
119 
120 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
121 		goto handle_tkip_countermeasure;
122 	else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
123 		goto release_mlme_lock;
124 
125 	if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
126 		if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN)) {
127 			if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE))
128 				goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
129 		} else {
130 			rtw_disassoc_cmd(padapter, 0, true);
131 
132 			if (check_fwstate(pmlmepriv, _FW_LINKED))
133 				rtw_indicate_disconnect(padapter);
134 
135 			rtw_free_assoc_resources(padapter, 1);
136 
137 			if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
138 				_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
139 				set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
140 			}
141 		}
142 	}
143 
144 handle_tkip_countermeasure:
145 	/* should we add something here...? */
146 
147 	if (padapter->securitypriv.btkip_countermeasure) {
148 		cur_time = jiffies;
149 
150 		if ((cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ) {
151 			padapter->securitypriv.btkip_countermeasure = false;
152 			padapter->securitypriv.btkip_countermeasure_time = 0;
153 		} else {
154 			status = _FAIL;
155 			goto release_mlme_lock;
156 		}
157 	}
158 
159 	memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
160 	pmlmepriv->assoc_by_bssid = true;
161 
162 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
163 		pmlmepriv->to_join = true;
164 	else
165 		status = rtw_do_join(padapter);
166 
167 release_mlme_lock:
168 	spin_unlock_bh(&pmlmepriv->lock);
169 
170 exit:
171 	return status;
172 }
173 
rtw_set_802_11_ssid(struct adapter * padapter,struct ndis_802_11_ssid * ssid)174 u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
175 {
176 	u8 status = _SUCCESS;
177 	u32 cur_time = 0;
178 
179 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
180 	struct wlan_network *pnetwork = &pmlmepriv->cur_network;
181 
182 	if (!padapter->hw_init_completed) {
183 		status = _FAIL;
184 		goto exit;
185 	}
186 
187 	spin_lock_bh(&pmlmepriv->lock);
188 
189 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
190 		goto handle_tkip_countermeasure;
191 	} else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
192 		goto release_mlme_lock;
193 	}
194 
195 	if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
196 		if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) &&
197 		    (!memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength))) {
198 			if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
199 				if (!rtw_is_same_ibss(padapter, pnetwork)) {
200 					/* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
201 					rtw_disassoc_cmd(padapter, 0, true);
202 
203 					if (check_fwstate(pmlmepriv, _FW_LINKED))
204 						rtw_indicate_disconnect(padapter);
205 
206 					rtw_free_assoc_resources(padapter, 1);
207 
208 					if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
209 						_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
210 						set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
211 					}
212 				} else {
213 					goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
214 				}
215 			} else {
216 				rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1);
217 			}
218 		} else {
219 			rtw_disassoc_cmd(padapter, 0, true);
220 
221 			if (check_fwstate(pmlmepriv, _FW_LINKED))
222 				rtw_indicate_disconnect(padapter);
223 
224 			rtw_free_assoc_resources(padapter, 1);
225 
226 			if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
227 				_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
228 				set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
229 			}
230 		}
231 	}
232 
233 handle_tkip_countermeasure:
234 
235 	if (padapter->securitypriv.btkip_countermeasure) {
236 		cur_time = jiffies;
237 
238 		if ((cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ) {
239 			padapter->securitypriv.btkip_countermeasure = false;
240 			padapter->securitypriv.btkip_countermeasure_time = 0;
241 		} else {
242 			status = _FAIL;
243 			goto release_mlme_lock;
244 		}
245 	}
246 
247 	memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
248 	pmlmepriv->assoc_by_bssid = false;
249 
250 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
251 		pmlmepriv->to_join = true;
252 	} else {
253 		status = rtw_do_join(padapter);
254 	}
255 
256 release_mlme_lock:
257 	spin_unlock_bh(&pmlmepriv->lock);
258 
259 exit:
260 	return status;
261 }
262 
rtw_set_802_11_infrastructure_mode(struct adapter * padapter,enum ndis_802_11_network_infra networktype)263 u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter,
264 	enum ndis_802_11_network_infra networktype)
265 {
266 	struct	mlme_priv	*pmlmepriv = &padapter->mlmepriv;
267 	struct	wlan_network	*cur_network = &pmlmepriv->cur_network;
268 	enum ndis_802_11_network_infra *pold_state = &cur_network->network.InfrastructureMode;
269 
270 	if (*pold_state != networktype) {
271 		spin_lock_bh(&pmlmepriv->lock);
272 
273 		if (*pold_state == Ndis802_11APMode) {
274 			/* change to other mode from Ndis802_11APMode */
275 			cur_network->join_res = -1;
276 
277 			stop_ap_mode(padapter);
278 		}
279 
280 		if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
281 		    (*pold_state == Ndis802_11IBSS))
282 			rtw_disassoc_cmd(padapter, 0, true);
283 
284 		if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
285 		    (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
286 			rtw_free_assoc_resources(padapter, 1);
287 
288 		if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) {
289 			if (check_fwstate(pmlmepriv, _FW_LINKED))
290 				rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have chked whether  issue dis-assoc_cmd or not */
291 	       }
292 
293 		*pold_state = networktype;
294 
295 		_clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
296 
297 		switch (networktype) {
298 		case Ndis802_11IBSS:
299 			set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
300 			break;
301 		case Ndis802_11Infrastructure:
302 			set_fwstate(pmlmepriv, WIFI_STATION_STATE);
303 			break;
304 		case Ndis802_11APMode:
305 			set_fwstate(pmlmepriv, WIFI_AP_STATE);
306 			break;
307 		case Ndis802_11AutoUnknown:
308 		case Ndis802_11InfrastructureMax:
309 			break;
310 		}
311 		spin_unlock_bh(&pmlmepriv->lock);
312 	}
313 
314 	return true;
315 }
316 
rtw_set_802_11_disassociate(struct adapter * padapter)317 u8 rtw_set_802_11_disassociate(struct adapter *padapter)
318 {
319 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
320 
321 	spin_lock_bh(&pmlmepriv->lock);
322 
323 	if (check_fwstate(pmlmepriv, _FW_LINKED)) {
324 		rtw_disassoc_cmd(padapter, 0, true);
325 		rtw_indicate_disconnect(padapter);
326 		rtw_free_assoc_resources(padapter, 1);
327 		rtw_pwr_wakeup(padapter);
328 	}
329 
330 	spin_unlock_bh(&pmlmepriv->lock);
331 
332 	return true;
333 }
334 
rtw_set_802_11_bssid_list_scan(struct adapter * padapter,struct ndis_802_11_ssid * pssid,int ssid_max_num)335 u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_ssid *pssid, int ssid_max_num)
336 {
337 	struct	mlme_priv		*pmlmepriv = &padapter->mlmepriv;
338 	u8	res = true;
339 
340 	if (!padapter) {
341 		res = false;
342 		goto exit;
343 	}
344 	if (!padapter->hw_init_completed) {
345 		res = false;
346 		goto exit;
347 	}
348 
349 	if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) ||
350 	    (pmlmepriv->LinkDetectInfo.bBusyTraffic)) {
351 		/*  Scan or linking is in progress, do nothing. */
352 		res = true;
353 	} else {
354 		spin_lock_bh(&pmlmepriv->lock);
355 
356 		res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num);
357 
358 		spin_unlock_bh(&pmlmepriv->lock);
359 	}
360 exit:
361 
362 	return res;
363 }
364 
rtw_set_802_11_authentication_mode(struct adapter * padapter,enum ndis_802_11_auth_mode authmode)365 u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum ndis_802_11_auth_mode authmode)
366 {
367 	struct security_priv *psecuritypriv = &padapter->securitypriv;
368 	int res;
369 	u8 ret;
370 
371 	psecuritypriv->ndisauthtype = authmode;
372 
373 	if (psecuritypriv->ndisauthtype > 3)
374 		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
375 
376 	res = rtw_set_auth(padapter, psecuritypriv);
377 
378 	if (res == _SUCCESS)
379 		ret = true;
380 	else
381 		ret = false;
382 
383 	return ret;
384 }
385 
rtw_set_802_11_add_wep(struct adapter * padapter,struct ndis_802_11_wep * wep)386 u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep)
387 {
388 	int		keyid, res;
389 	struct security_priv *psecuritypriv = &padapter->securitypriv;
390 	u8		ret = _SUCCESS;
391 
392 	keyid = wep->KeyIndex & 0x3fffffff;
393 
394 	if (keyid >= 4) {
395 		ret = false;
396 		goto exit;
397 	}
398 
399 	switch (wep->KeyLength) {
400 	case 5:
401 		psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
402 		break;
403 	case 13:
404 		psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
405 		break;
406 	default:
407 		psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
408 		break;
409 	}
410 
411 	memcpy(&psecuritypriv->dot11DefKey[keyid].skey[0], &wep->KeyMaterial, wep->KeyLength);
412 
413 	psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength;
414 
415 	psecuritypriv->dot11PrivacyKeyIndex = keyid;
416 
417 	res = rtw_set_key(padapter, psecuritypriv, keyid, 1);
418 
419 	if (res == _FAIL)
420 		ret = false;
421 exit:
422 
423 	return ret;
424 }
425 
426 /*
427 * rtw_get_cur_max_rate -
428 * @adapter: pointer to struct adapter structure
429 *
430 * Return 0 or 100Kbps
431 */
rtw_get_cur_max_rate(struct adapter * adapter)432 u16 rtw_get_cur_max_rate(struct adapter *adapter)
433 {
434 	int	i = 0;
435 	u8	*p;
436 	u16	rate = 0, max_rate = 0;
437 	struct mlme_ext_priv	*pmlmeext = &adapter->mlmeextpriv;
438 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
439 	struct registry_priv *pregistrypriv = &adapter->registrypriv;
440 	struct mlme_priv	*pmlmepriv = &adapter->mlmepriv;
441 	struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
442 	struct ieee80211_ht_cap *pht_capie;
443 	u8	bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
444 	u16	mcs_rate = 0;
445 	u32	ht_ielen = 0;
446 
447 	if ((!check_fwstate(pmlmepriv, _FW_LINKED)) &&
448 	    (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
449 		return 0;
450 
451 	if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N)) {
452 		p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength - 12);
453 		if (p && ht_ielen > 0) {
454 			pht_capie = (struct ieee80211_ht_cap *)(p + 2);
455 
456 			memcpy(&mcs_rate, pht_capie->mcs.rx_mask, 2);
457 
458 			/* cur_bwmod is updated by beacon, pmlmeinfo is updated by association response */
459 			bw_40MHz = (pmlmeext->cur_bwmode && (HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH & pmlmeinfo->HT_info.infos[0])) ? 1 : 0;
460 
461 			short_GI_20 = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & IEEE80211_HT_CAP_SGI_20) ? 1 : 0;
462 			short_GI_40 = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & IEEE80211_HT_CAP_SGI_40) ? 1 : 0;
463 
464 			max_rate = rtw_mcs_rate(bw_40MHz & (pregistrypriv->cbw40_enable),
465 						short_GI_20,
466 						short_GI_40,
467 						pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate);
468 		}
469 	} else {
470 		while ((pcur_bss->SupportedRates[i] != 0) && (pcur_bss->SupportedRates[i] != 0xFF)) {
471 			rate = pcur_bss->SupportedRates[i] & 0x7F;
472 			if (rate > max_rate)
473 				max_rate = rate;
474 			i++;
475 		}
476 
477 		max_rate *= 5;
478 	}
479 
480 	return max_rate;
481 }
482