xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlan/mlan_sta_rx.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /** @file mlan_sta_rx.c
2  *
3  *  @brief This file contains the handling of RX in MLAN
4  *  module.
5  *
6  *
7  *  Copyright 2008-2022 NXP
8  *
9  *  This software file (the File) is distributed by NXP
10  *  under the terms of the GNU General Public License Version 2, June 1991
11  *  (the License).  You may use, redistribute and/or modify the File in
12  *  accordance with the terms and conditions of the License, a copy of which
13  *  is available by writing to the Free Software Foundation, Inc.,
14  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
15  *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
16  *
17  *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
20  *  this warranty disclaimer.
21  *
22  */
23 
24 /********************************************************
25 Change log:
26     10/27/2008: initial version
27 ********************************************************/
28 
29 #include "mlan.h"
30 #include "mlan_join.h"
31 #include "mlan_util.h"
32 #include "mlan_fw.h"
33 #include "mlan_main.h"
34 #include "mlan_11n_aggr.h"
35 #include "mlan_11n_rxreorder.h"
36 #include "mlan_11ax.h"
37 #ifdef DRV_EMBEDDED_SUPPLICANT
38 #include "authenticator_api.h"
39 #endif
40 
41 /********************************************************
42 		Local Variables
43 ********************************************************/
44 
45 /** Ethernet II header */
46 typedef struct {
47 	/** Ethernet II header destination address */
48 	t_u8 dest_addr[MLAN_MAC_ADDR_LENGTH];
49 	/** Ethernet II header source address */
50 	t_u8 src_addr[MLAN_MAC_ADDR_LENGTH];
51 	/** Ethernet II header length */
52 	t_u16 ethertype;
53 
54 } EthII_Hdr_t;
55 
56 /** IPv4 ARP request header */
57 typedef MLAN_PACK_START struct {
58 	/** Hardware type */
59 	t_u16 Htype;
60 	/** Protocol type */
61 	t_u16 Ptype;
62 	/** Hardware address length */
63 	t_u8 addr_len;
64 	/** Protocol address length */
65 	t_u8 proto_len;
66 	/** Operation code */
67 	t_u16 op_code;
68 	/** Source mac address */
69 	t_u8 src_mac[MLAN_MAC_ADDR_LENGTH];
70 	/** Sender IP address */
71 	t_u8 src_ip[4];
72 	/** Destination mac address */
73 	t_u8 dst_mac[MLAN_MAC_ADDR_LENGTH];
74 	/** Destination IP address */
75 	t_u8 dst_ip[4];
76 } MLAN_PACK_END IPv4_ARP_t;
77 
78 /** IPv6 Nadv packet header */
79 typedef MLAN_PACK_START struct {
80 	/** IP protocol version */
81 	t_u8 version;
82 	/** flow label */
83 	t_u8 flow_lab[3];
84 	/** Payload length */
85 	t_u16 payload_len;
86 	/** Next header type */
87 	t_u8 next_hdr;
88 	/** Hot limit */
89 	t_u8 hop_limit;
90 	/** Source address */
91 	t_u8 src_addr[16];
92 	/** Destination address */
93 	t_u8 dst_addr[16];
94 	/** ICMP type */
95 	t_u8 icmp_type;
96 	/** IPv6 Code */
97 	t_u8 ipv6_code;
98 	/** IPv6 Checksum */
99 	t_u16 ipv6_checksum;
100 	/** Flags */
101 	t_u32 flags;
102 	/** Target address */
103 	t_u8 taget_addr[16];
104 	/** Reserved */
105 	t_u8 rev[8];
106 } MLAN_PACK_END IPv6_Nadv_t;
107 
108 /********************************************************
109 		Global functions
110 ********************************************************/
111 /**
112  *  @brief This function check and discard IPv4 and IPv6 gratuitous broadcast
113  * packets
114  *
115  *  @param prx_pkt     A pointer to RxPacketHdr_t structure of received packet
116  *  @param pmadapter   A pointer to pmlan_adapter structure
117  *  @return            TRUE if found such type of packets, FALSE not found
118  */
discard_gratuitous_ARP_msg(RxPacketHdr_t * prx_pkt,pmlan_adapter pmadapter)119 static t_u8 discard_gratuitous_ARP_msg(RxPacketHdr_t *prx_pkt,
120 				       pmlan_adapter pmadapter)
121 {
122 	t_u8 proto_ARP_type[] = {0x08, 0x06};
123 	t_u8 proto_ARP_type_v6[] = {0x86, 0xDD};
124 	IPv4_ARP_t *parp_hdr;
125 	IPv6_Nadv_t *pNadv_hdr;
126 	t_u8 ret = MFALSE;
127 
128 	/* IPV4 pkt check
129 	 * A gratuitous ARP is an ARP packet
130 	 * where the source and destination IP are both set to
131 	 * the IP of the machine issuing the packet.
132 	 */
133 	if (memcmp(pmadapter, proto_ARP_type, &prx_pkt->eth803_hdr.h803_len,
134 		   sizeof(proto_ARP_type)) == 0) {
135 		parp_hdr = (IPv4_ARP_t *)(&prx_pkt->rfc1042_hdr);
136 		/* Graguitous ARP can be ARP request or ARP reply*/
137 		if ((parp_hdr->op_code == mlan_htons(0x01)) ||
138 		    (parp_hdr->op_code == mlan_htons(0x02)))
139 			if (memcmp(pmadapter, parp_hdr->src_ip,
140 				   parp_hdr->dst_ip, 4) == 0)
141 				ret = MTRUE;
142 	}
143 
144 	/* IPV6 pkt check
145 	 * An unsolicited Neighbor Advertisement pkt is
146 	 * marked by a cleared Solicited Flag
147 	 */
148 	if (memcmp(pmadapter, proto_ARP_type_v6, &prx_pkt->eth803_hdr.h803_len,
149 		   sizeof(proto_ARP_type_v6)) == 0) {
150 		pNadv_hdr = (IPv6_Nadv_t *)(&prx_pkt->rfc1042_hdr);
151 		/* Check Nadv type: next header is ICMPv6 and
152 		 * icmp type is Nadv */
153 		if (pNadv_hdr->next_hdr == 0x3A && pNadv_hdr->icmp_type == 0x88)
154 			if ((pNadv_hdr->flags & mlan_htonl(0x40000000)) == 0)
155 				ret = MTRUE;
156 	}
157 
158 	return ret;
159 }
160 
161 /**
162  *  @brief This function process tdls action frame
163  *
164  *  @param priv        A pointer to mlan_private structure
165  *  @param pbuf        A pointer to tdls action frame buffer
166  *  @param len         len of tdls action frame buffer
167  *  @return            N/A
168  */
wlan_process_tdls_action_frame(pmlan_private priv,t_u8 * pbuf,t_u32 len)169 void wlan_process_tdls_action_frame(pmlan_private priv, t_u8 *pbuf, t_u32 len)
170 {
171 	sta_node *sta_ptr = MNULL;
172 	IEEEtypes_VendorHeader_t *pvendor_ie = MNULL;
173 	const t_u8 wmm_oui[] = {0x00, 0x50, 0xf2, 0x02};
174 	t_u8 *peer;
175 	t_u8 *pos, *end;
176 	t_u8 action;
177 	int ie_len = 0;
178 	t_u8 i;
179 	int rate_len;
180 	IEEEtypes_Extension_t *ext_ie;
181 
182 #define TDLS_PAYLOAD_TYPE 2
183 #define TDLS_CATEGORY 0x0c
184 #define TDLS_REQ_FIX_LEN 6
185 #define TDLS_RESP_FIX_LEN 8
186 #define TDLS_CONFIRM_FIX_LEN 6
187 	if (len < (sizeof(EthII_Hdr_t) + 3))
188 		return;
189 	if (*(t_u8 *)(pbuf + sizeof(EthII_Hdr_t)) != TDLS_PAYLOAD_TYPE)
190 		/*TDLS payload type = 2*/
191 		return;
192 	if (*(t_u8 *)(pbuf + sizeof(EthII_Hdr_t) + 1) != TDLS_CATEGORY)
193 		/*TDLS category = 0xc */
194 		return;
195 	peer = pbuf + MLAN_MAC_ADDR_LENGTH;
196 
197 	action = *(t_u8 *)(pbuf + sizeof(EthII_Hdr_t) + 2);
198 	/*2= payload type + category*/
199 
200 	if (action > TDLS_SETUP_CONFIRM) {
201 		/*just handle TDLS setup request/response/confirm */
202 		PRINTM(MMSG, "Recv TDLS Action: peer=" MACSTR ", action=%d\n",
203 		       MAC2STR(peer), action);
204 		return;
205 	}
206 
207 	sta_ptr = wlan_add_station_entry(priv, peer);
208 	if (!sta_ptr)
209 		return;
210 	if (action == TDLS_SETUP_REQUEST) { /*setup request*/
211 		sta_ptr->status = TDLS_NOT_SETUP;
212 		PRINTM(MMSG, "Recv TDLS SETUP Request: peer=" MACSTR "\n",
213 		       MAC2STR(peer));
214 		wlan_hold_tdls_packets(priv, peer);
215 		if (len < (sizeof(EthII_Hdr_t) + TDLS_REQ_FIX_LEN))
216 			return;
217 		pos = pbuf + sizeof(EthII_Hdr_t) + 4;
218 		/*payload 1+ category 1 + action 1 +dialog 1*/
219 		sta_ptr->capability = mlan_ntohs(*(t_u16 *)pos);
220 		ie_len = len - sizeof(EthII_Hdr_t) - TDLS_REQ_FIX_LEN;
221 		pos += 2;
222 	} else if (action == 1) { /*setup respons*/
223 		PRINTM(MMSG, "Recv TDLS SETUP Response: peer=" MACSTR "\n",
224 		       MAC2STR(peer));
225 		if (len < (sizeof(EthII_Hdr_t) + TDLS_RESP_FIX_LEN))
226 			return;
227 		pos = pbuf + sizeof(EthII_Hdr_t) + 6;
228 		/*payload 1+ category 1 + action 1 +dialog 1 +status 2*/
229 		sta_ptr->capability = mlan_ntohs(*(t_u16 *)pos);
230 		ie_len = len - sizeof(EthII_Hdr_t) - TDLS_RESP_FIX_LEN;
231 		pos += 2;
232 	} else { /*setup confirm*/
233 		PRINTM(MMSG, "Recv TDLS SETUP Confirm: peer=" MACSTR "\n",
234 		       MAC2STR(peer));
235 		if (len < (sizeof(EthII_Hdr_t) + TDLS_CONFIRM_FIX_LEN))
236 			return;
237 		pos = pbuf + sizeof(EthII_Hdr_t) + TDLS_CONFIRM_FIX_LEN;
238 		/*payload 1+ category 1 + action 1 +dialog 1 + status 2*/
239 		ie_len = len - sizeof(EthII_Hdr_t) - TDLS_CONFIRM_FIX_LEN;
240 	}
241 	for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
242 		if (pos + 2 + pos[1] > end)
243 			break;
244 		switch (*pos) {
245 		case SUPPORTED_RATES:
246 			sta_ptr->rate_len =
247 				MIN(pos[1], sizeof(sta_ptr->support_rate));
248 			for (i = 0; i < sta_ptr->rate_len; i++)
249 				sta_ptr->support_rate[i] = pos[2 + i];
250 			break;
251 		case EXTENDED_SUPPORTED_RATES:
252 			rate_len = MIN(pos[1], sizeof(sta_ptr->support_rate) -
253 						       sta_ptr->rate_len);
254 			for (i = 0; i < rate_len; i++)
255 				sta_ptr->support_rate[sta_ptr->rate_len + i] =
256 					pos[2 + i];
257 			sta_ptr->rate_len += rate_len;
258 			break;
259 		case HT_CAPABILITY:
260 			memcpy_ext(priv->adapter, (t_u8 *)&sta_ptr->HTcap, pos,
261 				   sizeof(IEEEtypes_HTCap_t),
262 				   sizeof(IEEEtypes_HTCap_t));
263 			sta_ptr->is_11n_enabled = 1;
264 			DBG_HEXDUMP(MDAT_D, "TDLS HT capability",
265 				    (t_u8 *)(&sta_ptr->HTcap),
266 				    MIN(sizeof(IEEEtypes_HTCap_t),
267 					MAX_DATA_DUMP_LEN));
268 			break;
269 		case HT_OPERATION:
270 			memcpy_ext(priv->adapter, &sta_ptr->HTInfo, pos,
271 				   sizeof(IEEEtypes_HTInfo_t),
272 				   sizeof(IEEEtypes_HTInfo_t));
273 			DBG_HEXDUMP(MDAT_D, "TDLS HT info",
274 				    (t_u8 *)(&sta_ptr->HTInfo),
275 				    MIN(sizeof(IEEEtypes_HTInfo_t),
276 					MAX_DATA_DUMP_LEN));
277 			break;
278 		case BSSCO_2040:
279 			memcpy_ext(priv->adapter, (t_u8 *)&sta_ptr->BSSCO_20_40,
280 				   pos, sizeof(IEEEtypes_2040BSSCo_t),
281 				   sizeof(IEEEtypes_2040BSSCo_t));
282 			break;
283 		case EXT_CAPABILITY:
284 			sta_ptr->ExtCap.ieee_hdr.len =
285 				MIN(pos[1], sizeof(ExtCap_t));
286 			memcpy_ext(priv->adapter, (t_u8 *)&sta_ptr->ExtCap, pos,
287 				   sta_ptr->ExtCap.ieee_hdr.len +
288 					   sizeof(IEEEtypes_Header_t),
289 				   sizeof(IEEEtypes_ExtCap_t));
290 			DBG_HEXDUMP(MDAT_D, "TDLS Extended capability",
291 				    (t_u8 *)(&sta_ptr->ExtCap),
292 				    sta_ptr->ExtCap.ieee_hdr.len + 2);
293 			break;
294 		case RSN_IE:
295 			sta_ptr->rsn_ie.ieee_hdr.len =
296 				MIN(pos[1], IEEE_MAX_IE_SIZE -
297 						    sizeof(IEEEtypes_Header_t));
298 			memcpy_ext(priv->adapter, (t_u8 *)&sta_ptr->rsn_ie, pos,
299 				   sta_ptr->rsn_ie.ieee_hdr.len +
300 					   sizeof(IEEEtypes_Header_t),
301 				   sizeof(IEEEtypes_Generic_t));
302 			DBG_HEXDUMP(MDAT_D, "TDLS Rsn ie ",
303 				    (t_u8 *)(&sta_ptr->rsn_ie),
304 				    sta_ptr->rsn_ie.ieee_hdr.len +
305 					    sizeof(IEEEtypes_Header_t));
306 			break;
307 		case QOS_INFO:
308 			sta_ptr->qos_info = pos[2];
309 			sta_ptr->is_wmm_enabled = MTRUE;
310 			PRINTM(MDAT_D, "TDLS qos info %x\n", sta_ptr->qos_info);
311 			break;
312 		case VENDOR_SPECIFIC_221:
313 			pvendor_ie = (IEEEtypes_VendorHeader_t *)pos;
314 			if (!memcmp(priv->adapter, pvendor_ie->oui, wmm_oui,
315 				    sizeof(wmm_oui))) {
316 				sta_ptr->is_wmm_enabled = MTRUE;
317 				sta_ptr->qos_info = pos[8]; /** qos info in wmm
318 							       parameters in
319 							       response and
320 							       confirm */
321 				PRINTM(MDAT_D, "TDLS qos info %x\n",
322 				       sta_ptr->qos_info);
323 			}
324 			break;
325 		case LINK_ID:
326 			memcpy_ext(priv->adapter, (t_u8 *)&sta_ptr->link_ie,
327 				   pos, sizeof(IEEEtypes_LinkIDElement_t),
328 				   sizeof(IEEEtypes_LinkIDElement_t));
329 			break;
330 
331 		case VHT_CAPABILITY:
332 			memcpy_ext(priv->adapter, (t_u8 *)&sta_ptr->vht_cap,
333 				   pos, sizeof(IEEEtypes_VHTCap_t),
334 				   sizeof(IEEEtypes_VHTCap_t));
335 			sta_ptr->is_11ac_enabled = 1;
336 			DBG_HEXDUMP(MCMD_D, "Rx TDLS VHT capability",
337 				    (t_u8 *)(&sta_ptr->vht_cap),
338 				    MIN(sizeof(IEEEtypes_VHTCap_t),
339 					MAX_DATA_DUMP_LEN));
340 			break;
341 		case VHT_OPERATION:
342 			memcpy_ext(priv->adapter, (t_u8 *)&sta_ptr->vht_oprat,
343 				   pos, sizeof(IEEEtypes_VHTOprat_t),
344 				   sizeof(IEEEtypes_VHTOprat_t));
345 			DBG_HEXDUMP(MCMD_D, "Rx TDLS VHT Operation",
346 				    (t_u8 *)(&sta_ptr->vht_oprat),
347 				    MIN(sizeof(IEEEtypes_VHTOprat_t),
348 					MAX_DATA_DUMP_LEN));
349 			break;
350 		case AID_INFO:
351 			memcpy_ext(priv->adapter, (t_u8 *)&sta_ptr->aid_info,
352 				   pos, sizeof(IEEEtypes_AID_t),
353 				   sizeof(IEEEtypes_AID_t));
354 			DBG_HEXDUMP(MCMD_D, "Rx TDLS AID Info",
355 				    (t_u8 *)(&sta_ptr->aid_info),
356 				    MIN(sizeof(IEEEtypes_AID_t),
357 					MAX_DATA_DUMP_LEN));
358 			break;
359 		case EXTENSION:
360 			ext_ie = (IEEEtypes_Extension_t *)pos;
361 			if (ext_ie->ext_id == HE_CAPABILITY) {
362 				memcpy_ext(priv->adapter,
363 					   (t_u8 *)&sta_ptr->tdls_he_cap, pos,
364 					   ext_ie->ieee_hdr.len +
365 						   sizeof(IEEEtypes_Header_t),
366 					   sizeof(IEEEtypes_HECap_t));
367 				sta_ptr->tdls_he_cap.ieee_hdr.len =
368 					MIN(ext_ie->ieee_hdr.len,
369 					    sizeof(IEEEtypes_HECap_t) -
370 						    sizeof(IEEEtypes_Header_t));
371 				sta_ptr->is_11ax_enabled = 1;
372 				DBG_HEXDUMP(MCMD_D, "Rx TDLS HE Capability",
373 					    (t_u8 *)(&sta_ptr->tdls_he_cap),
374 					    MIN(sizeof(IEEEtypes_Header_t) +
375 							sta_ptr->tdls_he_cap
376 								.ieee_hdr.len,
377 						sizeof(IEEEtypes_HECap_t)));
378 			} else if (ext_ie->ext_id == HE_OPERATION) {
379 				memcpy_ext(priv->adapter,
380 					   (t_u8 *)&sta_ptr->he_op, pos,
381 					   ext_ie->ieee_hdr.len +
382 						   sizeof(IEEEtypes_Header_t),
383 					   sizeof(IEEEtypes_HeOp_t));
384 				ext_ie->ieee_hdr.len =
385 					MIN(ext_ie->ieee_hdr.len,
386 					    sizeof(IEEEtypes_HeOp_t) -
387 						    sizeof(IEEEtypes_Header_t));
388 				DBG_HEXDUMP(MCMD_D, "Rx TDLS HE Operation",
389 					    (t_u8 *)(&sta_ptr->he_op),
390 					    MIN(sizeof(IEEEtypes_Header_t) +
391 							ext_ie->ieee_hdr.len,
392 						MAX_DATA_DUMP_LEN));
393 			}
394 			break;
395 		default:
396 			break;
397 		}
398 	}
399 	return;
400 }
401 
402 /**
403  *  @brief This function get pxpd info for radiotap info
404  *
405  *  @param priv A pointer to pmlan_private
406  *  @param prx_pd   A pointer to RxPD
407  *  @param prt_info   A pointer to radiotap_info
408  *
409  *  @return        N/A
410  */
wlan_rxpdinfo_to_radiotapinfo(pmlan_private priv,RxPD * prx_pd,radiotap_info * prt_info)411 void wlan_rxpdinfo_to_radiotapinfo(pmlan_private priv, RxPD *prx_pd,
412 				   radiotap_info *prt_info)
413 {
414 	radiotap_info rt_info_tmp;
415 	t_u8 rx_rate_info = 0;
416 	t_u8 mcs_index = 0;
417 	t_u8 format = 0;
418 	t_u8 bw = 0;
419 	t_u8 gi = 0;
420 	t_u8 ldpc = 0;
421 	t_u8 ext_rate_info = 0;
422 
423 	memset(priv->adapter, &rt_info_tmp, 0x00, sizeof(rt_info_tmp));
424 	rt_info_tmp.snr = prx_pd->snr;
425 	rt_info_tmp.nf = prx_pd->nf;
426 	rt_info_tmp.band_config = (prx_pd->rx_info & 0xf);
427 	rt_info_tmp.chan_num = (prx_pd->rx_info & RXPD_CHAN_MASK) >> 5;
428 	ext_rate_info = (t_u8)(prx_pd->rx_info >> 16);
429 
430 	rt_info_tmp.antenna = prx_pd->antenna;
431 	rx_rate_info = prx_pd->rate_info;
432 	if ((rx_rate_info & 0x3) == MLAN_RATE_FORMAT_VHT) {
433 		/* VHT rate */
434 		format = MLAN_RATE_FORMAT_VHT;
435 		mcs_index = MIN(prx_pd->rx_rate & 0xF, 9);
436 		/* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
437 		bw = (rx_rate_info & 0xC) >> 2;
438 		/* LGI: gi =0, SGI: gi = 1 */
439 		gi = (rx_rate_info & 0x10) >> 4;
440 	} else if ((rx_rate_info & 0x3) == MLAN_RATE_FORMAT_HT) {
441 		/* HT rate */
442 		format = MLAN_RATE_FORMAT_HT;
443 		mcs_index = prx_pd->rx_rate;
444 		/* 20M: bw=0, 40M: bw=1 */
445 		bw = (rx_rate_info & 0xC) >> 2;
446 		/* LGI: gi =0, SGI: gi = 1 */
447 		gi = (rx_rate_info & 0x10) >> 4;
448 	} else {
449 		/* LG rate */
450 		format = MLAN_RATE_FORMAT_LG;
451 		mcs_index = (prx_pd->rx_rate > MLAN_RATE_INDEX_OFDM0) ?
452 				    prx_pd->rx_rate - 1 :
453 				    prx_pd->rx_rate;
454 	}
455 	ldpc = rx_rate_info & 0x40;
456 
457 	rt_info_tmp.rate_info.mcs_index = mcs_index;
458 	rt_info_tmp.rate_info.rate_info =
459 		(ldpc << 5) | (format << 3) | (bw << 1) | gi;
460 	rt_info_tmp.rate_info.bitrate =
461 		wlan_index_to_data_rate(priv->adapter, prx_pd->rx_rate,
462 					prx_pd->rate_info, ext_rate_info);
463 
464 	if (prx_pd->flags & RXPD_FLAG_EXTRA_HEADER)
465 		memcpy_ext(priv->adapter, &rt_info_tmp.extra_info,
466 			   (t_u8 *)prx_pd + sizeof(*prx_pd),
467 			   sizeof(rt_info_tmp.extra_info),
468 			   sizeof(rt_info_tmp.extra_info));
469 
470 	memset(priv->adapter, prt_info, 0x00, sizeof(radiotap_info));
471 	memcpy_ext(priv->adapter, prt_info, &rt_info_tmp, sizeof(rt_info_tmp),
472 		   sizeof(radiotap_info));
473 
474 	return;
475 }
476 
477 /**
478  *  @brief This function processes received packet and forwards it
479  *          to kernel/upper layer
480  *
481  *  @param pmadapter A pointer to mlan_adapter
482  *  @param pmbuf   A pointer to mlan_buffer which includes the received packet
483  *
484  *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
485  */
wlan_process_rx_packet(pmlan_adapter pmadapter,pmlan_buffer pmbuf)486 mlan_status wlan_process_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
487 {
488 	mlan_status ret = MLAN_STATUS_SUCCESS;
489 	pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
490 	RxPacketHdr_t *prx_pkt;
491 	RxPD *prx_pd;
492 	int hdr_chop;
493 	EthII_Hdr_t *peth_hdr;
494 	t_u8 rfc1042_eth_hdr[MLAN_MAC_ADDR_LENGTH] = {0xaa, 0xaa, 0x03,
495 						      0x00, 0x00, 0x00};
496 	t_u8 snap_oui_802_h[MLAN_MAC_ADDR_LENGTH] = {0xaa, 0xaa, 0x03,
497 						     0x00, 0x00, 0xf8};
498 	t_u8 appletalk_aarp_type[2] = {0x80, 0xf3};
499 	t_u8 ipx_snap_type[2] = {0x81, 0x37};
500 	t_u8 tdls_action_type[2] = {0x89, 0x0d};
501 #ifdef DRV_EMBEDDED_SUPPLICANT
502 	t_u8 eapol_type[2] = {0x88, 0x8e};
503 #endif
504 	t_u8 ext_rate_info = 0;
505 
506 	ENTER();
507 
508 	prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
509 	prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset);
510 
511 /** Small debug type */
512 #define DBG_TYPE_SMALL 2
513 /** Size of debugging structure */
514 #define SIZE_OF_DBG_STRUCT 4
515 	if (prx_pd->rx_pkt_type == PKT_TYPE_DEBUG) {
516 		t_u8 dbg_type;
517 		dbg_type = *(t_u8 *)&prx_pkt->eth803_hdr;
518 		if (dbg_type == DBG_TYPE_SMALL) {
519 			PRINTM(MFW_D, "\n");
520 			DBG_HEXDUMP(MFW_D, "FWDBG",
521 				    (char *)((t_u8 *)&prx_pkt->eth803_hdr +
522 					     SIZE_OF_DBG_STRUCT),
523 				    prx_pd->rx_pkt_length);
524 			PRINTM(MFW_D, "FWDBG::\n");
525 		}
526 		goto done;
527 	}
528 
529 	PRINTM(MINFO,
530 	       "RX Data: data_len - prx_pd->rx_pkt_offset = %d - %d = %d\n",
531 	       pmbuf->data_len, prx_pd->rx_pkt_offset,
532 	       pmbuf->data_len - prx_pd->rx_pkt_offset);
533 
534 	HEXDUMP("RX Data: Dest", prx_pkt->eth803_hdr.dest_addr,
535 		sizeof(prx_pkt->eth803_hdr.dest_addr));
536 	HEXDUMP("RX Data: Src", prx_pkt->eth803_hdr.src_addr,
537 		sizeof(prx_pkt->eth803_hdr.src_addr));
538 
539 	if ((memcmp(pmadapter, &prx_pkt->rfc1042_hdr, snap_oui_802_h,
540 		    sizeof(snap_oui_802_h)) == 0) ||
541 	    ((memcmp(pmadapter, &prx_pkt->rfc1042_hdr, rfc1042_eth_hdr,
542 		     sizeof(rfc1042_eth_hdr)) == 0) &&
543 	     memcmp(pmadapter, &prx_pkt->rfc1042_hdr.snap_type,
544 		    appletalk_aarp_type, sizeof(appletalk_aarp_type)) &&
545 	     memcmp(pmadapter, &prx_pkt->rfc1042_hdr.snap_type, ipx_snap_type,
546 		    sizeof(ipx_snap_type)))) {
547 		/*
548 		 * Replace the 803 header and rfc1042 header (llc/snap) with an
549 		 * EthernetII header, keep the src/dst and snap_type
550 		 * (ethertype). The firmware only passes up SNAP frames
551 		 * converting all RX Data from 802.11 to 802.2/LLC/SNAP frames.
552 		 * To create the Ethernet II, just move the src, dst address
553 		 * right before the snap_type.
554 		 */
555 		peth_hdr =
556 			(EthII_Hdr_t *)((t_u8 *)&prx_pkt->eth803_hdr +
557 					sizeof(prx_pkt->eth803_hdr) +
558 					sizeof(prx_pkt->rfc1042_hdr) -
559 					sizeof(prx_pkt->eth803_hdr.dest_addr) -
560 					sizeof(prx_pkt->eth803_hdr.src_addr) -
561 					sizeof(prx_pkt->rfc1042_hdr.snap_type));
562 
563 		memcpy_ext(pmadapter, peth_hdr->src_addr,
564 			   prx_pkt->eth803_hdr.src_addr,
565 			   sizeof(peth_hdr->src_addr),
566 			   sizeof(peth_hdr->src_addr));
567 		memcpy_ext(pmadapter, peth_hdr->dest_addr,
568 			   prx_pkt->eth803_hdr.dest_addr,
569 			   sizeof(peth_hdr->dest_addr),
570 			   sizeof(peth_hdr->dest_addr));
571 
572 		/* Chop off the RxPD + the excess memory from the 802.2/llc/snap
573 		 *  header that was removed.
574 		 */
575 		hdr_chop = (t_u32)((t_ptr)peth_hdr - (t_ptr)prx_pd);
576 	} else {
577 		HEXDUMP("RX Data: LLC/SNAP", (t_u8 *)&prx_pkt->rfc1042_hdr,
578 			sizeof(prx_pkt->rfc1042_hdr));
579 		if ((priv->hotspot_cfg & HOTSPOT_ENABLED) &&
580 		    discard_gratuitous_ARP_msg(prx_pkt, pmadapter)) {
581 			ret = MLAN_STATUS_SUCCESS;
582 			PRINTM(MDATA,
583 			       "Bypass sending Gratuitous ARP frame to Kernel.\n");
584 			goto done;
585 		}
586 		if (!memcmp(pmadapter, &prx_pkt->eth803_hdr.h803_len,
587 			    tdls_action_type, sizeof(tdls_action_type))) {
588 			wlan_process_tdls_action_frame(
589 				priv, ((t_u8 *)prx_pd + prx_pd->rx_pkt_offset),
590 				prx_pd->rx_pkt_length);
591 		}
592 		/* Chop off the RxPD */
593 		hdr_chop = (t_u32)((t_ptr)&prx_pkt->eth803_hdr - (t_ptr)prx_pd);
594 	}
595 
596 	/* Chop off the leading header bytes so the it points to the start of
597 	 *   either the reconstructed EthII frame or the 802.2/llc/snap frame
598 	 */
599 	pmbuf->data_len -= hdr_chop;
600 	pmbuf->data_offset += hdr_chop;
601 	pmbuf->pparent = MNULL;
602 	DBG_HEXDUMP(MDAT_D, "RxPD", (t_u8 *)prx_pd,
603 		    MIN(sizeof(RxPD), MAX_DATA_DUMP_LEN));
604 	DBG_HEXDUMP(MDAT_D, "Rx Payload",
605 		    ((t_u8 *)prx_pd + prx_pd->rx_pkt_offset),
606 		    MIN(prx_pd->rx_pkt_length, MAX_DATA_DUMP_LEN));
607 
608 	priv->rxpd_rate = prx_pd->rx_rate;
609 	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
610 						  &pmbuf->out_ts_sec,
611 						  &pmbuf->out_ts_usec);
612 	PRINTM_NETINTF(MDATA, priv);
613 	PRINTM(MDATA, "%lu.%06lu : Data => kernel seq_num=%d tid=%d\n",
614 	       pmbuf->out_ts_sec, pmbuf->out_ts_usec, prx_pd->seq_num,
615 	       prx_pd->priority);
616 	if (pmadapter->enable_net_mon) {
617 		pmbuf->flags |= MLAN_BUF_FLAG_NET_MONITOR;
618 		goto mon_process;
619 	}
620 
621 #ifdef DRV_EMBEDDED_SUPPLICANT
622 	if (supplicantIsEnabled(priv->psapriv) &&
623 	    (!memcmp(pmadapter, &prx_pkt->eth803_hdr.h803_len, eapol_type,
624 		     sizeof(eapol_type)))) {
625 		// BML_SET_OFFSET(bufDesc, offset);
626 		if (ProcessEAPoLPkt(priv->psapriv, pmbuf)) {
627 			pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
628 			ret = MLAN_STATUS_SUCCESS;
629 			PRINTM(MMSG,
630 			       "host supplicant eapol pkt process done.\n");
631 
632 			LEAVE();
633 			return ret;
634 		}
635 	}
636 #endif
637 
638 mon_process:
639 	if (pmbuf->flags & MLAN_BUF_FLAG_NET_MONITOR) {
640 		// Use some rxpd space to save rxpd info for radiotap header
641 		// We should insure radiotap_info is not bigger than RxPD
642 		wlan_rxpdinfo_to_radiotapinfo(
643 			priv, prx_pd,
644 			(radiotap_info *)(pmbuf->pbuf + pmbuf->data_offset -
645 					  sizeof(radiotap_info)));
646 	}
647 
648 	if (MFALSE || priv->rx_pkt_info) {
649 		ext_rate_info = (t_u8)(prx_pd->rx_info >> 16);
650 		pmbuf->u.rx_info.data_rate =
651 			wlan_index_to_data_rate(priv->adapter, prx_pd->rx_rate,
652 						prx_pd->rate_info,
653 						ext_rate_info);
654 
655 		pmbuf->u.rx_info.channel =
656 			(prx_pd->rx_info & RXPD_CHAN_MASK) >> 5;
657 		pmbuf->u.rx_info.antenna = prx_pd->antenna;
658 		pmbuf->u.rx_info.rssi = prx_pd->snr - prx_pd->nf;
659 	}
660 	ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle,
661 						    pmbuf);
662 	if (ret == MLAN_STATUS_FAILURE) {
663 		pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
664 		PRINTM(MERROR,
665 		       "STA Rx Error: moal_recv_packet returned error\n");
666 	}
667 done:
668 	if (ret != MLAN_STATUS_PENDING)
669 		pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
670 #ifdef USB
671 	else if (IS_USB(pmadapter->card_type))
672 		pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle,
673 							MNULL, MLAN_USB_EP_DATA,
674 							MLAN_STATUS_SUCCESS);
675 #endif
676 	LEAVE();
677 
678 	return ret;
679 }
680 
681 /**
682  *   @brief This function processes the received buffer
683  *
684  *   @param adapter A pointer to mlan_adapter
685  *   @param pmbuf     A pointer to the received buffer
686  *
687  *   @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
688  */
wlan_ops_sta_process_rx_packet(t_void * adapter,pmlan_buffer pmbuf)689 mlan_status wlan_ops_sta_process_rx_packet(t_void *adapter, pmlan_buffer pmbuf)
690 {
691 	pmlan_adapter pmadapter = (pmlan_adapter)adapter;
692 	mlan_status ret = MLAN_STATUS_SUCCESS;
693 	RxPD *prx_pd;
694 	RxPacketHdr_t *prx_pkt;
695 	pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
696 	t_u8 ta[MLAN_MAC_ADDR_LENGTH];
697 	t_u16 rx_pkt_type = 0;
698 	wlan_mgmt_pkt *pmgmt_pkt_hdr = MNULL;
699 
700 	sta_node *sta_ptr = MNULL;
701 	t_u16 adj_rx_rate = 0;
702 	t_u8 antenna = 0;
703 	ENTER();
704 
705 	prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
706 	/* Endian conversion */
707 	endian_convert_RxPD(prx_pd);
708 	if (prx_pd->flags & RXPD_FLAG_EXTRA_HEADER) {
709 		endian_convert_RxPD_extra_header(
710 			(rxpd_extra_info *)((t_u8 *)prx_pd + sizeof(*prx_pd)));
711 	}
712 	if (priv->adapter->pcard_info->v14_fw_api) {
713 		t_u8 rxpd_rate_info_orig = prx_pd->rate_info;
714 		prx_pd->rate_info = wlan_convert_v14_rx_rate_info(
715 			priv, rxpd_rate_info_orig);
716 		PRINTM(MINFO,
717 		       "STA RX: v14_fw_api=%d rx_rate =%d rxpd_rate_info=0x%x->0x%x\n",
718 		       priv->adapter->pcard_info->v14_fw_api, prx_pd->rx_rate,
719 		       rxpd_rate_info_orig, prx_pd->rate_info);
720 	}
721 	rx_pkt_type = prx_pd->rx_pkt_type;
722 	prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset);
723 
724 	if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) !=
725 	    (t_u16)pmbuf->data_len) {
726 		PRINTM(MERROR,
727 		       "Wrong rx packet: len=%d,rx_pkt_offset=%d,"
728 		       " rx_pkt_length=%d\n",
729 		       pmbuf->data_len, prx_pd->rx_pkt_offset,
730 		       prx_pd->rx_pkt_length);
731 		pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
732 		ret = MLAN_STATUS_FAILURE;
733 		pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
734 		goto done;
735 	}
736 	pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length;
737 
738 	if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask &&
739 	    prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME) {
740 		/* Check if this is mgmt packet and needs to
741 		 * forwarded to app as an event
742 		 */
743 		pmgmt_pkt_hdr = (wlan_mgmt_pkt *)((t_u8 *)prx_pd +
744 						  prx_pd->rx_pkt_offset);
745 		pmgmt_pkt_hdr->frm_len =
746 			wlan_le16_to_cpu(pmgmt_pkt_hdr->frm_len);
747 
748 		if ((pmgmt_pkt_hdr->wlan_header.frm_ctl &
749 		     IEEE80211_FC_MGMT_FRAME_TYPE_MASK) == 0)
750 			wlan_process_802dot11_mgmt_pkt(
751 				pmadapter->priv[pmbuf->bss_index],
752 				(t_u8 *)&pmgmt_pkt_hdr->wlan_header,
753 				pmgmt_pkt_hdr->frm_len + sizeof(wlan_mgmt_pkt) -
754 					sizeof(pmgmt_pkt_hdr->frm_len),
755 				prx_pd);
756 		pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
757 		goto done;
758 	}
759 	if (rx_pkt_type != PKT_TYPE_BAR) {
760 		priv->rxpd_rate_info = prx_pd->rate_info;
761 		priv->rxpd_rate = prx_pd->rx_rate;
762 		priv->rxpd_rx_info = (t_u8)(prx_pd->rx_info >> 16);
763 		if (priv->bss_type == MLAN_BSS_TYPE_STA) {
764 			antenna = wlan_adjust_antenna(priv, prx_pd);
765 			adj_rx_rate = wlan_adjust_data_rate(
766 				priv, priv->rxpd_rate, priv->rxpd_rate_info);
767 			pmadapter->callbacks.moal_hist_data_add(
768 				pmadapter->pmoal_handle, pmbuf->bss_index,
769 				adj_rx_rate, prx_pd->snr, prx_pd->nf, antenna);
770 		}
771 	}
772 
773 	/*
774 	 * If the packet is not an unicast packet then send the packet
775 	 * directly to os. Don't pass thru rx reordering
776 	 */
777 	if ((!IS_11N_ENABLED(priv) &&
778 	     !(prx_pd->flags & RXPD_FLAG_PKT_DIRECT_LINK)) ||
779 	    memcmp(priv->adapter, priv->curr_addr,
780 		   prx_pkt->eth803_hdr.dest_addr, MLAN_MAC_ADDR_LENGTH)) {
781 		priv->snr = prx_pd->snr;
782 		priv->nf = prx_pd->nf;
783 		wlan_process_rx_packet(pmadapter, pmbuf);
784 		goto done;
785 	}
786 
787 	if (queuing_ra_based(priv) ||
788 	    (prx_pd->flags & RXPD_FLAG_PKT_DIRECT_LINK)) {
789 		memcpy_ext(pmadapter, ta, prx_pkt->eth803_hdr.src_addr,
790 			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
791 		if (prx_pd->priority < MAX_NUM_TID) {
792 			PRINTM(MDATA, "adhoc/tdls packet %p " MACSTR "\n",
793 			       pmbuf, MAC2STR(ta));
794 			sta_ptr = wlan_get_station_entry(priv, ta);
795 			if (sta_ptr) {
796 				sta_ptr->rx_seq[prx_pd->priority] =
797 					prx_pd->seq_num;
798 				sta_ptr->snr = prx_pd->snr;
799 				sta_ptr->nf = prx_pd->nf;
800 				if (prx_pd->flags & RXPD_FLAG_PKT_DIRECT_LINK) {
801 					pmadapter->callbacks
802 						.moal_updata_peer_signal(
803 							pmadapter->pmoal_handle,
804 							pmbuf->bss_index, ta,
805 							prx_pd->snr,
806 							prx_pd->nf);
807 				}
808 			}
809 			if (!sta_ptr || (!sta_ptr->is_11n_enabled &&
810 					 !sta_ptr->is_11ax_enabled)) {
811 				wlan_process_rx_packet(pmadapter, pmbuf);
812 				goto done;
813 			}
814 		}
815 	} else {
816 		priv->snr = prx_pd->snr;
817 		priv->nf = prx_pd->nf;
818 		if ((rx_pkt_type != PKT_TYPE_BAR) &&
819 		    (prx_pd->priority < MAX_NUM_TID))
820 			priv->rx_seq[prx_pd->priority] = prx_pd->seq_num;
821 		memcpy_ext(pmadapter, ta,
822 			   priv->curr_bss_params.bss_descriptor.mac_address,
823 			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
824 	}
825 	if ((priv->port_ctrl_mode == MTRUE && priv->port_open == MFALSE) &&
826 	    (rx_pkt_type != PKT_TYPE_BAR)) {
827 		mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority,
828 				       ta, (t_u8)prx_pd->rx_pkt_type,
829 				       (t_void *)RX_PKT_DROPPED_IN_FW);
830 		if (rx_pkt_type == PKT_TYPE_AMSDU) {
831 			pmbuf->data_len = prx_pd->rx_pkt_length;
832 			pmbuf->data_offset += prx_pd->rx_pkt_offset;
833 			wlan_11n_deaggregate_pkt(priv, pmbuf);
834 		} else {
835 			wlan_process_rx_packet(pmadapter, pmbuf);
836 		}
837 		goto done;
838 	}
839 	/* Reorder and send to OS */
840 	ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority,
841 				     ta, (t_u8)prx_pd->rx_pkt_type,
842 				     (void *)pmbuf);
843 	if (ret || (rx_pkt_type == PKT_TYPE_BAR))
844 		pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
845 
846 done:
847 
848 	LEAVE();
849 	return ret;
850 }
851