Mention branches and keyring.
[releases.git] / core / rtw_ioctl_set.c
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
11 u8 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
25 u8 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
34 exit:
35         return ret;
36 }
37
38 u8 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                 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) == true) {
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.mac_address;
96
97                                 memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
98
99                                 rtw_update_registrypriv_dev_network(padapter);
100
101                                 rtw_generate_random_ibss(pibss);
102
103                                 if (rtw_createbss_cmd(padapter) != _SUCCESS) {
104                                         ret =  false;
105                                         goto exit;
106                                 }
107
108                                 pmlmepriv->to_join = false;
109
110                         } else {
111                                 /*  can't associate ; reset under-linking */
112                                 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
113
114                                 /* when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue */
115                                 /* we try to issue sitesurvey firstly */
116                                 if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false
117                                         || rtw_to_roam(padapter) > 0
118                                 ) {
119                                         ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
120                                         if (ret != _SUCCESS)
121                                                 pmlmepriv->to_join = false;
122
123                                 } else {
124                                         ret = _FAIL;
125                                         pmlmepriv->to_join = false;
126                                 }
127                         }
128
129                 }
130
131         }
132
133 exit:
134         return ret;
135 }
136
137 u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
138 {
139         u8 status = _SUCCESS;
140
141         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
142         struct wlan_network *pnetwork = &pmlmepriv->cur_network;
143
144         netdev_dbg(padapter->pnetdev, "set ssid [%s] fw_state = 0x%08x\n",
145                    ssid->ssid, get_fwstate(pmlmepriv));
146
147         if (padapter->hw_init_completed == false) {
148                 status = _FAIL;
149                 goto exit;
150         }
151
152         spin_lock_bh(&pmlmepriv->lock);
153
154         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
155                 goto handle_tkip_countermeasure;
156         else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
157                 goto release_mlme_lock;
158
159         if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
160                 if ((pmlmepriv->assoc_ssid.ssid_length == ssid->ssid_length) &&
161                     (!memcmp(&pmlmepriv->assoc_ssid.ssid, ssid->ssid, ssid->ssid_length))) {
162                         if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false)) {
163                                 if (rtw_is_same_ibss(padapter, pnetwork) == false) {
164                                         /* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
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                                 } else {
177                                         goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
178                                 }
179                         } else {
180                                 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1);
181                         }
182                 } else {
183                         rtw_disassoc_cmd(padapter, 0, true);
184
185                         if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
186                                 rtw_indicate_disconnect(padapter);
187
188                         rtw_free_assoc_resources(padapter, 1);
189
190                         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
191                                 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
192                                 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
193                         }
194                 }
195         }
196
197 handle_tkip_countermeasure:
198         if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
199                 status = _FAIL;
200                 goto release_mlme_lock;
201         }
202
203         if (rtw_validate_ssid(ssid) == false) {
204                 status = _FAIL;
205                 goto release_mlme_lock;
206         }
207
208         memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
209         pmlmepriv->assoc_by_bssid = false;
210
211         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
212                 pmlmepriv->to_join = true;
213         else
214                 status = rtw_do_join(padapter);
215
216 release_mlme_lock:
217         spin_unlock_bh(&pmlmepriv->lock);
218
219 exit:
220
221         return status;
222 }
223
224 u8 rtw_set_802_11_connect(struct adapter *padapter, u8 *bssid, struct ndis_802_11_ssid *ssid)
225 {
226         u8 status = _SUCCESS;
227         bool bssid_valid = true;
228         bool ssid_valid = true;
229         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
230
231         if (!ssid || rtw_validate_ssid(ssid) == false)
232                 ssid_valid = false;
233
234         if (!bssid || rtw_validate_bssid(bssid) == false)
235                 bssid_valid = false;
236
237         if (!ssid_valid && !bssid_valid) {
238                 status = _FAIL;
239                 goto exit;
240         }
241
242         if (padapter->hw_init_completed == false) {
243                 status = _FAIL;
244                 goto exit;
245         }
246
247         spin_lock_bh(&pmlmepriv->lock);
248
249         netdev_dbg(padapter->pnetdev, FUNC_ADPT_FMT "  fw_state = 0x%08x\n",
250                    FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv));
251
252         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
253                 goto handle_tkip_countermeasure;
254         else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
255                 goto release_mlme_lock;
256
257 handle_tkip_countermeasure:
258         if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
259                 status = _FAIL;
260                 goto release_mlme_lock;
261         }
262
263         if (ssid && ssid_valid)
264                 memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
265         else
266                 memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
267
268         if (bssid && bssid_valid) {
269                 memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
270                 pmlmepriv->assoc_by_bssid = true;
271         } else {
272                 pmlmepriv->assoc_by_bssid = false;
273         }
274
275         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
276                 pmlmepriv->to_join = true;
277         else
278                 status = rtw_do_join(padapter);
279
280 release_mlme_lock:
281         spin_unlock_bh(&pmlmepriv->lock);
282
283 exit:
284         return status;
285 }
286
287 u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter,
288         enum ndis_802_11_network_infrastructure networktype)
289 {
290         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
291         struct  wlan_network    *cur_network = &pmlmepriv->cur_network;
292         enum ndis_802_11_network_infrastructure *pold_state = &(cur_network->network.infrastructure_mode);
293
294         if (*pold_state != networktype) {
295                 if (*pold_state == Ndis802_11APMode) {
296                         /* change to other mode from Ndis802_11APMode */
297                         cur_network->join_res = -1;
298
299                         stop_ap_mode(padapter);
300                 }
301
302                 spin_lock_bh(&pmlmepriv->lock);
303
304                 if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) || (*pold_state == Ndis802_11IBSS))
305                         rtw_disassoc_cmd(padapter, 0, true);
306
307                 if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||
308                         (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true))
309                         rtw_free_assoc_resources(padapter, 1);
310
311                 if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) {
312                         if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
313                                 rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have checked whether issue dis-assoc_cmd or not */
314                }
315
316                 *pold_state = networktype;
317
318                 _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
319
320                 switch (networktype) {
321                 case Ndis802_11IBSS:
322                         set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
323                         break;
324
325                 case Ndis802_11Infrastructure:
326                         set_fwstate(pmlmepriv, WIFI_STATION_STATE);
327                         break;
328
329                 case Ndis802_11APMode:
330                         set_fwstate(pmlmepriv, WIFI_AP_STATE);
331                         start_ap_mode(padapter);
332                         /* rtw_indicate_connect(padapter); */
333
334                         break;
335
336                 case Ndis802_11AutoUnknown:
337                 case Ndis802_11InfrastructureMax:
338                         break;
339                 }
340
341                 /* SecClearAllKeys(adapter); */
342
343                 spin_unlock_bh(&pmlmepriv->lock);
344         }
345         return true;
346 }
347
348
349 u8 rtw_set_802_11_disassociate(struct adapter *padapter)
350 {
351         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
352
353         spin_lock_bh(&pmlmepriv->lock);
354
355         if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
356                 rtw_disassoc_cmd(padapter, 0, true);
357                 rtw_indicate_disconnect(padapter);
358                 /* modify for CONFIG_IEEE80211W, none 11w can use it */
359                 rtw_free_assoc_resources_cmd(padapter);
360                 rtw_pwr_wakeup(padapter);
361         }
362
363         spin_unlock_bh(&pmlmepriv->lock);
364
365         return true;
366 }
367
368 u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_ssid *pssid, int ssid_max_num)
369 {
370         struct  mlme_priv       *pmlmepriv = &padapter->mlmepriv;
371         u8 res = true;
372
373         if (!padapter) {
374                 res = false;
375                 goto exit;
376         }
377         if (padapter->hw_init_completed == false) {
378                 res = false;
379                 goto exit;
380         }
381
382         if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) ||
383                 (pmlmepriv->LinkDetectInfo.bBusyTraffic == true)) {
384                 /*  Scan or linking is in progress, do nothing. */
385                 res = true;
386
387         } else {
388                 if (rtw_is_scan_deny(padapter))
389                         return _SUCCESS;
390
391                 spin_lock_bh(&pmlmepriv->lock);
392
393                 res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num, NULL, 0);
394
395                 spin_unlock_bh(&pmlmepriv->lock);
396         }
397 exit:
398
399         return res;
400 }
401
402 u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum ndis_802_11_authentication_mode authmode)
403 {
404         struct security_priv *psecuritypriv = &padapter->securitypriv;
405         int res;
406         u8 ret;
407
408         psecuritypriv->ndisauthtype = authmode;
409
410         if (psecuritypriv->ndisauthtype > 3)
411                 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
412
413         res = rtw_set_auth(padapter, psecuritypriv);
414
415         if (res == _SUCCESS)
416                 ret = true;
417         else
418                 ret = false;
419
420         return ret;
421 }
422
423 u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep)
424 {
425
426         signed int              keyid, res;
427         struct security_priv *psecuritypriv = &(padapter->securitypriv);
428         u8 ret = _SUCCESS;
429
430         keyid = wep->key_index & 0x3fffffff;
431
432         if (keyid >= 4) {
433                 ret = false;
434                 goto exit;
435         }
436
437         switch (wep->key_length) {
438         case 5:
439                 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
440                 break;
441         case 13:
442                 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
443                 break;
444         default:
445                 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
446                 break;
447         }
448
449         memcpy(&(psecuritypriv->dot11DefKey[keyid].skey[0]), &(wep->key_material), wep->key_length);
450
451         psecuritypriv->dot11DefKeylen[keyid] = wep->key_length;
452
453         psecuritypriv->dot11PrivacyKeyIndex = keyid;
454
455         res = rtw_set_key(padapter, psecuritypriv, keyid, 1, true);
456
457         if (res == _FAIL)
458                 ret = false;
459 exit:
460
461         return ret;
462 }
463
464 /*
465 * rtw_get_cur_max_rate -
466 * @adapter: pointer to struct adapter structure
467 *
468 * Return 0 or 100Kbps
469 */
470 u16 rtw_get_cur_max_rate(struct adapter *adapter)
471 {
472         int     i = 0;
473         u16 rate = 0, max_rate = 0;
474         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
475         struct wlan_bssid_ex    *pcur_bss = &pmlmepriv->cur_network.network;
476         struct sta_info *psta = NULL;
477         u8 short_GI = 0;
478
479         if ((check_fwstate(pmlmepriv, _FW_LINKED) != true)
480                 && (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != true))
481                 return 0;
482
483         psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(pmlmepriv));
484         if (!psta)
485                 return 0;
486
487         short_GI = query_ra_short_GI(psta);
488
489         if (is_supported_ht(psta->wireless_mode)) {
490                 max_rate = rtw_mcs_rate(psta->bw_mode == CHANNEL_WIDTH_40 ? 1 : 0,
491                                         short_GI,
492                                         psta->htpriv.ht_cap.mcs.rx_mask);
493         } else {
494                 while ((pcur_bss->supported_rates[i] != 0) && (pcur_bss->supported_rates[i] != 0xFF)) {
495                         rate = pcur_bss->supported_rates[i]&0x7F;
496                         if (rate > max_rate)
497                                 max_rate = rate;
498                         i++;
499                 }
500
501                 max_rate = max_rate*10/2;
502         }
503
504         return max_rate;
505 }