1 /*
2  * Copyright (c) 2016 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(net_wifi_mgmt, CONFIG_NET_L2_WIFI_MGMT_LOG_LEVEL);
9 
10 #include <errno.h>
11 #include <string.h>
12 
13 #include <zephyr/net/net_core.h>
14 #include <zephyr/net/net_if.h>
15 #include <zephyr/net/wifi_mgmt.h>
16 #ifdef CONFIG_WIFI_NM
17 #include <zephyr/net/wifi_nm.h>
18 #endif /* CONFIG_WIFI_NM */
19 
wifi_security_txt(enum wifi_security_type security)20 const char *wifi_security_txt(enum wifi_security_type security)
21 {
22 	switch (security) {
23 	case WIFI_SECURITY_TYPE_NONE:
24 		return "OPEN";
25 	case WIFI_SECURITY_TYPE_WEP:
26 		return "WEP";
27 	case WIFI_SECURITY_TYPE_WPA_PSK:
28 		return "WPA-PSK";
29 	case WIFI_SECURITY_TYPE_PSK:
30 		return "WPA2-PSK";
31 	case WIFI_SECURITY_TYPE_PSK_SHA256:
32 		return "WPA2-PSK-SHA256";
33 	case WIFI_SECURITY_TYPE_SAE:
34 		return "WPA3-SAE";
35 	case WIFI_SECURITY_TYPE_WAPI:
36 		return "WAPI";
37 	case WIFI_SECURITY_TYPE_EAP:
38 		return "EAP";
39 	case WIFI_SECURITY_TYPE_UNKNOWN:
40 	default:
41 		return "UNKNOWN";
42 	}
43 }
44 
wifi_mfp_txt(enum wifi_mfp_options mfp)45 const char *wifi_mfp_txt(enum wifi_mfp_options mfp)
46 {
47 	switch (mfp) {
48 	case WIFI_MFP_DISABLE:
49 		return "Disable";
50 	case WIFI_MFP_OPTIONAL:
51 		return "Optional";
52 	case WIFI_MFP_REQUIRED:
53 		return "Required";
54 	case WIFI_MFP_UNKNOWN:
55 	default:
56 		return "UNKNOWN";
57 	}
58 }
59 
wifi_band_txt(enum wifi_frequency_bands band)60 const char *wifi_band_txt(enum wifi_frequency_bands band)
61 {
62 	switch (band) {
63 	case WIFI_FREQ_BAND_2_4_GHZ:
64 		return "2.4GHz";
65 	case WIFI_FREQ_BAND_5_GHZ:
66 		return "5GHz";
67 	case WIFI_FREQ_BAND_6_GHZ:
68 		return "6GHz";
69 	case WIFI_FREQ_BAND_UNKNOWN:
70 	default:
71 		return "UNKNOWN";
72 	}
73 }
74 
wifi_state_txt(enum wifi_iface_state state)75 const char *wifi_state_txt(enum wifi_iface_state state)
76 {
77 	switch (state) {
78 	case WIFI_STATE_DISCONNECTED:
79 		return "DISCONNECTED";
80 	case WIFI_STATE_INACTIVE:
81 		return "INACTIVE";
82 	case WIFI_STATE_INTERFACE_DISABLED:
83 		return "INTERFACE_DISABLED";
84 	case WIFI_STATE_SCANNING:
85 		return "SCANNING";
86 	case WIFI_STATE_AUTHENTICATING:
87 		return "AUTHENTICATING";
88 	case WIFI_STATE_ASSOCIATING:
89 		return "ASSOCIATING";
90 	case WIFI_STATE_ASSOCIATED:
91 		return "ASSOCIATED";
92 	case WIFI_STATE_4WAY_HANDSHAKE:
93 		return "4WAY_HANDSHAKE";
94 	case WIFI_STATE_GROUP_HANDSHAKE:
95 		return "GROUP_HANDSHAKE";
96 	case WIFI_STATE_COMPLETED:
97 		return "COMPLETED";
98 	case WIFI_STATE_UNKNOWN:
99 	default:
100 		return "UNKNOWN";
101 	}
102 }
103 
wifi_mode_txt(enum wifi_iface_mode mode)104 const char *wifi_mode_txt(enum wifi_iface_mode mode)
105 {
106 	switch (mode) {
107 	case WIFI_MODE_INFRA:
108 		return "STATION";
109 	case WIFI_MODE_IBSS:
110 		return "ADHOC";
111 	case WIFI_MODE_AP:
112 		return "ACCESS POINT";
113 	case WIFI_MODE_P2P_GO:
114 		return "P2P GROUP OWNER";
115 	case WIFI_MODE_P2P_GROUP_FORMATION:
116 		return "P2P GROUP FORMATION";
117 	case WIFI_MODE_MESH:
118 		return "MESH";
119 	case WIFI_MODE_UNKNOWN:
120 	default:
121 		return "UNKNOWN";
122 	}
123 }
124 
wifi_link_mode_txt(enum wifi_link_mode link_mode)125 const char *wifi_link_mode_txt(enum wifi_link_mode link_mode)
126 {
127 	switch (link_mode) {
128 	case WIFI_0:
129 		return "WIFI 0 (802.11)";
130 	case WIFI_1:
131 		return "WIFI 1 (802.11b)";
132 	case WIFI_2:
133 		return "WIFI 2 (802.11a)";
134 	case WIFI_3:
135 		return "WIFI 3 (802.11g)";
136 	case WIFI_4:
137 		return "WIFI 4 (802.11n/HT)";
138 	case WIFI_5:
139 		return "WIFI 5 (802.11ac/VHT)";
140 	case WIFI_6:
141 		return "WIFI 6 (802.11ax/HE)";
142 	case WIFI_6E:
143 		return "WIFI 6E (802.11ax 6GHz/HE)";
144 	case WIFI_7:
145 		return "WIFI 7 (802.11be/EHT)";
146 	case WIFI_LINK_MODE_UNKNOWN:
147 	default:
148 		return "UNKNOWN";
149 	}
150 }
151 
wifi_ps_txt(enum wifi_ps ps_name)152 const char *wifi_ps_txt(enum wifi_ps ps_name)
153 {
154 	switch (ps_name) {
155 	case WIFI_PS_DISABLED:
156 		return "Power save disabled";
157 	case WIFI_PS_ENABLED:
158 		return "Power save enabled";
159 	default:
160 		return "UNKNOWN";
161 	}
162 }
163 
wifi_ps_mode_txt(enum wifi_ps_mode ps_mode)164 const char *wifi_ps_mode_txt(enum wifi_ps_mode ps_mode)
165 {
166 	switch (ps_mode) {
167 	case WIFI_PS_MODE_LEGACY:
168 		return "Legacy power save";
169 	case WIFI_PS_MODE_WMM:
170 		return "WMM power save";
171 	default:
172 		return "UNKNOWN";
173 	}
174 }
175 
wifi_twt_operation_txt(enum wifi_twt_operation twt_operation)176 const char *wifi_twt_operation_txt(enum wifi_twt_operation twt_operation)
177 {
178 	switch (twt_operation) {
179 	case WIFI_TWT_SETUP:
180 		return "TWT setup";
181 	case WIFI_TWT_TEARDOWN:
182 		return "TWT teardown";
183 	default:
184 		return "UNKNOWN";
185 	}
186 }
187 
wifi_twt_negotiation_type_txt(enum wifi_twt_negotiation_type twt_negotiation)188 const char *wifi_twt_negotiation_type_txt(enum wifi_twt_negotiation_type twt_negotiation)
189 {
190 	switch (twt_negotiation) {
191 	case WIFI_TWT_INDIVIDUAL:
192 		return "TWT individual negotiation";
193 	case WIFI_TWT_BROADCAST:
194 		return "TWT broadcast negotiation";
195 	case WIFI_TWT_WAKE_TBTT:
196 		return "TWT wake TBTT negotiation";
197 	default:
198 		return "UNKNOWN";
199 	}
200 }
201 
wifi_twt_setup_cmd_txt(enum wifi_twt_setup_cmd twt_setup)202 const char *wifi_twt_setup_cmd_txt(enum wifi_twt_setup_cmd twt_setup)
203 {
204 	switch (twt_setup) {
205 	case WIFI_TWT_SETUP_CMD_REQUEST:
206 		return "TWT request";
207 	case WIFI_TWT_SETUP_CMD_SUGGEST:
208 		return "TWT suggest";
209 	case WIFI_TWT_SETUP_CMD_DEMAND:
210 		return "TWT demand";
211 	case WIFI_TWT_SETUP_CMD_GROUPING:
212 		return "TWT grouping";
213 	case WIFI_TWT_SETUP_CMD_ACCEPT:
214 		return "TWT accept";
215 	case WIFI_TWT_SETUP_CMD_ALTERNATE:
216 		return "TWT alternate";
217 	case WIFI_TWT_SETUP_CMD_DICTATE:
218 		return "TWT dictate";
219 	case WIFI_TWT_SETUP_CMD_REJECT:
220 		return "TWT reject";
221 	default:
222 		return "UNKNOWN";
223 	}
224 }
225 
wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode)226 const char *wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode)
227 {
228 	switch (ps_wakeup_mode) {
229 	case WIFI_PS_WAKEUP_MODE_DTIM:
230 		return "PS wakeup mode DTIM";
231 	case WIFI_PS_WAKEUP_MODE_LISTEN_INTERVAL:
232 		return "PS wakeup mode listen interval";
233 	default:
234 		return "UNKNOWN";
235 	}
236 }
237 
get_wifi_api(struct net_if * iface)238 static const struct wifi_mgmt_ops *const get_wifi_api(struct net_if *iface)
239 {
240 	const struct device *dev = net_if_get_device(iface);
241 	struct net_wifi_mgmt_offload *off_api =
242 			(struct net_wifi_mgmt_offload *) dev->api;
243 #ifdef CONFIG_WIFI_NM
244 	struct wifi_nm_instance *nm = wifi_nm_get_instance_iface(iface);
245 
246 	if (nm) {
247 		return nm->ops;
248 	}
249 #endif /* CONFIG_WIFI_NM */
250 	return off_api ? off_api->wifi_mgmt_api : NULL;
251 }
252 
wifi_connect(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)253 static int wifi_connect(uint32_t mgmt_request, struct net_if *iface,
254 			void *data, size_t len)
255 {
256 	struct wifi_connect_req_params *params =
257 		(struct wifi_connect_req_params *)data;
258 	const struct device *dev = net_if_get_device(iface);
259 
260 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
261 
262 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->connect == NULL) {
263 		return -ENOTSUP;
264 	}
265 
266 	LOG_HEXDUMP_DBG(params->ssid, params->ssid_length, "ssid");
267 	LOG_HEXDUMP_DBG(params->psk, params->psk_length, "psk");
268 	if (params->sae_password) {
269 		LOG_HEXDUMP_DBG(params->sae_password, params->sae_password_length, "sae");
270 	}
271 	NET_DBG("ch %u sec %u", params->channel, params->security);
272 
273 	if ((params->security > WIFI_SECURITY_TYPE_MAX) ||
274 	    (params->ssid_length > WIFI_SSID_MAX_LEN) ||
275 	    (params->ssid_length == 0U) ||
276 	    ((params->security == WIFI_SECURITY_TYPE_PSK ||
277 		  params->security == WIFI_SECURITY_TYPE_WPA_PSK ||
278 		  params->security == WIFI_SECURITY_TYPE_PSK_SHA256) &&
279 	     ((params->psk_length < 8) || (params->psk_length > 64) ||
280 	      (params->psk_length == 0U) || !params->psk)) ||
281 	    ((params->security == WIFI_SECURITY_TYPE_SAE) &&
282 	      ((params->psk_length == 0U) || !params->psk) &&
283 		  ((params->sae_password_length == 0U) || !params->sae_password)) ||
284 	    ((params->channel != WIFI_CHANNEL_ANY) &&
285 	     (params->channel > WIFI_CHANNEL_MAX)) ||
286 	    !params->ssid) {
287 		return -EINVAL;
288 	}
289 
290 	return wifi_mgmt_api->connect(dev, params);
291 }
292 
293 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_CONNECT, wifi_connect);
294 
scan_result_cb(struct net_if * iface,int status,struct wifi_scan_result * entry)295 static void scan_result_cb(struct net_if *iface, int status,
296 			    struct wifi_scan_result *entry)
297 {
298 	if (!iface) {
299 		return;
300 	}
301 
302 	if (!entry) {
303 		struct wifi_status scan_status = {
304 			.status = status,
305 		};
306 
307 		net_mgmt_event_notify_with_info(NET_EVENT_WIFI_SCAN_DONE,
308 						iface, &scan_status,
309 						sizeof(struct wifi_status));
310 		return;
311 	}
312 
313 #ifndef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS_ONLY
314 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_SCAN_RESULT, iface,
315 					entry, sizeof(struct wifi_scan_result));
316 #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS_ONLY */
317 }
318 
wifi_scan(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)319 static int wifi_scan(uint32_t mgmt_request, struct net_if *iface,
320 		     void *data, size_t len)
321 {
322 	const struct device *dev = net_if_get_device(iface);
323 	struct wifi_scan_params *params = data;
324 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
325 
326 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->scan == NULL) {
327 		return -ENOTSUP;
328 	}
329 
330 #ifdef CONFIG_WIFI_MGMT_FORCED_PASSIVE_SCAN
331 	struct wifi_scan_params default_params = {0};
332 
333 	if (params == NULL) {
334 		params = &default_params;
335 	}
336 	params->scan_type = WIFI_SCAN_TYPE_PASSIVE;
337 #endif /* CONFIG_WIFI_MGMT_FORCED_PASSIVE_SCAN */
338 
339 	return wifi_mgmt_api->scan(dev, params, scan_result_cb);
340 }
341 
342 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_SCAN, wifi_scan);
343 
wifi_disconnect(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)344 static int wifi_disconnect(uint32_t mgmt_request, struct net_if *iface,
345 			   void *data, size_t len)
346 {
347 	const struct device *dev = net_if_get_device(iface);
348 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
349 
350 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->disconnect == NULL) {
351 		return -ENOTSUP;
352 	}
353 
354 	return wifi_mgmt_api->disconnect(dev);
355 }
356 
357 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_DISCONNECT, wifi_disconnect);
358 
wifi_mgmt_raise_connect_result_event(struct net_if * iface,int status)359 void wifi_mgmt_raise_connect_result_event(struct net_if *iface, int status)
360 {
361 	struct wifi_status cnx_status = {
362 		.status = status,
363 	};
364 
365 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_CONNECT_RESULT,
366 					iface, &cnx_status,
367 					sizeof(struct wifi_status));
368 }
369 
wifi_mgmt_raise_disconnect_result_event(struct net_if * iface,int status)370 void wifi_mgmt_raise_disconnect_result_event(struct net_if *iface, int status)
371 {
372 	struct wifi_status cnx_status = {
373 		.status = status,
374 	};
375 
376 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_DISCONNECT_RESULT,
377 					iface, &cnx_status,
378 					sizeof(struct wifi_status));
379 }
380 
wifi_ap_enable(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)381 static int wifi_ap_enable(uint32_t mgmt_request, struct net_if *iface,
382 			  void *data, size_t len)
383 {
384 	struct wifi_connect_req_params *params =
385 		(struct wifi_connect_req_params *)data;
386 	const struct device *dev = net_if_get_device(iface);
387 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
388 
389 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_enable == NULL) {
390 		return -ENOTSUP;
391 	}
392 
393 	return wifi_mgmt_api->ap_enable(dev, params);
394 }
395 
396 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_ENABLE, wifi_ap_enable);
397 
wifi_ap_disable(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)398 static int wifi_ap_disable(uint32_t mgmt_request, struct net_if *iface,
399 			  void *data, size_t len)
400 {
401 	const struct device *dev = net_if_get_device(iface);
402 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
403 
404 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_enable == NULL) {
405 		return -ENOTSUP;
406 	}
407 
408 	return wifi_mgmt_api->ap_disable(dev);
409 }
410 
411 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_DISABLE, wifi_ap_disable);
412 
wifi_ap_sta_disconnect(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)413 static int wifi_ap_sta_disconnect(uint32_t mgmt_request, struct net_if *iface,
414 				  void *data, size_t len)
415 {
416 	const struct device *dev = net_if_get_device(iface);
417 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
418 	uint8_t *mac = data;
419 
420 	if (dev == NULL) {
421 		return -ENODEV;
422 	}
423 
424 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_sta_disconnect == NULL) {
425 		return -ENOTSUP;
426 	}
427 
428 	if (!data || len != sizeof(uint8_t) * WIFI_MAC_ADDR_LEN) {
429 		return -EINVAL;
430 	}
431 
432 	return wifi_mgmt_api->ap_sta_disconnect(dev, mac);
433 }
434 
435 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_STA_DISCONNECT, wifi_ap_sta_disconnect);
436 
wifi_iface_status(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)437 static int wifi_iface_status(uint32_t mgmt_request, struct net_if *iface,
438 			  void *data, size_t len)
439 {
440 	const struct device *dev = net_if_get_device(iface);
441 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
442 	struct wifi_iface_status *status = data;
443 
444 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->iface_status == NULL) {
445 		return -ENOTSUP;
446 	}
447 
448 	if (!data || len != sizeof(*status)) {
449 		return -EINVAL;
450 	}
451 
452 	return wifi_mgmt_api->iface_status(dev, status);
453 }
454 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_IFACE_STATUS, wifi_iface_status);
455 
wifi_mgmt_raise_iface_status_event(struct net_if * iface,struct wifi_iface_status * iface_status)456 void wifi_mgmt_raise_iface_status_event(struct net_if *iface,
457 		struct wifi_iface_status *iface_status)
458 {
459 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_IFACE_STATUS,
460 					iface, iface_status,
461 					sizeof(struct wifi_iface_status));
462 }
463 
464 #ifdef CONFIG_NET_STATISTICS_WIFI
wifi_iface_stats(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)465 static int wifi_iface_stats(uint32_t mgmt_request, struct net_if *iface,
466 			  void *data, size_t len)
467 {
468 	const struct device *dev = net_if_get_device(iface);
469 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
470 	struct net_stats_wifi *stats = data;
471 
472 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->get_stats == NULL) {
473 		return -ENOTSUP;
474 	}
475 
476 	if (!data || len != sizeof(*stats)) {
477 		return -EINVAL;
478 	}
479 
480 	return wifi_mgmt_api->get_stats(dev, stats);
481 }
482 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_WIFI, wifi_iface_stats);
483 #endif /* CONFIG_NET_STATISTICS_WIFI */
484 
wifi_set_power_save(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)485 static int wifi_set_power_save(uint32_t mgmt_request, struct net_if *iface,
486 			  void *data, size_t len)
487 {
488 	const struct device *dev = net_if_get_device(iface);
489 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
490 	struct wifi_ps_params *ps_params = data;
491 	struct wifi_iface_status info = { 0 };
492 
493 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->set_power_save == NULL) {
494 		return -ENOTSUP;
495 	}
496 
497 	switch (ps_params->type) {
498 	case WIFI_PS_PARAM_LISTEN_INTERVAL:
499 	case WIFI_PS_PARAM_MODE:
500 		if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &info,
501 			     sizeof(struct wifi_iface_status))) {
502 			ps_params->fail_reason =
503 				WIFI_PS_PARAM_FAIL_UNABLE_TO_GET_IFACE_STATUS;
504 			return -EIO;
505 		}
506 
507 		if (info.state == WIFI_STATE_COMPLETED) {
508 			ps_params->fail_reason =
509 				WIFI_PS_PARAM_FAIL_DEVICE_CONNECTED;
510 			return -ENOTSUP;
511 		}
512 		break;
513 	case WIFI_PS_PARAM_STATE:
514 	case WIFI_PS_PARAM_WAKEUP_MODE:
515 	case WIFI_PS_PARAM_TIMEOUT:
516 		break;
517 	default:
518 		ps_params->fail_reason =
519 			WIFI_PS_PARAM_FAIL_OPERATION_NOT_SUPPORTED;
520 		return -ENOTSUP;
521 	}
522 
523 	return wifi_mgmt_api->set_power_save(dev, ps_params);
524 }
525 
526 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_PS, wifi_set_power_save);
527 
wifi_get_power_save_config(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)528 static int wifi_get_power_save_config(uint32_t mgmt_request, struct net_if *iface,
529 			  void *data, size_t len)
530 {
531 	const struct device *dev = net_if_get_device(iface);
532 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
533 	struct wifi_ps_config *ps_config = data;
534 
535 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->get_power_save_config == NULL) {
536 		return -ENOTSUP;
537 	}
538 
539 	if (!data || len != sizeof(*ps_config)) {
540 		return -EINVAL;
541 	}
542 
543 	return wifi_mgmt_api->get_power_save_config(dev, ps_config);
544 }
545 
546 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_PS_CONFIG, wifi_get_power_save_config);
547 
wifi_set_twt(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)548 static int wifi_set_twt(uint32_t mgmt_request, struct net_if *iface,
549 			  void *data, size_t len)
550 {
551 	const struct device *dev = net_if_get_device(iface);
552 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
553 	struct wifi_twt_params *twt_params = data;
554 	struct wifi_iface_status info = { 0 };
555 
556 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->set_twt == NULL) {
557 		twt_params->fail_reason =
558 			WIFI_TWT_FAIL_OPERATION_NOT_SUPPORTED;
559 		return -ENOTSUP;
560 	}
561 
562 	if (twt_params->operation == WIFI_TWT_TEARDOWN) {
563 		return wifi_mgmt_api->set_twt(dev, twt_params);
564 	}
565 
566 	if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &info,
567 			sizeof(struct wifi_iface_status))) {
568 		twt_params->fail_reason =
569 			WIFI_TWT_FAIL_UNABLE_TO_GET_IFACE_STATUS;
570 		goto fail;
571 	}
572 
573 	if (info.state != WIFI_STATE_COMPLETED) {
574 		twt_params->fail_reason =
575 			WIFI_TWT_FAIL_DEVICE_NOT_CONNECTED;
576 		goto fail;
577 	}
578 
579 #ifdef CONFIG_WIFI_MGMT_TWT_CHECK_IP
580 	if ((!net_if_ipv4_get_global_addr(iface, NET_ADDR_PREFERRED)) &&
581 	    (!net_if_ipv6_get_global_addr(NET_ADDR_PREFERRED, &iface))) {
582 		twt_params->fail_reason =
583 			WIFI_TWT_FAIL_IP_NOT_ASSIGNED;
584 		goto fail;
585 	}
586 #else
587 	NET_WARN("Check for valid IP address been disabled. "
588 		 "Device might be unreachable or might not receive traffic.\n");
589 #endif /* CONFIG_WIFI_MGMT_TWT_CHECK_IP */
590 
591 	if (info.link_mode < WIFI_6) {
592 		twt_params->fail_reason =
593 			WIFI_TWT_FAIL_PEER_NOT_HE_CAPAB;
594 		goto fail;
595 	}
596 
597 	if (!info.twt_capable) {
598 		twt_params->fail_reason =
599 			WIFI_TWT_FAIL_PEER_NOT_TWT_CAPAB;
600 		goto fail;
601 	}
602 
603 	return wifi_mgmt_api->set_twt(dev, twt_params);
604 fail:
605 	return -ENOEXEC;
606 
607 }
608 
609 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_TWT, wifi_set_twt);
610 
wifi_mgmt_raise_twt_event(struct net_if * iface,struct wifi_twt_params * twt_params)611 void wifi_mgmt_raise_twt_event(struct net_if *iface, struct wifi_twt_params *twt_params)
612 {
613 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_TWT,
614 					iface, twt_params,
615 					sizeof(struct wifi_twt_params));
616 }
617 
wifi_reg_domain(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)618 static int wifi_reg_domain(uint32_t mgmt_request, struct net_if *iface,
619 			   void *data, size_t len)
620 {
621 	const struct device *dev = net_if_get_device(iface);
622 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
623 	struct wifi_reg_domain *reg_domain = data;
624 
625 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->reg_domain == NULL) {
626 		return -ENOTSUP;
627 	}
628 
629 	if (!data || len != sizeof(*reg_domain)) {
630 		return -EINVAL;
631 	}
632 
633 	return wifi_mgmt_api->reg_domain(dev, reg_domain);
634 }
635 
636 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_REG_DOMAIN, wifi_reg_domain);
637 
wifi_mgmt_raise_twt_sleep_state(struct net_if * iface,int twt_sleep_state)638 void wifi_mgmt_raise_twt_sleep_state(struct net_if *iface,
639 				     int twt_sleep_state)
640 {
641 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_TWT_SLEEP_STATE,
642 					iface, &twt_sleep_state,
643 					sizeof(twt_sleep_state));
644 }
645 
wifi_mode(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)646 static int wifi_mode(uint32_t mgmt_request, struct net_if *iface,
647 				void *data, size_t len)
648 {
649 	const struct device *dev = net_if_get_device(iface);
650 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
651 	struct wifi_mode_info *mode_info = data;
652 
653 	if (dev == NULL) {
654 		return -ENODEV;
655 	}
656 
657 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->mode == NULL) {
658 		return -ENOTSUP;
659 	}
660 
661 	return wifi_mgmt_api->mode(dev, mode_info);
662 }
663 
664 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_MODE, wifi_mode);
665 
wifi_packet_filter(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)666 static int wifi_packet_filter(uint32_t mgmt_request, struct net_if *iface,
667 				void *data, size_t len)
668 {
669 	const struct device *dev = net_if_get_device(iface);
670 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
671 	struct wifi_filter_info *filter_info = data;
672 
673 	if (dev == NULL) {
674 		return -ENODEV;
675 	}
676 
677 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->filter == NULL) {
678 		return -ENOTSUP;
679 	}
680 
681 	return wifi_mgmt_api->filter(dev, filter_info);
682 }
683 
684 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_PACKET_FILTER, wifi_packet_filter);
685 
wifi_channel(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)686 static int wifi_channel(uint32_t mgmt_request, struct net_if *iface,
687 				void *data, size_t len)
688 {
689 	const struct device *dev = net_if_get_device(iface);
690 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
691 	struct wifi_channel_info *channel_info = data;
692 
693 	if (dev == NULL) {
694 		return -ENODEV;
695 	}
696 
697 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->channel == NULL) {
698 		return -ENOTSUP;
699 	}
700 
701 	return wifi_mgmt_api->channel(dev, channel_info);
702 }
703 
704 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_CHANNEL, wifi_channel);
705 
wifi_get_version(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)706 static int wifi_get_version(uint32_t mgmt_request, struct net_if *iface,
707 			   void *data, size_t len)
708 {
709 	const struct device *dev = net_if_get_device(iface);
710 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
711 	struct wifi_version *ver_params = data;
712 
713 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->get_version == NULL) {
714 		return -ENOTSUP;
715 	}
716 
717 	return wifi_mgmt_api->get_version(dev, ver_params);
718 }
719 
720 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_VERSION, wifi_get_version);
721 
722 #ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS
wifi_mgmt_raise_raw_scan_result_event(struct net_if * iface,struct wifi_raw_scan_result * raw_scan_result)723 void wifi_mgmt_raise_raw_scan_result_event(struct net_if *iface,
724 					   struct wifi_raw_scan_result *raw_scan_result)
725 {
726 	if (raw_scan_result->frame_length > CONFIG_WIFI_MGMT_RAW_SCAN_RESULT_LENGTH) {
727 		LOG_INF("raw scan result frame length = %d too big,"
728 			 "saving upto max raw scan length = %d",
729 			 raw_scan_result->frame_length,
730 			 CONFIG_WIFI_MGMT_RAW_SCAN_RESULT_LENGTH);
731 	}
732 
733 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_RAW_SCAN_RESULT,
734 					iface, raw_scan_result,
735 					sizeof(*raw_scan_result));
736 }
737 #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */
738 
wifi_mgmt_raise_disconnect_complete_event(struct net_if * iface,int status)739 void wifi_mgmt_raise_disconnect_complete_event(struct net_if *iface,
740 					       int status)
741 {
742 	struct wifi_status cnx_status = {
743 		.status = status,
744 	};
745 
746 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_DISCONNECT_COMPLETE,
747 					iface, &cnx_status,
748 					sizeof(struct wifi_status));
749 }
750 
wifi_mgmt_raise_ap_enable_result_event(struct net_if * iface,enum wifi_ap_status status)751 void wifi_mgmt_raise_ap_enable_result_event(struct net_if *iface,
752 					    enum wifi_ap_status status)
753 {
754 	struct wifi_status cnx_status = {
755 		.status = status,
756 	};
757 
758 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_AP_ENABLE_RESULT,
759 					iface, &cnx_status,
760 					sizeof(enum wifi_ap_status));
761 }
762 
wifi_mgmt_raise_ap_disable_result_event(struct net_if * iface,enum wifi_ap_status status)763 void wifi_mgmt_raise_ap_disable_result_event(struct net_if *iface,
764 					     enum wifi_ap_status status)
765 {
766 	struct wifi_status cnx_status = {
767 		.status = status,
768 	};
769 
770 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_AP_DISABLE_RESULT,
771 					iface, &cnx_status,
772 					sizeof(enum wifi_ap_status));
773 }
774 
wifi_mgmt_raise_ap_sta_connected_event(struct net_if * iface,struct wifi_ap_sta_info * sta_info)775 void wifi_mgmt_raise_ap_sta_connected_event(struct net_if *iface,
776 					    struct wifi_ap_sta_info *sta_info)
777 {
778 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_AP_STA_CONNECTED,
779 					iface, sta_info,
780 					sizeof(struct wifi_ap_sta_info));
781 }
782 
wifi_mgmt_raise_ap_sta_disconnected_event(struct net_if * iface,struct wifi_ap_sta_info * sta_info)783 void wifi_mgmt_raise_ap_sta_disconnected_event(struct net_if *iface,
784 					       struct wifi_ap_sta_info *sta_info)
785 {
786 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_AP_STA_DISCONNECTED,
787 					iface, sta_info,
788 					sizeof(struct wifi_ap_sta_info));
789 }
790