zephyr/subsys/net/lib/shell/net_shell.c
Jukka Rissanen 5afeade2fc net: shell: Add tcp command
Move "tcp" command to a separate file.

Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
2023-10-23 10:40:28 +02:00

949 lines
21 KiB
C

/** @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 <kernel_internal.h>
#include <zephyr/pm/device.h>
#include <zephyr/random/random.h>
#include <stdlib.h>
#include <stdio.h>
#include <zephyr/shell/shell.h>
#include <zephyr/shell/shell_uart.h>
#include <zephyr/net/net_if.h>
#include <zephyr/sys/printk.h>
#if defined(CONFIG_NET_L2_ETHERNET) && defined(CONFIG_NET_L2_ETHERNET_MGMT)
#include <zephyr/net/ethernet.h>
#include <zephyr/net/ethernet_mgmt.h>
#endif /* CONFIG_NET_L2_ETHERNET */
#include "common.h"
#include "connection.h"
#if defined(CONFIG_NET_L2_ETHERNET_MGMT)
#include <zephyr/net/ethernet_mgmt.h>
#endif
#if defined(CONFIG_NET_L2_VIRTUAL)
#include <zephyr/net/virtual.h>
#endif
#if defined(CONFIG_NET_L2_VIRTUAL_MGMT)
#include <zephyr/net/virtual_mgmt.h>
#endif
#if defined(CONFIG_NET_L2_PPP)
#include <zephyr/net/ppp.h>
#include "ppp/ppp_internal.h"
#endif
#include "net_shell.h"
#include <zephyr/sys/fdtable.h>
#include "websocket/websocket_internal.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));
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)) {
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>";
}
#if defined(CONFIG_NET_UDP) && defined(CONFIG_NET_NATIVE_UDP)
static struct net_context *udp_ctx;
static const struct shell *udp_shell;
K_SEM_DEFINE(udp_send_wait, 0, 1);
static void udp_rcvd(struct net_context *context, struct net_pkt *pkt,
union net_ip_header *ip_hdr,
union net_proto_header *proto_hdr, int status,
void *user_data)
{
if (pkt) {
size_t len = net_pkt_remaining_data(pkt);
uint8_t byte;
PR_SHELL(udp_shell, "Received UDP packet: ");
for (size_t i = 0; i < len; ++i) {
net_pkt_read_u8(pkt, &byte);
PR_SHELL(udp_shell, "%02x ", byte);
}
PR_SHELL(udp_shell, "\n");
net_pkt_unref(pkt);
}
}
static void udp_sent(struct net_context *context, int status, void *user_data)
{
ARG_UNUSED(context);
ARG_UNUSED(status);
ARG_UNUSED(user_data);
PR_SHELL(udp_shell, "Message sent\n");
k_sem_give(&udp_send_wait);
}
#endif
static int cmd_net_udp_bind(const struct shell *sh, size_t argc,
char *argv[])
{
#if !defined(CONFIG_NET_UDP) || !defined(CONFIG_NET_NATIVE_UDP)
ARG_UNUSED(sh);
ARG_UNUSED(argc);
ARG_UNUSED(argv);
return -EOPNOTSUPP;
#else
char *addr_str = NULL;
char *endptr = NULL;
uint16_t port;
int ret;
struct net_if *iface;
struct sockaddr addr;
int addrlen;
if (argc < 3) {
PR_WARNING("Not enough arguments given for udp bind command\n");
return -EINVAL;
}
addr_str = argv[1];
port = strtol(argv[2], &endptr, 0);
if (endptr == argv[2]) {
PR_WARNING("Invalid port number\n");
return -EINVAL;
}
if (udp_ctx && net_context_is_used(udp_ctx)) {
PR_WARNING("Network context already in use\n");
return -EALREADY;
}
memset(&addr, 0, sizeof(addr));
ret = net_ipaddr_parse(addr_str, strlen(addr_str), &addr);
if (ret < 0) {
PR_WARNING("Cannot parse address \"%s\"\n", addr_str);
return ret;
}
ret = net_context_get(addr.sa_family, SOCK_DGRAM, IPPROTO_UDP,
&udp_ctx);
if (ret < 0) {
PR_WARNING("Cannot get UDP context (%d)\n", ret);
return ret;
}
udp_shell = sh;
if (IS_ENABLED(CONFIG_NET_IPV6) && addr.sa_family == AF_INET6) {
net_sin6(&addr)->sin6_port = htons(port);
addrlen = sizeof(struct sockaddr_in6);
iface = net_if_ipv6_select_src_iface(
&net_sin6(&addr)->sin6_addr);
} else if (IS_ENABLED(CONFIG_NET_IPV4) && addr.sa_family == AF_INET) {
net_sin(&addr)->sin_port = htons(port);
addrlen = sizeof(struct sockaddr_in);
iface = net_if_ipv4_select_src_iface(
&net_sin(&addr)->sin_addr);
} else {
PR_WARNING("IPv6 and IPv4 are disabled, cannot %s.\n", "bind");
goto release_ctx;
}
if (!iface) {
PR_WARNING("No interface to send to given host\n");
goto release_ctx;
}
net_context_set_iface(udp_ctx, iface);
ret = net_context_bind(udp_ctx, &addr, addrlen);
if (ret < 0) {
PR_WARNING("Binding to UDP port failed (%d)\n", ret);
goto release_ctx;
}
ret = net_context_recv(udp_ctx, udp_rcvd, K_NO_WAIT, NULL);
if (ret < 0) {
PR_WARNING("Receiving from UDP port failed (%d)\n", ret);
goto release_ctx;
}
return 0;
release_ctx:
ret = net_context_put(udp_ctx);
if (ret < 0) {
PR_WARNING("Cannot put UDP context (%d)\n", ret);
}
return 0;
#endif
}
static int cmd_net_udp_close(const struct shell *sh, size_t argc,
char *argv[])
{
#if !defined(CONFIG_NET_UDP) || !defined(CONFIG_NET_NATIVE_UDP)
ARG_UNUSED(sh);
ARG_UNUSED(argc);
ARG_UNUSED(argv);
return -EOPNOTSUPP;
#else
int ret;
if (!udp_ctx || !net_context_is_used(udp_ctx)) {
PR_WARNING("Network context is not used. Cannot close.\n");
return -EINVAL;
}
ret = net_context_put(udp_ctx);
if (ret < 0) {
PR_WARNING("Cannot close UDP port (%d)\n", ret);
}
return 0;
#endif
}
static int cmd_net_udp_send(const struct shell *sh, size_t argc,
char *argv[])
{
#if !defined(CONFIG_NET_UDP) || !defined(CONFIG_NET_NATIVE_UDP)
ARG_UNUSED(sh);
ARG_UNUSED(argc);
ARG_UNUSED(argv);
return -EOPNOTSUPP;
#else
char *host = NULL;
char *endptr = NULL;
uint16_t port;
uint8_t *payload = NULL;
int ret;
struct net_if *iface;
struct sockaddr addr;
int addrlen;
if (argc < 4) {
PR_WARNING("Not enough arguments given for udp send command\n");
return -EINVAL;
}
host = argv[1];
port = strtol(argv[2], &endptr, 0);
payload = argv[3];
if (endptr == argv[2]) {
PR_WARNING("Invalid port number\n");
return -EINVAL;
}
if (udp_ctx && net_context_is_used(udp_ctx)) {
PR_WARNING("Network context already in use\n");
return -EALREADY;
}
memset(&addr, 0, sizeof(addr));
ret = net_ipaddr_parse(host, strlen(host), &addr);
if (ret < 0) {
PR_WARNING("Cannot parse address \"%s\"\n", host);
return ret;
}
ret = net_context_get(addr.sa_family, SOCK_DGRAM, IPPROTO_UDP,
&udp_ctx);
if (ret < 0) {
PR_WARNING("Cannot get UDP context (%d)\n", ret);
return ret;
}
udp_shell = sh;
if (IS_ENABLED(CONFIG_NET_IPV6) && addr.sa_family == AF_INET6) {
net_sin6(&addr)->sin6_port = htons(port);
addrlen = sizeof(struct sockaddr_in6);
iface = net_if_ipv6_select_src_iface(
&net_sin6(&addr)->sin6_addr);
} else if (IS_ENABLED(CONFIG_NET_IPV4) && addr.sa_family == AF_INET) {
net_sin(&addr)->sin_port = htons(port);
addrlen = sizeof(struct sockaddr_in);
iface = net_if_ipv4_select_src_iface(
&net_sin(&addr)->sin_addr);
} else {
PR_WARNING("IPv6 and IPv4 are disabled, cannot %s.\n", "send");
goto release_ctx;
}
if (!iface) {
PR_WARNING("No interface to send to given host\n");
goto release_ctx;
}
net_context_set_iface(udp_ctx, iface);
ret = net_context_recv(udp_ctx, udp_rcvd, K_NO_WAIT, NULL);
if (ret < 0) {
PR_WARNING("Setting rcv callback failed (%d)\n", ret);
goto release_ctx;
}
ret = net_context_sendto(udp_ctx, payload, strlen(payload), &addr,
addrlen, udp_sent, K_FOREVER, NULL);
if (ret < 0) {
PR_WARNING("Sending packet failed (%d)\n", ret);
goto release_ctx;
}
ret = k_sem_take(&udp_send_wait, K_SECONDS(2));
if (ret == -EAGAIN) {
PR_WARNING("UDP packet sending failed\n");
}
release_ctx:
ret = net_context_put(udp_ctx);
if (ret < 0) {
PR_WARNING("Cannot put UDP context (%d)\n", ret);
}
return 0;
#endif
}
static int cmd_net_udp(const struct shell *sh, size_t argc, char *argv[])
{
ARG_UNUSED(sh);
ARG_UNUSED(argc);
ARG_UNUSED(argv);
return 0;
}
#if defined(CONFIG_NET_L2_VIRTUAL)
static void virtual_iface_cb(struct net_if *iface, void *user_data)
{
struct net_shell_user_data *data = user_data;
const struct shell *sh = data->sh;
int *count = data->user_data;
char *name, buf[CONFIG_NET_L2_VIRTUAL_MAX_NAME_LEN];
struct net_if *orig_iface;
if (net_if_l2(iface) != &NET_L2_GET_NAME(VIRTUAL)) {
return;
}
if (*count == 0) {
PR("Interface Attached-To Description\n");
(*count)++;
}
orig_iface = net_virtual_get_iface(iface);
name = net_virtual_get_name(iface, buf, sizeof(buf));
PR("%d %c %s\n",
net_if_get_by_iface(iface),
orig_iface ? net_if_get_by_iface(orig_iface) + '0' : '-',
name);
(*count)++;
}
static void attached_iface_cb(struct net_if *iface, void *user_data)
{
struct net_shell_user_data *data = user_data;
const struct shell *sh = data->sh;
int *count = data->user_data;
char buf[CONFIG_NET_L2_VIRTUAL_MAX_NAME_LEN];
const char *name;
struct virtual_interface_context *ctx, *tmp;
if (sys_slist_is_empty(&iface->config.virtual_interfaces)) {
return;
}
if (*count == 0) {
PR("Interface Below-of Description\n");
(*count)++;
}
PR("%d ", net_if_get_by_iface(iface));
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&iface->config.virtual_interfaces,
ctx, tmp, node) {
if (ctx->virtual_iface == iface) {
continue;
}
PR("%d ", net_if_get_by_iface(ctx->virtual_iface));
}
name = net_virtual_get_name(iface, buf, sizeof(buf));
if (name == NULL) {
name = iface2str(iface, NULL);
}
PR(" %s\n", name);
(*count)++;
}
#endif /* CONFIG_NET_L2_VIRTUAL */
static int cmd_net_virtual(const struct shell *sh, size_t argc,
char *argv[])
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
#if defined(CONFIG_NET_L2_VIRTUAL)
struct net_shell_user_data user_data;
int count = 0;
user_data.sh = sh;
user_data.user_data = &count;
net_if_foreach(virtual_iface_cb, &user_data);
count = 0;
PR("\n");
net_if_foreach(attached_iface_cb, &user_data);
#else
PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_L2_VIRTUAL",
"virtual network interface");
#endif
return 0;
}
#if defined(CONFIG_NET_VLAN)
static void iface_vlan_del_cb(struct net_if *iface, void *user_data)
{
struct net_shell_user_data *data = user_data;
const struct shell *sh = data->sh;
uint16_t vlan_tag = POINTER_TO_UINT(data->user_data);
int ret;
ret = net_eth_vlan_disable(iface, vlan_tag);
if (ret < 0) {
if (ret != -ESRCH) {
PR_WARNING("Cannot delete VLAN tag %d from "
"interface %d (%p)\n",
vlan_tag,
net_if_get_by_iface(iface),
iface);
}
return;
}
PR("VLAN tag %d removed from interface %d (%p)\n", vlan_tag,
net_if_get_by_iface(iface), iface);
}
static void iface_vlan_cb(struct net_if *iface, void *user_data)
{
struct ethernet_context *ctx = net_if_l2_data(iface);
struct net_shell_user_data *data = user_data;
const struct shell *sh = data->sh;
int *count = data->user_data;
int i;
if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
return;
}
if (*count == 0) {
PR(" Interface Type Tag\n");
}
if (!ctx->vlan_enabled) {
PR_WARNING("VLAN tag(s) not set\n");
return;
}
for (i = 0; i < NET_VLAN_MAX_COUNT; i++) {
if (!ctx->vlan[i].iface || ctx->vlan[i].iface != iface) {
continue;
}
if (ctx->vlan[i].tag == NET_VLAN_TAG_UNSPEC) {
continue;
}
PR("[%d] %p %s %d\n", net_if_get_by_iface(iface), iface,
iface2str(iface, NULL), ctx->vlan[i].tag);
break;
}
(*count)++;
}
#endif /* CONFIG_NET_VLAN */
static int cmd_net_vlan(const struct shell *sh, size_t argc, char *argv[])
{
#if defined(CONFIG_NET_VLAN)
struct net_shell_user_data user_data;
int count;
#endif
#if defined(CONFIG_NET_VLAN)
count = 0;
user_data.sh = sh;
user_data.user_data = &count;
net_if_foreach(iface_vlan_cb, &user_data);
#else
PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_VLAN", "VLAN");
#endif /* CONFIG_NET_VLAN */
return 0;
}
static int cmd_net_vlan_add(const struct shell *sh, size_t argc,
char *argv[])
{
#if defined(CONFIG_NET_VLAN)
int arg = 0;
int ret;
uint16_t tag;
struct net_if *iface;
char *endptr;
uint32_t iface_idx;
#endif
#if defined(CONFIG_NET_VLAN)
/* vlan add <tag> <interface index> */
if (!argv[++arg]) {
PR_WARNING("VLAN tag missing.\n");
goto usage;
}
tag = strtol(argv[arg], &endptr, 10);
if (*endptr != '\0') {
PR_WARNING("Invalid tag %s\n", argv[arg]);
return -ENOEXEC;
}
if (!argv[++arg]) {
PR_WARNING("Network interface index missing.\n");
goto usage;
}
iface_idx = strtol(argv[arg], &endptr, 10);
if (*endptr != '\0') {
PR_WARNING("Invalid index %s\n", argv[arg]);
goto usage;
}
iface = net_if_get_by_index(iface_idx);
if (!iface) {
PR_WARNING("Network interface index %d is invalid.\n",
iface_idx);
goto usage;
}
if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
PR_WARNING("Network interface %d (%p) is not ethernet interface\n",
net_if_get_by_iface(iface), iface);
return -ENOEXEC;
}
ret = net_eth_vlan_enable(iface, tag);
if (ret < 0) {
if (ret == -ENOENT) {
PR_WARNING("No IP address configured.\n");
}
PR_WARNING("Cannot set VLAN tag (%d)\n", ret);
return -ENOEXEC;
}
PR("VLAN tag %d set to interface %d (%p)\n", tag,
net_if_get_by_iface(iface), iface);
return 0;
usage:
PR("Usage:\n");
PR("\tvlan add <tag> <interface index>\n");
#else
PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_VLAN", "VLAN");
#endif /* CONFIG_NET_VLAN */
return 0;
}
static int cmd_net_vlan_del(const struct shell *sh, size_t argc,
char *argv[])
{
#if defined(CONFIG_NET_VLAN)
int arg = 0;
struct net_shell_user_data user_data;
char *endptr;
uint16_t tag;
#endif
#if defined(CONFIG_NET_VLAN)
/* vlan del <tag> */
if (!argv[++arg]) {
PR_WARNING("VLAN tag missing.\n");
goto usage;
}
tag = strtol(argv[arg], &endptr, 10);
if (*endptr != '\0') {
PR_WARNING("Invalid tag %s\n", argv[arg]);
return -ENOEXEC;
}
user_data.sh = sh;
user_data.user_data = UINT_TO_POINTER((uint32_t)tag);
net_if_foreach(iface_vlan_del_cb, &user_data);
return 0;
usage:
PR("Usage:\n");
PR("\tvlan del <tag>\n");
#else
PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_VLAN", "VLAN");
#endif /* CONFIG_NET_VLAN */
return 0;
}
#if defined(CONFIG_WEBSOCKET_CLIENT)
static void websocket_context_cb(struct websocket_context *context,
void *user_data)
{
struct net_shell_user_data *data = user_data;
const struct shell *sh = data->sh;
struct net_context *net_ctx;
int *count = data->user_data;
/* +7 for []:port */
char addr_local[ADDR_LEN + 7];
char addr_remote[ADDR_LEN + 7] = "";
net_ctx = z_get_fd_obj(context->real_sock, NULL, 0);
if (net_ctx == NULL) {
PR_ERROR("Invalid fd %d", context->real_sock);
return;
}
get_addresses(net_ctx, addr_local, sizeof(addr_local),
addr_remote, sizeof(addr_remote));
PR("[%2d] %p/%p\t%p %16s\t%16s\n",
(*count) + 1, context, net_ctx,
net_context_get_iface(net_ctx),
addr_local, addr_remote);
(*count)++;
}
#endif /* CONFIG_WEBSOCKET_CLIENT */
static int cmd_net_websocket(const struct shell *sh, size_t argc,
char *argv[])
{
#if defined(CONFIG_WEBSOCKET_CLIENT)
struct net_shell_user_data user_data;
int count = 0;
ARG_UNUSED(argc);
ARG_UNUSED(argv);
PR(" websocket/net_ctx\tIface "
"Local \tRemote\n");
user_data.sh = sh;
user_data.user_data = &count;
websocket_context_foreach(websocket_context_cb, &user_data);
if (count == 0) {
PR("No connections\n");
}
#else
PR_INFO("Set %s to enable %s support.\n", "CONFIG_WEBSOCKET_CLIENT",
"Websocket");
#endif /* CONFIG_WEBSOCKET_CLIENT */
return 0;
}
#if defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION)
SHELL_DYNAMIC_CMD_CREATE(iface_index, iface_index_get);
#endif /* CONFIG_NET_SHELL_DYN_CMD_COMPLETION */
SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_vlan,
SHELL_CMD(add, NULL,
"'net vlan add <tag> <index>' adds VLAN tag to the "
"network interface.",
cmd_net_vlan_add),
SHELL_CMD(del, NULL,
"'net vlan del <tag>' deletes VLAN tag from the network "
"interface.",
cmd_net_vlan_del),
SHELL_SUBCMD_SET_END
);
SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_udp,
SHELL_CMD(bind, NULL,
"'net udp bind <addr> <port>' binds to UDP local port.",
cmd_net_udp_bind),
SHELL_CMD(close, NULL,
"'net udp close' closes previously bound port.",
cmd_net_udp_close),
SHELL_CMD(send, NULL,
"'net udp send <host> <port> <payload>' "
"sends UDP packet to a network host.",
cmd_net_udp_send),
SHELL_SUBCMD_SET_END
);
SHELL_STATIC_SUBCMD_SET_CREATE(net_commands,
SHELL_CMD(udp, &net_cmd_udp, "Send/recv UDP packet", cmd_net_udp),
SHELL_CMD(virtual, NULL, "Show virtual network interfaces.",
cmd_net_virtual),
SHELL_CMD(vlan, &net_cmd_vlan, "Show VLAN information.", cmd_net_vlan),
SHELL_CMD(websocket, NULL, "Print information about WebSocket "
"connections.",
cmd_net_websocket),
SHELL_SUBCMD_SET_END
);
SHELL_CMD_REGISTER(net_old, &net_commands, "Networking commands", NULL);
/* 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;
}