xref: /wlan-driver/qca-wifi-host-cmn/iot_sim/core/iot_sim_utils.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2020, The Linux Foundation. All rights reserved.
3*5113495bSYour Name  *
4*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for any
5*5113495bSYour Name  * purpose with or without fee is hereby granted, provided that the above
6*5113495bSYour Name  * copyright notice and this permission notice appear in all copies.
7*5113495bSYour Name  *
8*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9*5113495bSYour Name  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10*5113495bSYour Name  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11*5113495bSYour Name  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12*5113495bSYour Name  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13*5113495bSYour Name  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14*5113495bSYour Name  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*5113495bSYour Name  */
16*5113495bSYour Name 
17*5113495bSYour Name #include <wlan_iot_sim_utils_api.h>
18*5113495bSYour Name #include <qdf_module.h>
19*5113495bSYour Name #include <qdf_delayed_work.h>
20*5113495bSYour Name #include "../../core/iot_sim_cmn_api_i.h"
21*5113495bSYour Name #include <wlan_objmgr_pdev_obj.h>
22*5113495bSYour Name #include <wlan_objmgr_vdev_obj.h>
23*5113495bSYour Name #include <wlan_objmgr_peer_obj.h>
24*5113495bSYour Name 
25*5113495bSYour Name #define IEEE80211_FRAME_BODY_OFFSET 0x18
26*5113495bSYour Name #define IEEE80211_TSF_LEN       (8)
27*5113495bSYour Name 
28*5113495bSYour Name /*
29*5113495bSYour Name  * iot_sim_apply_content_change_rule - function to apply content change rule
30*5113495bSYour Name  *				       packet from upper stack will be modified
31*5113495bSYour Name  *				       as per the user content.
32*5113495bSYour Name  * @piot_sim_rule: iot_sim rule structure
33*5113495bSYour Name  * @nbuf: skb coming from upper stack
34*5113495bSYour Name  * @fixed_param_length: length of fixed parameters in frame body
35*5113495bSYour Name  *
36*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on successful content update or otherwise
37*5113495bSYour Name  *	   QDF_STATUS_E_NOSUPPORT, no content change rule found for this frame
38*5113495bSYour Name  */
39*5113495bSYour Name QDF_STATUS
iot_sim_update_beacon_template_struct(qdf_nbuf_t nbuf,struct beacon_tmpl_params * param)40*5113495bSYour Name iot_sim_update_beacon_template_struct(qdf_nbuf_t nbuf,
41*5113495bSYour Name 				      struct beacon_tmpl_params *param)
42*5113495bSYour Name {
43*5113495bSYour Name 	struct ie_header *ie = NULL;
44*5113495bSYour Name 	uint16_t offset = 0, ie_len = 0;
45*5113495bSYour Name 	struct ieee80211_ath_channelswitch_ie *csa = NULL;
46*5113495bSYour Name 	struct ieee80211_extendedchannelswitch_ie *ecsa = NULL;
47*5113495bSYour Name 	struct extn_ie_header *extn_ie = NULL;
48*5113495bSYour Name 
49*5113495bSYour Name 	if (!param)
50*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
51*5113495bSYour Name 
52*5113495bSYour Name 	/**
53*5113495bSYour Name 	 * Skip fixed field
54*5113495bSYour Name 	 */
55*5113495bSYour Name 	offset += IEEE80211_TSF_LEN; /* TSF field */
56*5113495bSYour Name 	offset += 2; /* Beacon interval */
57*5113495bSYour Name 	offset += 2; /* Capability Information */
58*5113495bSYour Name 
59*5113495bSYour Name 	ie_len = wbuf_get_pktlen(nbuf) -
60*5113495bSYour Name 		 sizeof(struct ieee80211_frame) - offset;
61*5113495bSYour Name 	ie = (struct ie_header *)((uint8_t *)qdf_nbuf_data(nbuf) +
62*5113495bSYour Name 				  sizeof(struct ieee80211_frame) + offset);
63*5113495bSYour Name 
64*5113495bSYour Name 	while (ie_len >= sizeof(struct ie_header)) {
65*5113495bSYour Name 		ie_len -= sizeof(struct ie_header);
66*5113495bSYour Name 		if (!ie->ie_len) {
67*5113495bSYour Name 			ie += 1;
68*5113495bSYour Name 			continue;
69*5113495bSYour Name 		}
70*5113495bSYour Name 
71*5113495bSYour Name 		if (ie_len < ie->ie_len) {
72*5113495bSYour Name 			iot_sim_err("Incomplete corrupted IE:%x", ie->ie_id);
73*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
74*5113495bSYour Name 		}
75*5113495bSYour Name 
76*5113495bSYour Name 		switch (ie->ie_id) {
77*5113495bSYour Name 		case WLAN_ELEMID_TIM:
78*5113495bSYour Name 			if (ie->ie_len < WLAN_TIM_IE_MIN_LENGTH) {
79*5113495bSYour Name 				iot_sim_err("Invalid TIM IE Length");
80*5113495bSYour Name 				goto err;
81*5113495bSYour Name 			}
82*5113495bSYour Name 			param->tim_ie_offset = ((uint8_t *)ie -
83*5113495bSYour Name 						(uint8_t *)qdf_nbuf_data(nbuf));
84*5113495bSYour Name 			break;
85*5113495bSYour Name 		case WLAN_ELEMID_CHANSWITCHANN:
86*5113495bSYour Name 			if (ie->ie_len != WLAN_CSA_IE_MAX_LEN) {
87*5113495bSYour Name 				iot_sim_err("Invalid CSA IE Length");
88*5113495bSYour Name 				goto err;
89*5113495bSYour Name 			}
90*5113495bSYour Name 			csa =
91*5113495bSYour Name 			(struct ieee80211_ath_channelswitch_ie *)ie;
92*5113495bSYour Name 			param->csa_switch_count_offset =
93*5113495bSYour Name 				(((uint8_t *)&csa->tbttcount) -
94*5113495bSYour Name 				 (uint8_t *)qdf_nbuf_data(nbuf));
95*5113495bSYour Name 			break;
96*5113495bSYour Name 		case WLAN_ELEMID_EXTCHANSWITCHANN:
97*5113495bSYour Name 			if (ie->ie_len != WLAN_XCSA_IE_MAX_LEN) {
98*5113495bSYour Name 				iot_sim_err("Invalid ECSA IE Length");
99*5113495bSYour Name 				goto err;
100*5113495bSYour Name 			}
101*5113495bSYour Name 			ecsa =
102*5113495bSYour Name 			(struct ieee80211_extendedchannelswitch_ie *)ie;
103*5113495bSYour Name 			param->ext_csa_switch_count_offset =
104*5113495bSYour Name 				(((uint8_t *)&ecsa->tbttcount) -
105*5113495bSYour Name 				 (uint8_t *)qdf_nbuf_data(nbuf));
106*5113495bSYour Name 			break;
107*5113495bSYour Name 		case WLAN_ELEMID_EXTN_ELEM:
108*5113495bSYour Name 			extn_ie = (struct extn_ie_header *)ie;
109*5113495bSYour Name 			switch (extn_ie->ie_extn_id) {
110*5113495bSYour Name 			case WLAN_EXTN_ELEMID_ESP:
111*5113495bSYour Name 				param->esp_ie_offset =
112*5113495bSYour Name 					((uint8_t *)ie -
113*5113495bSYour Name 					 (uint8_t *)qdf_nbuf_data(nbuf));
114*5113495bSYour Name 				break;
115*5113495bSYour Name 			case WLAN_EXTN_ELEMID_MUEDCA:
116*5113495bSYour Name 				param->mu_edca_ie_offset =
117*5113495bSYour Name 					((uint8_t *)ie -
118*5113495bSYour Name 					 (uint8_t *)qdf_nbuf_data(nbuf));
119*5113495bSYour Name 				break;
120*5113495bSYour Name 			default:
121*5113495bSYour Name 				break;
122*5113495bSYour Name 			}
123*5113495bSYour Name 			break;
124*5113495bSYour Name 		case WLAN_ELEMID_MULTIPLE_BSSID:
125*5113495bSYour Name 			offset = ((uint8_t *)ie -
126*5113495bSYour Name 				 (uint8_t *)qdf_nbuf_data(nbuf));
127*5113495bSYour Name 			param->mbssid_ie_offset = offset;
128*5113495bSYour Name 			break;
129*5113495bSYour Name 		default:
130*5113495bSYour Name 			break;
131*5113495bSYour Name 		}
132*5113495bSYour Name 		/* Consume info element */
133*5113495bSYour Name 		ie_len -= ie->ie_len;
134*5113495bSYour Name 		/* Go to next IE */
135*5113495bSYour Name 		ie = (struct ie_header *)((uint8_t *)ie +
136*5113495bSYour Name 					  sizeof(struct ie_header) +
137*5113495bSYour Name 					  ie->ie_len);
138*5113495bSYour Name 	}
139*5113495bSYour Name 	param->tmpl_len = wbuf_get_pktlen(nbuf);
140*5113495bSYour Name 	param->tmpl_len_aligned = roundup(param->tmpl_len,
141*5113495bSYour Name 					  sizeof(uint32_t));
142*5113495bSYour Name 	param->frm = (uint8_t *)qdf_nbuf_data(nbuf);
143*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
144*5113495bSYour Name err:
145*5113495bSYour Name 	return QDF_STATUS_E_INVAL;
146*5113495bSYour Name }
147*5113495bSYour Name 
148*5113495bSYour Name QDF_STATUS
iot_sim_apply_content_change_rule(struct wlan_objmgr_pdev * pdev,struct iot_sim_rule * piot_sim_rule,qdf_nbuf_t nbuf,int fixed_param_length,struct beacon_tmpl_params * param)149*5113495bSYour Name iot_sim_apply_content_change_rule(struct wlan_objmgr_pdev *pdev,
150*5113495bSYour Name 				  struct iot_sim_rule *piot_sim_rule,
151*5113495bSYour Name 				  qdf_nbuf_t nbuf,
152*5113495bSYour Name 				  int fixed_param_length,
153*5113495bSYour Name 				  struct beacon_tmpl_params *param)
154*5113495bSYour Name {
155*5113495bSYour Name 	uint8_t *buf = NULL;
156*5113495bSYour Name 	qdf_size_t buf_len = 0;
157*5113495bSYour Name 	int offset = 0;
158*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
159*5113495bSYour Name 
160*5113495bSYour Name 	if (!piot_sim_rule->frm_content || !piot_sim_rule->len)
161*5113495bSYour Name 		return QDF_STATUS_E_NOSUPPORT;
162*5113495bSYour Name 
163*5113495bSYour Name 	buf_len = qdf_nbuf_len(nbuf);
164*5113495bSYour Name 	buf = qdf_nbuf_data(nbuf);
165*5113495bSYour Name 
166*5113495bSYour Name 	if (piot_sim_rule->offset ==
167*5113495bSYour Name 			IEEE80211_FRAME_BODY_OFFSET) {
168*5113495bSYour Name 		offset = IEEE80211_FRAME_BODY_OFFSET;
169*5113495bSYour Name 	} else if (piot_sim_rule->offset == 0) {
170*5113495bSYour Name 		offset = 0;
171*5113495bSYour Name 	} else if (buf[piot_sim_rule->offset] ==
172*5113495bSYour Name 			piot_sim_rule->frm_content[0]) {
173*5113495bSYour Name 		offset = piot_sim_rule->offset;
174*5113495bSYour Name 	}  else {
175*5113495bSYour Name 		offset = IEEE80211_FRAME_BODY_OFFSET +
176*5113495bSYour Name 			fixed_param_length;
177*5113495bSYour Name 		while (((offset + 1) < buf_len) &&
178*5113495bSYour Name 		       (buf[offset] < piot_sim_rule->frm_content[0])) {
179*5113495bSYour Name 			offset += buf[offset + 1] + 2;
180*5113495bSYour Name 		}
181*5113495bSYour Name 	}
182*5113495bSYour Name 
183*5113495bSYour Name 	if (offset <= buf_len) {
184*5113495bSYour Name 		buf += offset;
185*5113495bSYour Name 		qdf_mem_copy(buf, piot_sim_rule->frm_content,
186*5113495bSYour Name 			     piot_sim_rule->len);
187*5113495bSYour Name 		qdf_nbuf_set_pktlen(nbuf, offset +
188*5113495bSYour Name 				piot_sim_rule->len);
189*5113495bSYour Name 		iot_sim_debug("iot_sim: Content updated");
190*5113495bSYour Name 	} else {
191*5113495bSYour Name 		iot_sim_err("Failed to modify content");
192*5113495bSYour Name 	}
193*5113495bSYour Name 
194*5113495bSYour Name 	if (IEEE80211_IS_BEACON((struct ieee80211_frame *)qdf_nbuf_data(nbuf)))
195*5113495bSYour Name 		status = iot_sim_update_beacon_template_struct(nbuf, param);
196*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
197*5113495bSYour Name 			iot_sim_err("Failed to update beacon param");
198*5113495bSYour Name 
199*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
200*5113495bSYour Name }
201*5113495bSYour Name 
202*5113495bSYour Name /*
203*5113495bSYour Name  * iot_sim_apply_delay_drop_rule - function to apply delay or drop rule.
204*5113495bSYour Name  *                                 If drop rule is set, buffer will be freed
205*5113495bSYour Name  *                                 here and proper return value will be sent to
206*5113495bSYour Name  *			           tgt layer. In case of delay rule, delayed
207*5113495bSYour Name  *                                 workqueue will be scheduled for rx frame
208*5113495bSYour Name  *                                 processing
209*5113495bSYour Name  *
210*5113495bSYour Name  * @piot_sim_rule: iot_sim rule structure
211*5113495bSYour Name  * @nbuf: skb coming from upper stack
212*5113495bSYour Name  *
213*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on successful drop
214*5113495bSYour Name  *	   QDF_STATUS_E_NULL_VALUE, when drop rule is applied
215*5113495bSYour Name  */
216*5113495bSYour Name QDF_STATUS
iot_sim_apply_delay_drop_rule(struct iot_sim_rule * piot_sim_rule,qdf_nbuf_t nbuf,struct mgmt_rx_event_params * param,struct iot_sim_context * isc,struct qdf_mac_addr * mac_addr)217*5113495bSYour Name iot_sim_apply_delay_drop_rule(struct iot_sim_rule *piot_sim_rule,
218*5113495bSYour Name 			      qdf_nbuf_t nbuf,
219*5113495bSYour Name 			      struct mgmt_rx_event_params *param,
220*5113495bSYour Name 			      struct iot_sim_context *isc,
221*5113495bSYour Name 			      struct qdf_mac_addr *mac_addr)
222*5113495bSYour Name {
223*5113495bSYour Name 	struct mgmt_rx_event_params *rx_param;
224*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(isc->pdev_obj);
225*5113495bSYour Name 	struct wlan_objmgr_peer **peer = &piot_sim_rule->peer;
226*5113495bSYour Name 
227*5113495bSYour Name 	if (!piot_sim_rule->drop &&
228*5113495bSYour Name 	    !piot_sim_rule->delay_dur)
229*5113495bSYour Name 		return QDF_STATUS_E_NOSUPPORT;
230*5113495bSYour Name 
231*5113495bSYour Name 	if (piot_sim_rule->drop && nbuf) {
232*5113495bSYour Name 		qdf_nbuf_free(nbuf);
233*5113495bSYour Name 		iot_sim_debug("iot_sim: Drop rule applied");
234*5113495bSYour Name 	} else if (piot_sim_rule->delay_dur) {
235*5113495bSYour Name 		if (nbuf == piot_sim_rule->sec_buf) {
236*5113495bSYour Name 			iot_sim_debug("iot_sim: rx frame process after delay");
237*5113495bSYour Name 			return QDF_STATUS_E_NOSUPPORT;
238*5113495bSYour Name 		}
239*5113495bSYour Name 
240*5113495bSYour Name 		if (piot_sim_rule->nbuf_list[0]) {
241*5113495bSYour Name 			if (!qdf_delayed_work_stop(piot_sim_rule->
242*5113495bSYour Name 						   dwork)) {
243*5113495bSYour Name 				piot_sim_rule->nbuf_list[1] = nbuf;
244*5113495bSYour Name 				return QDF_STATUS_SUCCESS;
245*5113495bSYour Name 			}
246*5113495bSYour Name 
247*5113495bSYour Name 			if (*peer) {
248*5113495bSYour Name 				wlan_objmgr_peer_release_ref(*peer,
249*5113495bSYour Name 							     WLAN_IOT_SIM_ID);
250*5113495bSYour Name 				*peer = NULL;
251*5113495bSYour Name 			}
252*5113495bSYour Name 
253*5113495bSYour Name 			qdf_nbuf_free(piot_sim_rule->nbuf_list[0]);
254*5113495bSYour Name 			qdf_mem_free(piot_sim_rule->rx_param->rx_params);
255*5113495bSYour Name 			qdf_mem_free(piot_sim_rule->rx_param);
256*5113495bSYour Name 		}
257*5113495bSYour Name 
258*5113495bSYour Name 		rx_param = qdf_mem_malloc(sizeof(struct mgmt_rx_event_params));
259*5113495bSYour Name 		if (!rx_param) {
260*5113495bSYour Name 			iot_sim_err("rx_param alloc failed");
261*5113495bSYour Name 			return QDF_STATUS_E_NOSUPPORT;
262*5113495bSYour Name 		}
263*5113495bSYour Name 
264*5113495bSYour Name 		qdf_mem_copy(rx_param, param,
265*5113495bSYour Name 			     sizeof(struct mgmt_rx_event_params));
266*5113495bSYour Name 		rx_param->rx_params = qdf_mem_malloc(RX_STATUS_SIZE);
267*5113495bSYour Name 		if (!rx_param->rx_params) {
268*5113495bSYour Name 			iot_sim_err("rx_param->rx_params alloc failed");
269*5113495bSYour Name 			qdf_mem_free(rx_param);
270*5113495bSYour Name 			return QDF_STATUS_E_NOSUPPORT;
271*5113495bSYour Name 		}
272*5113495bSYour Name 
273*5113495bSYour Name 		*peer = wlan_objmgr_get_peer(psoc, param->pdev_id,
274*5113495bSYour Name 					     (uint8_t *)mac_addr,
275*5113495bSYour Name 					     WLAN_IOT_SIM_ID);
276*5113495bSYour Name 		qdf_mem_copy(rx_param->rx_params,
277*5113495bSYour Name 			     param->rx_params, RX_STATUS_SIZE);
278*5113495bSYour Name 		piot_sim_rule->rx_param = rx_param;
279*5113495bSYour Name 		piot_sim_rule->nbuf_list[0] = nbuf;
280*5113495bSYour Name 		if (!qdf_delayed_work_start(piot_sim_rule->dwork,
281*5113495bSYour Name 					    piot_sim_rule->delay_dur)) {
282*5113495bSYour Name 			iot_sim_err("delayed_work_start failed");
283*5113495bSYour Name 			qdf_mem_free(rx_param->rx_params);
284*5113495bSYour Name 			qdf_mem_free(rx_param);
285*5113495bSYour Name 			if (*peer) {
286*5113495bSYour Name 				wlan_objmgr_peer_release_ref(*peer,
287*5113495bSYour Name 							     WLAN_IOT_SIM_ID);
288*5113495bSYour Name 				*peer = NULL;
289*5113495bSYour Name 			}
290*5113495bSYour Name 			return QDF_STATUS_E_NOSUPPORT;
291*5113495bSYour Name 		}
292*5113495bSYour Name 
293*5113495bSYour Name 		iot_sim_err("iot_sim: Delay rule applied");
294*5113495bSYour Name 	}
295*5113495bSYour Name 
296*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
297*5113495bSYour Name }
298*5113495bSYour Name 
299*5113495bSYour Name /*
300*5113495bSYour Name  * iot_sim_frame_update - Function to parse input packet coming from upper
301*5113495bSYour Name  *			  stack in Tx direction and to tgt layer in Rx
302*5113495bSYour Name  *			  direction. This function will also check if rule
303*5113495bSYour Name  *			  for that frame type/subtype is set or not and call
304*5113495bSYour Name  *			  specific operation functions.
305*5113495bSYour Name  *
306*5113495bSYour Name  * @pdev: pdev object
307*5113495bSYour Name  * @nbuf: input packet
308*5113495bSYour Name  * @param: beacon template cmd parameter
309*5113495bSYour Name  * @tx: tx or not
310*5113495bSYour Name  * @rx_param: mgmt_rx_event_params
311*5113495bSYour Name  *
312*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS in general
313*5113495bSYour Name  *	   QDF_STATUS_E_NOSUPPORT, no content change rule found for this frame
314*5113495bSYour Name  */
iot_sim_frame_update(struct wlan_objmgr_pdev * pdev,qdf_nbuf_t nbuf,struct beacon_tmpl_params * param,bool tx,struct mgmt_rx_event_params * rx_param)315*5113495bSYour Name QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf,
316*5113495bSYour Name 				struct beacon_tmpl_params *param,
317*5113495bSYour Name 				bool tx, struct mgmt_rx_event_params *rx_param)
318*5113495bSYour Name {
319*5113495bSYour Name 	uint8_t type, subtype, seq = 0;
320*5113495bSYour Name 	struct iot_sim_context *isc;
321*5113495bSYour Name 	uint8_t *buf = qdf_nbuf_data(nbuf), *frm = NULL;
322*5113495bSYour Name 	int fixed_param_len = 0;
323*5113495bSYour Name 	bool is_action_frm = false;
324*5113495bSYour Name 	uint8_t cat, cat_index;
325*5113495bSYour Name 	int auth_seq_index = 0;
326*5113495bSYour Name 	struct iot_sim_rule *piot_sim_rule = NULL;
327*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
328*5113495bSYour Name 	struct iot_sim_rule_per_peer *peer_rule;
329*5113495bSYour Name 	struct ieee80211_frame *wh = (struct ieee80211_frame *)buf;
330*5113495bSYour Name 	struct qdf_mac_addr *mac_addr;
331*5113495bSYour Name 	bool deauth_disassoc = false;
332*5113495bSYour Name 
333*5113495bSYour Name 	isc = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_IOT_SIM_COMP);
334*5113495bSYour Name 	if (!isc) {
335*5113495bSYour Name 		iot_sim_err("pdev IOT_SIM object is NULL!");
336*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
337*5113495bSYour Name 	}
338*5113495bSYour Name 
339*5113495bSYour Name 	type = (buf[0] & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT;
340*5113495bSYour Name 	subtype = (buf[0] & IEEE80211_FC0_SUBTYPE_MASK);
341*5113495bSYour Name 
342*5113495bSYour Name 	if (type == IEEE80211_FC0_TYPE_MGT &&
343*5113495bSYour Name 	    subtype == IEEE80211_FC0_SUBTYPE_AUTH) {
344*5113495bSYour Name 	/* Authentication frame */
345*5113495bSYour Name 		auth_seq_index = IEEE80211_FRAME_BODY_OFFSET + 2;
346*5113495bSYour Name 		seq = le16toh(*(u_int16_t *)(buf + auth_seq_index));
347*5113495bSYour Name 	} else if (type == IEEE80211_FC0_TYPE_MGT &&
348*5113495bSYour Name 		   (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP ||
349*5113495bSYour Name 		    subtype == IEEE80211_FC0_SUBTYPE_BEACON))
350*5113495bSYour Name 	/* Probe response frame */
351*5113495bSYour Name 		fixed_param_len = 12;
352*5113495bSYour Name 	else if (type == IEEE80211_FC0_TYPE_MGT &&
353*5113495bSYour Name 		 (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_RESP ||
354*5113495bSYour Name 		  subtype == IEEE80211_FC0_SUBTYPE_REASSOC_RESP))
355*5113495bSYour Name 	/* Assoc/Reassoc response frame */
356*5113495bSYour Name 		fixed_param_len = 6;
357*5113495bSYour Name 	else if (type == IEEE80211_FC0_TYPE_MGT &&
358*5113495bSYour Name 		 (subtype == IEEE80211_FC0_SUBTYPE_DEAUTH ||
359*5113495bSYour Name 		  subtype == IEEE80211_FC0_SUBTYPE_DISASSOC))
360*5113495bSYour Name 		deauth_disassoc = true;
361*5113495bSYour Name 	else if (type == IEEE80211_FC0_TYPE_MGT &&
362*5113495bSYour Name 		 subtype == IEEE80211_FC0_SUBTYPE_ACTION) {
363*5113495bSYour Name 	/* Action frame */
364*5113495bSYour Name 		frm = buf + IEEE80211_FRAME_BODY_OFFSET;
365*5113495bSYour Name 
366*5113495bSYour Name 		is_action_frm = true;
367*5113495bSYour Name 		if (iot_sim_get_index_for_action_frm(frm, &cat,
368*5113495bSYour Name 						     &cat_index, !tx)) {
369*5113495bSYour Name 			iot_sim_err("get_index_for_action_frm failed");
370*5113495bSYour Name 			return QDF_STATUS_SUCCESS;
371*5113495bSYour Name 		}
372*5113495bSYour Name 	}
373*5113495bSYour Name 
374*5113495bSYour Name 	subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
375*5113495bSYour Name 	iot_sim_debug("iot_sim: type:%d subtype:%d seq:%d, action:%u dir:%s",
376*5113495bSYour Name 		      type, subtype, seq, is_action_frm,
377*5113495bSYour Name 		      tx ? "TX" : "RX");
378*5113495bSYour Name 
379*5113495bSYour Name 	if (tx)
380*5113495bSYour Name 		mac_addr = (struct qdf_mac_addr *)wh->i_addr1;
381*5113495bSYour Name 	else
382*5113495bSYour Name 		mac_addr = (struct qdf_mac_addr *)wh->i_addr2;
383*5113495bSYour Name 
384*5113495bSYour Name 	peer_rule = iot_sim_find_peer_from_mac(isc, mac_addr);
385*5113495bSYour Name 	if (!peer_rule)
386*5113495bSYour Name 		peer_rule = &isc->bcast_peer;
387*5113495bSYour Name 
388*5113495bSYour Name 	if (!peer_rule)
389*5113495bSYour Name 		goto no_peer_rule;
390*5113495bSYour Name 
391*5113495bSYour Name 	qdf_spin_lock_bh(&isc->iot_sim_lock);
392*5113495bSYour Name 
393*5113495bSYour Name 	if (!peer_rule->rule_per_seq[seq])
394*5113495bSYour Name 		goto norule;
395*5113495bSYour Name 
396*5113495bSYour Name 	if (is_action_frm)
397*5113495bSYour Name 		piot_sim_rule = peer_rule->rule_per_seq[seq]->
398*5113495bSYour Name 			rule_per_action_frm[cat][cat_index];
399*5113495bSYour Name 	else
400*5113495bSYour Name 		piot_sim_rule = peer_rule->rule_per_seq[seq]->
401*5113495bSYour Name 			rule_per_type[type][subtype];
402*5113495bSYour Name 
403*5113495bSYour Name 	if (!piot_sim_rule)
404*5113495bSYour Name 		goto norule;
405*5113495bSYour Name 
406*5113495bSYour Name 	if (tx) {
407*5113495bSYour Name 		if (IEEE80211_IS_BEACON((struct ieee80211_frame *)
408*5113495bSYour Name 					qdf_nbuf_data(nbuf))) {
409*5113495bSYour Name 			if (isc->bcn_buf)
410*5113495bSYour Name 				qdf_nbuf_free(isc->bcn_buf);
411*5113495bSYour Name 			isc->bcn_buf = qdf_nbuf_copy(nbuf);
412*5113495bSYour Name 			status =
413*5113495bSYour Name 			   iot_sim_apply_content_change_rule(pdev,
414*5113495bSYour Name 							     piot_sim_rule,
415*5113495bSYour Name 							     isc->bcn_buf,
416*5113495bSYour Name 							     fixed_param_len,
417*5113495bSYour Name 							     param);
418*5113495bSYour Name 		} else {
419*5113495bSYour Name 			status =
420*5113495bSYour Name 			   iot_sim_apply_content_change_rule(pdev,
421*5113495bSYour Name 							     piot_sim_rule,
422*5113495bSYour Name 							     nbuf,
423*5113495bSYour Name 							     fixed_param_len,
424*5113495bSYour Name 							     param);
425*5113495bSYour Name 		}
426*5113495bSYour Name 
427*5113495bSYour Name 		if (status == QDF_STATUS_E_NOSUPPORT) {
428*5113495bSYour Name 			if (deauth_disassoc && piot_sim_rule->drop) {
429*5113495bSYour Name 				status = QDF_STATUS_E_NULL_VALUE;
430*5113495bSYour Name 				iot_sim_debug("iot_sim: frame to be dropped");
431*5113495bSYour Name 			} else
432*5113495bSYour Name 				goto norule;
433*5113495bSYour Name 		}
434*5113495bSYour Name 	} else {
435*5113495bSYour Name 		status = iot_sim_apply_delay_drop_rule(piot_sim_rule,
436*5113495bSYour Name 						       nbuf, rx_param,
437*5113495bSYour Name 						       isc, mac_addr);
438*5113495bSYour Name 		if (QDF_IS_STATUS_SUCCESS(status))
439*5113495bSYour Name 			status = QDF_STATUS_E_NULL_VALUE;
440*5113495bSYour Name 		else
441*5113495bSYour Name 			status = QDF_STATUS_SUCCESS;
442*5113495bSYour Name 	}
443*5113495bSYour Name 
444*5113495bSYour Name 	qdf_spin_unlock_bh(&isc->iot_sim_lock);
445*5113495bSYour Name 	return status;
446*5113495bSYour Name 
447*5113495bSYour Name norule:
448*5113495bSYour Name 	iot_sim_debug("Rule not set for this frame");
449*5113495bSYour Name 	qdf_spin_unlock_bh(&isc->iot_sim_lock);
450*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
451*5113495bSYour Name no_peer_rule:
452*5113495bSYour Name 	iot_sim_debug("Rule not set for this peer");
453*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
454*5113495bSYour Name }
455