blob: f63c6ca3324184d9ba1c3da48229697e14ac37df [file] [log] [blame]
/*
* Copyright (c) 2016 Intel Corporation
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(net_shell);
#include <zephyr/net/ppp.h>
#include "net_shell_private.h"
#if defined(CONFIG_NET_L2_PPP)
#include <zephyr/net/ppp.h>
#include "ppp/ppp_internal.h"
#endif
static int cmd_net_ppp_ping(const struct shell *sh, size_t argc, char *argv[])
{
#if defined(CONFIG_NET_PPP)
if (argv[1]) {
int ret, idx = get_iface_idx(sh, argv[1]);
if (idx < 0) {
return -ENOEXEC;
}
ret = net_ppp_ping(idx, MSEC_PER_SEC * 1);
if (ret < 0) {
if (ret == -EAGAIN) {
PR_INFO("PPP Echo-Req timeout.\n");
} else if (ret == -ENODEV || ret == -ENOENT) {
PR_INFO("Not a PPP interface (%d)\n", idx);
} else {
PR_INFO("PPP Echo-Req failed (%d)\n", ret);
}
} else {
if (ret > 1000) {
PR_INFO("%s%d msec\n",
"Received PPP Echo-Reply in ",
ret / 1000);
} else {
PR_INFO("%s%d usec\n",
"Received PPP Echo-Reply in ", ret);
}
}
} else {
PR_INFO("PPP network interface must be given.\n");
return -ENOEXEC;
}
#else
PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_L2_PPP", "PPP");
#endif
return 0;
}
static int cmd_net_ppp_status(const struct shell *sh, size_t argc, char *argv[])
{
#if defined(CONFIG_NET_PPP)
int idx = 0;
struct ppp_context *ctx;
if (argv[1]) {
idx = get_iface_idx(sh, argv[1]);
if (idx < 0) {
return -ENOEXEC;
}
}
ctx = net_ppp_context_get(idx);
if (!ctx) {
PR_INFO("PPP context not found.\n");
return -ENOEXEC;
}
PR("PPP phase : %s (%d)\n", ppp_phase_str(ctx->phase),
ctx->phase);
PR("LCP state : %s (%d)\n",
ppp_state_str(ctx->lcp.fsm.state), ctx->lcp.fsm.state);
PR("LCP retransmits : %u\n", ctx->lcp.fsm.retransmits);
PR("LCP NACK loops : %u\n", ctx->lcp.fsm.nack_loops);
PR("LCP NACKs recv : %u\n", ctx->lcp.fsm.recv_nack_loops);
PR("LCP current id : %d\n", ctx->lcp.fsm.id);
PR("LCP ACK received : %s\n", ctx->lcp.fsm.ack_received ?
"yes" : "no");
#if defined(CONFIG_NET_IPV4)
PR("IPCP state : %s (%d)\n",
ppp_state_str(ctx->ipcp.fsm.state), ctx->ipcp.fsm.state);
PR("IPCP retransmits : %u\n", ctx->ipcp.fsm.retransmits);
PR("IPCP NACK loops : %u\n", ctx->ipcp.fsm.nack_loops);
PR("IPCP NACKs recv : %u\n", ctx->ipcp.fsm.recv_nack_loops);
PR("IPCP current id : %d\n", ctx->ipcp.fsm.id);
PR("IPCP ACK received : %s\n", ctx->ipcp.fsm.ack_received ?
"yes" : "no");
#endif /* CONFIG_NET_IPV4 */
#if defined(CONFIG_NET_IPV6)
PR("IPv6CP state : %s (%d)\n",
ppp_state_str(ctx->ipv6cp.fsm.state), ctx->ipv6cp.fsm.state);
PR("IPv6CP retransmits : %u\n", ctx->ipv6cp.fsm.retransmits);
PR("IPv6CP NACK loops : %u\n", ctx->ipv6cp.fsm.nack_loops);
PR("IPv6CP NACKs recv : %u\n", ctx->ipv6cp.fsm.recv_nack_loops);
PR("IPv6CP current id : %d\n", ctx->ipv6cp.fsm.id);
PR("IPv6CP ACK received : %s\n", ctx->ipv6cp.fsm.ack_received ?
"yes" : "no");
#endif /* CONFIG_NET_IPV6 */
#if defined(CONFIG_NET_L2_PPP_PAP)
PR("PAP state : %s (%d)\n",
ppp_state_str(ctx->pap.fsm.state), ctx->pap.fsm.state);
PR("PAP retransmits : %u\n", ctx->pap.fsm.retransmits);
PR("PAP NACK loops : %u\n", ctx->pap.fsm.nack_loops);
PR("PAP NACKs recv : %u\n", ctx->pap.fsm.recv_nack_loops);
PR("PAP current id : %d\n", ctx->pap.fsm.id);
PR("PAP ACK received : %s\n", ctx->pap.fsm.ack_received ?
"yes" : "no");
#endif /* CONFIG_NET_L2_PPP_PAP */
#else
PR_INFO("Set %s to enable %s support.\n",
"CONFIG_NET_L2_PPP and CONFIG_NET_PPP", "PPP");
#endif
return 0;
}
#if defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION)
#define MAX_IFACE_HELP_STR_LEN sizeof("longbearername (0xabcd0123)")
#define MAX_IFACE_STR_LEN sizeof("xxx")
#if defined(CONFIG_NET_PPP)
static char iface_ppp_help_buffer[MAX_IFACE_COUNT][MAX_IFACE_HELP_STR_LEN];
static char iface_ppp_index_buffer[MAX_IFACE_COUNT][MAX_IFACE_STR_LEN];
static char *set_iface_ppp_index_buffer(size_t idx)
{
struct net_if *iface = net_if_get_by_index(idx);
/* Network interfaces start at 1 */
if (idx == 0) {
return "";
}
if (!iface) {
return NULL;
}
if (net_if_l2(iface) != &NET_L2_GET_NAME(PPP)) {
return NULL;
}
snprintk(iface_ppp_index_buffer[idx], MAX_IFACE_STR_LEN, "%d", (uint8_t)idx);
return iface_ppp_index_buffer[idx];
}
static char *set_iface_ppp_index_help(size_t idx)
{
struct net_if *iface = net_if_get_by_index(idx);
/* Network interfaces start at 1 */
if (idx == 0) {
return "";
}
if (!iface) {
return NULL;
}
if (net_if_l2(iface) != &NET_L2_GET_NAME(PPP)) {
return NULL;
}
#if defined(CONFIG_NET_INTERFACE_NAME)
char name[CONFIG_NET_INTERFACE_NAME_LEN + 1];
net_if_get_name(iface, name, CONFIG_NET_INTERFACE_NAME_LEN);
name[CONFIG_NET_INTERFACE_NAME_LEN] = '\0';
snprintk(iface_ppp_help_buffer[idx], MAX_IFACE_HELP_STR_LEN,
"%s [%s] (%p)", name, iface2str(iface, NULL), iface);
#else
snprintk(iface_ppp_help_buffer[idx], MAX_IFACE_HELP_STR_LEN,
"%s (%p)", iface2str(iface, NULL), iface);
#endif
return iface_ppp_help_buffer[idx];
}
static void iface_ppp_index_get(size_t idx, struct shell_static_entry *entry);
SHELL_DYNAMIC_CMD_CREATE(iface_ppp_index, iface_ppp_index_get);
static void iface_ppp_index_get(size_t idx, struct shell_static_entry *entry)
{
entry->handler = NULL;
entry->help = set_iface_ppp_index_help(idx);
entry->subcmd = &iface_ppp_index;
entry->syntax = set_iface_ppp_index_buffer(idx);
}
#define IFACE_PPP_DYN_CMD &iface_ppp_index
#else
#define IFACE_PPP_DYN_CMD NULL
#endif /* CONFIG_NET_PPP */
#else
#define IFACE_PPP_DYN_CMD NULL
#endif /* CONFIG_NET_SHELL_DYN_CMD_COMPLETION */
SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_ppp,
SHELL_CMD(ping, IFACE_PPP_DYN_CMD,
"'net ppp ping <index>' sends Echo-request to PPP interface.",
cmd_net_ppp_ping),
SHELL_CMD(status, NULL,
"'net ppp status' prints information about PPP.",
cmd_net_ppp_status),
SHELL_SUBCMD_SET_END
);
SHELL_SUBCMD_ADD((net), ppp, &net_cmd_ppp,
"PPP information.",
cmd_net_ppp_status, 1, 0);