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 
14 extern void indicate_wx_scan_complete_event(struct adapter *padapter);
15 
rtw_validate_ssid(struct ndis_802_11_ssid * ssid)16 u8 rtw_validate_ssid(struct ndis_802_11_ssid *ssid)
17 {
18 	u8	 i;
19 	u8	ret = true;
20 
21 	if (ssid->SsidLength > 32) {
22 		ret = false;
23 		goto exit;
24 	}
25 
26 	for (i = 0; i < ssid->SsidLength; i++) {
27 		/* wifi, printable ascii code must be supported */
28 		if (!((ssid->Ssid[i] >= 0x20) && (ssid->Ssid[i] <= 0x7e))) {
29 			ret = false;
30 			break;
31 		}
32 	}
33 
34 exit:
35 
36 	return ret;
37 }
38 
rtw_do_join(struct adapter * padapter)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 = phead->next;
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 ||
67 		    pmlmepriv->to_roaming > 0) {
68 			/*  submit site_survey_cmd */
69 			ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
70 			if (_SUCCESS != ret)
71 				pmlmepriv->to_join = false;
72 		} else {
73 			pmlmepriv->to_join = false;
74 			ret = _FAIL;
75 		}
76 
77 		goto exit;
78 	} else {
79 		int select_ret;
80 
81 		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
82 		select_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
83 		if (select_ret == _SUCCESS) {
84 			pmlmepriv->to_join = false;
85 			_set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
86 		} else {
87 			if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
88 				/*  submit createbss_cmd to change to a ADHOC_MASTER */
89 
90 				/* pmlmepriv->lock has been acquired by caller... */
91 				struct wlan_bssid_ex    *pdev_network = &padapter->registrypriv.dev_network;
92 
93 				pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
94 
95 				pibss = padapter->registrypriv.dev_network.MacAddress;
96 
97 				memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
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 				pmlmepriv->to_join = false;
109 			} else {
110 				/*  can't associate ; reset under-linking */
111 				_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
112 
113 				/* when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue */
114 				/* we try to issue sitesurvey firstly */
115 				if (!pmlmepriv->LinkDetectInfo.bBusyTraffic ||
116 				    pmlmepriv->to_roaming > 0) {
117 					ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
118 					if (_SUCCESS != ret)
119 						pmlmepriv->to_join = false;
120 				} else {
121 					ret = _FAIL;
122 					pmlmepriv->to_join = false;
123 				}
124 			}
125 		}
126 	}
127 
128 exit:
129 
130 	return ret;
131 }
132 
rtw_set_802_11_bssid(struct adapter * padapter,u8 * bssid)133 u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid)
134 {
135 	u8 status = _SUCCESS;
136 	u32 cur_time = 0;
137 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
138 
139 	DBG_88E_LEVEL(_drv_info_, "set bssid:%pM\n", bssid);
140 
141 	if ((bssid[0] == 0x00 && bssid[1] == 0x00 && bssid[2] == 0x00 &&
142 	     bssid[3] == 0x00 && bssid[4] == 0x00 && bssid[5] == 0x00) ||
143 	    (bssid[0] == 0xFF && bssid[1] == 0xFF && bssid[2] == 0xFF &&
144 	     bssid[3] == 0xFF && bssid[4] == 0xFF && bssid[5] == 0xFF)) {
145 		status = _FAIL;
146 		goto exit;
147 	}
148 
149 	spin_lock_bh(&pmlmepriv->lock);
150 
151 	DBG_88E("Set BSSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
152 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
153 		goto handle_tkip_countermeasure;
154 	else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
155 		goto release_mlme_lock;
156 
157 	if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
158 		if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN)) {
159 			if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE))
160 				goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
161 		} else {
162 			rtw_disassoc_cmd(padapter, 0, true);
163 
164 			if (check_fwstate(pmlmepriv, _FW_LINKED))
165 				rtw_indicate_disconnect(padapter);
166 
167 			rtw_free_assoc_resources(padapter, 1);
168 
169 			if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
170 				_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
171 				set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
172 			}
173 		}
174 	}
175 
176 handle_tkip_countermeasure:
177 	/* should we add something here...? */
178 
179 	if (padapter->securitypriv.btkip_countermeasure) {
180 		cur_time = jiffies;
181 
182 		if ((cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ) {
183 			padapter->securitypriv.btkip_countermeasure = false;
184 			padapter->securitypriv.btkip_countermeasure_time = 0;
185 		} else {
186 			status = _FAIL;
187 			goto release_mlme_lock;
188 		}
189 	}
190 
191 	memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
192 	pmlmepriv->assoc_by_bssid = true;
193 
194 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
195 		pmlmepriv->to_join = true;
196 	else
197 		status = rtw_do_join(padapter);
198 
199 release_mlme_lock:
200 	spin_unlock_bh(&pmlmepriv->lock);
201 
202 exit:
203 	return status;
204 }
205 
rtw_set_802_11_ssid(struct adapter * padapter,struct ndis_802_11_ssid * ssid)206 u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
207 {
208 	u8 status = _SUCCESS;
209 	u32 cur_time = 0;
210 
211 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
212 	struct wlan_network *pnetwork = &pmlmepriv->cur_network;
213 
214 	DBG_88E_LEVEL(_drv_info_, "set ssid [%s] fw_state=0x%08x\n",
215 		      ssid->Ssid, get_fwstate(pmlmepriv));
216 
217 	if (!padapter->hw_init_completed) {
218 		status = _FAIL;
219 		goto exit;
220 	}
221 
222 	spin_lock_bh(&pmlmepriv->lock);
223 
224 	DBG_88E("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
225 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
226 		goto handle_tkip_countermeasure;
227 	} else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
228 		goto release_mlme_lock;
229 	}
230 
231 	if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
232 		if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) &&
233 		    (!memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength))) {
234 			if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
235 				if (!rtw_is_same_ibss(padapter, pnetwork)) {
236 					/* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
237 					rtw_disassoc_cmd(padapter, 0, true);
238 
239 					if (check_fwstate(pmlmepriv, _FW_LINKED))
240 						rtw_indicate_disconnect(padapter);
241 
242 					rtw_free_assoc_resources(padapter, 1);
243 
244 					if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
245 						_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
246 						set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
247 					}
248 				} else {
249 					goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
250 				}
251 			} else {
252 				rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1);
253 			}
254 		} else {
255 			rtw_disassoc_cmd(padapter, 0, true);
256 
257 			if (check_fwstate(pmlmepriv, _FW_LINKED))
258 				rtw_indicate_disconnect(padapter);
259 
260 			rtw_free_assoc_resources(padapter, 1);
261 
262 			if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
263 				_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
264 				set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
265 			}
266 		}
267 	}
268 
269 handle_tkip_countermeasure:
270 
271 	if (padapter->securitypriv.btkip_countermeasure) {
272 		cur_time = jiffies;
273 
274 		if ((cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ) {
275 			padapter->securitypriv.btkip_countermeasure = false;
276 			padapter->securitypriv.btkip_countermeasure_time = 0;
277 		} else {
278 			status = _FAIL;
279 			goto release_mlme_lock;
280 		}
281 	}
282 
283 	memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
284 	pmlmepriv->assoc_by_bssid = false;
285 
286 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
287 		pmlmepriv->to_join = true;
288 	} else {
289 		status = rtw_do_join(padapter);
290 	}
291 
292 release_mlme_lock:
293 	spin_unlock_bh(&pmlmepriv->lock);
294 
295 exit:
296 	return status;
297 }
298 
rtw_set_802_11_infrastructure_mode(struct adapter * padapter,enum ndis_802_11_network_infra networktype)299 u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter,
300 	enum ndis_802_11_network_infra networktype)
301 {
302 	struct	mlme_priv	*pmlmepriv = &padapter->mlmepriv;
303 	struct	wlan_network	*cur_network = &pmlmepriv->cur_network;
304 	enum ndis_802_11_network_infra *pold_state = &cur_network->network.InfrastructureMode;
305 
306 	if (*pold_state != networktype) {
307 		spin_lock_bh(&pmlmepriv->lock);
308 
309 		/* DBG_88E("change mode, old_mode =%d, new_mode =%d, fw_state = 0x%x\n", *pold_state, networktype, get_fwstate(pmlmepriv)); */
310 
311 		if (*pold_state == Ndis802_11APMode) {
312 			/* change to other mode from Ndis802_11APMode */
313 			cur_network->join_res = -1;
314 
315 #ifdef CONFIG_88EU_AP_MODE
316 			stop_ap_mode(padapter);
317 #endif
318 		}
319 
320 		if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
321 		    (*pold_state == Ndis802_11IBSS))
322 			rtw_disassoc_cmd(padapter, 0, true);
323 
324 		if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
325 		    (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
326 			rtw_free_assoc_resources(padapter, 1);
327 
328 		if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) {
329 			if (check_fwstate(pmlmepriv, _FW_LINKED))
330 				rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have chked whether  issue dis-assoc_cmd or not */
331 	       }
332 
333 		*pold_state = networktype;
334 
335 		_clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
336 
337 		switch (networktype) {
338 		case Ndis802_11IBSS:
339 			set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
340 			break;
341 		case Ndis802_11Infrastructure:
342 			set_fwstate(pmlmepriv, WIFI_STATION_STATE);
343 			break;
344 		case Ndis802_11APMode:
345 			set_fwstate(pmlmepriv, WIFI_AP_STATE);
346 #ifdef CONFIG_88EU_AP_MODE
347 			start_ap_mode(padapter);
348 #endif
349 			break;
350 		case Ndis802_11AutoUnknown:
351 		case Ndis802_11InfrastructureMax:
352 			break;
353 		}
354 		spin_unlock_bh(&pmlmepriv->lock);
355 	}
356 
357 	return true;
358 }
359 
rtw_set_802_11_disassociate(struct adapter * padapter)360 u8 rtw_set_802_11_disassociate(struct adapter *padapter)
361 {
362 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
363 
364 	spin_lock_bh(&pmlmepriv->lock);
365 
366 	if (check_fwstate(pmlmepriv, _FW_LINKED)) {
367 		rtw_disassoc_cmd(padapter, 0, true);
368 		rtw_indicate_disconnect(padapter);
369 		rtw_free_assoc_resources(padapter, 1);
370 		rtw_pwr_wakeup(padapter);
371 	}
372 
373 	spin_unlock_bh(&pmlmepriv->lock);
374 
375 	return true;
376 }
377 
rtw_set_802_11_bssid_list_scan(struct adapter * padapter,struct ndis_802_11_ssid * pssid,int ssid_max_num)378 u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_ssid *pssid, int ssid_max_num)
379 {
380 	struct	mlme_priv		*pmlmepriv = &padapter->mlmepriv;
381 	u8	res = true;
382 
383 	if (!padapter) {
384 		res = false;
385 		goto exit;
386 	}
387 	if (!padapter->hw_init_completed) {
388 		res = false;
389 		goto exit;
390 	}
391 
392 	if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) ||
393 	    (pmlmepriv->LinkDetectInfo.bBusyTraffic)) {
394 		/*  Scan or linking is in progress, do nothing. */
395 		res = true;
396 	} else {
397 		if (rtw_is_scan_deny(padapter)) {
398 			DBG_88E(FUNC_ADPT_FMT": scan deny\n", FUNC_ADPT_ARG(padapter));
399 			indicate_wx_scan_complete_event(padapter);
400 			return _SUCCESS;
401 		}
402 
403 		spin_lock_bh(&pmlmepriv->lock);
404 
405 		res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num, NULL, 0);
406 
407 		spin_unlock_bh(&pmlmepriv->lock);
408 	}
409 exit:
410 
411 	return res;
412 }
413 
rtw_set_802_11_authentication_mode(struct adapter * padapter,enum ndis_802_11_auth_mode authmode)414 u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum ndis_802_11_auth_mode authmode)
415 {
416 	struct security_priv *psecuritypriv = &padapter->securitypriv;
417 	int res;
418 	u8 ret;
419 
420 	psecuritypriv->ndisauthtype = authmode;
421 
422 	if (psecuritypriv->ndisauthtype > 3)
423 		psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
424 
425 	res = rtw_set_auth(padapter, psecuritypriv);
426 
427 	if (res == _SUCCESS)
428 		ret = true;
429 	else
430 		ret = false;
431 
432 	return ret;
433 }
434 
rtw_set_802_11_add_wep(struct adapter * padapter,struct ndis_802_11_wep * wep)435 u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep)
436 {
437 	int		keyid, res;
438 	struct security_priv *psecuritypriv = &padapter->securitypriv;
439 	u8		ret = _SUCCESS;
440 
441 	keyid = wep->KeyIndex & 0x3fffffff;
442 
443 	if (keyid >= 4) {
444 		ret = false;
445 		goto exit;
446 	}
447 
448 	switch (wep->KeyLength) {
449 	case 5:
450 		psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
451 		break;
452 	case 13:
453 		psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
454 		break;
455 	default:
456 		psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
457 		break;
458 	}
459 
460 	memcpy(&psecuritypriv->dot11DefKey[keyid].skey[0], &wep->KeyMaterial, wep->KeyLength);
461 
462 	psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength;
463 
464 	psecuritypriv->dot11PrivacyKeyIndex = keyid;
465 
466 	res = rtw_set_key(padapter, psecuritypriv, keyid, 1);
467 
468 	if (res == _FAIL)
469 		ret = false;
470 exit:
471 
472 	return ret;
473 }
474 
rtw_set_802_11_remove_wep(struct adapter * padapter,u32 keyindex)475 u8 rtw_set_802_11_remove_wep(struct adapter *padapter, u32 keyindex)
476 {
477 	u8 ret = _SUCCESS;
478 
479 	if (keyindex >= 0x80000000 || !padapter) {
480 		ret = false;
481 		goto exit;
482 	} else {
483 		int res;
484 		struct security_priv *psecuritypriv = &padapter->securitypriv;
485 		if (keyindex < 4) {
486 			memset(&psecuritypriv->dot11DefKey[keyindex], 0, 16);
487 			res = rtw_set_key(padapter, psecuritypriv, keyindex, 0);
488 			psecuritypriv->dot11DefKeylen[keyindex] = 0;
489 			if (res == _FAIL)
490 				ret = _FAIL;
491 		} else {
492 			ret = _FAIL;
493 		}
494 	}
495 exit:
496 
497 	return ret;
498 }
499 
rtw_set_802_11_add_key(struct adapter * padapter,struct ndis_802_11_key * key)500 u8 rtw_set_802_11_add_key(struct adapter *padapter, struct ndis_802_11_key *key)
501 {
502 	uint	encryptionalgo;
503 	u8 *pbssid;
504 	struct sta_info *stainfo;
505 	u8	bgroup = false;
506 	u8	bgrouptkey = false;/* can be removed later */
507 	u8	ret = _SUCCESS;
508 
509 	if (((key->KeyIndex & 0x80000000) == 0) && ((key->KeyIndex & 0x40000000) > 0)) {
510 		/*  It is invalid to clear bit 31 and set bit 30. If the miniport driver encounters this combination, */
511 		/*  it must fail the request and return NDIS_STATUS_INVALID_DATA. */
512 		ret = _FAIL;
513 		goto exit;
514 	}
515 
516 	if (key->KeyIndex & 0x40000000) {
517 		/*  Pairwise key */
518 
519 		pbssid = get_bssid(&padapter->mlmepriv);
520 		stainfo = rtw_get_stainfo(&padapter->stapriv, pbssid);
521 
522 		if (stainfo && padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
523 			encryptionalgo = stainfo->dot118021XPrivacy;
524 		else
525 			encryptionalgo = padapter->securitypriv.dot11PrivacyAlgrthm;
526 
527 		if (key->KeyIndex & 0x000000FF) {
528 			/*  The key index is specified in the lower 8 bits by values of zero to 255. */
529 			/*  The key index should be set to zero for a Pairwise key, and the driver should fail with */
530 			/*  NDIS_STATUS_INVALID_DATA if the lower 8 bits is not zero */
531 			ret = _FAIL;
532 			goto exit;
533 		}
534 
535 		/*  check BSSID */
536 		if (is_broadcast_ether_addr(key->BSSID)) {
537 			ret = false;
538 			goto exit;
539 		}
540 
541 		/*  Check key length for TKIP. */
542 		if ((encryptionalgo == _TKIP_) && (key->KeyLength != 32)) {
543 			ret = _FAIL;
544 			goto exit;
545 		}
546 
547 		/*  Check key length for AES. */
548 		if ((encryptionalgo == _AES_) && (key->KeyLength != 16)) {
549 			/*  For our supplicant, EAPPkt9x.vxd, cannot differentiate TKIP and AES case. */
550 			if (key->KeyLength == 32) {
551 				key->KeyLength = 16;
552 			} else {
553 				ret = _FAIL;
554 				goto exit;
555 			}
556 		}
557 
558 		/*  Check key length for WEP. For NDTEST, 2005.01.27, by rcnjko. */
559 		if ((encryptionalgo == _WEP40_ || encryptionalgo == _WEP104_) &&
560 		    (key->KeyLength != 5 && key->KeyLength != 13)) {
561 			ret = _FAIL;
562 			goto exit;
563 		}
564 
565 		bgroup = false;
566 	} else {
567 		/*  Group key - KeyIndex(BIT(30) == 0) */
568 		/*  when add wep key through add key and didn't assigned encryption type before */
569 		if ((padapter->securitypriv.ndisauthtype <= 3) &&
570 		    (padapter->securitypriv.dot118021XGrpPrivacy == 0)) {
571 			switch (key->KeyLength) {
572 			case 5:
573 				padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
574 				break;
575 			case 13:
576 				padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
577 				break;
578 			default:
579 				padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
580 				break;
581 			}
582 
583 			encryptionalgo = padapter->securitypriv.dot11PrivacyAlgrthm;
584 		} else {
585 			encryptionalgo = padapter->securitypriv.dot118021XGrpPrivacy;
586 		}
587 
588 		if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE) && !is_broadcast_ether_addr(key->BSSID)) {
589 			ret = _FAIL;
590 			goto exit;
591 		}
592 
593 		/*  Check key length for TKIP */
594 		if ((encryptionalgo == _TKIP_) && (key->KeyLength != 32)) {
595 			ret = _FAIL;
596 			goto exit;
597 		} else if (encryptionalgo == _AES_ && (key->KeyLength != 16 && key->KeyLength != 32)) {
598 			/*  Check key length for AES */
599 			/*  For NDTEST, we allow keylen = 32 in this case. 2005.01.27, by rcnjko. */
600 			ret = _FAIL;
601 			goto exit;
602 		}
603 
604 		/*  Change the key length for EAPPkt9x.vxd. Added by Annie, 2005-11-03. */
605 		if ((encryptionalgo ==  _AES_) && (key->KeyLength == 32))
606 			key->KeyLength = 16;
607 
608 		if (key->KeyIndex & 0x8000000) {/* error ??? 0x8000_0000 */
609 			bgrouptkey = true;
610 		}
611 
612 		if ((check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE)) &&
613 		    (check_fwstate(&padapter->mlmepriv, _FW_LINKED)))
614 			bgrouptkey = true;
615 		bgroup = true;
616 	}
617 
618 	/*  If WEP encryption algorithm, just call rtw_set_802_11_add_wep(). */
619 	if ((padapter->securitypriv.dot11AuthAlgrthm != dot11AuthAlgrthm_8021X) &&
620 	    (encryptionalgo == _WEP40_ || encryptionalgo == _WEP104_)) {
621 		u32 keyindex;
622 		u32 len = FIELD_OFFSET(struct ndis_802_11_key, KeyMaterial) + key->KeyLength;
623 		struct ndis_802_11_wep *wep = &padapter->securitypriv.ndiswep;
624 
625 		wep->Length = len;
626 		keyindex = key->KeyIndex & 0x7fffffff;
627 		wep->KeyIndex = keyindex;
628 		wep->KeyLength = key->KeyLength;
629 
630 		memcpy(wep->KeyMaterial, key->KeyMaterial, key->KeyLength);
631 		memcpy(&padapter->securitypriv.dot11DefKey[keyindex].skey[0], key->KeyMaterial, key->KeyLength);
632 
633 		padapter->securitypriv.dot11DefKeylen[keyindex] = key->KeyLength;
634 		padapter->securitypriv.dot11PrivacyKeyIndex = keyindex;
635 
636 		ret = rtw_set_802_11_add_wep(padapter, wep);
637 		goto exit;
638 	}
639 	if (key->KeyIndex & 0x20000000) {
640 		/*  SetRSC */
641 		if (bgroup) {
642 			unsigned long long keysrc = key->KeyRSC & 0x00FFFFFFFFFFFFULL;
643 			memcpy(&padapter->securitypriv.dot11Grprxpn, &keysrc, 8);
644 		} else {
645 			unsigned long long keysrc = key->KeyRSC & 0x00FFFFFFFFFFFFULL;
646 			memcpy(&padapter->securitypriv.dot11Grptxpn, &keysrc, 8);
647 		}
648 	}
649 
650 	/*  Indicate this key idx is used for TX */
651 	/*  Save the key in KeyMaterial */
652 	if (bgroup) { /*  Group transmit key */
653 		int res;
654 
655 		if (bgrouptkey)
656 			padapter->securitypriv.dot118021XGrpKeyid = (u8)key->KeyIndex;
657 		if ((key->KeyIndex & 0x3) == 0) {
658 			ret = _FAIL;
659 			goto exit;
660 		}
661 		memset(&padapter->securitypriv.dot118021XGrpKey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
662 		memset(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
663 		memset(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
664 
665 		if ((key->KeyIndex & 0x10000000)) {
666 			memcpy(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 16, 8);
667 			memcpy(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 24, 8);
668 		} else {
669 			memcpy(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 24, 8);
670 			memcpy(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 16, 8);
671 		}
672 
673 		/* set group key by index */
674 		memcpy(&padapter->securitypriv.dot118021XGrpKey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial, key->KeyLength);
675 
676 		key->KeyIndex = key->KeyIndex & 0x03;
677 
678 		padapter->securitypriv.binstallGrpkey = true;
679 
680 		padapter->securitypriv.bcheck_grpkey = false;
681 
682 		res = rtw_set_key(padapter, &padapter->securitypriv, key->KeyIndex, 1);
683 
684 		if (res == _FAIL)
685 			ret = _FAIL;
686 
687 		goto exit;
688 
689 	} else { /*  Pairwise Key */
690 		u8 res;
691 
692 		pbssid = get_bssid(&padapter->mlmepriv);
693 		stainfo = rtw_get_stainfo(&padapter->stapriv, pbssid);
694 
695 		if (stainfo) {
696 			memset(&stainfo->dot118021x_UncstKey, 0, 16);/*  clear keybuffer */
697 
698 			memcpy(&stainfo->dot118021x_UncstKey, key->KeyMaterial, 16);
699 
700 			if (encryptionalgo == _TKIP_) {
701 				padapter->securitypriv.busetkipkey = false;
702 
703 				/* _set_timer(&padapter->securitypriv.tkip_timer, 50); */
704 
705 				/*  if TKIP, save the Receive/Transmit MIC key in KeyMaterial[128-255] */
706 				if ((key->KeyIndex & 0x10000000)) {
707 					memcpy(&stainfo->dot11tkiptxmickey, key->KeyMaterial + 16, 8);
708 					memcpy(&stainfo->dot11tkiprxmickey, key->KeyMaterial + 24, 8);
709 
710 				} else {
711 					memcpy(&stainfo->dot11tkiptxmickey, key->KeyMaterial + 24, 8);
712 					memcpy(&stainfo->dot11tkiprxmickey, key->KeyMaterial + 16, 8);
713 				}
714 			}
715 
716 			/* Set key to CAM through H2C command */
717 			if (bgrouptkey) /* never go to here */
718 				res = rtw_setstakey_cmd(padapter, (unsigned char *)stainfo, false);
719 			else
720 				res = rtw_setstakey_cmd(padapter, (unsigned char *)stainfo, true);
721 			if (!res)
722 				ret = _FAIL;
723 		}
724 	}
725 exit:
726 
727 	return ret;
728 }
729 
rtw_set_802_11_remove_key(struct adapter * padapter,struct ndis_802_11_remove_key * key)730 u8 rtw_set_802_11_remove_key(struct adapter *padapter, struct ndis_802_11_remove_key *key)
731 {
732 	u8 *pbssid;
733 	struct sta_info *stainfo;
734 	u8	bgroup = (key->KeyIndex & 0x4000000) > 0 ? false : true;
735 	u8	keyIndex = (u8)key->KeyIndex & 0x03;
736 	u8	ret = _SUCCESS;
737 
738 	if ((key->KeyIndex & 0xbffffffc) > 0) {
739 		ret = _FAIL;
740 		goto exit;
741 	}
742 
743 	if (bgroup) {
744 		/*  clear group key by index */
745 
746 		memset(&padapter->securitypriv.dot118021XGrpKey[keyIndex], 0, 16);
747 
748 		/*  \todo Send a H2C Command to Firmware for removing this Key in CAM Entry. */
749 	} else {
750 		pbssid = get_bssid(&padapter->mlmepriv);
751 		stainfo = rtw_get_stainfo(&padapter->stapriv, pbssid);
752 		if (stainfo) {
753 			/*  clear key by BSSID */
754 			memset(&stainfo->dot118021x_UncstKey, 0, 16);
755 
756 			/*  \todo Send a H2C Command to Firmware for disable this Key in CAM Entry. */
757 		} else {
758 			ret = _FAIL;
759 			goto exit;
760 		}
761 	}
762 exit:
763 
764 	return ret;
765 }
766 
767 /*
768 * rtw_get_cur_max_rate -
769 * @adapter: pointer to struct adapter structure
770 *
771 * Return 0 or 100Kbps
772 */
rtw_get_cur_max_rate(struct adapter * adapter)773 u16 rtw_get_cur_max_rate(struct adapter *adapter)
774 {
775 	int	i = 0;
776 	u8	*p;
777 	u16	rate = 0, max_rate = 0;
778 	struct mlme_ext_priv	*pmlmeext = &adapter->mlmeextpriv;
779 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
780 	struct registry_priv *pregistrypriv = &adapter->registrypriv;
781 	struct mlme_priv	*pmlmepriv = &adapter->mlmepriv;
782 	struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
783 	struct ieee80211_ht_cap *pht_capie;
784 	u8	rf_type = 0;
785 	u8	bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
786 	u16	mcs_rate = 0;
787 	u32	ht_ielen = 0;
788 
789 	if (adapter->registrypriv.mp_mode == 1) {
790 		if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
791 			return 0;
792 	}
793 
794 	if ((!check_fwstate(pmlmepriv, _FW_LINKED)) &&
795 	    (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
796 		return 0;
797 
798 	if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N)) {
799 		p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength - 12);
800 		if (p && ht_ielen > 0) {
801 			pht_capie = (struct ieee80211_ht_cap *)(p + 2);
802 
803 			memcpy(&mcs_rate, pht_capie->mcs.rx_mask, 2);
804 
805 			/* cur_bwmod is updated by beacon, pmlmeinfo is updated by association response */
806 			bw_40MHz = (pmlmeext->cur_bwmode && (HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH & pmlmeinfo->HT_info.infos[0])) ? 1 : 0;
807 
808 			short_GI_20 = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & IEEE80211_HT_CAP_SGI_20) ? 1 : 0;
809 			short_GI_40 = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & IEEE80211_HT_CAP_SGI_40) ? 1 : 0;
810 
811 			rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
812 			max_rate = rtw_mcs_rate(
813 				rf_type,
814 				bw_40MHz & (pregistrypriv->cbw40_enable),
815 				short_GI_20,
816 				short_GI_40,
817 				pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate
818 			);
819 		}
820 	} else {
821 		while ((pcur_bss->SupportedRates[i] != 0) && (pcur_bss->SupportedRates[i] != 0xFF)) {
822 			rate = pcur_bss->SupportedRates[i] & 0x7F;
823 			if (rate > max_rate)
824 				max_rate = rate;
825 			i++;
826 		}
827 
828 		max_rate *= 5;
829 	}
830 
831 	return max_rate;
832 }
833 
834 /*
835 * rtw_set_scan_mode -
836 * @adapter: pointer to struct adapter structure
837 * @scan_mode:
838 *
839 * Return _SUCCESS or _FAIL
840 */
rtw_set_scan_mode(struct adapter * adapter,enum rt_scan_type scan_mode)841 int rtw_set_scan_mode(struct adapter *adapter, enum rt_scan_type scan_mode)
842 {
843 	if (scan_mode != SCAN_ACTIVE && scan_mode != SCAN_PASSIVE)
844 		return _FAIL;
845 
846 	adapter->mlmepriv.scan_mode = scan_mode;
847 
848 	return _SUCCESS;
849 }
850 
851 /*
852 * rtw_set_channel_plan -
853 * @adapter: pointer to struct adapter structure
854 * @channel_plan:
855 *
856 * Return _SUCCESS or _FAIL
857 */
rtw_set_channel_plan(struct adapter * adapter,u8 channel_plan)858 int rtw_set_channel_plan(struct adapter *adapter, u8 channel_plan)
859 {
860 	/* handle by cmd_thread to sync with scan operation */
861 	return rtw_set_chplan_cmd(adapter, channel_plan, 1);
862 }
863 
864 /*
865 * rtw_set_country -
866 * @adapter: pointer to struct adapter structure
867 * @country_code: string of country code
868 *
869 * Return _SUCCESS or _FAIL
870 */
rtw_set_country(struct adapter * adapter,const char * country_code)871 int rtw_set_country(struct adapter *adapter, const char *country_code)
872 {
873 	int channel_plan = RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G;
874 
875 	DBG_88E("%s country_code:%s\n", __func__, country_code);
876 
877 	/* TODO: should have a table to match country code and RT_CHANNEL_DOMAIN */
878 	/* TODO: should consider 2-character and 3-character country code */
879 	if (0 == strcmp(country_code, "US"))
880 		channel_plan = RT_CHANNEL_DOMAIN_FCC;
881 	else if (0 == strcmp(country_code, "EU"))
882 		channel_plan = RT_CHANNEL_DOMAIN_ETSI;
883 	else if (0 == strcmp(country_code, "JP"))
884 		channel_plan = RT_CHANNEL_DOMAIN_MKK;
885 	else if (0 == strcmp(country_code, "CN"))
886 		channel_plan = RT_CHANNEL_DOMAIN_CHINA;
887 	else
888 		DBG_88E("%s unknown country_code:%s\n", __func__, country_code);
889 
890 	return rtw_set_channel_plan(adapter, channel_plan);
891 }
892