xref: /wlan-dirver/qca-wifi-host-cmn/umac/wifi_pos/src/wifi_pos_pasn_api.c (revision 87ce989ee0b2172d08cfc0e040cdb9ca3fcce1e8)
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