1 /* 2 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 * DOC: wifi_pos_pasn_api.c 18 * This file defines the 11az PASN authentication related APIs for wifi_pos 19 * component. 20 */ 21 22 #include <wlan_lmac_if_def.h> 23 #include "wifi_pos_api.h" 24 #include "wifi_pos_pasn_api.h" 25 #include "wifi_pos_utils_i.h" 26 #include "wifi_pos_main_i.h" 27 #include "os_if_wifi_pos.h" 28 #include "os_if_wifi_pos_utils.h" 29 #include "target_if_wifi_pos.h" 30 #include "target_if_wifi_pos_rx_ops.h" 31 #include "wlan_objmgr_cmn.h" 32 #include "wlan_objmgr_global_obj.h" 33 #include "wlan_objmgr_psoc_obj.h" 34 #include "wlan_objmgr_peer_obj.h" 35 #include "wlan_lmac_if_def.h" 36 37 void wifi_pos_set_11az_failed_peers(struct wlan_objmgr_vdev *vdev, 38 struct qdf_mac_addr *mac_addr) 39 { 40 struct wifi_pos_vdev_priv_obj *vdev_pos_obj; 41 struct wifi_pos_11az_context *pasn_context; 42 uint8_t i; 43 44 vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev); 45 if (!vdev_pos_obj) { 46 wifi_pos_err("Wifi pos vdev priv obj is null"); 47 return; 48 } 49 50 pasn_context = &vdev_pos_obj->pasn_context; 51 if (!pasn_context->num_failed_peers) 52 goto add_failed_peer; 53 54 for (i = 0; i < WLAN_MAX_11AZ_PEERS; i++) { 55 if (qdf_is_macaddr_equal(mac_addr, 56 &pasn_context->failed_peer_list[i])) { 57 wifi_pos_debug("Peer: " QDF_MAC_ADDR_FMT " already exists in failed list", 58 QDF_MAC_ADDR_REF(mac_addr->bytes)); 59 return; 60 } 61 } 62 63 add_failed_peer: 64 for (i = 0; i < WLAN_MAX_11AZ_PEERS; i++) { 65 if (qdf_is_macaddr_broadcast( 66 &pasn_context->failed_peer_list[i])) { 67 qdf_copy_macaddr(&pasn_context->failed_peer_list[i], 68 mac_addr); 69 pasn_context->num_failed_peers++; 70 wifi_pos_debug("Added failed peer: " QDF_MAC_ADDR_FMT " at idx[%d]", 71 QDF_MAC_ADDR_REF(mac_addr->bytes), i); 72 73 return; 74 } 75 } 76 77 wifi_pos_debug("Not able to set failed peer"); 78 } 79 80 void wifi_pos_add_peer_to_list(struct wlan_objmgr_vdev *vdev, 81 struct wlan_pasn_request *req, 82 bool is_peer_create_required) 83 { 84 struct wifi_pos_vdev_priv_obj *vdev_pos_obj; 85 struct wifi_pos_11az_context *pasn_context; 86 struct wlan_pasn_request *secure_list, *unsecure_list, *dst_entry; 87 uint8_t i; 88 89 vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev); 90 if (!vdev_pos_obj) { 91 wifi_pos_err("Wifi pos vdev priv obj is null"); 92 return; 93 } 94 95 pasn_context = &vdev_pos_obj->pasn_context; 96 secure_list = pasn_context->secure_peer_list; 97 unsecure_list = pasn_context->unsecure_peer_list; 98 99 /* Find the 1st empty slot and copy the entry to peer list */ 100 for (i = 0; i < WLAN_MAX_11AZ_PEERS; i++) { 101 if (req->peer_type == WLAN_WIFI_POS_PASN_SECURE_PEER) 102 dst_entry = &secure_list[i]; 103 else 104 dst_entry = &unsecure_list[i]; 105 106 /* Current slot is not empty */ 107 if (!qdf_is_macaddr_broadcast(&dst_entry->peer_mac)) 108 continue; 109 110 *dst_entry = *req; 111 if (is_peer_create_required) 112 pasn_context->num_pending_peer_creation++; 113 114 if (req->peer_type == WLAN_WIFI_POS_PASN_SECURE_PEER) 115 pasn_context->num_secure_peers++; 116 else 117 pasn_context->num_unsecure_peers++; 118 119 wifi_pos_debug("Added %s peer: " QDF_MAC_ADDR_FMT " at idx[%d]", 120 (req->peer_type == WLAN_WIFI_POS_PASN_SECURE_PEER) ? "secure" : "unsecure", 121 QDF_MAC_ADDR_REF(mac_addr), i); 122 123 break; 124 } 125 } 126 127 /** 128 * wifi_pos_move_peers_to_fail_list - Move the peers in secure/unsecure list 129 * to failed peer list 130 * @vdev: Vdev pointer 131 * @peer_mac: Peer mac address 132 * @peer_type: Secure or unsecure PASN peer 133 * 134 * Return: None 135 */ 136 static 137 void wifi_pos_move_peers_to_fail_list(struct wlan_objmgr_vdev *vdev, 138 struct qdf_mac_addr *peer_mac, 139 enum wifi_pos_pasn_peer_type peer_type) 140 { 141 uint8_t i; 142 struct wifi_pos_vdev_priv_obj *vdev_pos_obj; 143 struct wifi_pos_11az_context *pasn_context; 144 struct wlan_pasn_request *secure_list, *unsecure_list, *list; 145 struct qdf_mac_addr entry_to_copy; 146 147 vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev); 148 if (!vdev_pos_obj) { 149 wifi_pos_err("Wifi pos vdev priv obj is null"); 150 return; 151 } 152 153 pasn_context = &vdev_pos_obj->pasn_context; 154 155 /* 156 * Broadcast mac address will be sent by caller when initiate 157 * external auth fails and to move the entire list to failed 158 * peers list 159 */ 160 if (qdf_is_macaddr_broadcast(peer_mac)) { 161 /* Clear the entire list and move it to failed peers list */ 162 if (peer_type == WLAN_WIFI_POS_PASN_SECURE_PEER) 163 list = pasn_context->secure_peer_list; 164 else if (peer_type == WLAN_WIFI_POS_PASN_UNSECURE_PEER) 165 list = pasn_context->secure_peer_list; 166 167 for (i = 0; i < WLAN_MAX_11AZ_PEERS; i++) { 168 /* 169 * if valid entry exist in the list, set that mac 170 * address to failed list and clear that mac from the 171 * secure/unsecure list 172 */ 173 if (!qdf_is_macaddr_broadcast(&list[i].peer_mac)) { 174 wifi_pos_set_11az_failed_peers( 175 vdev, &list[i].peer_mac); 176 qdf_set_macaddr_broadcast(&list[i].peer_mac); 177 } 178 } 179 180 return; 181 } 182 183 secure_list = pasn_context->secure_peer_list; 184 unsecure_list = pasn_context->unsecure_peer_list; 185 /* 186 * This condition is hit when peer create confirm for a pasn 187 * peer is received with failure status 188 */ 189 for (i = 0; i < WLAN_MAX_11AZ_PEERS; i++) { 190 /* 191 * Clear the indvidual entry that exist for the given 192 * mac address in secure/unsecure list 193 */ 194 if (qdf_is_macaddr_equal(peer_mac, &secure_list[i].peer_mac)) { 195 entry_to_copy = secure_list[i].peer_mac; 196 qdf_set_macaddr_broadcast(&secure_list[i].peer_mac); 197 pasn_context->num_secure_peers--; 198 } else if (qdf_is_macaddr_equal(peer_mac, 199 &unsecure_list[i].peer_mac)) { 200 entry_to_copy = unsecure_list[i].peer_mac; 201 qdf_set_macaddr_broadcast(&unsecure_list[i].peer_mac); 202 pasn_context->num_unsecure_peers--; 203 } else { 204 continue; 205 } 206 207 wifi_pos_set_11az_failed_peers(vdev, &entry_to_copy); 208 break; 209 } 210 } 211 212 static QDF_STATUS 213 wifi_pos_request_external_pasn_auth(struct wlan_objmgr_psoc *psoc, 214 struct wlan_objmgr_vdev *vdev) 215 { 216 struct wifi_pos_vdev_priv_obj *vdev_pos_obj; 217 struct wifi_pos_osif_ops *osif_cb; 218 struct wifi_pos_11az_context *pasn_context; 219 QDF_STATUS status; 220 221 if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE) 222 return QDF_STATUS_E_INVAL; 223 224 osif_cb = wifi_pos_get_osif_callbacks(psoc); 225 if (!osif_cb || !osif_cb->osif_initiate_pasn_cb) { 226 wifi_pos_err("OSIF %s cb is NULL", 227 !osif_cb ? "" : "PASN"); 228 return QDF_STATUS_E_FAILURE; 229 } 230 231 vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev); 232 if (!vdev_pos_obj) { 233 wifi_pos_err("Wifi pos vdev priv obj is null"); 234 return QDF_STATUS_E_FAILURE; 235 } 236 237 pasn_context = &vdev_pos_obj->pasn_context; 238 239 status = osif_cb->osif_initiate_pasn_cb(vdev, 240 pasn_context->secure_peer_list, 241 pasn_context->num_secure_peers, 242 true); 243 244 return status; 245 } 246 247 static QDF_STATUS 248 wifi_pos_check_and_initiate_pasn_authentication(struct wlan_objmgr_psoc *psoc, 249 struct wlan_objmgr_vdev *vdev, 250 struct wifi_pos_11az_context *pasn_ctx) 251 { 252 struct qdf_mac_addr bcast_mac = QDF_MAC_ADDR_BCAST_INIT; 253 QDF_STATUS status; 254 255 if (pasn_ctx->num_pending_peer_creation) 256 return QDF_STATUS_SUCCESS; 257 258 status = wifi_pos_request_external_pasn_auth(psoc, vdev); 259 if (QDF_IS_STATUS_ERROR(status)) { 260 wifi_pos_err("Initiate Pasn Authentication failed"); 261 wifi_pos_move_peers_to_fail_list(vdev, &bcast_mac, 262 WLAN_WIFI_POS_PASN_SECURE_PEER); 263 /* TODO send PASN_STATUS cmd from here */ 264 } 265 266 return status; 267 } 268 269 QDF_STATUS wifi_pos_handle_ranging_peer_create(struct wlan_objmgr_psoc *psoc, 270 struct wlan_pasn_request *req, 271 uint8_t vdev_id, 272 uint8_t total_entries) 273 { 274 struct wifi_pos_legacy_ops *legacy_cb; 275 struct wlan_objmgr_peer *peer; 276 struct wlan_objmgr_vdev *vdev; 277 struct wifi_pos_vdev_priv_obj *vdev_pos_obj; 278 struct wifi_pos_11az_context *pasn_context; 279 QDF_STATUS status; 280 uint8_t i; 281 282 legacy_cb = wifi_pos_get_legacy_ops(psoc); 283 if (!legacy_cb || !legacy_cb->pasn_peer_create_cb) { 284 wifi_pos_err("legacy callbacks is not registered"); 285 return QDF_STATUS_E_FAILURE; 286 } 287 288 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 289 WLAN_WIFI_POS_CORE_ID); 290 if (!vdev) { 291 wifi_pos_err("Vdev object is null"); 292 return QDF_STATUS_E_FAILURE; 293 } 294 295 wifi_pos_debug("PASN peer create request received. Num peers:%d", 296 total_entries); 297 for (i = 0; i < total_entries; i++) { 298 peer = wlan_objmgr_get_peer_by_mac(psoc, req[i].peer_mac.bytes, 299 WLAN_WIFI_POS_CORE_ID); 300 /* 301 * If already PASN peer is found, then this is a request to 302 * initiate PASN authentication alone and not to send 303 * peer create to fw 304 */ 305 if (peer && 306 (wlan_peer_get_peer_type(peer) == WLAN_PEER_RTT_PASN)) { 307 wifi_pos_debug("PASN Peer: " QDF_MAC_ADDR_FMT "already exists", 308 QDF_MAC_ADDR_REF(req[i].peer_mac.bytes)); 309 wifi_pos_add_peer_to_list(vdev, &req[i], false); 310 wlan_objmgr_peer_release_ref(peer, 311 WLAN_WIFI_POS_CORE_ID); 312 continue; 313 } else if (peer) { 314 /* 315 * If a peer with given mac address already exists which 316 * is not a PASN peer, then move this peer to failed 317 * list 318 */ 319 wifi_pos_debug("Peer: " QDF_MAC_ADDR_FMT "of type:%d already exist", 320 QDF_MAC_ADDR_REF(req[i].peer_mac.bytes), 321 wlan_peer_get_peer_type(peer)); 322 wifi_pos_set_11az_failed_peers(vdev, &req[i].peer_mac); 323 wlan_objmgr_peer_release_ref(peer, 324 WLAN_WIFI_POS_CORE_ID); 325 continue; 326 } 327 328 status = legacy_cb->pasn_peer_create_cb(psoc, &req[i].peer_mac, 329 vdev_id); 330 if (QDF_IS_STATUS_ERROR(status)) { 331 wifi_pos_set_11az_failed_peers(vdev, &req[i].peer_mac); 332 continue; 333 } 334 wifi_pos_add_peer_to_list(vdev, &req[i], true); 335 } 336 337 vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev); 338 if (!vdev_pos_obj) { 339 wifi_pos_err("Wifi pos vdev priv obj is null"); 340 wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID); 341 return QDF_STATUS_E_FAILURE; 342 } 343 344 /* 345 * This condition occurs when firmware requests for PASN peer 346 * create with all PASN peers which are already created. 347 */ 348 pasn_context = &vdev_pos_obj->pasn_context; 349 status = wifi_pos_check_and_initiate_pasn_authentication(psoc, vdev, 350 pasn_context); 351 wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID); 352 353 return status; 354 } 355 356 QDF_STATUS 357 wifi_pos_handle_ranging_peer_create_rsp(struct wlan_objmgr_psoc *psoc, 358 uint8_t vdev_id, 359 struct qdf_mac_addr *peer_mac, 360 uint8_t peer_create_status) 361 { 362 struct wlan_objmgr_vdev *vdev; 363 struct wifi_pos_vdev_priv_obj *vdev_pos_obj; 364 struct wifi_pos_11az_context *pasn_context; 365 QDF_STATUS status = QDF_STATUS_SUCCESS; 366 367 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 368 WLAN_WIFI_POS_CORE_ID); 369 if (!vdev) { 370 wifi_pos_err("Vdev object is null"); 371 return QDF_STATUS_E_FAILURE; 372 } 373 374 vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev); 375 if (!vdev_pos_obj) { 376 wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID); 377 wifi_pos_err("Wifi pos vdev priv obj is null"); 378 return QDF_STATUS_E_FAILURE; 379 } 380 381 pasn_context = &vdev_pos_obj->pasn_context; 382 if (pasn_context->num_pending_peer_creation) 383 pasn_context->num_pending_peer_creation--; 384 385 wifi_pos_debug("Received peer create response for " QDF_MAC_ADDR_FMT " status:%d pending_count:%d", 386 QDF_MAC_ADDR_REF(peer_mac.bytes), peer_create_status, 387 pasn_context->num_pending_peer_creation); 388 if (peer_create_status) 389 wifi_pos_move_peers_to_fail_list(vdev, peer_mac, 390 WLAN_WIFI_POS_PASN_PEER_TYPE_MAX); 391 392 status = wifi_pos_check_and_initiate_pasn_authentication(psoc, vdev, 393 pasn_context); 394 wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID); 395 396 return QDF_STATUS_SUCCESS; 397 } 398 399 QDF_STATUS wifi_pos_handle_ranging_peer_delete(struct wlan_objmgr_psoc *psoc, 400 struct wlan_pasn_request *req, 401 uint8_t vdev_id, 402 uint8_t total_entries) 403 { 404 struct wifi_pos_legacy_ops *legacy_cb; 405 struct wlan_objmgr_peer *peer; 406 bool no_fw_peer_delete; 407 QDF_STATUS status = QDF_STATUS_SUCCESS; 408 409 legacy_cb = wifi_pos_get_legacy_ops(psoc); 410 if (!legacy_cb || !legacy_cb->pasn_peer_delete_cb) { 411 wifi_pos_err("legacy callback is not registered"); 412 return QDF_STATUS_E_FAILURE; 413 } 414 415 for (i = 0; i < total_entries; i++) { 416 peer = wlan_objmgr_get_peer_by_mac(psoc, req[i].peer_mac.bytes, 417 WLAN_WIFI_POS_CORE_ID); 418 if (peer && 419 (wlan_peer_get_peer_type(peer) == WLAN_PEER_RTT_PASN)) { 420 no_fw_peer_delete = WIFI_POS_IS_PEER_ALREADY_DELETED( 421 req[i].control_flags); 422 wifi_pos_debug("Delete PASN Peer: " QDF_MAC_ADDR_FMT, 423 QDF_MAC_ADDR_REF(req[i].peer_mac.bytes)); 424 status = legacy_cb->pasn_peer_delete_cb( 425 psoc, &req[i].peer_mac, 426 vdev_id, no_fw_peer_delete); 427 428 wlan_objmgr_peer_release_ref(peer, 429 WLAN_WIFI_POS_CORE_ID); 430 continue; 431 } else { 432 wifi_pos_debug("PASN Peer: " QDF_MAC_ADDR_FMT "doesn't exist", 433 QDF_MAC_ADDR_REF(req[i].peer_mac.bytes)); 434 if (peer) 435 wlan_objmgr_peer_release_ref( 436 peer, WLAN_WIFI_POS_CORE_ID); 437 438 continue; 439 } 440 } 441 442 return QDF_STATUS_SUCCESS; 443 } 444