xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/core/rtw_ft.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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