1 /** @file
2  * @brief Network shell module
3  *
4  * Provide some networking shell commands that can be useful to applications.
5  */
6 
7 /*
8  * Copyright (c) 2016 Intel Corporation
9  * Copyright (c) 2023 Nordic Semiconductor ASA
10  *
11  * SPDX-License-Identifier: Apache-2.0
12  */
13 
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(net_shell, LOG_LEVEL_DBG);
16 
17 #include <zephyr/kernel.h>
18 #include <zephyr/random/random.h>
19 #include <stdlib.h>
20 
21 #include <zephyr/net/ethernet.h>
22 
23 #include "net_shell_private.h"
24 #include "net_shell.h"
25 
get_iface_idx(const struct shell * sh,char * index_str)26 int get_iface_idx(const struct shell *sh, char *index_str)
27 {
28 	char *endptr;
29 	int idx;
30 
31 	if (!index_str) {
32 		PR_WARNING("Interface index is missing.\n");
33 		return -EINVAL;
34 	}
35 
36 	idx = strtol(index_str, &endptr, 10);
37 	if (*endptr != '\0') {
38 		PR_WARNING("Invalid index %s\n", index_str);
39 		return -ENOENT;
40 	}
41 
42 	if (idx < 0 || idx > 255) {
43 		PR_WARNING("Invalid index %d\n", idx);
44 		return -ERANGE;
45 	}
46 
47 	return idx;
48 }
49 
addrtype2str(enum net_addr_type addr_type)50 const char *addrtype2str(enum net_addr_type addr_type)
51 {
52 	switch (addr_type) {
53 	case NET_ADDR_ANY:
54 		return "<unknown type>";
55 	case NET_ADDR_AUTOCONF:
56 		return "autoconf";
57 	case NET_ADDR_DHCP:
58 		return "DHCP";
59 	case NET_ADDR_MANUAL:
60 		return "manual";
61 	case NET_ADDR_OVERRIDABLE:
62 		return "overridable";
63 	}
64 
65 	return "<invalid type>";
66 }
67 
addrstate2str(enum net_addr_state addr_state)68 const char *addrstate2str(enum net_addr_state addr_state)
69 {
70 	switch (addr_state) {
71 	case NET_ADDR_ANY_STATE:
72 		return "<unknown state>";
73 	case NET_ADDR_TENTATIVE:
74 		return "tentative";
75 	case NET_ADDR_PREFERRED:
76 		return "preferred";
77 	case NET_ADDR_DEPRECATED:
78 		return "deprecated";
79 	}
80 
81 	return "<invalid state>";
82 }
83 
84 #if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE)
get_addresses(struct net_context * context,char addr_local[],int local_len,char addr_remote[],int remote_len)85 void get_addresses(struct net_context *context,
86 		   char addr_local[], int local_len,
87 		   char addr_remote[], int remote_len)
88 {
89 	if (IS_ENABLED(CONFIG_NET_IPV6) && context->local.family == AF_INET6) {
90 		snprintk(addr_local, local_len, "[%s]:%u",
91 			 net_sprint_ipv6_addr(
92 				 net_sin6_ptr(&context->local)->sin6_addr),
93 			 ntohs(net_sin6_ptr(&context->local)->sin6_port));
94 		snprintk(addr_remote, remote_len, "[%s]:%u",
95 			 net_sprint_ipv6_addr(
96 				 &net_sin6(&context->remote)->sin6_addr),
97 			 ntohs(net_sin6(&context->remote)->sin6_port));
98 
99 	} else if (IS_ENABLED(CONFIG_NET_IPV4) && context->local.family == AF_INET) {
100 		snprintk(addr_local, local_len, "%s:%d",
101 			 net_sprint_ipv4_addr(
102 				 net_sin_ptr(&context->local)->sin_addr),
103 			 ntohs(net_sin_ptr(&context->local)->sin_port));
104 
105 		/* Check if we need to print the v4-mapping-to-v6 address */
106 		if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6) &&
107 		    net_sin(&context->remote)->sin_family == AF_INET6 &&
108 		    net_ipv6_addr_is_v4_mapped(&net_sin6(&context->remote)->sin6_addr)) {
109 			snprintk(addr_remote, remote_len, "[%s]:%d",
110 				 net_sprint_ipv6_addr(
111 					 &net_sin6(&context->remote)->sin6_addr),
112 				 ntohs(net_sin6(&context->remote)->sin6_port));
113 		} else {
114 			snprintk(addr_remote, remote_len, "%s:%d",
115 				 net_sprint_ipv4_addr(
116 					 &net_sin(&context->remote)->sin_addr),
117 				 ntohs(net_sin(&context->remote)->sin_port));
118 		}
119 
120 	} else if (context->local.family == AF_UNSPEC) {
121 		snprintk(addr_local, local_len, "AF_UNSPEC");
122 	} else if (context->local.family == AF_PACKET) {
123 		snprintk(addr_local, local_len, "AF_PACKET");
124 	} else if (context->local.family == AF_CAN) {
125 		snprintk(addr_local, local_len, "AF_CAN");
126 	} else {
127 		snprintk(addr_local, local_len, "AF_UNK(%d)",
128 			 context->local.family);
129 	}
130 }
131 #endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */
132 
iface2str(struct net_if * iface,const char ** extra)133 const char *iface2str(struct net_if *iface, const char **extra)
134 {
135 #ifdef CONFIG_NET_L2_IEEE802154
136 	if (net_if_l2(iface) == &NET_L2_GET_NAME(IEEE802154)) {
137 		if (extra) {
138 			*extra = "=============";
139 		}
140 
141 		return "IEEE 802.15.4";
142 	}
143 #endif
144 
145 #ifdef CONFIG_NET_L2_ETHERNET
146 	if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
147 		struct ethernet_context *eth_ctx = net_if_l2_data(iface);
148 
149 		if (eth_ctx->eth_if_type == L2_ETH_IF_TYPE_WIFI) {
150 			if (extra) {
151 				*extra = "====";
152 			}
153 
154 			return "WiFi";
155 		}
156 
157 		if (extra) {
158 			*extra = "========";
159 		}
160 
161 		return "Ethernet";
162 	}
163 #endif
164 
165 #ifdef CONFIG_NET_L2_VIRTUAL
166 	if (net_if_l2(iface) == &NET_L2_GET_NAME(VIRTUAL)) {
167 		if (extra) {
168 			*extra = "=======";
169 		}
170 
171 		return "Virtual";
172 	}
173 #endif
174 
175 #ifdef CONFIG_NET_L2_PPP
176 	if (net_if_l2(iface) == &NET_L2_GET_NAME(PPP)) {
177 		if (extra) {
178 			*extra = "===";
179 		}
180 
181 		return "PPP";
182 	}
183 #endif
184 
185 #ifdef CONFIG_NET_L2_DUMMY
186 	if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) {
187 		if (extra) {
188 			*extra = "=====";
189 		}
190 
191 		return "Dummy";
192 	}
193 #endif
194 
195 #ifdef CONFIG_NET_L2_OPENTHREAD
196 	if (net_if_l2(iface) == &NET_L2_GET_NAME(OPENTHREAD)) {
197 		if (extra) {
198 			*extra = "==========";
199 		}
200 
201 		return "OpenThread";
202 	}
203 #endif
204 
205 #ifdef CONFIG_NET_L2_BT
206 	if (net_if_l2(iface) == &NET_L2_GET_NAME(BLUETOOTH)) {
207 		if (extra) {
208 			*extra = "=========";
209 		}
210 
211 		return "Bluetooth";
212 	}
213 #endif
214 
215 #ifdef CONFIG_NET_OFFLOAD
216 	if (net_if_is_ip_offloaded(iface)) {
217 		if (extra) {
218 			*extra = "==========";
219 		}
220 
221 		return "IP Offload";
222 	}
223 #endif
224 
225 #ifdef CONFIG_NET_L2_CANBUS_RAW
226 	if (net_if_l2(iface) == &NET_L2_GET_NAME(CANBUS_RAW)) {
227 		if (extra) {
228 			*extra = "==========";
229 		}
230 
231 		return "CANBUS_RAW";
232 	}
233 #endif
234 
235 	if (extra) {
236 		*extra = "==============";
237 	}
238 
239 	return "<unknown type>";
240 }
241 
242 /* Placeholder for net commands that are configured in the rest of the .c files */
243 SHELL_SUBCMD_SET_CREATE(net_cmds, (net));
244 
245 SHELL_CMD_REGISTER(net, &net_cmds, "Networking commands", NULL);
246 
net_shell_init(void)247 int net_shell_init(void)
248 {
249 	if (IS_ENABLED(CONFIG_NET_MGMT_EVENT_MONITOR_AUTO_START)) {
250 		events_enable();
251 	}
252 
253 	return 0;
254 }
255