1 /*
2  * Copyright (c) 2016 Intel Corporation
3  * Copyright (c) 2023 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/logging/log.h>
9 LOG_MODULE_DECLARE(net_shell);
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/shell/shell_uart.h>
13 #include <zephyr/net/net_mgmt.h>
14 #include <zephyr/net/net_event.h>
15 #include <zephyr/net/coap_mgmt.h>
16 #include <zephyr/net/ethernet_mgmt.h>
17 
18 #include "net_shell_private.h"
19 
20 #if defined(CONFIG_NET_MGMT_EVENT_MONITOR)
21 #define THREAD_PRIORITY K_PRIO_COOP(2)
22 #define MAX_EVENT_INFO_SIZE NET_EVENT_INFO_MAX_SIZE
23 #define MONITOR_L2_MASK (_NET_EVENT_IF_BASE)
24 #define MONITOR_L3_IPV4_MASK (_NET_EVENT_IPV4_BASE | NET_MGMT_COMMAND_MASK)
25 #define MONITOR_L3_IPV6_MASK (_NET_EVENT_IPV6_BASE | NET_MGMT_COMMAND_MASK)
26 #define MONITOR_L4_MASK (_NET_EVENT_L4_BASE | NET_MGMT_COMMAND_MASK)
27 
28 #if defined(CONFIG_NET_L2_ETHERNET_MGMT)
29 #define MONITOR_L2_ETHERNET_MASK (_NET_ETHERNET_BASE)
30 static struct net_mgmt_event_callback l2_ethernet_cb;
31 #endif
32 
33 static bool net_event_monitoring;
34 static bool net_event_shutting_down;
35 static struct net_mgmt_event_callback l2_cb;
36 static struct net_mgmt_event_callback l3_ipv4_cb;
37 static struct net_mgmt_event_callback l3_ipv6_cb;
38 static struct net_mgmt_event_callback l4_cb;
39 static struct k_thread event_mon;
40 static K_THREAD_STACK_DEFINE(event_mon_stack, CONFIG_NET_MGMT_EVENT_MONITOR_STACK_SIZE);
41 
42 static const char unknown_event_str[] = "<unknown event>";
43 
44 struct event_msg {
45 	struct net_if *iface;
46 	size_t len;
47 	uint32_t event;
48 	uint8_t data[MAX_EVENT_INFO_SIZE];
49 };
50 
51 K_MSGQ_DEFINE(event_mon_msgq, sizeof(struct event_msg),
52 	      CONFIG_NET_MGMT_EVENT_QUEUE_SIZE, sizeof(intptr_t));
53 
event_handler(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)54 static void event_handler(struct net_mgmt_event_callback *cb,
55 			  uint32_t mgmt_event, struct net_if *iface)
56 {
57 	struct event_msg msg;
58 	int ret;
59 
60 	memset(&msg, 0, sizeof(msg));
61 
62 	msg.len = MIN(sizeof(msg.data), cb->info_length);
63 	msg.event = mgmt_event;
64 	msg.iface = iface;
65 
66 	if (cb->info_length > 0) {
67 		memcpy(msg.data, cb->info, msg.len);
68 	}
69 
70 	ret = k_msgq_put(&event_mon_msgq, (void *)&msg, K_MSEC(10));
71 	if (ret < 0) {
72 		NET_ERR("Cannot write to msgq (%d)\n", ret);
73 	}
74 }
75 
get_l2_desc(struct event_msg * msg,const char ** desc,const char ** desc2,char * extra_info,size_t extra_info_len)76 static char *get_l2_desc(struct event_msg *msg,
77 			 const char **desc, const char **desc2,
78 			 char *extra_info, size_t extra_info_len)
79 {
80 	static const char *desc_unknown = unknown_event_str;
81 	char *info = NULL;
82 
83 #if defined(CONFIG_NET_L2_ETHERNET_MGMT)
84 #define MAX_VLAN_TAG_INFO_STR_LEN sizeof("tag xxxx disabled")
85 	static char vlan_buf[MAX_VLAN_TAG_INFO_STR_LEN + 1];
86 #endif
87 
88 	*desc = desc_unknown;
89 
90 	switch (msg->event) {
91 	case NET_EVENT_IF_DOWN:
92 		*desc = "interface";
93 		*desc2 = "down";
94 		break;
95 	case NET_EVENT_IF_UP:
96 		*desc = "interface";
97 		*desc2 = "up";
98 		break;
99 	case NET_EVENT_IF_ADMIN_UP:
100 		*desc = "interface";
101 		*desc2 = "admin up";
102 		break;
103 	case NET_EVENT_IF_ADMIN_DOWN:
104 		*desc = "interface";
105 		*desc2 = "admin down";
106 		break;
107 	case NET_EVENT_ETHERNET_CARRIER_ON:
108 #if defined(CONFIG_NET_L2_ETHERNET_MGMT)
109 		*desc = "Ethernet";
110 		*desc2 = "carrier on";
111 #endif
112 		break;
113 	case NET_EVENT_ETHERNET_CARRIER_OFF:
114 #if defined(CONFIG_NET_L2_ETHERNET_MGMT)
115 		*desc = "Ethernet";
116 		*desc2 = "carrier off";
117 #endif
118 		break;
119 	case NET_EVENT_ETHERNET_VLAN_TAG_ENABLED: {
120 #if defined(CONFIG_NET_L2_ETHERNET_MGMT)
121 		uint16_t tag = *((uint16_t *)msg->data);
122 
123 		*desc = "VLAN";
124 		snprintk(vlan_buf, MAX_VLAN_TAG_INFO_STR_LEN,
125 			 "tag %u enabled", (uint16_t)tag);
126 		*desc2 = vlan_buf;
127 #endif
128 		break;
129 	}
130 	case NET_EVENT_ETHERNET_VLAN_TAG_DISABLED: {
131 #if defined(CONFIG_NET_L2_ETHERNET_MGMT)
132 		uint16_t tag = *((uint16_t *)msg->data);
133 
134 		*desc = "VLAN";
135 		snprintk(vlan_buf, MAX_VLAN_TAG_INFO_STR_LEN,
136 			 "tag %u enabled", (uint16_t)tag);
137 		*desc2 = vlan_buf;
138 #endif
139 		break;
140 	}
141 	}
142 
143 	return info;
144 }
145 
get_l3_desc(struct event_msg * msg,const char ** desc,const char ** desc2,char * extra_info,size_t extra_info_len)146 static char *get_l3_desc(struct event_msg *msg,
147 			 const char **desc, const char **desc2,
148 			 char *extra_info, size_t extra_info_len)
149 {
150 	static const char *desc_unknown = unknown_event_str;
151 	char *info = NULL;
152 
153 #if defined(CONFIG_NET_PMTU)
154 #define MAX_PMTU_INFO_STR_LEN sizeof("changed MTU xxxxx for")
155 	static char pmtu_buf[MAX_PMTU_INFO_STR_LEN + 1];
156 #endif
157 
158 	*desc = desc_unknown;
159 
160 	switch (msg->event) {
161 	case NET_EVENT_IPV6_ADDR_ADD:
162 		*desc = "IPv6 address";
163 		*desc2 = "add";
164 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
165 				     extra_info_len);
166 		break;
167 	case NET_EVENT_IPV6_ADDR_DEPRECATED:
168 		*desc = "IPv6 address";
169 		*desc2 = "deprecated";
170 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
171 				     extra_info_len);
172 		break;
173 	case NET_EVENT_IPV6_ADDR_DEL:
174 		*desc = "IPv6 address";
175 		*desc2 = "del";
176 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
177 				     extra_info_len);
178 		break;
179 	case NET_EVENT_IPV6_MADDR_ADD:
180 		*desc = "IPv6 mcast address";
181 		*desc2 = "add";
182 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
183 				     extra_info_len);
184 		break;
185 	case NET_EVENT_IPV6_MADDR_DEL:
186 		*desc = "IPv6 mcast address";
187 		*desc2 = "del";
188 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
189 				     extra_info_len);
190 		break;
191 	case NET_EVENT_IPV6_PREFIX_ADD:
192 		*desc = "IPv6 prefix";
193 		*desc2 = "add";
194 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
195 				     extra_info_len);
196 		break;
197 	case NET_EVENT_IPV6_PREFIX_DEL:
198 		*desc = "IPv6 prefix";
199 		*desc2 = "del";
200 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
201 				     extra_info_len);
202 		break;
203 	case NET_EVENT_IPV6_MCAST_JOIN:
204 		*desc = "IPv6 mcast";
205 		*desc2 = "join";
206 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
207 				     extra_info_len);
208 		break;
209 	case NET_EVENT_IPV6_MCAST_LEAVE:
210 		*desc = "IPv6 mcast";
211 		*desc2 = "leave";
212 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
213 				     extra_info_len);
214 		break;
215 	case NET_EVENT_IPV6_ROUTER_ADD:
216 		*desc = "IPv6 router";
217 		*desc2 = "add";
218 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
219 				     extra_info_len);
220 		break;
221 	case NET_EVENT_IPV6_ROUTER_DEL:
222 		*desc = "IPv6 router";
223 		*desc2 = "del";
224 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
225 				     extra_info_len);
226 		break;
227 	case NET_EVENT_IPV6_ROUTE_ADD:
228 		*desc = "IPv6 route";
229 		*desc2 = "add";
230 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
231 				     extra_info_len);
232 		break;
233 	case NET_EVENT_IPV6_ROUTE_DEL:
234 		*desc = "IPv6 route";
235 		*desc2 = "del";
236 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
237 				     extra_info_len);
238 		break;
239 	case NET_EVENT_IPV6_DAD_SUCCEED:
240 		*desc = "IPv6 DAD";
241 		*desc2 = "ok";
242 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
243 				     extra_info_len);
244 		break;
245 	case NET_EVENT_IPV6_DAD_FAILED:
246 		*desc = "IPv6 DAD";
247 		*desc2 = "fail";
248 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
249 				     extra_info_len);
250 		break;
251 	case NET_EVENT_IPV6_NBR_ADD:
252 		*desc = "IPv6 neighbor";
253 		*desc2 = "add";
254 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
255 				     extra_info_len);
256 		break;
257 	case NET_EVENT_IPV6_NBR_DEL:
258 		*desc = "IPv6 neighbor";
259 		*desc2 = "del";
260 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
261 				     extra_info_len);
262 		break;
263 	case NET_EVENT_IPV6_PE_ENABLED:
264 		*desc = "IPv6 PE";
265 		*desc2 = "enabled";
266 		break;
267 	case NET_EVENT_IPV6_PE_DISABLED:
268 		*desc = "IPv6 PE";
269 		*desc2 = "disabled";
270 		break;
271 	case NET_EVENT_IPV6_PE_FILTER_ADD:
272 		*desc = "IPv6 PE filter";
273 		*desc2 = "add";
274 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
275 				     extra_info_len);
276 		break;
277 	case NET_EVENT_IPV6_PE_FILTER_DEL:
278 		*desc = "IPv6 PE filter";
279 		*desc2 = "del";
280 		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
281 				     extra_info_len);
282 		break;
283 	case NET_EVENT_IPV4_ADDR_ADD:
284 		*desc = "IPv4 address";
285 		*desc2 = "add";
286 		info = net_addr_ntop(AF_INET, msg->data, extra_info,
287 				     extra_info_len);
288 		break;
289 	case NET_EVENT_IPV4_ADDR_DEL:
290 		*desc = "IPv4 address";
291 		*desc2 = "del";
292 		info = net_addr_ntop(AF_INET, msg->data, extra_info,
293 				     extra_info_len);
294 		break;
295 	case NET_EVENT_IPV4_MADDR_ADD:
296 		*desc = "IPv4 mcast address";
297 		*desc2 = "add";
298 		info = net_addr_ntop(AF_INET, msg->data, extra_info,
299 				     extra_info_len);
300 		break;
301 	case NET_EVENT_IPV4_MADDR_DEL:
302 		*desc = "IPv4 mcast address";
303 		*desc2 = "del";
304 		info = net_addr_ntop(AF_INET, msg->data, extra_info,
305 				     extra_info_len);
306 		break;
307 	case NET_EVENT_IPV4_ROUTER_ADD:
308 		*desc = "IPv4 router";
309 		*desc2 = "add";
310 		info = net_addr_ntop(AF_INET, msg->data, extra_info,
311 				     extra_info_len);
312 		break;
313 	case NET_EVENT_IPV4_ROUTER_DEL:
314 		*desc = "IPv4 router";
315 		*desc2 = "del";
316 		info = net_addr_ntop(AF_INET, msg->data, extra_info,
317 				     extra_info_len);
318 		break;
319 	case NET_EVENT_IPV4_DHCP_START:
320 		*desc = "DHCPv4";
321 		*desc2 = "start";
322 		break;
323 	case NET_EVENT_IPV4_DHCP_BOUND:
324 		*desc = "DHCPv4";
325 		*desc2 = "bound";
326 #if defined(CONFIG_NET_DHCPV4)
327 		struct net_if_dhcpv4 *data = (struct net_if_dhcpv4 *)msg->data;
328 
329 		info = net_addr_ntop(AF_INET, &data->requested_ip, extra_info,
330 				     extra_info_len);
331 #endif
332 		break;
333 	case NET_EVENT_IPV4_DHCP_STOP:
334 		*desc = "DHCPv4";
335 		*desc2 = "stop";
336 		break;
337 	case NET_EVENT_IPV4_MCAST_JOIN:
338 		*desc = "IPv4 mcast";
339 		*desc2 = "join";
340 		info = net_addr_ntop(AF_INET, msg->data, extra_info,
341 				     extra_info_len);
342 		break;
343 	case NET_EVENT_IPV4_MCAST_LEAVE:
344 		*desc = "IPv4 mcast";
345 		*desc2 = "leave";
346 		info = net_addr_ntop(AF_INET, msg->data, extra_info,
347 				     extra_info_len);
348 		break;
349 	case NET_EVENT_IPV4_ACD_SUCCEED:
350 		*desc = "IPv4 ACD";
351 		*desc2 = "ok";
352 		info = net_addr_ntop(AF_INET, msg->data, extra_info,
353 				     extra_info_len);
354 		break;
355 	case NET_EVENT_IPV4_ACD_FAILED:
356 		*desc = "IPv4 ACD";
357 		*desc2 = "fail";
358 		info = net_addr_ntop(AF_INET, msg->data, extra_info,
359 				     extra_info_len);
360 		break;
361 	case NET_EVENT_IPV4_PMTU_CHANGED: {
362 #if defined(CONFIG_NET_IPV4_PMTU)
363 		struct net_event_ipv4_pmtu_info *pmtu_info =
364 			(struct net_event_ipv4_pmtu_info *)msg->data;
365 
366 		*desc = "IPV4 PMTU";
367 		*desc2 = pmtu_buf;
368 		snprintk(pmtu_buf, MAX_PMTU_INFO_STR_LEN,
369 			 "changed MTU %u for", (uint16_t)pmtu_info->mtu);
370 		info = net_addr_ntop(AF_INET, &pmtu_info->dst, extra_info,
371 				     extra_info_len);
372 #endif
373 		break;
374 	}
375 	case NET_EVENT_IPV6_PMTU_CHANGED: {
376 #if defined(CONFIG_NET_IPV6_PMTU)
377 		struct net_event_ipv6_pmtu_info *pmtu_info =
378 			(struct net_event_ipv6_pmtu_info *)msg->data;
379 
380 		*desc = "IPV6 PMTU";
381 		*desc2 = pmtu_buf;
382 		snprintk(pmtu_buf, MAX_PMTU_INFO_STR_LEN,
383 			 "changed MTU %u for", (uint16_t)pmtu_info->mtu);
384 		info = net_addr_ntop(AF_INET6, &pmtu_info->dst, extra_info,
385 				     extra_info_len);
386 #endif
387 		break;
388 	}
389 	}
390 
391 	return info;
392 }
393 
sockaddr_ntop(const struct sockaddr * addr,char * dst,size_t size)394 static char *sockaddr_ntop(const struct sockaddr *addr, char *dst, size_t size)
395 {
396 	if (addr->sa_family == AF_INET) {
397 		return net_addr_ntop(AF_INET, &net_sin(addr)->sin_addr, dst, size);
398 	} else if (addr->sa_family == AF_INET6) {
399 		return net_addr_ntop(AF_INET6, &net_sin6(addr)->sin6_addr, dst, size);
400 	}
401 
402 	return NULL;
403 }
404 
get_l4_desc(struct event_msg * msg,const char ** desc,const char ** desc2,char * extra_info,size_t extra_info_len)405 static char *get_l4_desc(struct event_msg *msg,
406 			 const char **desc, const char **desc2,
407 			 char *extra_info, size_t extra_info_len)
408 {
409 	static const char *desc_unknown = unknown_event_str;
410 	char *info = NULL;
411 
412 	*desc = desc_unknown;
413 
414 	switch (msg->event) {
415 	case NET_EVENT_L4_CONNECTED:
416 		*desc = "connected";
417 		break;
418 	case NET_EVENT_L4_DISCONNECTED:
419 		*desc = "disconnected";
420 		break;
421 	case NET_EVENT_L4_IPV4_CONNECTED:
422 		*desc = "IPv4 connectivity";
423 		*desc2 = "available";
424 		break;
425 	case NET_EVENT_L4_IPV4_DISCONNECTED:
426 		*desc = "IPv4 connectivity";
427 		*desc2 = "lost";
428 		break;
429 	case NET_EVENT_L4_IPV6_CONNECTED:
430 		*desc = "IPv6 connectivity";
431 		*desc2 = "available";
432 		break;
433 	case NET_EVENT_L4_IPV6_DISCONNECTED:
434 		*desc = "IPv6 connectivity";
435 		*desc2 = "lost";
436 		break;
437 	case NET_EVENT_DNS_SERVER_ADD: {
438 		struct sockaddr *addr = (struct sockaddr *)msg->data;
439 
440 		*desc = "DNS server";
441 		*desc2 = "add";
442 
443 		info = sockaddr_ntop(addr, extra_info, extra_info_len);
444 
445 		break;
446 	}
447 	case NET_EVENT_DNS_SERVER_DEL: {
448 		struct sockaddr *addr = (struct sockaddr *)msg->data;
449 
450 		*desc = "DNS server";
451 		*desc2 = "del";
452 
453 		info = sockaddr_ntop(addr, extra_info, extra_info_len);
454 
455 		break;
456 	}
457 	case NET_EVENT_HOSTNAME_CHANGED:
458 		*desc = "Hostname changed";
459 		break;
460 	case NET_EVENT_COAP_SERVICE_STARTED:
461 		*desc = "CoAP service";
462 		*desc2 = "started";
463 		break;
464 	case NET_EVENT_COAP_SERVICE_STOPPED:
465 		*desc = "CoAP service";
466 		*desc2 = "stopped";
467 		break;
468 	case NET_EVENT_COAP_OBSERVER_ADDED:
469 		*desc = "CoAP observer";
470 		*desc2 = "added";
471 		break;
472 	case NET_EVENT_COAP_OBSERVER_REMOVED:
473 		*desc = "CoAP observer";
474 		*desc2 = "removed";
475 		break;
476 	case NET_EVENT_CAPTURE_STARTED:
477 		*desc = "Capture";
478 		*desc2 = "started";
479 		break;
480 	case NET_EVENT_CAPTURE_STOPPED:
481 		*desc = "Capture";
482 		*desc2 = "stopped";
483 		break;
484 	}
485 
486 	return info;
487 }
488 
489 /* We use a separate thread in order not to do any shell printing from
490  * event handler callback (to avoid stack size issues).
491  */
event_mon_handler(const struct shell * sh,void * p2,void * p3)492 static void event_mon_handler(const struct shell *sh, void *p2, void *p3)
493 {
494 	char extra_info[NET_IPV6_ADDR_LEN];
495 	struct event_msg msg;
496 
497 	ARG_UNUSED(p2);
498 	ARG_UNUSED(p3);
499 	net_mgmt_init_event_callback(&l2_cb, event_handler,
500 				     MONITOR_L2_MASK);
501 	net_mgmt_add_event_callback(&l2_cb);
502 
503 	net_mgmt_init_event_callback(&l3_ipv4_cb, event_handler,
504 				     MONITOR_L3_IPV4_MASK);
505 	net_mgmt_add_event_callback(&l3_ipv4_cb);
506 
507 	net_mgmt_init_event_callback(&l3_ipv6_cb, event_handler,
508 				     MONITOR_L3_IPV6_MASK);
509 	net_mgmt_add_event_callback(&l3_ipv6_cb);
510 
511 	net_mgmt_init_event_callback(&l4_cb, event_handler,
512 				     MONITOR_L4_MASK);
513 	net_mgmt_add_event_callback(&l4_cb);
514 
515 #if defined(CONFIG_NET_L2_ETHERNET_MGMT)
516 	net_mgmt_init_event_callback(&l2_ethernet_cb, event_handler,
517 				     MONITOR_L2_ETHERNET_MASK);
518 	net_mgmt_add_event_callback(&l2_ethernet_cb);
519 #endif
520 
521 	while (net_event_shutting_down == false) {
522 		const char *layer_str = "<unknown layer>";
523 		const char *desc = "", *desc2 = "";
524 		char *info = NULL;
525 		uint32_t layer;
526 
527 		(void)k_msgq_get(&event_mon_msgq, &msg, K_FOREVER);
528 
529 		if (msg.iface == NULL && msg.event == 0 && msg.len == 0) {
530 			/* This is the stop message */
531 			continue;
532 		}
533 
534 		layer = NET_MGMT_GET_LAYER(msg.event);
535 		if (layer == NET_MGMT_LAYER_L2) {
536 			layer_str = "L2";
537 			info = get_l2_desc(&msg, &desc, &desc2,
538 					   extra_info, NET_IPV6_ADDR_LEN);
539 		} else if (layer == NET_MGMT_LAYER_L3) {
540 			layer_str = "L3";
541 			info = get_l3_desc(&msg, &desc, &desc2,
542 					   extra_info, NET_IPV6_ADDR_LEN);
543 		} else if (layer == NET_MGMT_LAYER_L4) {
544 			layer_str = "L4";
545 			info = get_l4_desc(&msg, &desc, &desc2,
546 					   extra_info, NET_IPV6_ADDR_LEN);
547 		}
548 
549 		if (desc == unknown_event_str) {
550 			PR_INFO("EVENT: %s [%d] %s%s%s%s%s (0x%08x)\n", layer_str,
551 				net_if_get_by_iface(msg.iface), desc,
552 				desc2 ? " " : "", desc2 ? desc2 : "",
553 				info ? " " : "", info ? info : "", msg.event);
554 		} else {
555 			PR_INFO("EVENT: %s [%d] %s%s%s%s%s\n", layer_str,
556 				net_if_get_by_iface(msg.iface), desc,
557 				desc2 ? " " : "", desc2 ? desc2 : "",
558 				info ? " " : "", info ? info : "");
559 		}
560 	}
561 
562 	net_mgmt_del_event_callback(&l2_cb);
563 	net_mgmt_del_event_callback(&l3_ipv4_cb);
564 	net_mgmt_del_event_callback(&l3_ipv6_cb);
565 	net_mgmt_del_event_callback(&l4_cb);
566 
567 #if defined(CONFIG_NET_L2_ETHERNET_MGMT)
568 	net_mgmt_del_event_callback(&l2_ethernet_cb);
569 #endif
570 
571 	k_msgq_purge(&event_mon_msgq);
572 
573 	net_event_monitoring = false;
574 	net_event_shutting_down = false;
575 
576 	PR_INFO("Network event monitoring %s.\n", "disabled");
577 }
578 #endif
579 
cmd_net_events_on(const struct shell * sh,size_t argc,char * argv[])580 static int cmd_net_events_on(const struct shell *sh, size_t argc, char *argv[])
581 {
582 #if defined(CONFIG_NET_MGMT_EVENT_MONITOR)
583 	k_tid_t tid;
584 
585 	if (net_event_monitoring) {
586 		PR_INFO("Network event monitoring is already %s.\n",
587 			"enabled");
588 		return -ENOEXEC;
589 	}
590 
591 	tid = k_thread_create(&event_mon, event_mon_stack,
592 			      K_THREAD_STACK_SIZEOF(event_mon_stack),
593 			      (k_thread_entry_t)event_mon_handler,
594 			      (void *)sh, NULL, NULL, THREAD_PRIORITY, 0,
595 			      K_FOREVER);
596 	if (!tid) {
597 		PR_ERROR("Cannot create network event monitor thread!");
598 		return -ENOEXEC;
599 	}
600 
601 	k_thread_name_set(tid, "event_mon");
602 
603 	PR_INFO("Network event monitoring %s.\n", "enabled");
604 
605 	net_event_monitoring = true;
606 	net_event_shutting_down = false;
607 
608 	k_thread_start(tid);
609 #else
610 	PR_INFO("Network management events are not supported. "
611 		"Set CONFIG_NET_MGMT_EVENT_MONITOR to enable it.\n");
612 #endif
613 
614 	return 0;
615 }
616 
cmd_net_events_off(const struct shell * sh,size_t argc,char * argv[])617 static int cmd_net_events_off(const struct shell *sh, size_t argc, char *argv[])
618 {
619 #if defined(CONFIG_NET_MGMT_EVENT_MONITOR)
620 	static const struct event_msg msg;
621 	int ret;
622 
623 	if (!net_event_monitoring) {
624 		PR_INFO("Network event monitoring is already %s.\n",
625 			"disabled");
626 		return -ENOEXEC;
627 	}
628 
629 	net_event_shutting_down = true;
630 
631 	ret = k_msgq_put(&event_mon_msgq, (void *)&msg, K_MSEC(100));
632 	if (ret < 0) {
633 		PR_ERROR("Cannot write to msgq (%d)\n", ret);
634 		return -ENOEXEC;
635 	}
636 #else
637 	PR_INFO("Network management events are not supported. "
638 		"Set CONFIG_NET_MGMT_EVENT_MONITOR to enable it.\n");
639 #endif
640 
641 	return 0;
642 }
643 
cmd_net_events(const struct shell * sh,size_t argc,char * argv[])644 static int cmd_net_events(const struct shell *sh, size_t argc, char *argv[])
645 {
646 #if defined(CONFIG_NET_MGMT_EVENT_MONITOR)
647 	PR("Network event monitoring is %s.\n",
648 	   net_event_monitoring ? "enabled" : "disabled");
649 
650 	if (!argv[1]) {
651 		PR_INFO("Give 'on' to enable event monitoring and "
652 			"'off' to disable it.\n");
653 	}
654 #else
655 	PR_INFO("Network management events are not supported. "
656 		"Set CONFIG_NET_MGMT_EVENT_MONITOR to enable it.\n");
657 #endif
658 
659 	return 0;
660 }
661 
events_enable(void)662 void events_enable(void)
663 {
664 	static const char * const argv[] = {
665 		"on",
666 		NULL
667 	};
668 
669 	(void)cmd_net_events_on(shell_backend_uart_get_ptr(), 1, (char **)argv);
670 }
671 
672 SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_events,
673 	SHELL_CMD(on, NULL, "Turn on network event monitoring.",
674 		  cmd_net_events_on),
675 	SHELL_CMD(off, NULL, "Turn off network event monitoring.",
676 		  cmd_net_events_off),
677 	SHELL_SUBCMD_SET_END
678 );
679 
680 SHELL_SUBCMD_ADD((net), events, &net_cmd_events, "Monitor network management events.",
681 		 cmd_net_events, 1, 1);
682