/* * Copyright (c) 2016 Intel Corporation * Copyright (c) 2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #include LOG_MODULE_DECLARE(net_shell); #include #include "net_shell_private.h" #include #if defined(CONFIG_NET_CAPTURE) #define DEFAULT_DEV_NAME "NET_CAPTURE0" static const struct device *capture_dev; static void get_address_str(const struct sockaddr *addr, char *str, int str_len) { if (IS_ENABLED(CONFIG_NET_IPV6) && addr->sa_family == AF_INET6) { snprintk(str, str_len, "[%s]:%u", net_sprint_ipv6_addr(&net_sin6(addr)->sin6_addr), ntohs(net_sin6(addr)->sin6_port)); } else if (IS_ENABLED(CONFIG_NET_IPV4) && addr->sa_family == AF_INET) { snprintk(str, str_len, "%s:%d", net_sprint_ipv4_addr(&net_sin(addr)->sin_addr), ntohs(net_sin(addr)->sin_port)); } else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) && addr->sa_family == AF_PACKET) { snprintk(str, str_len, "AF_PACKET"); } else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && addr->sa_family == AF_CAN) { snprintk(str, str_len, "AF_CAN"); } else if (addr->sa_family == AF_UNSPEC) { snprintk(str, str_len, "AF_UNSPEC"); } else { snprintk(str, str_len, "AF_UNK(%d)", addr->sa_family); } } static void capture_cb(struct net_capture_info *info, void *user_data) { struct net_shell_user_data *data = user_data; const struct shell *sh = data->sh; int *count = data->user_data; char addr_local[ADDR_LEN + 7]; char addr_peer[ADDR_LEN + 7]; if (*count == 0) { PR(" \t\tCapture Tunnel\n"); PR("Device\t\tiface iface Local\t\t\tPeer\n"); } get_address_str(info->local, addr_local, sizeof(addr_local)); get_address_str(info->peer, addr_peer, sizeof(addr_peer)); PR("%s\t%c %d %s\t%s\n", info->capture_dev->name, info->is_enabled ? (net_if_get_by_iface(info->capture_iface) + '0') : '-', net_if_get_by_iface(info->tunnel_iface), addr_local, addr_peer); (*count)++; } #endif static int cmd_net_capture(const struct shell *sh, size_t argc, char *argv[]) { #if defined(CONFIG_NET_CAPTURE) bool ret; if (capture_dev == NULL) { capture_dev = device_get_binding(DEFAULT_DEV_NAME); } if (capture_dev == NULL) { PR_INFO("Network packet capture %s\n", "not configured"); } else { struct net_shell_user_data user_data; int count = 0; ret = net_capture_is_enabled(capture_dev); PR_INFO("Network packet capture %s\n", ret ? "enabled" : "disabled"); user_data.sh = sh; user_data.user_data = &count; net_capture_foreach(capture_cb, &user_data); } #else ARG_UNUSED(argc); ARG_UNUSED(argv); PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_CAPTURE", "network packet capture"); #endif return 0; } static int cmd_net_capture_setup(const struct shell *sh, size_t argc, char *argv[]) { #if defined(CONFIG_NET_CAPTURE) int ret, arg = 1; const char *remote, *local, *peer; remote = argv[arg++]; if (!remote) { PR_WARNING("Remote IP address not specified.\n"); return -ENOEXEC; } local = argv[arg++]; if (!local) { PR_WARNING("Local IP address not specified.\n"); return -ENOEXEC; } peer = argv[arg]; if (!peer) { PR_WARNING("Peer IP address not specified.\n"); return -ENOEXEC; } if (capture_dev != NULL) { PR_INFO("Capture already setup, cleaning up settings.\n"); net_capture_cleanup(capture_dev); capture_dev = NULL; } ret = net_capture_setup(remote, local, peer, &capture_dev); if (ret < 0) { PR_WARNING("Capture cannot be setup (%d)\n", ret); return -ENOEXEC; } PR_INFO("Capture setup done, next enable it by " "\"net capture enable \"\n"); #else ARG_UNUSED(argc); ARG_UNUSED(argv); PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_CAPTURE", "network packet capture"); #endif return 0; } static int cmd_net_capture_cleanup(const struct shell *sh, size_t argc, char *argv[]) { ARG_UNUSED(argc); ARG_UNUSED(argv); #if defined(CONFIG_NET_CAPTURE) int ret; if (capture_dev == NULL) { return 0; } ret = net_capture_cleanup(capture_dev); if (ret < 0) { PR_WARNING("Capture %s failed (%d)\n", "cleanup", ret); return -ENOEXEC; } capture_dev = NULL; #else PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_CAPTURE", "network packet capture"); #endif return 0; } static int cmd_net_capture_enable(const struct shell *sh, size_t argc, char *argv[]) { ARG_UNUSED(argc); ARG_UNUSED(argv); #if defined(CONFIG_NET_CAPTURE) int ret, arg = 1, if_index; struct net_if *iface; if (capture_dev == NULL) { return 0; } if (argv[arg] == NULL) { PR_WARNING("Interface index is missing. Please give interface " "what you want to monitor\n"); return -ENOEXEC; } if_index = atoi(argv[arg++]); if (if_index == 0) { PR_WARNING("Interface index %d is invalid.\n", if_index); return -ENOEXEC; } iface = net_if_get_by_index(if_index); if (iface == NULL) { PR_WARNING("No such interface with index %d\n", if_index); return -ENOEXEC; } ret = net_capture_enable(capture_dev, iface); if (ret < 0) { PR_WARNING("Capture %s failed (%d)\n", "enable", ret); return -ENOEXEC; } #else PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_CAPTURE", "network packet capture"); #endif return 0; } static int cmd_net_capture_disable(const struct shell *sh, size_t argc, char *argv[]) { ARG_UNUSED(argc); ARG_UNUSED(argv); #if defined(CONFIG_NET_CAPTURE) int ret; if (capture_dev == NULL) { return 0; } ret = net_capture_disable(capture_dev); if (ret < 0) { PR_WARNING("Capture %s failed (%d)\n", "disable", ret); return -ENOEXEC; } #else PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_CAPTURE", "network packet capture"); #endif return 0; } SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_capture, SHELL_CMD(setup, NULL, "Setup network packet capture.\n" "'net capture setup '\n" " is the (outer) endpoint IP address,\n" " is the (inner) local IP address,\n" " is the (inner) peer IP address\n" "Local and Peer addresses can have UDP port number in them (optional)\n" "like 198.0.51.2:9000 or [2001:db8:100::2]:4242", cmd_net_capture_setup), SHELL_CMD(cleanup, NULL, "Cleanup network packet capture.", cmd_net_capture_cleanup), SHELL_CMD(enable, NULL, "Enable network packet capture for a given " "network interface.\n" "'net capture enable '", cmd_net_capture_enable), SHELL_CMD(disable, NULL, "Disable network packet capture.", cmd_net_capture_disable), SHELL_SUBCMD_SET_END ); SHELL_SUBCMD_ADD((net), capture, &net_cmd_capture, "Configure network packet capture.", cmd_net_capture, 1, 0);