1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2017 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15
16 #include <drv_types.h>
17
18 #ifdef CONFIG_RTW_80211R
19
20 #ifndef RTW_FT_DBG
21 #define RTW_FT_DBG 0
22 #endif
23 #if RTW_FT_DBG
24 #define RTW_FT_INFO(fmt, arg...) \
25 RTW_INFO(fmt, arg)
26 #define RTW_FT_DUMP(str, data, len) \
27 RTW_INFO_DUMP(str, data, len)
28 #else
29 #define RTW_FT_INFO(fmt, arg...) do {} while (0)
30 #define RTW_FT_DUMP(str, data, len) do {} while (0)
31 #endif
32
rtw_ft_info_init(struct ft_roam_info * pft)33 void rtw_ft_info_init(struct ft_roam_info *pft)
34 {
35 _rtw_memset(pft, 0, sizeof(struct ft_roam_info));
36 pft->ft_flags = 0
37 | RTW_FT_EN
38 | RTW_FT_OTD_EN
39 #ifdef CONFIG_RTW_BTM_ROAM
40 | RTW_FT_BTM_ROAM
41 #endif
42 ;
43 pft->ft_updated_bcn = _FALSE;
44 RTW_FT_INFO("%s : ft_flags=0x%02x\n", __func__, pft->ft_flags);
45 }
46
rtw_ft_proc_flags_set(struct file * file,const char __user * buffer,size_t count,loff_t * pos,void * data)47 ssize_t rtw_ft_proc_flags_set(struct file *file,
48 const char __user *buffer, size_t count, loff_t *pos, void *data)
49 {
50 struct net_device *dev = data;
51 _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
52
53 char tmp[32];
54 u8 flags;
55
56 if (count < 1)
57 return -EFAULT;
58
59 if (count > sizeof(tmp)) {
60 rtw_warn_on(1);
61 return -EFAULT;
62 }
63
64 if (buffer && !copy_from_user(tmp, buffer, count)) {
65 int num = sscanf(tmp, "%hhx", &flags);
66 if (num == 1)
67 adapter->mlmepriv.ft_roam.ft_flags = flags;
68 }
69
70 return count;
71
72 }
73
rtw_ft_proc_flags_get(struct seq_file * m,void * v)74 int rtw_ft_proc_flags_get(struct seq_file *m, void *v)
75 {
76 struct net_device *dev = m->private;
77 _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
78
79 RTW_PRINT_SEL(m, "0x%02x\n", adapter->mlmepriv.ft_roam.ft_flags);
80
81 return 0;
82 }
83
rtw_ft_chk_roaming_candidate(_adapter * padapter,struct wlan_network * competitor)84 u8 rtw_ft_chk_roaming_candidate(
85 _adapter *padapter, struct wlan_network *competitor)
86 {
87 u8 *pmdie;
88 u32 mdie_len = 0;
89 struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
90
91 if (!(pmdie = rtw_get_ie(&competitor->network.IEs[12], _MDIE_,
92 &mdie_len, competitor->network.IELength-12))) {
93 RTW_INFO("FT : MDIE not foud in competitor!\n");
94 return _FALSE;
95 }
96
97 if (!_rtw_memcmp(&pft_roam->mdid, (pmdie+2), 2)) {
98 RTW_INFO("FT : unmatched MDIE!\n");
99 return _FALSE;
100 }
101
102 /*The candidate don't support over-the-DS*/
103 if (rtw_ft_valid_otd_candidate(padapter, pmdie)) {
104 RTW_INFO("FT: ignore the candidate("
105 MAC_FMT ") for over-the-DS\n",
106 MAC_ARG(competitor->network.MacAddress));
107 /* rtw_ft_clr_flags(padapter, RTW_FT_PEER_OTD_EN); */
108 return _FALSE;
109 }
110
111 if (rtw_ft_chk_flags(padapter, RTW_FT_TEST_RSSI_ROAM)) {
112 if (!_rtw_memcmp(
113 padapter->mlmepriv.cur_network.network.MacAddress,
114 competitor->network.MacAddress, ETH_ALEN)) {
115 competitor->network.PhyInfo.rssi +=20;
116 RTW_FT_INFO("%s : update "MAC_FMT
117 " RSSI to %d for RTW_FT_TEST_RSSI_ROAM\n",
118 __func__, MAC_ARG(competitor->network.MacAddress),
119 (int)competitor->network.PhyInfo.rssi);
120 rtw_ft_clr_flags(padapter, RTW_FT_TEST_RSSI_ROAM);
121 }
122 }
123
124 return _TRUE;
125 }
126
rtw_ft_update_stainfo(_adapter * padapter,WLAN_BSSID_EX * pnetwork)127 void rtw_ft_update_stainfo(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
128 {
129 struct sta_priv *pstapriv = &padapter->stapriv;
130 struct sta_info *psta = NULL;
131
132 psta = rtw_get_stainfo(pstapriv, pnetwork->MacAddress);
133 if (psta == NULL)
134 psta = rtw_alloc_stainfo(pstapriv, pnetwork->MacAddress);
135
136 if (padapter->securitypriv.dot11AuthAlgrthm ==
137 dot11AuthAlgrthm_8021X) {
138 padapter->securitypriv.binstallGrpkey = _FALSE;
139 padapter->securitypriv.busetkipkey = _FALSE;
140 padapter->securitypriv.bgrpkey_handshake = _FALSE;
141
142 psta->ieee8021x_blocked = _TRUE;
143 psta->dot118021XPrivacy = \
144 padapter->securitypriv.dot11PrivacyAlgrthm;
145 _rtw_memset((u8 *)&psta->dot118021x_UncstKey,
146 0, sizeof(union Keytype));
147 _rtw_memset((u8 *)&psta->dot11tkiprxmickey,
148 0, sizeof(union Keytype));
149 _rtw_memset((u8 *)&psta->dot11tkiptxmickey,
150 0, sizeof(union Keytype));
151 }
152
153 }
154
rtw_ft_reassoc_event_callback(_adapter * padapter,u8 * pbuf)155 void rtw_ft_reassoc_event_callback(_adapter *padapter, u8 *pbuf)
156 {
157 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
158 struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf;
159 struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
160 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
161 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
162 WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&(pmlmeinfo->network);
163 struct cfg80211_ft_event_params ft_evt_parms;
164
165 _rtw_memset(&ft_evt_parms, 0, sizeof(ft_evt_parms));
166 rtw_ft_update_stainfo(padapter, pnetwork);
167 ft_evt_parms.ies_len = pft_roam->ft_event.ies_len;
168 ft_evt_parms.ies = rtw_zmalloc(ft_evt_parms.ies_len);
169 if (ft_evt_parms.ies) {
170 _rtw_memcpy((void *)ft_evt_parms.ies,
171 pft_roam->ft_event.ies, ft_evt_parms.ies_len);
172 } else
173 goto err_2;
174
175 ft_evt_parms.target_ap = rtw_zmalloc(ETH_ALEN);
176 if (ft_evt_parms.target_ap) {
177 _rtw_memcpy((void *)ft_evt_parms.target_ap,
178 pstassoc->macaddr, ETH_ALEN);
179 } else
180 goto err_1;
181
182 ft_evt_parms.ric_ies = pft_roam->ft_event.ric_ies;
183 ft_evt_parms.ric_ies_len = pft_roam->ft_event.ric_ies_len;
184
185 /* It's a KERNEL issue between v4.11 ~ v4.16,
186 * <= v4.10, NLMSG_DEFAULT_SIZE is used for nlmsg_new().
187 * v4.11 ~ v4.16, only used "100 + >ric_ies_len" for nlmsg_new()
188 * even then DRIVER don't support RIC.
189 * >= v4.17, issue should correct as "100 + ies_len + ric_ies_len".
190 */
191 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) && \
192 (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)))
193 if (!ft_evt_parms.ric_ies_len)
194 ft_evt_parms.ric_ies_len = ft_evt_parms.ies_len;
195 else
196 ft_evt_parms.ric_ies_len += ft_evt_parms.ies_len;
197 #endif
198
199 rtw_ft_lock_set_status(padapter, RTW_FT_AUTHENTICATED_STA);
200 rtw_cfg80211_ft_event(padapter, &ft_evt_parms);
201 RTW_INFO("%s: to "MAC_FMT"\n", __func__,
202 MAC_ARG(ft_evt_parms.target_ap));
203
204 rtw_mfree((u8 *)pft_roam->ft_event.target_ap, ETH_ALEN);
205 err_1:
206 rtw_mfree((u8 *)ft_evt_parms.ies, ft_evt_parms.ies_len);
207 err_2:
208 return;
209 }
210
rtw_ft_validate_akm_type(_adapter * padapter,struct wlan_network * pnetwork)211 void rtw_ft_validate_akm_type(_adapter *padapter,
212 struct wlan_network *pnetwork)
213 {
214 struct security_priv *psecuritypriv = &(padapter->securitypriv);
215 struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
216 u32 tmp_len;
217 u8 *ptmp;
218
219 /*IEEE802.11-2012 Std. Table 8-101-AKM suite selectors*/
220 if (rtw_ft_valid_akm(padapter, psecuritypriv->rsn_akm_suite_type)) {
221 ptmp = rtw_get_ie(&pnetwork->network.IEs[12],
222 _MDIE_, &tmp_len,
223 (pnetwork->network.IELength-12));
224 if (ptmp) {
225 pft_roam->mdid = *(u16 *)(ptmp+2);
226 pft_roam->ft_cap = *(ptmp+4);
227
228 RTW_INFO("FT: target "MAC_FMT
229 " mdid=(0x%2x), capacity=(0x%2x)\n",
230 MAC_ARG(pnetwork->network.MacAddress),
231 pft_roam->mdid, pft_roam->ft_cap);
232
233 rtw_ft_set_flags(padapter, RTW_FT_PEER_EN);
234
235 RTW_FT_INFO("%s : peer support FTOTA(0x%02x),"
236 " ft_roam_on_expired=0x%02x\n",
237 __func__, pft_roam->ft_flags,
238 pft_roam->ft_roam_on_expired);
239
240 if (rtw_ft_otd_roam_en(padapter)) {
241 rtw_ft_set_flags(padapter, RTW_FT_PEER_OTD_EN);
242 RTW_FT_INFO("%s : peer support FTOTD(0x%02x)\n",
243 __func__, pft_roam->ft_flags);
244 } else {
245 pft_roam->ft_cap &= ~BIT(0);
246 rtw_ft_clr_flags(padapter, RTW_FT_PEER_OTD_EN);
247 RTW_FT_INFO("%s : update mdid=0x%02x, "
248 "cap=0x%02x, flag=0x%02x\n",
249 __func__, pft_roam->mdid,
250 pft_roam->ft_cap,
251 pft_roam->ft_flags);
252 }
253 } else {
254 /* Don't use FT roaming if target AP cannot support FT */
255 rtw_ft_clr_flags(padapter,
256 (RTW_FT_PEER_EN|RTW_FT_PEER_OTD_EN));
257 rtw_ft_reset_status(padapter);
258 }
259 } else {
260 /* It could be a non-FT connection */
261 rtw_ft_clr_flags(padapter,
262 (RTW_FT_PEER_EN|RTW_FT_PEER_OTD_EN));
263 rtw_ft_reset_status(padapter);
264 }
265
266 RTW_FT_INFO("%s : ft_flags=0x%02x\n", __func__, pft_roam->ft_flags);
267 }
268
rtw_ft_update_bcn(_adapter * padapter,union recv_frame * precv_frame)269 void rtw_ft_update_bcn(_adapter *padapter, union recv_frame *precv_frame)
270 {
271 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
272 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
273 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
274 u8 *pframe = precv_frame->u.hdr.rx_data;
275 uint len = precv_frame->u.hdr.len;
276 WLAN_BSSID_EX *pbss;
277
278 if (rtw_ft_chk_status(padapter,RTW_FT_ASSOCIATED_STA)
279 && (pmlmepriv->ft_roam.ft_updated_bcn == _FALSE)) {
280 pbss = (WLAN_BSSID_EX*)rtw_malloc(sizeof(WLAN_BSSID_EX));
281 if (pbss) {
282 if (collect_bss_info(
283 padapter, precv_frame, pbss) == _SUCCESS) {
284 struct beacon_keys recv_beacon;
285
286 rtw_update_network(
287 &(pmlmepriv->cur_network.network),
288 pbss, padapter, _TRUE);
289
290 /* Move into rtw_get_bcn_keys */
291 /* rtw_get_bcn_info(&(pmlmepriv->cur_network)); */
292
293 /* update bcn keys */
294 if (rtw_get_bcn_keys(padapter, pframe, len,
295 &recv_beacon) == _TRUE) {
296
297 RTW_FT_INFO("%s: beacon keys ready\n",
298 __func__);
299
300 _rtw_memcpy(
301 &pmlmepriv->cur_beacon_keys,
302 &recv_beacon,
303 sizeof(recv_beacon));
304
305 if (is_hidden_ssid(
306 recv_beacon.ssid,
307 recv_beacon.ssid_len)) {
308
309 _rtw_memcpy(
310 pmlmepriv->cur_beacon_keys.ssid,
311 pmlmeinfo->network.Ssid.Ssid,
312 IW_ESSID_MAX_SIZE);
313
314 pmlmepriv->cur_beacon_keys.ssid_len = \
315 pmlmeinfo->network.Ssid.SsidLength;
316 }
317 } else {
318 RTW_ERR("%s: get beacon keys failed\n",
319 __func__);
320 _rtw_memset(
321 &pmlmepriv->cur_beacon_keys,
322 0, sizeof(recv_beacon));
323 }
324 #ifdef CONFIG_BCN_CNT_CONFIRM_HDL
325 pmlmepriv->new_beacon_cnts = 0;
326 #endif
327 }
328 rtw_mfree((u8*)pbss, sizeof(WLAN_BSSID_EX));
329 }
330
331 /* check the vendor of the assoc AP */
332 pmlmeinfo->assoc_AP_vendor =
333 check_assoc_AP(
334 pframe + sizeof(struct rtw_ieee80211_hdr_3addr),
335 (len - sizeof(struct rtw_ieee80211_hdr_3addr))
336 );
337
338 /* update TSF Value */
339 update_TSF(pmlmeext, pframe, len);
340 pmlmeext->bcn_cnt = 0;
341 pmlmeext->last_bcn_cnt = 0;
342 pmlmepriv->ft_roam.ft_updated_bcn = _TRUE;
343 }
344 }
345
rtw_ft_start_clnt_join(_adapter * padapter)346 void rtw_ft_start_clnt_join(_adapter *padapter)
347 {
348 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
349 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
350 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
351 struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
352
353 if (rtw_ft_otd_roam(padapter)) {
354 pmlmeinfo->state = WIFI_FW_AUTH_SUCCESS | WIFI_FW_STATION_STATE;
355 pft_roam->ft_event.ies =
356 (pft_roam->ft_action + \
357 sizeof(struct rtw_ieee80211_hdr_3addr) + 16);
358 pft_roam->ft_event.ies_len =
359 (pft_roam->ft_action_len - \
360 sizeof(struct rtw_ieee80211_hdr_3addr));
361
362 /*Not support RIC*/
363 pft_roam->ft_event.ric_ies = NULL;
364 pft_roam->ft_event.ric_ies_len = 0;
365 rtw_ft_report_evt(padapter);
366 return;
367 }
368
369 pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
370 start_clnt_auth(padapter);
371 }
372
rtw_ft_update_rsnie(_adapter * padapter,u8 bwrite,struct pkt_attrib * pattrib,u8 ** pframe)373 u8 rtw_ft_update_rsnie(
374 _adapter *padapter, u8 bwrite,
375 struct pkt_attrib *pattrib, u8 **pframe)
376 {
377 struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
378 u8 *pie;
379 u32 len;
380
381 pie = rtw_get_ie(pft_roam->updated_ft_ies, EID_WPA2, &len,
382 pft_roam->updated_ft_ies_len);
383
384 if (!bwrite)
385 return (pie)?_SUCCESS:_FAIL;
386
387 if (pie) {
388 *pframe = rtw_set_ie(((u8 *)*pframe), EID_WPA2, len,
389 pie+2, &(pattrib->pktlen));
390 } else
391 return _FAIL;
392
393 return _SUCCESS;
394 }
395
rtw_ft_update_mdie(_adapter * padapter,struct pkt_attrib * pattrib,u8 ** pframe)396 static u8 rtw_ft_update_mdie(
397 _adapter *padapter, struct pkt_attrib *pattrib, u8 **pframe)
398 {
399 struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
400 u8 *pie, mdie[3];
401 u32 len = 3;
402
403 if (rtw_ft_roam(padapter)) {
404 if ((pie = rtw_get_ie(pft_roam->updated_ft_ies, _MDIE_,
405 &len, pft_roam->updated_ft_ies_len))) {
406 pie = (pie + 2); /* ignore md-id & length */
407 } else
408 return _FAIL;
409 } else {
410 *((u16 *)&mdie[0]) = pft_roam->mdid;
411 mdie[2] = pft_roam->ft_cap;
412 pie = &mdie[0];
413 }
414
415 *pframe = rtw_set_ie(((u8 *)*pframe), _MDIE_,
416 len, pie, &(pattrib->pktlen));
417 return _SUCCESS;
418 }
419
rtw_ft_update_ftie(_adapter * padapter,struct pkt_attrib * pattrib,u8 ** pframe)420 static u8 rtw_ft_update_ftie(
421 _adapter *padapter, struct pkt_attrib *pattrib, u8 **pframe)
422 {
423 struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
424 u8 *pie;
425 u32 len;
426
427 if ((pie = rtw_get_ie(pft_roam->updated_ft_ies, _FTIE_, &len,
428 pft_roam->updated_ft_ies_len)) != NULL) {
429 *pframe = rtw_set_ie(*pframe, _FTIE_, len,
430 (pie+2), &(pattrib->pktlen));
431 } else
432 return _FAIL;
433
434 return _SUCCESS;
435 }
436
rtw_ft_build_auth_req_ies(_adapter * padapter,struct pkt_attrib * pattrib,u8 ** pframe)437 void rtw_ft_build_auth_req_ies(_adapter *padapter,
438 struct pkt_attrib *pattrib, u8 **pframe)
439 {
440 u8 ftie_append = _TRUE;
441
442 if (!pattrib || !(*pframe))
443 return;
444
445 if (!rtw_ft_roam(padapter))
446 return;
447
448 ftie_append = rtw_ft_update_rsnie(padapter, _TRUE, pattrib, pframe);
449 rtw_ft_update_mdie(padapter, pattrib, pframe);
450 if (ftie_append)
451 rtw_ft_update_ftie(padapter, pattrib, pframe);
452 }
453
rtw_ft_build_assoc_req_ies(_adapter * padapter,u8 is_reassoc,struct pkt_attrib * pattrib,u8 ** pframe)454 void rtw_ft_build_assoc_req_ies(_adapter *padapter,
455 u8 is_reassoc, struct pkt_attrib *pattrib, u8 **pframe)
456 {
457 if (!pattrib || !(*pframe))
458 return;
459
460 if (rtw_ft_chk_flags(padapter, RTW_FT_PEER_EN))
461 rtw_ft_update_mdie(padapter, pattrib, pframe);
462
463 if ((!is_reassoc) || (!rtw_ft_roam(padapter)))
464 return;
465
466 if (rtw_ft_update_rsnie(padapter, _FALSE, pattrib, pframe))
467 rtw_ft_update_ftie(padapter, pattrib, pframe);
468 }
469
rtw_ft_update_auth_rsp_ies(_adapter * padapter,u8 * pframe,u32 len)470 u8 rtw_ft_update_auth_rsp_ies(_adapter *padapter, u8 *pframe, u32 len)
471 {
472 u8 ret = _SUCCESS;
473 u8 target_ap_addr[ETH_ALEN] = {0};
474 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
475 struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
476
477 if (!rtw_ft_roam(padapter))
478 return _FAIL;
479
480 /*rtw_ft_report_reassoc_evt already,
481 * and waiting for cfg80211_rtw_update_ft_ies */
482 if (rtw_ft_authed_sta(padapter))
483 return ret;
484
485 if (!pframe || !len)
486 return _FAIL;
487
488 rtw_buf_update(&pmlmepriv->auth_rsp,
489 &pmlmepriv->auth_rsp_len, pframe, len);
490 pft_roam->ft_event.ies =
491 (pmlmepriv->auth_rsp + \
492 sizeof(struct rtw_ieee80211_hdr_3addr) + 6);
493 pft_roam->ft_event.ies_len =
494 (pmlmepriv->auth_rsp_len - \
495 sizeof(struct rtw_ieee80211_hdr_3addr) - 6);
496
497 /*Not support RIC*/
498 pft_roam->ft_event.ric_ies = NULL;
499 pft_roam->ft_event.ric_ies_len = 0;
500 _rtw_memcpy(target_ap_addr, pmlmepriv->assoc_bssid, ETH_ALEN);
501 rtw_ft_report_reassoc_evt(padapter, target_ap_addr);
502
503 return ret;
504 }
505
rtw_ft_start_clnt_action(_adapter * padapter,u8 * pTargetAddr)506 static void rtw_ft_start_clnt_action(_adapter *padapter, u8 *pTargetAddr)
507 {
508 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
509
510 rtw_ft_set_status(padapter, RTW_FT_REQUESTING_STA);
511 rtw_ft_issue_action_req(padapter, pTargetAddr);
512 _set_timer(&pmlmeext->ft_link_timer, REASSOC_TO);
513 }
514
rtw_ft_start_roam(_adapter * padapter,u8 * pTargetAddr)515 void rtw_ft_start_roam(_adapter *padapter, u8 *pTargetAddr)
516 {
517 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
518
519 if (rtw_ft_otd_roam(padapter)) {
520 RTW_FT_INFO("%s : try OTD roaming\n", __func__);
521 rtw_ft_start_clnt_action(padapter, pTargetAddr);
522 } else {
523 /* wait a little time to retrieve packets buffered
524 in the current ap while scan*/
525 RTW_FT_INFO("%s : start roaming timer\n", __func__);
526 _set_timer(&pmlmeext->ft_roam_timer, 30);
527 }
528 }
529
rtw_ft_issue_action_req(_adapter * padapter,u8 * pTargetAddr)530 void rtw_ft_issue_action_req(_adapter *padapter, u8 *pTargetAddr)
531 {
532 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
533 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
534 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
535 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
536 struct xmit_frame *pmgntframe;
537 struct rtw_ieee80211_hdr *pwlanhdr;
538 struct pkt_attrib *pattrib;
539 u8 *pframe;
540 u8 category = RTW_WLAN_CATEGORY_FT;
541 u8 action = RTW_WLAN_ACTION_FT_REQ;
542
543 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
544 if (pmgntframe == NULL)
545 return;
546
547 pattrib = &pmgntframe->attrib;
548 update_mgntframe_attrib(padapter, pattrib);
549 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
550
551 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
552 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
553 pwlanhdr->frame_ctl = 0;
554
555 _rtw_memcpy(pwlanhdr->addr1,
556 get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
557 _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
558 _rtw_memcpy(pwlanhdr->addr3,
559 get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
560
561 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
562 pmlmeext->mgnt_seq++;
563 set_frame_sub_type(pframe, WIFI_ACTION);
564
565 pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
566 pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
567
568 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
569 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
570
571 _rtw_memcpy(pframe, adapter_mac_addr(padapter), ETH_ALEN);
572 pframe += ETH_ALEN;
573 pattrib->pktlen += ETH_ALEN;
574
575 _rtw_memcpy(pframe, pTargetAddr, ETH_ALEN);
576 pframe += ETH_ALEN;
577 pattrib->pktlen += ETH_ALEN;
578
579 rtw_ft_update_mdie(padapter, pattrib, &pframe);
580 if (rtw_ft_update_rsnie(padapter, _TRUE, pattrib, &pframe))
581 rtw_ft_update_ftie(padapter, pattrib, &pframe);
582
583 RTW_INFO("FT : issue RTW_WLAN_ACTION_FT_REQ\n");
584 pattrib->last_txcmdsz = pattrib->pktlen;
585 dump_mgntframe(padapter, pmgntframe);
586 }
587
rtw_ft_report_evt(_adapter * padapter)588 void rtw_ft_report_evt(_adapter *padapter)
589 {
590 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
591 struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
592 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
593 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
594 WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&(pmlmeinfo->network);
595 struct cfg80211_ft_event_params ft_evt_parms;
596
597 _rtw_memset(&ft_evt_parms, 0, sizeof(ft_evt_parms));
598 rtw_ft_update_stainfo(padapter, pnetwork);
599
600 if (!pnetwork)
601 goto err_2;
602
603 ft_evt_parms.ies_len = pft_roam->ft_event.ies_len;
604 ft_evt_parms.ies = rtw_zmalloc(ft_evt_parms.ies_len);
605 if (ft_evt_parms.ies) {
606 _rtw_memcpy((void *)ft_evt_parms.ies,
607 pft_roam->ft_event.ies, ft_evt_parms.ies_len);
608 } else
609 goto err_2;
610
611 ft_evt_parms.target_ap = rtw_zmalloc(ETH_ALEN);
612 if (ft_evt_parms.target_ap) {
613 _rtw_memcpy((void *)ft_evt_parms.target_ap,
614 pnetwork->MacAddress, ETH_ALEN);
615 } else
616 goto err_1;
617
618 ft_evt_parms.ric_ies = pft_roam->ft_event.ric_ies;
619 ft_evt_parms.ric_ies_len = pft_roam->ft_event.ric_ies_len;
620
621 /* It's a KERNEL issue between v4.11 ~ v4.16,
622 * <= v4.10, NLMSG_DEFAULT_SIZE is used for nlmsg_new().
623 * v4.11 ~ v4.16, only used "100 + >ric_ies_len" for nlmsg_new()
624 * even then DRIVER don't support RIC.
625 * >= v4.17, issue should correct as "100 + ies_len + ric_ies_len".
626 */
627 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) && \
628 (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)))
629 ft_evt_parms.ric_ies_len = (ft_evt_parms.ies_len <= 100 )?
630 (0):(ft_evt_parms.ies_len - 100);
631 #endif
632
633 rtw_ft_lock_set_status(padapter, RTW_FT_AUTHENTICATED_STA);
634 rtw_cfg80211_ft_event(padapter, &ft_evt_parms);
635 RTW_INFO("FT: rtw_ft_report_evt\n");
636 rtw_mfree((u8 *)pft_roam->ft_event.target_ap, ETH_ALEN);
637 err_1:
638 rtw_mfree((u8 *)ft_evt_parms.ies, ft_evt_parms.ies_len);
639 err_2:
640 return;
641 }
642
rtw_ft_report_reassoc_evt(_adapter * padapter,u8 * pMacAddr)643 void rtw_ft_report_reassoc_evt(_adapter *padapter, u8 *pMacAddr)
644 {
645 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
646 struct cmd_priv *pcmdpriv = &(adapter_to_dvobj(padapter)->cmdpriv);
647 struct cmd_obj *pcmd_obj = NULL;
648 struct stassoc_event *passoc_sta_evt = NULL;
649 struct rtw_evt_header *evt_hdr = NULL;
650 u8 *pevtcmd = NULL;
651 u32 cmdsz = 0;
652
653 pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
654 if (pcmd_obj == NULL)
655 return;
656
657 cmdsz = (sizeof(struct stassoc_event) + sizeof(struct rtw_evt_header));
658 pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
659 if (pevtcmd == NULL) {
660 rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
661 return;
662 }
663
664 _rtw_init_listhead(&pcmd_obj->list);
665 pcmd_obj->padapter = padapter;
666 pcmd_obj->cmdcode = CMD_SET_MLME_EVT;
667 pcmd_obj->cmdsz = cmdsz;
668 pcmd_obj->parmbuf = pevtcmd;
669 pcmd_obj->rsp = NULL;
670 pcmd_obj->rspsz = 0;
671
672 evt_hdr = (struct rtw_evt_header *)(pevtcmd);
673 evt_hdr->len = sizeof(struct stassoc_event);
674 evt_hdr->id = EVT_FT_REASSOC;
675 evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
676
677 passoc_sta_evt = \
678 (struct stassoc_event *)(pevtcmd + \
679 sizeof(struct rtw_evt_header));
680 _rtw_memcpy((unsigned char *)(&(passoc_sta_evt->macaddr)),
681 pMacAddr, ETH_ALEN);
682 rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
683 }
684
rtw_ft_link_timer_hdl(void * ctx)685 void rtw_ft_link_timer_hdl(void *ctx)
686 {
687 _adapter *padapter = (_adapter *)ctx;
688 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
689 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
690 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
691 struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
692
693 if (rtw_ft_chk_status(padapter, RTW_FT_REQUESTING_STA)) {
694 if (pft_roam->ft_req_retry_cnt < RTW_FT_ACTION_REQ_LMT) {
695 pft_roam->ft_req_retry_cnt++;
696 rtw_ft_issue_action_req(padapter,
697 (u8 *)pmlmepriv->roam_network->network.MacAddress);
698 _set_timer(&pmlmeext->ft_link_timer, REASSOC_TO);
699 } else {
700 pft_roam->ft_req_retry_cnt = 0;
701 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
702 rtw_ft_set_status(padapter,
703 RTW_FT_ASSOCIATED_STA);
704 } else
705 rtw_ft_reset_status(padapter);
706 }
707 }
708 }
709
rtw_ft_roam_timer_hdl(void * ctx)710 void rtw_ft_roam_timer_hdl(void *ctx)
711 {
712 _adapter *padapter = (_adapter *)ctx;
713 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
714 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
715 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
716
717 RTW_FT_INFO("%s : try roaming\n", __func__);
718 receive_disconnect(padapter,
719 pmlmepriv->cur_network.network.MacAddress,
720 WLAN_REASON_ACTIVE_ROAM, _FALSE);
721 pmlmeinfo->disconnect_occurred_time = rtw_systime_to_ms(rtw_get_current_time());
722 pmlmeinfo->disconnect_code = DISCONNECTION_BY_DRIVER_DUE_TO_FT;
723 pmlmeinfo->wifi_reason_code = WLAN_REASON_UNSPECIFIED;
724 }
725
rtw_ft_roam_status_reset(_adapter * padapter)726 void rtw_ft_roam_status_reset(_adapter *padapter)
727 {
728 struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
729
730 if ((rtw_to_roam(padapter) > 0) &&
731 (!rtw_ft_chk_status(padapter, RTW_FT_REQUESTED_STA))) {
732 rtw_ft_reset_status(padapter);
733 }
734
735 padapter->mlmepriv.ft_roam.ft_updated_bcn = _FALSE;
736 }
737
rtw_ft_peer_info_init(struct sta_info * psta)738 void rtw_ft_peer_info_init(struct sta_info *psta)
739 {
740 struct rtw_sta_ft_info_t *peer = &(psta->ft_peer);
741 _rtw_memset(peer, 0, sizeof(struct rtw_sta_ft_info_t));
742 }
743
rtw_ft_peer_info_free(struct sta_info * psta)744 void rtw_ft_peer_info_free(struct sta_info *psta)
745 {
746 struct rtw_sta_ft_info_t *peer = &(psta->ft_peer);
747
748 rtw_buf_free(&peer->md_ie, &peer->md_len);
749 rtw_buf_free(&peer->rsn_ie, &peer->rsn_len);
750 rtw_buf_free(&peer->ft_ie, &peer->ft_len);
751 }
752
rtw_ft_update_sta_ies(_adapter * padapter,struct cfg80211_update_ft_ies_params * ie)753 int rtw_ft_update_sta_ies(_adapter *padapter,
754 struct cfg80211_update_ft_ies_params *ie)
755 {
756 struct security_priv *psecuritypriv = &(padapter->securitypriv);
757 struct sta_priv *pstapriv = &(padapter->stapriv);
758 struct sta_info *psta;
759 struct rtw_sta_ft_info_t *peer_info;
760 u8 *ptr, *paddr;
761 u32 len;
762 int ret = 0;
763
764 if (!CHECK_BIT(WLAN_AKM_TYPE_FT_PSK, psecuritypriv->akmp)
765 && !CHECK_BIT(WLAN_AKM_TYPE_FT_8021X, psecuritypriv->akmp)
766 && !CHECK_BIT(WLAN_AKM_TYPE_FT_OVER_SAE, psecuritypriv->akmp)) {
767 RTW_FT_INFO("%s : AKM=0x%x\n", __func__, psecuritypriv->akmp);
768 goto exit;
769 }
770
771 if ((ie->ie_len == 0) ||
772 (ie->ie_len >= RTW_FT_MAX_IE_SZ)) {
773 ret = - EINVAL;
774 goto exit;
775 }
776
777 if ((ptr = rtw_get_ie(ie->ie, WLAN_EID_VENDOR_SPECIFIC,
778 &len , ie->ie_len)) == NULL) {
779 RTW_ERR("FT : no station mac address found in ies\n");
780 ret = -EINVAL;
781 goto exit;
782 }
783
784 if (len != ETH_ALEN) {
785 RTW_ERR("FT : invalid station mac length(%u)\n", len);
786 ret = -EINVAL;
787 goto exit;
788 }
789
790 paddr = ptr + 2;
791 if ((psta = rtw_get_stainfo(pstapriv, paddr)) == NULL) {
792 RTW_ERR("FT : sta "MAC_FMT" not found!\n", MAC_ARG(paddr));
793 ret = -EINVAL;
794 goto exit;
795 }
796
797 RTW_FT_INFO("%s : update sta "MAC_FMT" ie, len=%lu\n",
798 __func__, MAC_ARG(paddr), ie->ie_len);
799 RTW_FT_DUMP("ie = ", ie->ie, ie->ie_len);
800
801 peer_info = &(psta->ft_peer);
802 if ((ptr = rtw_get_ie(ie->ie, EID_WPA2, &len , ie->ie_len)) != NULL) {
803 rtw_buf_update(&peer_info->rsn_ie,
804 &peer_info->rsn_len, ptr + 2, len);
805 RTW_FT_DUMP("rsn_ie = ", peer_info->rsn_ie,
806 peer_info->rsn_len);
807 }
808
809 if ((ptr = rtw_get_ie(ie->ie, _MDIE_, &len , ie->ie_len)) != NULL) {
810 rtw_buf_update(&peer_info->md_ie,
811 &peer_info->md_len, ptr + 2, len);
812 RTW_FT_DUMP("md_ie = ",
813 peer_info->md_ie, peer_info->md_len);
814 }
815
816 if ((ptr = rtw_get_ie(ie->ie, _FTIE_, &len , ie->ie_len)) != NULL) {
817 rtw_buf_update(&peer_info->ft_ie,
818 &peer_info->ft_len, ptr + 2, len);
819 RTW_FT_DUMP("ft_ie = ",
820 peer_info->ft_ie, peer_info->ft_len);
821 }
822
823 if (psta->authalg == WLAN_AUTH_FT)
824 issue_asocrsp(padapter, 0, psta, WIFI_REASSOCRSP);
825 exit:
826 return ret;
827 }
828
rtw_ft_update_assocresp_ies(struct net_device * net,struct cfg80211_ap_settings * settings)829 void rtw_ft_update_assocresp_ies(struct net_device *net,
830 struct cfg80211_ap_settings *settings)
831 {
832 _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
833 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
834 struct ft_roam_info *pinfo = &(pmlmepriv->ft_roam);
835 u8 *ie, *bcn_tail_ies, *assocrsp_ies;
836 int ielen, bcn_tail_len, assocrsp_ies_len, ret = 0;
837
838 bcn_tail_ies = (u8 *)settings->beacon.tail;
839 bcn_tail_len = (u32)settings->beacon.tail_len;
840 assocrsp_ies = (u8 *)settings->beacon.assocresp_ies;
841 assocrsp_ies_len = (u32)settings->beacon.assocresp_ies_len;
842
843 if ((bcn_tail_len > 0) &&
844 ((ie = rtw_get_ie(bcn_tail_ies, _MDIE_,
845 &ielen , bcn_tail_len)) != NULL)) {
846 pinfo->mdid = *(u16 *)(ie + 2);
847 pinfo->ft_cap = *(ie + 4);
848 RTW_FT_INFO("%s : mdid = 0x%04x, cap=0x%02x\n",
849 __func__, pinfo->mdid, pinfo->ft_cap);
850 }
851
852 if ((assocrsp_ies_len > 0) &&
853 ((ie = rtw_get_ie(assocrsp_ies, _FTIE_,
854 &ielen , assocrsp_ies_len)) != NULL)) {
855 _rtw_memset(pinfo->updated_ft_ies, 0, RTW_FT_MAX_IE_SZ);
856 _rtw_memcpy(pinfo->updated_ft_ies, ie + 2, ielen);
857 pinfo->updated_ft_ies_len = ielen;
858 RTW_FT_DUMP("FT : ft ie = ", ie + 2, ielen);
859 }
860
861 }
862
rtw_ft_process_ft_auth_rsp(_adapter * padapter,u8 * pframe,u32 len)863 void rtw_ft_process_ft_auth_rsp(_adapter *padapter, u8 *pframe, u32 len)
864 {
865 struct sta_priv *pstapriv = &(padapter->stapriv);
866 struct sta_info *psta = NULL;
867 u8 *ptr;
868 u32 plen;
869
870 ptr = pframe + IEEE80211_3ADDR_LEN + _AUTH_IE_OFFSET_;
871 plen = len - IEEE80211_3ADDR_LEN - _AUTH_IE_OFFSET_;
872
873 psta = rtw_get_stainfo(pstapriv, GetAddr1Ptr(pframe));
874 if (psta) {
875 _rtw_spinlock_bh(&psta->lock);
876 psta->state &= ~WIFI_FW_AUTH_NULL;
877 psta->state |= WIFI_FW_AUTH_SUCCESS;
878 psta->expire_to = pstapriv->assoc_to;
879 _rtw_spinunlock_bh(&psta->lock);
880 }
881 }
882
rtw_ft_build_assoc_rsp_ies(_adapter * padapter,struct sta_info * psta,struct pkt_attrib * pattrib,u8 ** pframe)883 void rtw_ft_build_assoc_rsp_ies(_adapter *padapter,
884 struct sta_info *psta, struct pkt_attrib *pattrib, u8 **pframe)
885 {
886 struct ft_roam_info *prinfo = &(padapter->mlmepriv.ft_roam);
887 struct rtw_sta_ft_info_t *peer_info;
888 u8 *pie, mdie[3] = {0};
889 u32 ielen;
890
891 if (psta == NULL)
892 return;
893
894 if (psta->authalg != WLAN_AUTH_FT) {
895 *((u16 *)&mdie[0]) = prinfo->mdid;
896 mdie[2] = prinfo->ft_cap;
897 pie = mdie;
898 ielen = 3;
899
900 if (prinfo->mdid > 0) {
901 *pframe = rtw_set_ie(((u8 *)*pframe),
902 _MDIE_, ielen , pie, &(pattrib->pktlen));
903 }
904
905 if (prinfo->updated_ft_ies_len > 0) {
906 *pframe = rtw_set_ie(((u8 *)*pframe),
907 _FTIE_, prinfo->updated_ft_ies_len,
908 prinfo->updated_ft_ies, &(pattrib->pktlen));
909 }
910 } else {
911 peer_info = &(psta->ft_peer);
912 if (peer_info->rsn_len > 0) {
913 *pframe = rtw_set_ie(((u8 *)*pframe), EID_WPA2,
914 peer_info->rsn_len, peer_info->rsn_ie,
915 &(pattrib->pktlen));
916 }
917
918 if (peer_info->md_len > 0) {
919 *pframe = rtw_set_ie(((u8 *)*pframe), _MDIE_,
920 peer_info->md_len, peer_info->md_ie,
921 &(pattrib->pktlen));
922 }
923
924 if (peer_info->ft_len > 0) {
925 *pframe = rtw_set_ie(((u8 *)*pframe), _FTIE_,
926 peer_info->ft_len, peer_info->ft_ie,
927 &(pattrib->pktlen));
928 }
929 }
930
931 }
932 #endif /* CONFIG_RTW_80211R */
933