• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <hal_data.h>
18 
19 #ifdef CONFIG_RTW_80211R
20 
21 #ifndef RTW_FT_DBG
22 	#define RTW_FT_DBG	0
23 #endif
24 #if RTW_FT_DBG
25 	#define RTW_FT_INFO(fmt, arg...)	\
26 		RTW_INFO(fmt, arg)
27 	#define RTW_FT_DUMP(str, data, len)	\
28 		RTW_INFO_DUMP(str, data, len)
29 #else
30 	#define RTW_FT_INFO(fmt, arg...) do {} while (0)
31 	#define RTW_FT_DUMP(str, data, len) do {} while (0)
32 #endif
33 
rtw_ft_info_init(struct ft_roam_info * pft)34 void rtw_ft_info_init(struct ft_roam_info *pft)
35 {
36 	_rtw_memset(pft, 0, sizeof(struct ft_roam_info));
37 	pft->ft_flags = 0
38 		| RTW_FT_EN
39 	/*	| RTW_FT_OTD_EN */
40 #ifdef CONFIG_RTW_BTM_ROAM
41 		| RTW_FT_BTM_ROAM
42 #endif
43 		;
44 	pft->ft_updated_bcn = _FALSE;
45 	RTW_FT_INFO("%s : ft_flags=0x%02x\n", __func__, pft->ft_flags);
46 }
47 
rtw_ft_proc_flags_set(struct file * file,const char __user * buffer,size_t count,loff_t * pos,void * data)48 ssize_t rtw_ft_proc_flags_set(struct file *file,
49 	const char __user *buffer, size_t count, loff_t *pos, void *data)
50 {
51 	struct net_device *dev = data;
52 	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
53 
54 	char tmp[32];
55 	u8 flags;
56 
57 	if (count < 1)
58 		return -EFAULT;
59 
60 	if (count > sizeof(tmp)) {
61 		rtw_warn_on(1);
62 		return -EFAULT;
63 	}
64 
65 	if (buffer && !copy_from_user(tmp, buffer, count)) {
66 		int num = sscanf(tmp, "%hhx", &flags);
67 		if (num == 1)
68 			adapter->mlmepriv.ft_roam.ft_flags = flags;
69 	}
70 
71 	return count;
72 
73 }
74 
rtw_ft_proc_flags_get(struct seq_file * m,void * v)75 int rtw_ft_proc_flags_get(struct seq_file *m, void *v)
76 {
77 	struct net_device *dev = m->private;
78 	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
79 
80 	RTW_PRINT_SEL(m, "0x%02x\n", adapter->mlmepriv.ft_roam.ft_flags);
81 
82 	return 0;
83 }
84 
rtw_ft_chk_roaming_candidate(_adapter * padapter,struct wlan_network * competitor)85 u8 rtw_ft_chk_roaming_candidate(
86 	_adapter *padapter, struct wlan_network *competitor)
87 {
88 	u8 *pmdie;
89 	u32 mdie_len = 0;
90 	struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
91 
92 	if (!(pmdie = rtw_get_ie(&competitor->network.IEs[12],
93 			_MDIE_, &mdie_len, competitor->network.IELength-12))) {
94 		RTW_INFO("FT : MDIE not foud in competitor!\n");
95 		return _FALSE;
96 	}
97 
98 	if (!_rtw_memcmp(&pft_roam->mdid, (pmdie+2), 2)) {
99 		RTW_INFO("FT : unmatched MDIE!\n");
100 		return _FALSE;
101 	}
102 
103 	/*The candidate don't support over-the-DS*/
104 	if (rtw_ft_valid_otd_candidate(padapter, pmdie)) {
105 		RTW_INFO("FT: ignore the candidate("
106 			MAC_FMT ") for over-the-DS\n",
107 			MAC_ARG(competitor->network.MacAddress));
108 		/*	rtw_ft_clr_flags(padapter, RTW_FT_PEER_OTD_EN); */
109 		return _FALSE;
110 	}
111 
112 	if (rtw_ft_chk_flags(padapter, RTW_FT_TEST_RSSI_ROAM)) {
113 		if (!_rtw_memcmp(padapter->mlmepriv.cur_network.network.MacAddress,
114 			competitor->network.MacAddress, ETH_ALEN) ) {
115 			competitor->network.Rssi +=20;
116 			RTW_FT_INFO("%s : update "MAC_FMT" RSSI to %d for RTW_FT_TEST_RSSI_ROAM\n",
117 				__func__, MAC_ARG(competitor->network.MacAddress),
118 				(int)competitor->network.Rssi);
119 			rtw_ft_clr_flags(padapter, RTW_FT_TEST_RSSI_ROAM);
120 		}
121 	}
122 
123 	return _TRUE;
124 }
125 
rtw_ft_update_stainfo(_adapter * padapter,WLAN_BSSID_EX * pnetwork)126 void rtw_ft_update_stainfo(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
127 {
128 	struct sta_priv		*pstapriv = &padapter->stapriv;
129 	struct sta_info		*psta = NULL;
130 
131 	psta = rtw_get_stainfo(pstapriv, pnetwork->MacAddress);
132 	if (psta == NULL)
133 		psta = rtw_alloc_stainfo(pstapriv, pnetwork->MacAddress);
134 
135 	if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
136 
137 		padapter->securitypriv.binstallGrpkey = _FALSE;
138 		padapter->securitypriv.busetkipkey = _FALSE;
139 		padapter->securitypriv.bgrpkey_handshake = _FALSE;
140 
141 		psta->ieee8021x_blocked = _TRUE;
142 		psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
143 
144 		_rtw_memset((u8 *)&psta->dot118021x_UncstKey, 0, sizeof(union Keytype));
145 		_rtw_memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof(union Keytype));
146 		_rtw_memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof(union Keytype));
147 	}
148 
149 }
150 
rtw_ft_reassoc_event_callback(_adapter * padapter,u8 * pbuf)151 void rtw_ft_reassoc_event_callback(_adapter *padapter, u8 *pbuf)
152 {
153 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
154 	struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf;
155 	struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
156 	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
157 	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
158 	WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&(pmlmeinfo->network);
159 	struct cfg80211_ft_event_params ft_evt_parms;
160 	_irqL irqL;
161 
162 	_rtw_memset(&ft_evt_parms, 0, sizeof(ft_evt_parms));
163 	rtw_ft_update_stainfo(padapter, pnetwork);
164 	ft_evt_parms.ies_len = pft_roam->ft_event.ies_len;
165 	ft_evt_parms.ies =  rtw_zmalloc(ft_evt_parms.ies_len);
166 	if (ft_evt_parms.ies)
167 		_rtw_memcpy((void *)ft_evt_parms.ies, pft_roam->ft_event.ies, ft_evt_parms.ies_len);
168 	 else
169 		goto err_2;
170 
171 	ft_evt_parms.target_ap = rtw_zmalloc(ETH_ALEN);
172 	if (ft_evt_parms.target_ap)
173 		_rtw_memcpy((void *)ft_evt_parms.target_ap, pstassoc->macaddr, ETH_ALEN);
174 	else
175 		goto err_1;
176 
177 	ft_evt_parms.ric_ies = pft_roam->ft_event.ric_ies;
178 	ft_evt_parms.ric_ies_len = pft_roam->ft_event.ric_ies_len;
179 
180 	/* It's a KERNEL issue between v4.11 ~ v4.16,
181 	* <= v4.10, NLMSG_DEFAULT_SIZE is used for nlmsg_new().
182 	* v4.11 ~ v4.16, only used "100 + >ric_ies_len" for nlmsg_new()
183 	*	even then DRIVER don't support RIC.
184 	* >= v4.17, issue should correct as "100 + ies_len + ric_ies_len".
185 	*/
186 	#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) && \
187 	(LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)))
188 		if (!ft_evt_parms.ric_ies_len)
189 			ft_evt_parms.ric_ies_len = ft_evt_parms.ies_len;
190 		else
191 			ft_evt_parms.ric_ies_len += ft_evt_parms.ies_len;
192 	#endif
193 
194 	rtw_ft_lock_set_status(padapter, RTW_FT_AUTHENTICATED_STA, &irqL);
195 	rtw_cfg80211_ft_event(padapter, &ft_evt_parms);
196 	RTW_INFO("%s: to "MAC_FMT"\n", __func__, MAC_ARG(ft_evt_parms.target_ap));
197 
198 	rtw_mfree((u8 *)pft_roam->ft_event.target_ap, ETH_ALEN);
199 err_1:
200 	rtw_mfree((u8 *)ft_evt_parms.ies, ft_evt_parms.ies_len);
201 err_2:
202 	return;
203 }
204 
rtw_ft_validate_akm_type(_adapter * padapter,struct wlan_network * pnetwork)205 void rtw_ft_validate_akm_type(_adapter  *padapter,
206 	struct wlan_network *pnetwork)
207 {
208 	struct security_priv *psecuritypriv = &(padapter->securitypriv);
209 	struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
210 	u32 tmp_len;
211 	u8 *ptmp;
212 
213 	/*IEEE802.11-2012 Std. Table 8-101-AKM suite selectors*/
214 	if (rtw_ft_valid_akm(padapter, psecuritypriv->rsn_akm_suite_type)) {
215 		ptmp = rtw_get_ie(&pnetwork->network.IEs[12],
216 				_MDIE_, &tmp_len, (pnetwork->network.IELength-12));
217 		if (ptmp) {
218 			pft_roam->mdid = *(u16 *)(ptmp+2);
219 			pft_roam->ft_cap = *(ptmp+4);
220 
221 			RTW_INFO("FT: target " MAC_FMT " mdid=(0x%2x), capacity=(0x%2x)\n",
222 				MAC_ARG(pnetwork->network.MacAddress), pft_roam->mdid, pft_roam->ft_cap);
223 			rtw_ft_set_flags(padapter, RTW_FT_PEER_EN);
224 			RTW_FT_INFO("%s : peer support FTOTA(0x%02x)\n", __func__, pft_roam->ft_flags);
225 
226 			if (rtw_ft_otd_roam_en(padapter)) {
227 				rtw_ft_set_flags(padapter, RTW_FT_PEER_OTD_EN);
228 				RTW_FT_INFO("%s : peer support FTOTD(0x%02x)\n", __func__, pft_roam->ft_flags);
229 			}
230 		} else {
231 			/* Don't use FT roaming if target AP cannot support FT */
232 			rtw_ft_clr_flags(padapter, (RTW_FT_PEER_EN|RTW_FT_PEER_OTD_EN));
233 			rtw_ft_reset_status(padapter);
234 		}
235 	} else {
236 		/* It could be a non-FT connection */
237 		rtw_ft_clr_flags(padapter, (RTW_FT_PEER_EN|RTW_FT_PEER_OTD_EN));
238 		rtw_ft_reset_status(padapter);
239 	}
240 
241 	RTW_FT_INFO("%s : ft_flags=0x%02x\n", __func__, pft_roam->ft_flags);
242 }
243 
rtw_ft_update_bcn(_adapter * padapter,union recv_frame * precv_frame)244 void rtw_ft_update_bcn(_adapter *padapter, union recv_frame *precv_frame)
245 {
246 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
247 	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
248 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
249 	u8 *pframe = precv_frame->u.hdr.rx_data;
250 	uint len = precv_frame->u.hdr.len;
251 	WLAN_BSSID_EX *pbss;
252 
253 	if (rtw_ft_chk_status(padapter,RTW_FT_ASSOCIATED_STA)
254 		&& (pmlmepriv->ft_roam.ft_updated_bcn == _FALSE)) {
255 		pbss = (WLAN_BSSID_EX*)rtw_malloc(sizeof(WLAN_BSSID_EX));
256 		if (pbss) {
257 			if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
258 				struct beacon_keys recv_beacon;
259 
260 				update_network(&(pmlmepriv->cur_network.network), pbss, padapter, _TRUE);
261 				/* Move into rtw_get_bcn_keys */
262 				/* rtw_get_bcn_info(&(pmlmepriv->cur_network)); */
263 
264 				/* update bcn keys */
265 				if (rtw_get_bcn_keys(padapter, pframe, len, &recv_beacon) == _TRUE) {
266 					RTW_FT_INFO("%s: beacon keys ready\n", __func__);
267 					_rtw_memcpy(&pmlmepriv->cur_beacon_keys,
268 						&recv_beacon, sizeof(recv_beacon));
269 					if (is_hidden_ssid(recv_beacon.ssid, recv_beacon.ssid_len)) {
270 						_rtw_memcpy(pmlmepriv->cur_beacon_keys.ssid, pmlmeinfo->network.Ssid.Ssid, IW_ESSID_MAX_SIZE);
271 						pmlmepriv->cur_beacon_keys.ssid_len = pmlmeinfo->network.Ssid.SsidLength;
272 					}
273 				} else {
274 					RTW_ERR("%s: get beacon keys failed\n", __func__);
275 					_rtw_memset(&pmlmepriv->cur_beacon_keys, 0, sizeof(recv_beacon));
276 				}
277 				#ifdef CONFIG_BCN_CNT_CONFIRM_HDL
278 				pmlmepriv->new_beacon_cnts = 0;
279 				#endif
280 			}
281 			rtw_mfree((u8*)pbss, sizeof(WLAN_BSSID_EX));
282 		}
283 
284 		/* check the vendor of the assoc AP */
285 		pmlmeinfo->assoc_AP_vendor =
286 			check_assoc_AP(pframe+sizeof(struct rtw_ieee80211_hdr_3addr),
287 				(len - sizeof(struct rtw_ieee80211_hdr_3addr)));
288 
289 		rtw_phydm_update_ap_vendor_ie(padapter);
290 
291 		/* update TSF Value */
292 		update_TSF(pmlmeext, pframe, len);
293 		pmlmeext->bcn_cnt = 0;
294 		pmlmeext->last_bcn_cnt = 0;
295 		pmlmepriv->ft_roam.ft_updated_bcn = _TRUE;
296 	}
297 }
298 
rtw_ft_start_clnt_join(_adapter * padapter)299 void rtw_ft_start_clnt_join(_adapter *padapter)
300 {
301 	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
302 	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
303 	struct	mlme_priv *pmlmepriv = &(padapter->mlmepriv);
304 	struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
305 
306 	if (rtw_ft_otd_roam(padapter)) {
307 		pmlmeinfo->state = WIFI_FW_AUTH_SUCCESS | WIFI_FW_STATION_STATE;
308 		pft_roam->ft_event.ies =
309 			(pft_roam->ft_action + sizeof(struct rtw_ieee80211_hdr_3addr) + 16);
310 		pft_roam->ft_event.ies_len =
311 			(pft_roam->ft_action_len - sizeof(struct rtw_ieee80211_hdr_3addr));
312 
313 		/*Not support RIC*/
314 		pft_roam->ft_event.ric_ies =  NULL;
315 		pft_roam->ft_event.ric_ies_len = 0;
316 		rtw_ft_report_evt(padapter);
317 		return;
318 	}
319 
320 	pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
321 	start_clnt_auth(padapter);
322 }
323 
rtw_ft_update_rsnie(_adapter * padapter,u8 bwrite,struct pkt_attrib * pattrib,u8 ** pframe)324 u8 rtw_ft_update_rsnie(
325 	_adapter *padapter, u8 bwrite,
326 	struct pkt_attrib *pattrib, u8 **pframe)
327 {
328 	struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
329 	u8 *pie;
330 	u32 len;
331 
332 	pie = rtw_get_ie(pft_roam->updated_ft_ies, EID_WPA2, &len,
333 			pft_roam->updated_ft_ies_len);
334 
335 	if (!bwrite)
336 		return (pie)?_SUCCESS:_FAIL;
337 
338 	if (pie) {
339 		*pframe = rtw_set_ie(((u8 *)*pframe), EID_WPA2, len,
340 						pie+2, &(pattrib->pktlen));
341 	} else
342 		return _FAIL;
343 
344 	return _SUCCESS;
345 }
346 
rtw_ft_update_mdie(_adapter * padapter,struct pkt_attrib * pattrib,u8 ** pframe)347 static u8 rtw_ft_update_mdie(
348 	_adapter *padapter, struct pkt_attrib *pattrib, u8 **pframe)
349 {
350 	struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
351 	u8 *pie, mdie[3];
352 	u32 len = 3;
353 
354 	if (rtw_ft_roam(padapter)) {
355 		if ((pie = rtw_get_ie(pft_roam->updated_ft_ies, _MDIE_,
356 				&len, pft_roam->updated_ft_ies_len))) {
357 			pie = (pie + 2); /* ignore md-id & length */
358 		} else
359 			return _FAIL;
360 	} else {
361 		*((u16 *)&mdie[0]) = pft_roam->mdid;
362 		mdie[2] = pft_roam->ft_cap;
363 		pie = &mdie[0];
364 	}
365 
366 	*pframe = rtw_set_ie(((u8 *)*pframe), _MDIE_, len , pie, &(pattrib->pktlen));
367 	return _SUCCESS;
368 }
369 
rtw_ft_update_ftie(_adapter * padapter,struct pkt_attrib * pattrib,u8 ** pframe)370 static u8 rtw_ft_update_ftie(
371 	_adapter *padapter, struct pkt_attrib *pattrib, u8 **pframe)
372 {
373 	struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
374 	u8 *pie;
375 	u32 len;
376 
377 	if ((pie = rtw_get_ie(pft_roam->updated_ft_ies, _FTIE_, &len,
378 				pft_roam->updated_ft_ies_len)) != NULL) {
379 		*pframe = rtw_set_ie(*pframe, _FTIE_, len ,
380 					(pie+2), &(pattrib->pktlen));
381 	} else
382 		return _FAIL;
383 
384 	return _SUCCESS;
385 }
386 
rtw_ft_build_auth_req_ies(_adapter * padapter,struct pkt_attrib * pattrib,u8 ** pframe)387 void rtw_ft_build_auth_req_ies(_adapter *padapter,
388 	struct pkt_attrib *pattrib, u8 **pframe)
389 {
390 	u8 ftie_append = _TRUE;
391 
392 	if (!pattrib || !(*pframe))
393 		return;
394 
395 	if (!rtw_ft_roam(padapter))
396 		return;
397 
398 	ftie_append = rtw_ft_update_rsnie(padapter, _TRUE, pattrib, pframe);
399 	rtw_ft_update_mdie(padapter, pattrib, pframe);
400 	if (ftie_append)
401 		rtw_ft_update_ftie(padapter, pattrib, pframe);
402 }
403 
rtw_ft_build_assoc_req_ies(_adapter * padapter,u8 is_reassoc,struct pkt_attrib * pattrib,u8 ** pframe)404 void rtw_ft_build_assoc_req_ies(_adapter *padapter,
405 	u8 is_reassoc, struct pkt_attrib *pattrib, u8 **pframe)
406 {
407 	if (!pattrib || !(*pframe))
408 		return;
409 
410 	if (rtw_ft_chk_flags(padapter, RTW_FT_PEER_EN))
411 		rtw_ft_update_mdie(padapter, pattrib, pframe);
412 
413 	if ((!is_reassoc) || (!rtw_ft_roam(padapter)))
414 		return;
415 
416 	if (rtw_ft_update_rsnie(padapter, _FALSE, pattrib, pframe))
417 		rtw_ft_update_ftie(padapter, pattrib, pframe);
418 }
419 
rtw_ft_update_auth_rsp_ies(_adapter * padapter,u8 * pframe,u32 len)420 u8 rtw_ft_update_auth_rsp_ies(_adapter *padapter, u8 *pframe, u32 len)
421 {
422 	u8 ret = _SUCCESS;
423 	u8 target_ap_addr[ETH_ALEN] = {0};
424 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
425 	struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
426 
427 	if (!rtw_ft_roam(padapter))
428 		return _FAIL;
429 
430 	/*rtw_ft_report_reassoc_evt already,
431 	 * and waiting for cfg80211_rtw_update_ft_ies */
432 	if (rtw_ft_authed_sta(padapter))
433 		return ret;
434 
435 	if (!pframe || !len)
436 		return _FAIL;
437 
438 	rtw_buf_update(&pmlmepriv->auth_rsp,
439 		&pmlmepriv->auth_rsp_len, pframe, len);
440 	pft_roam->ft_event.ies =
441 		(pmlmepriv->auth_rsp + sizeof(struct rtw_ieee80211_hdr_3addr) + 6);
442 	pft_roam->ft_event.ies_len =
443 		(pmlmepriv->auth_rsp_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 6);
444 
445 	/*Not support RIC*/
446 	pft_roam->ft_event.ric_ies =  NULL;
447 	pft_roam->ft_event.ric_ies_len =  0;
448 	_rtw_memcpy(target_ap_addr, pmlmepriv->assoc_bssid, ETH_ALEN);
449 	rtw_ft_report_reassoc_evt(padapter, target_ap_addr);
450 
451 	return ret;
452 }
453 
rtw_ft_start_clnt_action(_adapter * padapter,u8 * pTargetAddr)454 static void rtw_ft_start_clnt_action(_adapter *padapter, u8 *pTargetAddr)
455 {
456 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
457 
458 	rtw_ft_set_status(padapter, RTW_FT_REQUESTING_STA);
459 	rtw_ft_issue_action_req(padapter, pTargetAddr);
460 	_set_timer(&pmlmeext->ft_link_timer, REASSOC_TO);
461 }
462 
rtw_ft_start_roam(_adapter * padapter,u8 * pTargetAddr)463 void rtw_ft_start_roam(_adapter *padapter, u8 *pTargetAddr)
464 {
465 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
466 
467 	if (rtw_ft_otd_roam(padapter)) {
468 		RTW_FT_INFO("%s : try OTD roaming\n", __func__);
469 		rtw_ft_start_clnt_action(padapter, pTargetAddr);
470 	} else {
471 		/*wait a little time to retrieve packets buffered in the current ap while scan*/
472 		RTW_FT_INFO("%s : start roaming timer\n", __func__);
473 		_set_timer(&pmlmeext->ft_roam_timer, 30);
474 	}
475 }
476 
rtw_ft_issue_action_req(_adapter * padapter,u8 * pTargetAddr)477 void rtw_ft_issue_action_req(_adapter *padapter, u8 *pTargetAddr)
478 {
479 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
480 	struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
481 	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
482 	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
483 	struct xmit_frame *pmgntframe;
484 	struct rtw_ieee80211_hdr *pwlanhdr;
485 	struct pkt_attrib *pattrib;
486 	u8 *pframe;
487 	u8 category = RTW_WLAN_CATEGORY_FT;
488 	u8 action = RTW_WLAN_ACTION_FT_REQ;
489 
490 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
491 	if (pmgntframe == NULL)
492 		return;
493 
494 	pattrib = &pmgntframe->attrib;
495 	update_mgntframe_attrib(padapter, pattrib);
496 	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
497 
498 	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
499 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
500 	pwlanhdr->frame_ctl = 0;
501 
502 	_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
503 	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
504 	_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
505 
506 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
507 	pmlmeext->mgnt_seq++;
508 	set_frame_sub_type(pframe, WIFI_ACTION);
509 
510 	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
511 	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
512 
513 	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
514 	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
515 
516 	_rtw_memcpy(pframe, adapter_mac_addr(padapter), ETH_ALEN);
517 	pframe += ETH_ALEN;
518 	pattrib->pktlen += ETH_ALEN;
519 
520 	_rtw_memcpy(pframe, pTargetAddr, ETH_ALEN);
521 	pframe += ETH_ALEN;
522 	pattrib->pktlen += ETH_ALEN;
523 
524 	rtw_ft_update_mdie(padapter, pattrib, &pframe);
525 	if (rtw_ft_update_rsnie(padapter, _TRUE, pattrib, &pframe))
526 		rtw_ft_update_ftie(padapter, pattrib, &pframe);
527 
528 	RTW_INFO("FT : issue RTW_WLAN_ACTION_FT_REQ\n");
529 	pattrib->last_txcmdsz = pattrib->pktlen;
530 	dump_mgntframe(padapter, pmgntframe);
531 }
532 
rtw_ft_report_evt(_adapter * padapter)533 void rtw_ft_report_evt(_adapter *padapter)
534 {
535 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
536 	struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
537 	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
538 	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
539 	WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&(pmlmeinfo->network);
540 	struct cfg80211_ft_event_params ft_evt_parms;
541 	_irqL irqL;
542 
543 	_rtw_memset(&ft_evt_parms, 0, sizeof(ft_evt_parms));
544 	rtw_ft_update_stainfo(padapter, pnetwork);
545 
546 	if (!pnetwork)
547 		goto err_2;
548 
549 	ft_evt_parms.ies_len = pft_roam->ft_event.ies_len;
550 	ft_evt_parms.ies =  rtw_zmalloc(ft_evt_parms.ies_len);
551 	if (ft_evt_parms.ies)
552 		_rtw_memcpy((void *)ft_evt_parms.ies, pft_roam->ft_event.ies, ft_evt_parms.ies_len);
553 	 else
554 		goto err_2;
555 
556 	ft_evt_parms.target_ap = rtw_zmalloc(ETH_ALEN);
557 	if (ft_evt_parms.target_ap)
558 		_rtw_memcpy((void *)ft_evt_parms.target_ap, pnetwork->MacAddress, ETH_ALEN);
559 	else
560 		goto err_1;
561 
562 	ft_evt_parms.ric_ies = pft_roam->ft_event.ric_ies;
563 	ft_evt_parms.ric_ies_len = pft_roam->ft_event.ric_ies_len;
564 
565 	/* It's a KERNEL issue between v4.11 ~ v4.16,
566 	* <= v4.10, NLMSG_DEFAULT_SIZE is used for nlmsg_new().
567 	* v4.11 ~ v4.16, only used "100 + >ric_ies_len" for nlmsg_new()
568 	*	even then DRIVER don't support RIC.
569 	* >= v4.17, issue should correct as "100 + ies_len + ric_ies_len".
570 	*/
571 	#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) && \
572 	(LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)))
573 		ft_evt_parms.ric_ies_len = (ft_evt_parms.ies_len <= 100 )?
574 			(0):(ft_evt_parms.ies_len - 100);
575 	#endif
576 
577 	rtw_ft_lock_set_status(padapter, RTW_FT_AUTHENTICATED_STA, &irqL);
578 	rtw_cfg80211_ft_event(padapter, &ft_evt_parms);
579 	RTW_INFO("FT: rtw_ft_report_evt\n");
580 	rtw_mfree((u8 *)pft_roam->ft_event.target_ap, ETH_ALEN);
581 err_1:
582 	rtw_mfree((u8 *)ft_evt_parms.ies, ft_evt_parms.ies_len);
583 err_2:
584 	return;
585 }
586 
rtw_ft_report_reassoc_evt(_adapter * padapter,u8 * pMacAddr)587 void rtw_ft_report_reassoc_evt(_adapter *padapter, u8 *pMacAddr)
588 {
589 	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
590 	struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
591 	struct cmd_obj *pcmd_obj = NULL;
592 	struct stassoc_event *passoc_sta_evt = NULL;
593 	struct rtw_evt_header *evt_hdr = NULL;
594 	u8 *pevtcmd = NULL;
595 	u32 cmdsz = 0;
596 
597 	pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
598 	if (pcmd_obj == NULL)
599 		return;
600 
601 	cmdsz = (sizeof(struct stassoc_event) + sizeof(struct rtw_evt_header));
602 	pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
603 	if (pevtcmd == NULL) {
604 		rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
605 		return;
606 	}
607 
608 	_rtw_init_listhead(&pcmd_obj->list);
609 	pcmd_obj->cmdcode = CMD_SET_MLME_EVT;
610 	pcmd_obj->cmdsz = cmdsz;
611 	pcmd_obj->parmbuf = pevtcmd;
612 	pcmd_obj->rsp = NULL;
613 	pcmd_obj->rspsz  = 0;
614 
615 	evt_hdr = (struct rtw_evt_header *)(pevtcmd);
616 	evt_hdr->len = sizeof(struct stassoc_event);
617 	evt_hdr->id = EVT_FT_REASSOC;
618 	evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
619 
620 	passoc_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct rtw_evt_header));
621 	_rtw_memcpy((unsigned char *)(&(passoc_sta_evt->macaddr)), pMacAddr, ETH_ALEN);
622 	rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
623 }
624 
rtw_ft_link_timer_hdl(void * ctx)625 void rtw_ft_link_timer_hdl(void *ctx)
626 {
627 	_adapter *padapter = (_adapter *)ctx;
628 	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
629 	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
630 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
631 	struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
632 
633 	if (rtw_ft_chk_status(padapter, RTW_FT_REQUESTING_STA)) {
634 		if (pft_roam->ft_req_retry_cnt < RTW_FT_ACTION_REQ_LMT) {
635 			pft_roam->ft_req_retry_cnt++;
636 			rtw_ft_issue_action_req(padapter, (u8 *)pmlmepriv->roam_network->network.MacAddress);
637 			_set_timer(&pmlmeext->ft_link_timer, REASSOC_TO);
638 		} else {
639 			pft_roam->ft_req_retry_cnt = 0;
640 			if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
641 				rtw_ft_set_status(padapter, RTW_FT_ASSOCIATED_STA);
642 			else
643 				rtw_ft_reset_status(padapter);
644 		}
645 	}
646 }
647 
rtw_ft_roam_timer_hdl(void * ctx)648 void rtw_ft_roam_timer_hdl(void *ctx)
649 {
650 	_adapter *padapter = (_adapter *)ctx;
651 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
652 
653 	RTW_FT_INFO("%s : try roaming\n", __func__);
654 	receive_disconnect(padapter, pmlmepriv->cur_network.network.MacAddress
655 				, WLAN_REASON_ACTIVE_ROAM, _FALSE);
656 }
657 
rtw_ft_roam_status_reset(_adapter * padapter)658 void rtw_ft_roam_status_reset(_adapter *padapter)
659 {
660 	struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
661 
662 	if ((rtw_to_roam(padapter) > 0) &&
663 		(!rtw_ft_chk_status(padapter, RTW_FT_REQUESTED_STA))) {
664 		rtw_ft_reset_status(padapter);
665 	}
666 
667 	padapter->mlmepriv.ft_roam.ft_updated_bcn = _FALSE;
668 }
669 
670 #endif /* CONFIG_RTW_80211R */
671