| /** @file |
| * @brief Network shell module |
| * |
| * Provide some networking shell commands that can be useful to applications. |
| */ |
| |
| /* |
| * Copyright (c) 2016 Intel Corporation |
| * Copyright (c) 2023 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr/logging/log.h> |
| LOG_MODULE_REGISTER(net_shell, LOG_LEVEL_DBG); |
| |
| #include <zephyr/kernel.h> |
| #include <zephyr/random/random.h> |
| #include <stdlib.h> |
| |
| #include <zephyr/net/ethernet.h> |
| |
| #include "net_shell_private.h" |
| #include "net_shell.h" |
| |
| int get_iface_idx(const struct shell *sh, char *index_str) |
| { |
| char *endptr; |
| int idx; |
| |
| if (!index_str) { |
| PR_WARNING("Interface index is missing.\n"); |
| return -EINVAL; |
| } |
| |
| idx = strtol(index_str, &endptr, 10); |
| if (*endptr != '\0') { |
| PR_WARNING("Invalid index %s\n", index_str); |
| return -ENOENT; |
| } |
| |
| if (idx < 0 || idx > 255) { |
| PR_WARNING("Invalid index %d\n", idx); |
| return -ERANGE; |
| } |
| |
| return idx; |
| } |
| |
| const char *addrtype2str(enum net_addr_type addr_type) |
| { |
| switch (addr_type) { |
| case NET_ADDR_ANY: |
| return "<unknown type>"; |
| case NET_ADDR_AUTOCONF: |
| return "autoconf"; |
| case NET_ADDR_DHCP: |
| return "DHCP"; |
| case NET_ADDR_MANUAL: |
| return "manual"; |
| case NET_ADDR_OVERRIDABLE: |
| return "overridable"; |
| } |
| |
| return "<invalid type>"; |
| } |
| |
| const char *addrstate2str(enum net_addr_state addr_state) |
| { |
| switch (addr_state) { |
| case NET_ADDR_ANY_STATE: |
| return "<unknown state>"; |
| case NET_ADDR_TENTATIVE: |
| return "tentative"; |
| case NET_ADDR_PREFERRED: |
| return "preferred"; |
| case NET_ADDR_DEPRECATED: |
| return "deprecated"; |
| } |
| |
| return "<invalid state>"; |
| } |
| |
| #if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE) |
| void get_addresses(struct net_context *context, |
| char addr_local[], int local_len, |
| char addr_remote[], int remote_len) |
| { |
| if (IS_ENABLED(CONFIG_NET_IPV6) && context->local.family == AF_INET6) { |
| snprintk(addr_local, local_len, "[%s]:%u", |
| net_sprint_ipv6_addr( |
| net_sin6_ptr(&context->local)->sin6_addr), |
| ntohs(net_sin6_ptr(&context->local)->sin6_port)); |
| snprintk(addr_remote, remote_len, "[%s]:%u", |
| net_sprint_ipv6_addr( |
| &net_sin6(&context->remote)->sin6_addr), |
| ntohs(net_sin6(&context->remote)->sin6_port)); |
| |
| } else if (IS_ENABLED(CONFIG_NET_IPV4) && context->local.family == AF_INET) { |
| snprintk(addr_local, local_len, "%s:%d", |
| net_sprint_ipv4_addr( |
| net_sin_ptr(&context->local)->sin_addr), |
| ntohs(net_sin_ptr(&context->local)->sin_port)); |
| |
| /* Check if we need to print the v4-mapping-to-v6 address */ |
| if (IS_ENABLED(CONFIG_NET_IPV4_MAPPING_TO_IPV6) && |
| net_sin(&context->remote)->sin_family == AF_INET6 && |
| net_ipv6_addr_is_v4_mapped(&net_sin6(&context->remote)->sin6_addr)) { |
| snprintk(addr_remote, remote_len, "[%s]:%d", |
| net_sprint_ipv6_addr( |
| &net_sin6(&context->remote)->sin6_addr), |
| ntohs(net_sin6(&context->remote)->sin6_port)); |
| } else { |
| snprintk(addr_remote, remote_len, "%s:%d", |
| net_sprint_ipv4_addr( |
| &net_sin(&context->remote)->sin_addr), |
| ntohs(net_sin(&context->remote)->sin_port)); |
| } |
| |
| } else if (context->local.family == AF_UNSPEC) { |
| snprintk(addr_local, local_len, "AF_UNSPEC"); |
| } else if (context->local.family == AF_PACKET) { |
| snprintk(addr_local, local_len, "AF_PACKET"); |
| } else if (context->local.family == AF_CAN) { |
| snprintk(addr_local, local_len, "AF_CAN"); |
| } else { |
| snprintk(addr_local, local_len, "AF_UNK(%d)", |
| context->local.family); |
| } |
| } |
| #endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */ |
| |
| const char *iface2str(struct net_if *iface, const char **extra) |
| { |
| #ifdef CONFIG_NET_L2_IEEE802154 |
| if (net_if_l2(iface) == &NET_L2_GET_NAME(IEEE802154)) { |
| if (extra) { |
| *extra = "============="; |
| } |
| |
| return "IEEE 802.15.4"; |
| } |
| #endif |
| |
| #ifdef CONFIG_NET_L2_ETHERNET |
| if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) { |
| struct ethernet_context *eth_ctx = net_if_l2_data(iface); |
| |
| if (eth_ctx->eth_if_type == L2_ETH_IF_TYPE_WIFI) { |
| if (extra) { |
| *extra = "===="; |
| } |
| |
| return "WiFi"; |
| } |
| |
| if (extra) { |
| *extra = "========"; |
| } |
| |
| return "Ethernet"; |
| } |
| #endif |
| |
| #ifdef CONFIG_NET_L2_VIRTUAL |
| if (net_if_l2(iface) == &NET_L2_GET_NAME(VIRTUAL)) { |
| if (extra) { |
| *extra = "======="; |
| } |
| |
| return "Virtual"; |
| } |
| #endif |
| |
| #ifdef CONFIG_NET_L2_PPP |
| if (net_if_l2(iface) == &NET_L2_GET_NAME(PPP)) { |
| if (extra) { |
| *extra = "==="; |
| } |
| |
| return "PPP"; |
| } |
| #endif |
| |
| #ifdef CONFIG_NET_L2_DUMMY |
| if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) { |
| if (extra) { |
| *extra = "====="; |
| } |
| |
| return "Dummy"; |
| } |
| #endif |
| |
| #ifdef CONFIG_NET_L2_OPENTHREAD |
| if (net_if_l2(iface) == &NET_L2_GET_NAME(OPENTHREAD)) { |
| if (extra) { |
| *extra = "=========="; |
| } |
| |
| return "OpenThread"; |
| } |
| #endif |
| |
| #ifdef CONFIG_NET_L2_BT |
| if (net_if_l2(iface) == &NET_L2_GET_NAME(BLUETOOTH)) { |
| if (extra) { |
| *extra = "========="; |
| } |
| |
| return "Bluetooth"; |
| } |
| #endif |
| |
| #ifdef CONFIG_NET_OFFLOAD |
| if (net_if_is_ip_offloaded(iface)) { |
| if (extra) { |
| *extra = "=========="; |
| } |
| |
| return "IP Offload"; |
| } |
| #endif |
| |
| #ifdef CONFIG_NET_L2_CANBUS_RAW |
| if (net_if_l2(iface) == &NET_L2_GET_NAME(CANBUS_RAW)) { |
| if (extra) { |
| *extra = "=========="; |
| } |
| |
| return "CANBUS_RAW"; |
| } |
| #endif |
| |
| if (extra) { |
| *extra = "=============="; |
| } |
| |
| return "<unknown type>"; |
| } |
| |
| /* Placeholder for net commands that are configured in the rest of the .c files */ |
| SHELL_SUBCMD_SET_CREATE(net_cmds, (net)); |
| |
| SHELL_CMD_REGISTER(net, &net_cmds, "Networking commands", NULL); |
| |
| int net_shell_init(void) |
| { |
| if (IS_ENABLED(CONFIG_NET_MGMT_EVENT_MONITOR_AUTO_START)) { |
| events_enable(); |
| } |
| |
| return 0; |
| } |