1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _RTW_STA_MGT_C_
21 
22 #include <osdep_service.h>
23 #include <drv_types.h>
24 #include <recv_osdep.h>
25 #include <xmit_osdep.h>
26 #include <mlme_osdep.h>
27 #include <sta_info.h>
28 #include <linux/vmalloc.h>
29 
_rtw_init_stainfo(struct sta_info * psta)30 static void _rtw_init_stainfo(struct sta_info *psta)
31 {
32 	memset((u8 *)psta, 0, sizeof(struct sta_info));
33 
34 	 spin_lock_init(&psta->lock);
35 	INIT_LIST_HEAD(&psta->list);
36 	INIT_LIST_HEAD(&psta->hash_list);
37 	_rtw_init_queue(&psta->sleep_q);
38 	psta->sleepq_len = 0;
39 
40 	_rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
41 	_rtw_init_sta_recv_priv(&psta->sta_recvpriv);
42 
43 #ifdef CONFIG_88EU_AP_MODE
44 
45 	INIT_LIST_HEAD(&psta->asoc_list);
46 
47 	INIT_LIST_HEAD(&psta->auth_list);
48 
49 	psta->expire_to = 0;
50 
51 	psta->flags = 0;
52 
53 	psta->capability = 0;
54 
55 	psta->bpairwise_key_installed = false;
56 
57 	psta->nonerp_set = 0;
58 	psta->no_short_slot_time_set = 0;
59 	psta->no_short_preamble_set = 0;
60 	psta->no_ht_gf_set = 0;
61 	psta->no_ht_set = 0;
62 	psta->ht_20mhz_set = 0;
63 
64 	psta->under_exist_checking = 0;
65 
66 	psta->keep_alive_trycnt = 0;
67 
68 #endif	/*  CONFIG_88EU_AP_MODE */
69 
70 }
71 
_rtw_init_sta_priv(struct sta_priv * pstapriv)72 u32	_rtw_init_sta_priv(struct	sta_priv *pstapriv)
73 {
74 	struct sta_info *psta;
75 	s32 i;
76 
77 
78 	pstapriv->pallocated_stainfo_buf = vzalloc(sizeof(struct sta_info) * NUM_STA + 4);
79 
80 	if (!pstapriv->pallocated_stainfo_buf)
81 		return _FAIL;
82 
83 	pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 -
84 		((size_t)(pstapriv->pallocated_stainfo_buf) & 3);
85 
86 	_rtw_init_queue(&pstapriv->free_sta_queue);
87 
88 	spin_lock_init(&pstapriv->sta_hash_lock);
89 
90 	pstapriv->asoc_sta_count = 0;
91 	_rtw_init_queue(&pstapriv->sleep_q);
92 	_rtw_init_queue(&pstapriv->wakeup_q);
93 
94 	psta = (struct sta_info *)(pstapriv->pstainfo_buf);
95 
96 	for (i = 0; i < NUM_STA; i++) {
97 		_rtw_init_stainfo(psta);
98 
99 		INIT_LIST_HEAD(&(pstapriv->sta_hash[i]));
100 
101 		list_add_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
102 
103 		psta++;
104 	}
105 
106 #ifdef CONFIG_88EU_AP_MODE
107 
108 	pstapriv->sta_dz_bitmap = 0;
109 	pstapriv->tim_bitmap = 0;
110 
111 	INIT_LIST_HEAD(&pstapriv->asoc_list);
112 	INIT_LIST_HEAD(&pstapriv->auth_list);
113 	spin_lock_init(&pstapriv->asoc_list_lock);
114 	spin_lock_init(&pstapriv->auth_list_lock);
115 	pstapriv->asoc_list_cnt = 0;
116 	pstapriv->auth_list_cnt = 0;
117 
118 	pstapriv->auth_to = 3; /*  3*2 = 6 sec */
119 	pstapriv->assoc_to = 3;
120 	pstapriv->expire_to = 3; /*  3*2 = 6 sec */
121 	pstapriv->max_num_sta = NUM_STA;
122 #endif
123 
124 
125 	return _SUCCESS;
126 }
127 
rtw_stainfo_offset(struct sta_priv * stapriv,struct sta_info * sta)128 inline int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta)
129 {
130 	int offset = (((u8 *)sta) - stapriv->pstainfo_buf)/sizeof(struct sta_info);
131 
132 	if (!stainfo_offset_valid(offset))
133 		DBG_88E("%s invalid offset(%d), out of range!!!", __func__, offset);
134 
135 	return offset;
136 }
137 
rtw_get_stainfo_by_offset(struct sta_priv * stapriv,int offset)138 inline struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int offset)
139 {
140 	if (!stainfo_offset_valid(offset))
141 		DBG_88E("%s invalid offset(%d), out of range!!!", __func__, offset);
142 
143 	return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info));
144 }
145 
_rtw_free_sta_priv(struct sta_priv * pstapriv)146 u32	_rtw_free_sta_priv(struct	sta_priv *pstapriv)
147 {
148 	struct list_head *phead, *plist;
149 	struct sta_info *psta = NULL;
150 	struct recv_reorder_ctrl *preorder_ctrl;
151 	int	index;
152 
153 	if (pstapriv) {
154 		/*	delete all reordering_ctrl_timer		*/
155 		spin_lock_bh(&pstapriv->sta_hash_lock);
156 		for (index = 0; index < NUM_STA; index++) {
157 			phead = &(pstapriv->sta_hash[index]);
158 			plist = phead->next;
159 
160 			while (phead != plist) {
161 				int i;
162 				psta = container_of(plist, struct sta_info,
163 						    hash_list);
164 				plist = plist->next;
165 
166 				for (i = 0; i < 16; i++) {
167 					preorder_ctrl = &psta->recvreorder_ctrl[i];
168 					del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
169 				}
170 			}
171 		}
172 		spin_unlock_bh(&pstapriv->sta_hash_lock);
173 		/*===============================*/
174 
175 		if (pstapriv->pallocated_stainfo_buf)
176 			vfree(pstapriv->pallocated_stainfo_buf);
177 	}
178 
179 	return _SUCCESS;
180 }
181 
rtw_alloc_stainfo(struct sta_priv * pstapriv,u8 * hwaddr)182 struct	sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
183 {
184 	s32	index;
185 	struct list_head *phash_list;
186 	struct sta_info	*psta;
187 	struct __queue *pfree_sta_queue;
188 	struct recv_reorder_ctrl *preorder_ctrl;
189 	int i = 0;
190 	u16  wRxSeqInitialValue = 0xffff;
191 
192 
193 	pfree_sta_queue = &pstapriv->free_sta_queue;
194 
195 	spin_lock_bh(&(pfree_sta_queue->lock));
196 
197 	if (list_empty(&pfree_sta_queue->queue)) {
198 		spin_unlock_bh(&pfree_sta_queue->lock);
199 		psta = NULL;
200 	} else {
201 		psta = container_of((&pfree_sta_queue->queue)->next, struct sta_info, list);
202 		list_del_init(&(psta->list));
203 		spin_unlock_bh(&pfree_sta_queue->lock);
204 		_rtw_init_stainfo(psta);
205 		memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
206 		index = wifi_mac_hash(hwaddr);
207 		RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, ("rtw_alloc_stainfo: index=%x", index));
208 		if (index >= NUM_STA) {
209 			RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("ERROR => rtw_alloc_stainfo: index >= NUM_STA"));
210 			psta = NULL;
211 			goto exit;
212 		}
213 		phash_list = &(pstapriv->sta_hash[index]);
214 
215 		spin_lock_bh(&(pstapriv->sta_hash_lock));
216 
217 		list_add_tail(&psta->hash_list, phash_list);
218 
219 		pstapriv->asoc_sta_count++;
220 
221 		spin_unlock_bh(&pstapriv->sta_hash_lock);
222 
223 /*  Commented by Albert 2009/08/13 */
224 /*  For the SMC router, the sequence number of first packet of WPS handshake will be 0. */
225 /*  In this case, this packet will be dropped by recv_decache function if we use the 0x00 as the default value for tid_rxseq variable. */
226 /*  So, we initialize the tid_rxseq variable as the 0xffff. */
227 
228 		for (i = 0; i < 16; i++)
229 			memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], &wRxSeqInitialValue, 2);
230 
231 		RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
232 			 ("alloc number_%d stainfo  with hwaddr = %pM\n",
233 			 pstapriv->asoc_sta_count, hwaddr));
234 
235 		init_addba_retry_timer(pstapriv->padapter, psta);
236 
237 		/* for A-MPDU Rx reordering buffer control */
238 		for (i = 0; i < 16; i++) {
239 			preorder_ctrl = &psta->recvreorder_ctrl[i];
240 
241 			preorder_ctrl->padapter = pstapriv->padapter;
242 
243 			preorder_ctrl->enable = false;
244 
245 			preorder_ctrl->indicate_seq = 0xffff;
246 			preorder_ctrl->wend_b = 0xffff;
247 			preorder_ctrl->wsize_b = 64;/* 64; */
248 
249 			_rtw_init_queue(&preorder_ctrl->pending_recvframe_queue);
250 
251 			rtw_init_recv_timer(preorder_ctrl);
252 		}
253 
254 		/* init for DM */
255 		psta->rssi_stat.UndecoratedSmoothedPWDB = (-1);
256 		psta->rssi_stat.UndecoratedSmoothedCCK = (-1);
257 
258 		/* init for the sequence number of received management frame */
259 		psta->RxMgmtFrameSeqNum = 0xffff;
260 	}
261 
262 exit:
263 	return psta;
264 }
265 
266 /*  using pstapriv->sta_hash_lock to protect */
rtw_free_stainfo(struct adapter * padapter,struct sta_info * psta)267 u32	rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
268 {
269 	int i;
270 	struct __queue *pfree_sta_queue;
271 	struct recv_reorder_ctrl *preorder_ctrl;
272 	struct	sta_xmit_priv	*pstaxmitpriv;
273 	struct	xmit_priv	*pxmitpriv = &padapter->xmitpriv;
274 	struct	sta_priv *pstapriv = &padapter->stapriv;
275 
276 
277 	if (!psta)
278 		goto exit;
279 
280 	pfree_sta_queue = &pstapriv->free_sta_queue;
281 
282 	pstaxmitpriv = &psta->sta_xmitpriv;
283 
284 	spin_lock_bh(&pxmitpriv->lock);
285 
286 	rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q);
287 	psta->sleepq_len = 0;
288 
289 	rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
290 
291 	list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
292 
293 	rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
294 
295 	list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
296 
297 	rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
298 
299 	list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
300 
301 	rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
302 
303 	list_del_init(&(pstaxmitpriv->be_q.tx_pending));
304 
305 	spin_unlock_bh(&pxmitpriv->lock);
306 
307 	list_del_init(&psta->hash_list);
308 	RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
309 		 ("\n free number_%d stainfo with hwaddr=0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
310 		 pstapriv->asoc_sta_count, psta->hwaddr[0], psta->hwaddr[1],
311 		 psta->hwaddr[2], psta->hwaddr[3], psta->hwaddr[4],
312 		 psta->hwaddr[5]));
313 	pstapriv->asoc_sta_count--;
314 
315 	/*  re-init sta_info; 20061114 */
316 	_rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
317 	_rtw_init_sta_recv_priv(&psta->sta_recvpriv);
318 
319 	del_timer_sync(&psta->addba_retry_timer);
320 
321 	/* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
322 	for (i = 0; i < 16; i++) {
323 		struct list_head *phead, *plist;
324 		struct recv_frame *prhdr;
325 		struct recv_frame *prframe;
326 		struct __queue *ppending_recvframe_queue;
327 		struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
328 
329 		preorder_ctrl = &psta->recvreorder_ctrl[i];
330 
331 		del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
332 
333 		ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
334 
335 		spin_lock_bh(&ppending_recvframe_queue->lock);
336 
337 		phead =		get_list_head(ppending_recvframe_queue);
338 		plist = phead->next;
339 
340 		while (!list_empty(phead)) {
341 			prhdr = container_of(plist, struct recv_frame, list);
342 			prframe = (struct recv_frame *)prhdr;
343 
344 			plist = plist->next;
345 
346 			list_del_init(&(prframe->list));
347 
348 			rtw_free_recvframe(prframe, pfree_recv_queue);
349 		}
350 
351 		spin_unlock_bh(&ppending_recvframe_queue->lock);
352 	}
353 
354 	if (!(psta->state & WIFI_AP_STATE))
355 		rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, false);
356 
357 #ifdef CONFIG_88EU_AP_MODE
358 
359 	spin_lock_bh(&pstapriv->auth_list_lock);
360 	if (!list_empty(&psta->auth_list)) {
361 		list_del_init(&psta->auth_list);
362 		pstapriv->auth_list_cnt--;
363 	}
364 	spin_unlock_bh(&pstapriv->auth_list_lock);
365 
366 	psta->expire_to = 0;
367 
368 	psta->sleepq_ac_len = 0;
369 	psta->qos_info = 0;
370 
371 	psta->max_sp_len = 0;
372 	psta->uapsd_bk = 0;
373 	psta->uapsd_be = 0;
374 	psta->uapsd_vi = 0;
375 	psta->uapsd_vo = 0;
376 	psta->has_legacy_ac = 0;
377 
378 	pstapriv->sta_dz_bitmap &= ~BIT(psta->aid);
379 	pstapriv->tim_bitmap &= ~BIT(psta->aid);
380 
381 	if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) {
382 		pstapriv->sta_aid[psta->aid - 1] = NULL;
383 		psta->aid = 0;
384 	}
385 
386 	psta->under_exist_checking = 0;
387 
388 #endif	/*  CONFIG_88EU_AP_MODE */
389 
390 	spin_lock_bh(&(pfree_sta_queue->lock));
391 	list_add_tail(&psta->list, get_list_head(pfree_sta_queue));
392 	spin_unlock_bh(&pfree_sta_queue->lock);
393 
394 exit:
395 
396 
397 	return _SUCCESS;
398 }
399 
400 /*  free all stainfo which in sta_hash[all] */
rtw_free_all_stainfo(struct adapter * padapter)401 void rtw_free_all_stainfo(struct adapter *padapter)
402 {
403 	struct list_head *plist, *phead;
404 	s32	index;
405 	struct sta_info *psta = NULL;
406 	struct	sta_priv *pstapriv = &padapter->stapriv;
407 	struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter);
408 
409 
410 	if (pstapriv->asoc_sta_count == 1)
411 		return;
412 
413 	spin_lock_bh(&pstapriv->sta_hash_lock);
414 
415 	for (index = 0; index < NUM_STA; index++) {
416 		phead = &(pstapriv->sta_hash[index]);
417 		plist = phead->next;
418 
419 		while (phead != plist) {
420 			psta = container_of(plist, struct sta_info, hash_list);
421 
422 			plist = plist->next;
423 
424 			if (pbcmc_stainfo != psta)
425 				rtw_free_stainfo(padapter, psta);
426 		}
427 	}
428 	spin_unlock_bh(&pstapriv->sta_hash_lock);
429 }
430 
431 /* any station allocated can be searched by hash list */
rtw_get_stainfo(struct sta_priv * pstapriv,u8 * hwaddr)432 struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
433 {
434 	struct list_head *plist, *phead;
435 	struct sta_info *psta = NULL;
436 	u32	index;
437 	u8 *addr;
438 	u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
439 
440 
441 	if (!hwaddr)
442 		return NULL;
443 
444 	if (IS_MCAST(hwaddr))
445 		addr = bc_addr;
446 	else
447 		addr = hwaddr;
448 
449 	index = wifi_mac_hash(addr);
450 
451 	spin_lock_bh(&pstapriv->sta_hash_lock);
452 
453 	phead = &(pstapriv->sta_hash[index]);
454 	plist = phead->next;
455 
456 	while (phead != plist) {
457 		psta = container_of(plist, struct sta_info, hash_list);
458 
459 		if ((!memcmp(psta->hwaddr, addr, ETH_ALEN)) == true) {
460 			/*  if found the matched address */
461 			break;
462 		}
463 		psta = NULL;
464 		plist = plist->next;
465 	}
466 
467 	spin_unlock_bh(&pstapriv->sta_hash_lock);
468 	return psta;
469 }
470 
rtw_init_bcmc_stainfo(struct adapter * padapter)471 u32 rtw_init_bcmc_stainfo(struct adapter *padapter)
472 {
473 	struct sta_info		*psta;
474 	u32 res = _SUCCESS;
475 	unsigned char bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
476 	struct	sta_priv *pstapriv = &padapter->stapriv;
477 
478 
479 	psta = rtw_alloc_stainfo(pstapriv, bcast_addr);
480 
481 	if (!psta) {
482 		res = _FAIL;
483 		RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("rtw_alloc_stainfo fail"));
484 		goto exit;
485 	}
486 
487 	/*  default broadcast & multicast use macid 1 */
488 	psta->mac_id = 1;
489 
490 exit:
491 	return res;
492 }
493 
rtw_get_bcmc_stainfo(struct adapter * padapter)494 struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter)
495 {
496 	struct sta_info		*psta;
497 	struct sta_priv		*pstapriv = &padapter->stapriv;
498 	u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
499 	 psta = rtw_get_stainfo(pstapriv, bc_addr);
500 	return psta;
501 }
502 
rtw_access_ctrl(struct adapter * padapter,u8 * mac_addr)503 u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr)
504 {
505 	u8 res = true;
506 #ifdef CONFIG_88EU_AP_MODE
507 	struct list_head *plist, *phead;
508 	struct rtw_wlan_acl_node *paclnode;
509 	u8 match = false;
510 	struct sta_priv *pstapriv = &padapter->stapriv;
511 	struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
512 	struct __queue *pacl_node_q = &pacl_list->acl_node_q;
513 
514 	spin_lock_bh(&(pacl_node_q->lock));
515 	phead = get_list_head(pacl_node_q);
516 	plist = phead->next;
517 	while (phead != plist) {
518 		paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
519 		plist = plist->next;
520 
521 		if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN)) {
522 			if (paclnode->valid) {
523 				match = true;
524 				break;
525 			}
526 		}
527 	}
528 	spin_unlock_bh(&pacl_node_q->lock);
529 
530 	if (pacl_list->mode == 1)/* accept unless in deny list */
531 		res = (match) ? false : true;
532 	else if (pacl_list->mode == 2)/* deny unless in accept list */
533 		res = (match) ? true : false;
534 	else
535 		 res = true;
536 
537 #endif
538 
539 	return res;
540 }
541