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