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 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 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 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 */ 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