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 * const 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 * const 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 * const 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 * const 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 * const 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 * const 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 * const 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 * const 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 * const 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 * const 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 * const 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 * const 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_PSK_SHA256) &&
278 	     ((params->psk_length < 8) || (params->psk_length > 64) ||
279 	      (params->psk_length == 0U) || !params->psk)) ||
280 	    ((params->security == WIFI_SECURITY_TYPE_SAE) &&
281 	      ((params->psk_length == 0U) || !params->psk) &&
282 		  ((params->sae_password_length == 0U) || !params->sae_password)) ||
283 	    ((params->channel != WIFI_CHANNEL_ANY) &&
284 	     (params->channel > WIFI_CHANNEL_MAX)) ||
285 	    !params->ssid) {
286 		return -EINVAL;
287 	}
288 
289 	return wifi_mgmt_api->connect(dev, params);
290 }
291 
292 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_CONNECT, wifi_connect);
293 
scan_result_cb(struct net_if * iface,int status,struct wifi_scan_result * entry)294 static void scan_result_cb(struct net_if *iface, int status,
295 			    struct wifi_scan_result *entry)
296 {
297 	if (!iface) {
298 		return;
299 	}
300 
301 	if (!entry) {
302 		struct wifi_status scan_status = {
303 			.status = status,
304 		};
305 
306 		net_mgmt_event_notify_with_info(NET_EVENT_WIFI_SCAN_DONE,
307 						iface, &scan_status,
308 						sizeof(struct wifi_status));
309 		return;
310 	}
311 
312 #ifndef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS_ONLY
313 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_SCAN_RESULT, iface,
314 					entry, sizeof(struct wifi_scan_result));
315 #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS_ONLY */
316 }
317 
wifi_scan(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)318 static int wifi_scan(uint32_t mgmt_request, struct net_if *iface,
319 		     void *data, size_t len)
320 {
321 	const struct device *dev = net_if_get_device(iface);
322 	struct wifi_scan_params *params = data;
323 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
324 
325 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->scan == NULL) {
326 		return -ENOTSUP;
327 	}
328 
329 #ifdef CONFIG_WIFI_MGMT_FORCED_PASSIVE_SCAN
330 	struct wifi_scan_params default_params = {0};
331 
332 	if (params == NULL) {
333 		params = &default_params;
334 	}
335 	params->scan_type = WIFI_SCAN_TYPE_PASSIVE;
336 #endif /* CONFIG_WIFI_MGMT_FORCED_PASSIVE_SCAN */
337 
338 	return wifi_mgmt_api->scan(dev, params, scan_result_cb);
339 }
340 
341 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_SCAN, wifi_scan);
342 
wifi_disconnect(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)343 static int wifi_disconnect(uint32_t mgmt_request, struct net_if *iface,
344 			   void *data, size_t len)
345 {
346 	const struct device *dev = net_if_get_device(iface);
347 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
348 
349 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->disconnect == NULL) {
350 		return -ENOTSUP;
351 	}
352 
353 	return wifi_mgmt_api->disconnect(dev);
354 }
355 
356 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_DISCONNECT, wifi_disconnect);
357 
wifi_mgmt_raise_connect_result_event(struct net_if * iface,int status)358 void wifi_mgmt_raise_connect_result_event(struct net_if *iface, int status)
359 {
360 	struct wifi_status cnx_status = {
361 		.status = status,
362 	};
363 
364 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_CONNECT_RESULT,
365 					iface, &cnx_status,
366 					sizeof(struct wifi_status));
367 }
368 
wifi_mgmt_raise_disconnect_result_event(struct net_if * iface,int status)369 void wifi_mgmt_raise_disconnect_result_event(struct net_if *iface, int status)
370 {
371 	struct wifi_status cnx_status = {
372 		.status = status,
373 	};
374 
375 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_DISCONNECT_RESULT,
376 					iface, &cnx_status,
377 					sizeof(struct wifi_status));
378 }
379 
wifi_ap_enable(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)380 static int wifi_ap_enable(uint32_t mgmt_request, struct net_if *iface,
381 			  void *data, size_t len)
382 {
383 	struct wifi_connect_req_params *params =
384 		(struct wifi_connect_req_params *)data;
385 	const struct device *dev = net_if_get_device(iface);
386 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
387 
388 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_enable == NULL) {
389 		return -ENOTSUP;
390 	}
391 
392 	return wifi_mgmt_api->ap_enable(dev, params);
393 }
394 
395 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_ENABLE, wifi_ap_enable);
396 
wifi_ap_disable(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)397 static int wifi_ap_disable(uint32_t mgmt_request, struct net_if *iface,
398 			  void *data, size_t len)
399 {
400 	const struct device *dev = net_if_get_device(iface);
401 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
402 
403 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->ap_enable == NULL) {
404 		return -ENOTSUP;
405 	}
406 
407 	return wifi_mgmt_api->ap_disable(dev);
408 }
409 
410 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_DISABLE, wifi_ap_disable);
411 
wifi_iface_status(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)412 static int wifi_iface_status(uint32_t mgmt_request, struct net_if *iface,
413 			  void *data, size_t len)
414 {
415 	const struct device *dev = net_if_get_device(iface);
416 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
417 	struct wifi_iface_status *status = data;
418 
419 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->iface_status == NULL) {
420 		return -ENOTSUP;
421 	}
422 
423 	if (!data || len != sizeof(*status)) {
424 		return -EINVAL;
425 	}
426 
427 	return wifi_mgmt_api->iface_status(dev, status);
428 }
429 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_IFACE_STATUS, wifi_iface_status);
430 
wifi_mgmt_raise_iface_status_event(struct net_if * iface,struct wifi_iface_status * iface_status)431 void wifi_mgmt_raise_iface_status_event(struct net_if *iface,
432 		struct wifi_iface_status *iface_status)
433 {
434 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_IFACE_STATUS,
435 					iface, iface_status,
436 					sizeof(struct wifi_iface_status));
437 }
438 
439 #ifdef CONFIG_NET_STATISTICS_WIFI
wifi_iface_stats(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)440 static int wifi_iface_stats(uint32_t mgmt_request, struct net_if *iface,
441 			  void *data, size_t len)
442 {
443 	const struct device *dev = net_if_get_device(iface);
444 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
445 	struct net_stats_wifi *stats = data;
446 
447 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->get_stats == NULL) {
448 		return -ENOTSUP;
449 	}
450 
451 	if (!data || len != sizeof(*stats)) {
452 		return -EINVAL;
453 	}
454 
455 	return wifi_mgmt_api->get_stats(dev, stats);
456 }
457 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_WIFI, wifi_iface_stats);
458 #endif /* CONFIG_NET_STATISTICS_WIFI */
459 
wifi_set_power_save(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)460 static int wifi_set_power_save(uint32_t mgmt_request, struct net_if *iface,
461 			  void *data, size_t len)
462 {
463 	const struct device *dev = net_if_get_device(iface);
464 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
465 	struct wifi_ps_params *ps_params = data;
466 	struct wifi_iface_status info = { 0 };
467 
468 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->set_power_save == NULL) {
469 		return -ENOTSUP;
470 	}
471 
472 	switch (ps_params->type) {
473 	case WIFI_PS_PARAM_LISTEN_INTERVAL:
474 	case WIFI_PS_PARAM_MODE:
475 		if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &info,
476 			     sizeof(struct wifi_iface_status))) {
477 			ps_params->fail_reason =
478 				WIFI_PS_PARAM_FAIL_UNABLE_TO_GET_IFACE_STATUS;
479 			return -EIO;
480 		}
481 
482 		if (info.state == WIFI_STATE_COMPLETED) {
483 			ps_params->fail_reason =
484 				WIFI_PS_PARAM_FAIL_DEVICE_CONNECTED;
485 			return -ENOTSUP;
486 		}
487 		break;
488 	case WIFI_PS_PARAM_STATE:
489 	case WIFI_PS_PARAM_WAKEUP_MODE:
490 	case WIFI_PS_PARAM_TIMEOUT:
491 		break;
492 	default:
493 		ps_params->fail_reason =
494 			WIFI_PS_PARAM_FAIL_OPERATION_NOT_SUPPORTED;
495 		return -ENOTSUP;
496 	}
497 
498 	return wifi_mgmt_api->set_power_save(dev, ps_params);
499 }
500 
501 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_PS, wifi_set_power_save);
502 
wifi_get_power_save_config(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)503 static int wifi_get_power_save_config(uint32_t mgmt_request, struct net_if *iface,
504 			  void *data, size_t len)
505 {
506 	const struct device *dev = net_if_get_device(iface);
507 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
508 	struct wifi_ps_config *ps_config = data;
509 
510 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->get_power_save_config == NULL) {
511 		return -ENOTSUP;
512 	}
513 
514 	if (!data || len != sizeof(*ps_config)) {
515 		return -EINVAL;
516 	}
517 
518 	return wifi_mgmt_api->get_power_save_config(dev, ps_config);
519 }
520 
521 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_PS_CONFIG, wifi_get_power_save_config);
522 
wifi_set_twt(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)523 static int wifi_set_twt(uint32_t mgmt_request, struct net_if *iface,
524 			  void *data, size_t len)
525 {
526 	const struct device *dev = net_if_get_device(iface);
527 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
528 	struct wifi_twt_params *twt_params = data;
529 	struct wifi_iface_status info = { 0 };
530 
531 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->set_twt == NULL) {
532 		twt_params->fail_reason =
533 			WIFI_TWT_FAIL_OPERATION_NOT_SUPPORTED;
534 		return -ENOTSUP;
535 	}
536 
537 	if (twt_params->operation == WIFI_TWT_TEARDOWN) {
538 		return wifi_mgmt_api->set_twt(dev, twt_params);
539 	}
540 
541 	if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &info,
542 			sizeof(struct wifi_iface_status))) {
543 		twt_params->fail_reason =
544 			WIFI_TWT_FAIL_UNABLE_TO_GET_IFACE_STATUS;
545 		goto fail;
546 	}
547 
548 	if (info.state != WIFI_STATE_COMPLETED) {
549 		twt_params->fail_reason =
550 			WIFI_TWT_FAIL_DEVICE_NOT_CONNECTED;
551 		goto fail;
552 	}
553 
554 #ifdef CONFIG_WIFI_MGMT_TWT_CHECK_IP
555 	if ((!net_if_ipv4_get_global_addr(iface, NET_ADDR_PREFERRED)) &&
556 	    (!net_if_ipv6_get_global_addr(NET_ADDR_PREFERRED, &iface))) {
557 		twt_params->fail_reason =
558 			WIFI_TWT_FAIL_IP_NOT_ASSIGNED;
559 		goto fail;
560 	}
561 #else
562 	NET_WARN("Check for valid IP address been disabled. "
563 		 "Device might be unreachable or might not receive traffic.\n");
564 #endif /* CONFIG_WIFI_MGMT_TWT_CHECK_IP */
565 
566 	if (info.link_mode < WIFI_6) {
567 		twt_params->fail_reason =
568 			WIFI_TWT_FAIL_PEER_NOT_HE_CAPAB;
569 		goto fail;
570 	}
571 
572 	if (!info.twt_capable) {
573 		twt_params->fail_reason =
574 			WIFI_TWT_FAIL_PEER_NOT_TWT_CAPAB;
575 		goto fail;
576 	}
577 
578 	return wifi_mgmt_api->set_twt(dev, twt_params);
579 fail:
580 	return -ENOEXEC;
581 
582 }
583 
584 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_TWT, wifi_set_twt);
585 
wifi_mgmt_raise_twt_event(struct net_if * iface,struct wifi_twt_params * twt_params)586 void wifi_mgmt_raise_twt_event(struct net_if *iface, struct wifi_twt_params *twt_params)
587 {
588 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_TWT,
589 					iface, twt_params,
590 					sizeof(struct wifi_twt_params));
591 }
592 
wifi_reg_domain(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)593 static int wifi_reg_domain(uint32_t mgmt_request, struct net_if *iface,
594 			   void *data, size_t len)
595 {
596 	const struct device *dev = net_if_get_device(iface);
597 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
598 	struct wifi_reg_domain *reg_domain = data;
599 
600 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->reg_domain == NULL) {
601 		return -ENOTSUP;
602 	}
603 
604 	if (!data || len != sizeof(*reg_domain)) {
605 		return -EINVAL;
606 	}
607 
608 	return wifi_mgmt_api->reg_domain(dev, reg_domain);
609 }
610 
611 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_REG_DOMAIN, wifi_reg_domain);
612 
wifi_mgmt_raise_twt_sleep_state(struct net_if * iface,int twt_sleep_state)613 void wifi_mgmt_raise_twt_sleep_state(struct net_if *iface,
614 				     int twt_sleep_state)
615 {
616 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_TWT_SLEEP_STATE,
617 					iface, &twt_sleep_state,
618 					sizeof(twt_sleep_state));
619 }
620 
wifi_mode(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)621 static int wifi_mode(uint32_t mgmt_request, struct net_if *iface,
622 				void *data, size_t len)
623 {
624 	const struct device *dev = net_if_get_device(iface);
625 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
626 	struct wifi_mode_info *mode_info = data;
627 
628 	if (dev == NULL) {
629 		return -ENODEV;
630 	}
631 
632 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->mode == NULL) {
633 		return -ENOTSUP;
634 	}
635 
636 	return wifi_mgmt_api->mode(dev, mode_info);
637 }
638 
639 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_MODE, wifi_mode);
640 
wifi_packet_filter(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)641 static int wifi_packet_filter(uint32_t mgmt_request, struct net_if *iface,
642 				void *data, size_t len)
643 {
644 	const struct device *dev = net_if_get_device(iface);
645 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
646 	struct wifi_filter_info *filter_info = data;
647 
648 	if (dev == NULL) {
649 		return -ENODEV;
650 	}
651 
652 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->filter == NULL) {
653 		return -ENOTSUP;
654 	}
655 
656 	return wifi_mgmt_api->filter(dev, filter_info);
657 }
658 
659 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_PACKET_FILTER, wifi_packet_filter);
660 
wifi_channel(uint32_t mgmt_request,struct net_if * iface,void * data,size_t len)661 static int wifi_channel(uint32_t mgmt_request, struct net_if *iface,
662 				void *data, size_t len)
663 {
664 	const struct device *dev = net_if_get_device(iface);
665 	const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
666 	struct wifi_channel_info *channel_info = data;
667 
668 	if (dev == NULL) {
669 		return -ENODEV;
670 	}
671 
672 	if (wifi_mgmt_api == NULL || wifi_mgmt_api->channel == NULL) {
673 		return -ENOTSUP;
674 	}
675 
676 	return wifi_mgmt_api->channel(dev, channel_info);
677 }
678 
679 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_CHANNEL, wifi_channel);
680 
681 #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)682 void wifi_mgmt_raise_raw_scan_result_event(struct net_if *iface,
683 					   struct wifi_raw_scan_result *raw_scan_result)
684 {
685 	if (raw_scan_result->frame_length > CONFIG_WIFI_MGMT_RAW_SCAN_RESULT_LENGTH) {
686 		LOG_INF("raw scan result frame length = %d too big,"
687 			 "saving upto max raw scan length = %d",
688 			 raw_scan_result->frame_length,
689 			 CONFIG_WIFI_MGMT_RAW_SCAN_RESULT_LENGTH);
690 	}
691 
692 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_RAW_SCAN_RESULT,
693 					iface, raw_scan_result,
694 					sizeof(*raw_scan_result));
695 }
696 #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */
697 
wifi_mgmt_raise_disconnect_complete_event(struct net_if * iface,int status)698 void wifi_mgmt_raise_disconnect_complete_event(struct net_if *iface,
699 					       int status)
700 {
701 	struct wifi_status cnx_status = {
702 		.status = status,
703 	};
704 
705 	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_DISCONNECT_COMPLETE,
706 					iface, &cnx_status,
707 					sizeof(struct wifi_status));
708 }
709