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 #include <zephyr/random/random.h>
10 #include <strings.h>
11 LOG_MODULE_DECLARE(net_shell);
12 
13 #if defined(CONFIG_NET_L2_ETHERNET)
14 #include <zephyr/net/ethernet.h>
15 #endif
16 #if defined(CONFIG_NET_L2_ETHERNET_MGMT)
17 #include <zephyr/net/ethernet_mgmt.h>
18 #endif
19 #if defined(CONFIG_NET_L2_VIRTUAL)
20 #include <zephyr/net/virtual.h>
21 #endif
22 #if defined(CONFIG_ETH_PHY_DRIVER)
23 #include <zephyr/net/phy.h>
24 #endif
25 
26 #include "net_shell_private.h"
27 
28 #define UNICAST_MASK GENMASK(7, 1)
29 #define LOCAL_BIT BIT(1)
30 
31 #if defined(CONFIG_NET_L2_ETHERNET) && defined(CONFIG_NET_NATIVE)
32 struct ethernet_capabilities {
33 	enum ethernet_hw_caps capability;
34 	const char * const description;
35 };
36 
37 #define EC(cap, desc) { .capability = cap, .description = desc }
38 
39 static struct ethernet_capabilities eth_hw_caps[] = {
40 	EC(ETHERNET_HW_TX_CHKSUM_OFFLOAD, "TX checksum offload"),
41 	EC(ETHERNET_HW_RX_CHKSUM_OFFLOAD, "RX checksum offload"),
42 	EC(ETHERNET_HW_VLAN,              "Virtual LAN"),
43 	EC(ETHERNET_HW_VLAN_TAG_STRIP,    "VLAN Tag stripping"),
44 	EC(ETHERNET_AUTO_NEGOTIATION_SET, "Auto negotiation"),
45 	EC(ETHERNET_LINK_10BASE_T,        "10 Mbits"),
46 	EC(ETHERNET_LINK_100BASE_T,       "100 Mbits"),
47 	EC(ETHERNET_LINK_1000BASE_T,      "1 Gbits"),
48 	EC(ETHERNET_DUPLEX_SET,           "Half/full duplex"),
49 	EC(ETHERNET_PTP,                  "IEEE 802.1AS gPTP clock"),
50 	EC(ETHERNET_QAV,                  "IEEE 802.1Qav (credit shaping)"),
51 	EC(ETHERNET_QBV,                  "IEEE 802.1Qbv (scheduled traffic)"),
52 	EC(ETHERNET_QBU,                  "IEEE 802.1Qbu (frame preemption)"),
53 	EC(ETHERNET_TXTIME,               "TXTIME"),
54 	EC(ETHERNET_PROMISC_MODE,         "Promiscuous mode"),
55 	EC(ETHERNET_PRIORITY_QUEUES,      "Priority queues"),
56 	EC(ETHERNET_HW_FILTERING,         "MAC address filtering"),
57 	EC(ETHERNET_DSA_SLAVE_PORT,       "DSA slave port"),
58 	EC(ETHERNET_DSA_MASTER_PORT,      "DSA master port"),
59 	EC(ETHERNET_TXTIME,               "TXTIME supported"),
60 	EC(ETHERNET_TXINJECTION_MODE,     "TX-Injection supported"),
61 	EC(ETHERNET_LINK_2500BASE_T,      "2.5 Gbits"),
62 	EC(ETHERNET_LINK_5000BASE_T,      "5 Gbits"),
63 };
64 
print_supported_ethernet_capabilities(const struct shell * sh,struct net_if * iface)65 static void print_supported_ethernet_capabilities(
66 	const struct shell *sh, struct net_if *iface)
67 {
68 	enum ethernet_hw_caps caps = net_eth_get_hw_capabilities(iface);
69 
70 	ARRAY_FOR_EACH(eth_hw_caps, i) {
71 		if (caps & eth_hw_caps[i].capability) {
72 			PR("\t%s\n", eth_hw_caps[i].description);
73 		}
74 	}
75 }
76 #endif /* CONFIG_NET_L2_ETHERNET */
77 
78 #ifdef CONFIG_ETH_PHY_DRIVER
print_phy_link_state(const struct shell * sh,const struct device * phy_dev)79 static void print_phy_link_state(const struct shell *sh, const struct device *phy_dev)
80 {
81 	struct phy_link_state link;
82 	int ret;
83 
84 	ret = phy_get_link_state(phy_dev, &link);
85 	if (ret < 0) {
86 		PR_ERROR("Failed to get link state (%d)\n", ret);
87 		return;
88 	}
89 
90 	PR("Ethernet link speed: %s ", PHY_LINK_IS_SPEED_1000M(link.speed)  ? "1 Gbits"
91 				       : PHY_LINK_IS_SPEED_100M(link.speed) ? "100 Mbits"
92 									    : "10 Mbits");
93 
94 	PR("%s-duplex\n", PHY_LINK_IS_FULL_DUPLEX(link.speed) ? "full" : "half");
95 }
96 #endif
97 
iface_flags2str(struct net_if * iface)98 static const char *iface_flags2str(struct net_if *iface)
99 {
100 	static char str[sizeof("POINTOPOINT") + sizeof("PROMISC") +
101 			sizeof("NO_AUTO_START") + sizeof("SUSPENDED") +
102 			sizeof("MCAST_FORWARD") + sizeof("IPv4") +
103 			sizeof("IPv6") + sizeof("NO_ND") + sizeof("NO_MLD")];
104 	int pos = 0;
105 
106 	if (net_if_flag_is_set(iface, NET_IF_POINTOPOINT)) {
107 		pos += snprintk(str + pos, sizeof(str) - pos,
108 				"POINTOPOINT,");
109 	}
110 
111 	if (net_if_flag_is_set(iface, NET_IF_PROMISC)) {
112 		pos += snprintk(str + pos, sizeof(str) - pos,
113 				"PROMISC,");
114 	}
115 
116 	if (net_if_flag_is_set(iface, NET_IF_NO_AUTO_START)) {
117 		pos += snprintk(str + pos, sizeof(str) - pos,
118 				"NO_AUTO_START,");
119 	} else {
120 		pos += snprintk(str + pos, sizeof(str) - pos,
121 				"AUTO_START,");
122 	}
123 
124 	if (net_if_flag_is_set(iface, NET_IF_FORWARD_MULTICASTS)) {
125 		pos += snprintk(str + pos, sizeof(str) - pos,
126 				"MCAST_FORWARD,");
127 	}
128 
129 	if (net_if_flag_is_set(iface, NET_IF_IPV4)) {
130 		pos += snprintk(str + pos, sizeof(str) - pos,
131 				"IPv4,");
132 	}
133 
134 	if (net_if_flag_is_set(iface, NET_IF_IPV6)) {
135 		pos += snprintk(str + pos, sizeof(str) - pos,
136 				"IPv6,");
137 	}
138 
139 	if (net_if_flag_is_set(iface, NET_IF_IPV6_NO_ND)) {
140 		pos += snprintk(str + pos, sizeof(str) - pos,
141 				"NO_ND,");
142 	}
143 
144 	if (net_if_flag_is_set(iface, NET_IF_IPV6_NO_MLD)) {
145 		pos += snprintk(str + pos, sizeof(str) - pos,
146 				"NO_MLD,");
147 	}
148 
149 	/* get rid of last ',' character */
150 	str[pos - 1] = '\0';
151 
152 	return str;
153 }
154 
iface_cb(struct net_if * iface,void * user_data)155 static void iface_cb(struct net_if *iface, void *user_data)
156 {
157 	struct net_shell_user_data *data = user_data;
158 	const struct shell *sh = data->sh;
159 
160 #if defined(CONFIG_NET_NATIVE_IPV6)
161 	struct net_if_ipv6_prefix *prefix;
162 	struct net_if_router *router;
163 #endif
164 #if defined(CONFIG_NET_IPV6)
165 	struct net_if_ipv6 *ipv6;
166 #endif
167 #if defined(CONFIG_NET_IPV4)
168 	struct net_if_ipv4 *ipv4;
169 #endif
170 #if defined(CONFIG_NET_IP)
171 	struct net_if_addr *unicast;
172 	struct net_if_mcast_addr *mcast;
173 #endif
174 #if defined(CONFIG_NET_L2_ETHERNET_MGMT)
175 	struct ethernet_req_params params;
176 	int ret;
177 #endif
178 	const char *extra;
179 #if defined(CONFIG_NET_IP) || defined(CONFIG_NET_L2_ETHERNET_MGMT)
180 	int count;
181 #endif
182 
183 	if (data->user_data && data->user_data != iface) {
184 		return;
185 	}
186 
187 #if defined(CONFIG_NET_INTERFACE_NAME)
188 	char ifname[CONFIG_NET_INTERFACE_NAME_LEN + 1] = { 0 };
189 	int ret_name;
190 
191 	ret_name = net_if_get_name(iface, ifname, sizeof(ifname) - 1);
192 	if (ret_name < 1 || ifname[0] == '\0') {
193 		snprintk(ifname, sizeof(ifname), "?");
194 	}
195 
196 	PR("\nInterface %s (%p) (%s) [%d]\n", ifname, iface, iface2str(iface, &extra),
197 	   net_if_get_by_iface(iface));
198 #else
199 	PR("\nInterface %p (%s) [%d]\n", iface, iface2str(iface, &extra),
200 	   net_if_get_by_iface(iface));
201 #endif
202 	PR("===========================%s\n", extra);
203 
204 	if (!net_if_is_up(iface)) {
205 		PR_INFO("Interface is down.\n");
206 
207 		/* Show detailed information only when user asks information
208 		 * about one specific network interface.
209 		 */
210 		if (data->user_data == NULL) {
211 			return;
212 		}
213 	}
214 
215 #ifdef CONFIG_NET_POWER_MANAGEMENT
216 	if (net_if_is_suspended(iface)) {
217 		PR_INFO("Interface is suspended, thus not able to tx/rx.\n");
218 	}
219 #endif
220 
221 #if defined(CONFIG_NET_L2_VIRTUAL)
222 	if (!sys_slist_is_empty(&iface->config.virtual_interfaces)) {
223 		struct virtual_interface_context *ctx, *tmp;
224 
225 		PR("Virtual interfaces attached to this : ");
226 		SYS_SLIST_FOR_EACH_CONTAINER_SAFE(
227 					&iface->config.virtual_interfaces,
228 					ctx, tmp, node) {
229 			if (ctx->virtual_iface == iface) {
230 				continue;
231 			}
232 
233 			PR("%d ", net_if_get_by_iface(ctx->virtual_iface));
234 		}
235 
236 		PR("\n");
237 	}
238 
239 	if (net_if_l2(iface) == &NET_L2_GET_NAME(VIRTUAL)) {
240 		struct net_if *orig_iface;
241 		char *name, buf[CONFIG_NET_L2_VIRTUAL_MAX_NAME_LEN];
242 
243 		name = net_virtual_get_name(iface, buf, sizeof(buf));
244 		if (!(name && name[0])) {
245 			name = "<unknown>";
246 		}
247 
248 		PR("Virtual name : %s\n", name);
249 
250 		orig_iface = net_virtual_get_iface(iface);
251 		if (orig_iface == NULL) {
252 			PR("No attached network interface.\n");
253 		} else {
254 			PR("Attached  : %d (%s / %p)\n",
255 			   net_if_get_by_iface(orig_iface),
256 			   iface2str(orig_iface, NULL),
257 			   orig_iface);
258 		}
259 	}
260 #endif /* CONFIG_NET_L2_VIRTUAL */
261 
262 	net_if_lock(iface);
263 	if (net_if_get_link_addr(iface)->len > 0) {
264 		PR("Link addr : %s\n",
265 		   net_sprint_ll_addr(net_if_get_link_addr(iface)->addr,
266 				      net_if_get_link_addr(iface)->len));
267 	}
268 	net_if_unlock(iface);
269 
270 	PR("MTU       : %d\n", net_if_get_mtu(iface));
271 	PR("Flags     : %s\n", iface_flags2str(iface));
272 	PR("Device    : %s (%p)\n",
273 	   net_if_get_device(iface) ? net_if_get_device(iface)->name : "<?>",
274 	   net_if_get_device(iface));
275 
276 	PR("Status    : oper=%s, admin=%s, carrier=%s\n",
277 	   net_if_oper_state2str(net_if_oper_state(iface)),
278 	   net_if_is_admin_up(iface) ? "UP" : "DOWN",
279 	   net_if_is_carrier_ok(iface) ? "ON" : "OFF");
280 
281 #if defined(CONFIG_NET_L2_ETHERNET_MGMT)
282 	if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
283 		count = 0;
284 		ret = net_mgmt(NET_REQUEST_ETHERNET_GET_PRIORITY_QUEUES_NUM,
285 				iface, &params,
286 				sizeof(struct ethernet_req_params));
287 
288 		if (!ret && params.priority_queues_num) {
289 			count = params.priority_queues_num;
290 			PR("Priority queues:\n");
291 			for (int i = 0; i < count; ++i) {
292 				params.qav_param.queue_id = i;
293 				params.qav_param.type =
294 					ETHERNET_QAV_PARAM_TYPE_STATUS;
295 				ret = net_mgmt(
296 					NET_REQUEST_ETHERNET_GET_QAV_PARAM,
297 					iface, &params,
298 					sizeof(struct ethernet_req_params));
299 
300 				PR("\t%d: Qav ", i);
301 				if (ret) {
302 					PR("not supported\n");
303 				} else {
304 					PR("%s\n",
305 						params.qav_param.enabled ?
306 						"enabled" :
307 						"disabled");
308 				}
309 			}
310 		}
311 	}
312 #endif
313 
314 #if defined(CONFIG_NET_PROMISCUOUS_MODE)
315 	PR("Promiscuous mode : %s\n",
316 	   net_if_is_promisc(iface) ? "enabled" : "disabled");
317 #endif
318 
319 #if defined(CONFIG_NET_VLAN)
320 	if (net_if_l2(iface) == &NET_L2_GET_NAME(VIRTUAL)) {
321 		if (net_virtual_get_iface_capabilities(iface) & VIRTUAL_INTERFACE_VLAN) {
322 			uint16_t tag;
323 
324 			tag = net_eth_get_vlan_tag(iface);
325 			if (tag == NET_VLAN_TAG_UNSPEC) {
326 				PR("VLAN not configured\n");
327 			} else {
328 				PR("VLAN tag  : %d (0x%03x)\n", tag, tag);
329 			}
330 		}
331 	}
332 #endif
333 
334 #ifdef CONFIG_NET_L2_ETHERNET
335 	if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
336 		PR("Ethernet capabilities supported:\n");
337 		print_supported_ethernet_capabilities(sh, iface);
338 
339 #ifdef CONFIG_ETH_PHY_DRIVER
340 		const struct device *phy_dev = net_eth_get_phy(iface);
341 
342 		PR("Ethernet PHY device: %s (%p)\n", (phy_dev != NULL) ? phy_dev->name : "<none>",
343 		   phy_dev);
344 		if (phy_dev != NULL) {
345 			print_phy_link_state(sh, phy_dev);
346 		}
347 #endif /* CONFIG_ETH_PHY_DRIVER */
348 	}
349 #endif /* CONFIG_NET_L2_ETHERNET */
350 
351 #if defined(CONFIG_NET_IPV6)
352 	count = 0;
353 	ipv6 = iface->config.ip.ipv6;
354 
355 	if (!net_if_flag_is_set(iface, NET_IF_IPV6) || ipv6 == NULL) {
356 		PR("%s not %s for this interface.\n", "IPv6", "enabled");
357 		ipv6 = NULL;
358 		goto skip_ipv6;
359 	}
360 
361 	PR("IPv6 unicast addresses (max %d):\n", NET_IF_MAX_IPV6_ADDR);
362 	ARRAY_FOR_EACH(ipv6->unicast, i) {
363 		unicast = &ipv6->unicast[i];
364 
365 		if (!unicast->is_used) {
366 			continue;
367 		}
368 
369 		PR("\t%s %s %s%s%s%s\n",
370 		   net_sprint_ipv6_addr(&unicast->address.in6_addr),
371 		   addrtype2str(unicast->addr_type),
372 		   addrstate2str(unicast->addr_state),
373 		   unicast->is_infinite ? " infinite" : "",
374 		   unicast->is_mesh_local ? " meshlocal" : "",
375 		   unicast->is_temporary ? " temporary" : "");
376 		count++;
377 	}
378 
379 	if (count == 0) {
380 		PR("\t<none>\n");
381 	}
382 
383 	count = 0;
384 
385 	PR("IPv6 multicast addresses (max %d):\n", NET_IF_MAX_IPV6_MADDR);
386 	ARRAY_FOR_EACH(ipv6->mcast, i) {
387 		mcast = &ipv6->mcast[i];
388 
389 		if (!mcast->is_used) {
390 			continue;
391 		}
392 
393 		PR("\t%s%s\n", net_sprint_ipv6_addr(&mcast->address.in6_addr),
394 		   net_if_ipv6_maddr_is_joined(mcast) ? "" : "  <not joined>");
395 
396 		count++;
397 	}
398 
399 	if (count == 0) {
400 		PR("\t<none>\n");
401 	}
402 
403 #if defined(CONFIG_NET_NATIVE_IPV6)
404 	count = 0;
405 
406 	PR("IPv6 prefixes (max %d):\n", NET_IF_MAX_IPV6_PREFIX);
407 	ARRAY_FOR_EACH(ipv6->prefix, i) {
408 		prefix = &ipv6->prefix[i];
409 
410 		if (!prefix->is_used) {
411 			continue;
412 		}
413 
414 		PR("\t%s/%d%s\n",
415 		   net_sprint_ipv6_addr(&prefix->prefix),
416 		   prefix->len, prefix->is_infinite ? " infinite" : "");
417 
418 		count++;
419 	}
420 
421 	if (count == 0) {
422 		PR("\t<none>\n");
423 	}
424 
425 	router = net_if_ipv6_router_find_default(iface, NULL);
426 	if (router) {
427 		PR("IPv6 default router :\n");
428 		PR("\t%s%s\n",
429 		   net_sprint_ipv6_addr(&router->address.in6_addr),
430 		   router->is_infinite ? " infinite" : "");
431 	}
432 #endif /* CONFIG_NET_NATIVE_IPV6 */
433 
434 skip_ipv6:
435 
436 #if defined(CONFIG_NET_IPV6_PE)
437 	PR("IPv6 privacy extension   : %s (preferring %s addresses)\n",
438 	   iface->pe_enabled ? "enabled" : "disabled",
439 	   iface->pe_prefer_public ? "public" : "temporary");
440 #endif
441 
442 	if (ipv6) {
443 		PR("IPv6 hop limit           : %d\n",
444 		   ipv6->hop_limit);
445 		PR("IPv6 base reachable time : %d\n",
446 		   ipv6->base_reachable_time);
447 		PR("IPv6 reachable time      : %d\n",
448 		   ipv6->reachable_time);
449 		PR("IPv6 retransmit timer    : %d\n",
450 		   ipv6->retrans_timer);
451 	}
452 
453 #if defined(CONFIG_NET_DHCPV6)
454 	if (net_if_flag_is_set(iface, NET_IF_IPV6)) {
455 		PR("DHCPv6 renewal time (T1) : %llu ms\n",
456 		   iface->config.dhcpv6.t1);
457 		PR("DHCPv6 rebind time (T2)  : %llu ms\n",
458 		   iface->config.dhcpv6.t2);
459 		PR("DHCPv6 expire time       : %llu ms\n",
460 		   iface->config.dhcpv6.expire);
461 		if (iface->config.dhcpv6.params.request_addr) {
462 			PR("DHCPv6 address           : %s\n",
463 			   net_sprint_ipv6_addr(&iface->config.dhcpv6.addr));
464 		}
465 
466 		if (iface->config.dhcpv6.params.request_prefix) {
467 			PR("DHCPv6 prefix            : %s\n",
468 			   net_sprint_ipv6_addr(&iface->config.dhcpv6.prefix));
469 		}
470 
471 		PR("DHCPv6 state             : %s\n",
472 		   net_dhcpv6_state_name(iface->config.dhcpv6.state));
473 	}
474 #endif /* CONFIG_NET_DHCPV6 */
475 #endif /* CONFIG_NET_IPV6 */
476 
477 #if defined(CONFIG_NET_IPV4)
478 	/* No need to print IPv4 information for interface that does not
479 	 * support that protocol.
480 	 */
481 	if (
482 #if defined(CONFIG_NET_L2_IEEE802154)
483 		(net_if_l2(iface) == &NET_L2_GET_NAME(IEEE802154)) ||
484 #endif
485 		 0) {
486 		PR_WARNING("%s not %s for this interface.\n", "IPv4",
487 			   "supported");
488 		return;
489 	}
490 
491 	count = 0;
492 	ipv4 = iface->config.ip.ipv4;
493 
494 	if (!net_if_flag_is_set(iface, NET_IF_IPV4) || ipv4 == NULL) {
495 		PR("%s not %s for this interface.\n", "IPv4", "enabled");
496 		ipv4 = NULL;
497 		goto skip_ipv4;
498 	}
499 
500 	PR("IPv4 unicast addresses (max %d):\n", NET_IF_MAX_IPV4_ADDR);
501 	ARRAY_FOR_EACH(ipv4->unicast, i) {
502 		unicast = &ipv4->unicast[i].ipv4;
503 
504 		if (!unicast->is_used) {
505 			continue;
506 		}
507 
508 		PR("\t%s/%s %s %s%s\n",
509 		   net_sprint_ipv4_addr(&unicast->address.in_addr),
510 		   net_sprint_ipv4_addr(&ipv4->unicast[i].netmask),
511 
512 		   addrtype2str(unicast->addr_type),
513 		   addrstate2str(unicast->addr_state),
514 		   unicast->is_infinite ? " infinite" : "");
515 
516 		count++;
517 	}
518 
519 	if (count == 0) {
520 		PR("\t<none>\n");
521 	}
522 
523 	count = 0;
524 
525 	PR("IPv4 multicast addresses (max %d):\n", NET_IF_MAX_IPV4_MADDR);
526 	ARRAY_FOR_EACH(ipv4->mcast, i) {
527 		mcast = &ipv4->mcast[i];
528 
529 		if (!mcast->is_used) {
530 			continue;
531 		}
532 
533 		PR("\t%s%s\n", net_sprint_ipv4_addr(&mcast->address.in_addr),
534 		   net_if_ipv4_maddr_is_joined(mcast) ? "" : "  <not joined>");
535 
536 		count++;
537 	}
538 
539 	if (count == 0) {
540 		PR("\t<none>\n");
541 	}
542 
543 skip_ipv4:
544 
545 	if (ipv4) {
546 		PR("IPv4 gateway : %s\n",
547 		   net_sprint_ipv4_addr(&ipv4->gw));
548 	}
549 #endif /* CONFIG_NET_IPV4 */
550 
551 #if defined(CONFIG_NET_DHCPV4)
552 	if (net_if_flag_is_set(iface, NET_IF_IPV4)) {
553 		PR("DHCPv4 lease time : %u\n",
554 		   iface->config.dhcpv4.lease_time);
555 		PR("DHCPv4 renew time : %u\n",
556 		   iface->config.dhcpv4.renewal_time);
557 		PR("DHCPv4 server     : %s\n",
558 		   net_sprint_ipv4_addr(&iface->config.dhcpv4.server_id));
559 		PR("DHCPv4 requested  : %s\n",
560 		   net_sprint_ipv4_addr(&iface->config.dhcpv4.requested_ip));
561 		PR("DHCPv4 state      : %s\n",
562 		   net_dhcpv4_state_name(iface->config.dhcpv4.state));
563 		PR("DHCPv4 attempts   : %d\n",
564 		   iface->config.dhcpv4.attempts);
565 	}
566 #endif /* CONFIG_NET_DHCPV4 */
567 }
568 
cmd_net_set_mac(const struct shell * sh,size_t argc,char * argv[])569 static int cmd_net_set_mac(const struct shell *sh, size_t argc, char *argv[])
570 {
571 #if !defined(CONFIG_NET_L2_ETHERNET) || !defined(CONFIG_NET_L2_ETHERNET_MGMT)
572 	PR_WARNING("Unsupported command, please enable CONFIG_NET_L2_ETHERNET "
573 		"and CONFIG_NET_L2_ETHERNET_MGMT\n");
574 	return -ENOEXEC;
575 #else
576 	struct net_if *iface;
577 	struct ethernet_req_params params;
578 	char *mac_addr = params.mac_address.addr;
579 	int idx;
580 	int ret;
581 
582 	if (argc < 3) {
583 		PR_WARNING("Missing interface index and/or MAC address\n");
584 		goto err;
585 	}
586 
587 	idx = get_iface_idx(sh, argv[1]);
588 	if (idx < 0) {
589 		goto err;
590 	}
591 
592 	iface = net_if_get_by_index(idx);
593 	if (!iface) {
594 		PR_WARNING("No such interface in index %d\n", idx);
595 		goto err;
596 	}
597 
598 	if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
599 		PR_WARNING("MAC address can be set only for Ethernet\n");
600 		goto err;
601 	}
602 
603 	if (!strncasecmp(argv[2], "random", 6)) {
604 		sys_rand_get(mac_addr, NET_ETH_ADDR_LEN);
605 		mac_addr[0] = (mac_addr[0] & UNICAST_MASK) | LOCAL_BIT;
606 	} else {
607 		if ((net_bytes_from_str(mac_addr, sizeof(params.mac_address), argv[2]) < 0) ||
608 		    !net_eth_is_addr_valid(&params.mac_address)) {
609 			PR_WARNING("Invalid MAC address: %s\n", argv[2]);
610 			goto err;
611 		}
612 	}
613 
614 	ret = net_mgmt(NET_REQUEST_ETHERNET_SET_MAC_ADDRESS, iface, &params, sizeof(params));
615 	if (ret < 0) {
616 		if (ret == -EACCES) {
617 			PR_WARNING("MAC address cannot be set when interface is operational\n");
618 			goto err;
619 		}
620 		PR_WARNING("Failed to set MAC address (%d)\n", ret);
621 		goto err;
622 	}
623 
624 	PR_INFO("MAC address set to %s\n",
625 		net_sprint_ll_addr(net_if_get_link_addr(iface)->addr,
626 		net_if_get_link_addr(iface)->len));
627 
628 	return 0;
629 err:
630 	return -ENOEXEC;
631 #endif /* CONFIG_NET_L2_ETHERNET */
632 }
633 
cmd_net_iface_up(const struct shell * sh,size_t argc,char * argv[])634 static int cmd_net_iface_up(const struct shell *sh, size_t argc, char *argv[])
635 {
636 	struct net_if *iface;
637 	int idx, ret;
638 
639 	idx = get_iface_idx(sh, argv[1]);
640 	if (idx < 0) {
641 		return -ENOEXEC;
642 	}
643 
644 	iface = net_if_get_by_index(idx);
645 	if (!iface) {
646 		PR_WARNING("No such interface in index %d\n", idx);
647 		return -ENOEXEC;
648 	}
649 
650 	if (net_if_is_up(iface)) {
651 		PR_WARNING("Interface %d is already up.\n", idx);
652 		return -ENOEXEC;
653 	}
654 
655 	ret = net_if_up(iface);
656 	if (ret) {
657 		PR_WARNING("Cannot take interface %d up (%d)\n", idx, ret);
658 		return -ENOEXEC;
659 	}
660 
661 	PR("Interface %d is up\n", idx);
662 
663 	return 0;
664 }
665 
cmd_net_iface_down(const struct shell * sh,size_t argc,char * argv[])666 static int cmd_net_iface_down(const struct shell *sh, size_t argc, char *argv[])
667 {
668 	struct net_if *iface;
669 	int idx, ret;
670 
671 	idx = get_iface_idx(sh, argv[1]);
672 	if (idx < 0) {
673 		return -ENOEXEC;
674 	}
675 
676 	iface = net_if_get_by_index(idx);
677 	if (!iface) {
678 		PR_WARNING("No such interface in index %d\n", idx);
679 		return -ENOEXEC;
680 	}
681 
682 	ret = net_if_down(iface);
683 	if (ret) {
684 		PR_WARNING("Cannot take interface %d down (%d)\n", idx, ret);
685 		return -ENOEXEC;
686 	}
687 
688 	PR("Interface %d is down\n", idx);
689 
690 	return 0;
691 }
692 
cmd_net_iface(const struct shell * sh,size_t argc,char * argv[])693 static int cmd_net_iface(const struct shell *sh, size_t argc, char *argv[])
694 {
695 	struct net_if *iface = NULL;
696 	struct net_shell_user_data user_data;
697 	int idx;
698 
699 	if (argv[1]) {
700 		idx = get_iface_idx(sh, argv[1]);
701 		if (idx < 0) {
702 			return -ENOEXEC;
703 		}
704 
705 		iface = net_if_get_by_index(idx);
706 		if (!iface) {
707 			PR_WARNING("No such interface in index %d\n", idx);
708 			return -ENOEXEC;
709 		}
710 	}
711 
712 #if defined(CONFIG_NET_HOSTNAME_ENABLE)
713 	PR("Hostname: %s\n\n", net_hostname_get());
714 #endif
715 
716 	user_data.sh = sh;
717 	user_data.user_data = iface;
718 
719 	net_if_foreach(iface_cb, &user_data);
720 
721 	return 0;
722 }
723 
724 #if defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION)
725 
726 #include "iface_dynamic.h"
727 
728 #endif /* CONFIG_NET_SHELL_DYN_CMD_COMPLETION */
729 
730 SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_iface,
731 	SHELL_CMD(up, IFACE_DYN_CMD,
732 		  "'net iface up <index>' takes network interface up.",
733 		  cmd_net_iface_up),
734 	SHELL_CMD(down, IFACE_DYN_CMD,
735 		  "'net iface down <index>' takes network interface "
736 		  "down.",
737 		  cmd_net_iface_down),
738 	SHELL_CMD(show, IFACE_DYN_CMD,
739 		  "'net iface <index>' shows network interface "
740 		  "information.",
741 		  cmd_net_iface),
742 	SHELL_CMD(set_mac, IFACE_DYN_CMD,
743 		  "'net iface set_mac <index> <MAC>' sets MAC address for the network interface.",
744 		  cmd_net_set_mac),
745 	SHELL_SUBCMD_SET_END
746 );
747 
748 SHELL_SUBCMD_ADD((net), iface, &net_cmd_iface,
749 		 "Print information about network interfaces.",
750 		 cmd_net_iface, 1, 1);
751