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 LOG_MODULE_DECLARE(net_shell);
10
11 #include <zephyr/net/ppp.h>
12
13 #include "net_shell_private.h"
14
15 #if defined(CONFIG_NET_L2_PPP)
16 #include <zephyr/net/ppp.h>
17 #include "ppp/ppp_internal.h"
18 #endif
19
cmd_net_ppp_ping(const struct shell * sh,size_t argc,char * argv[])20 static int cmd_net_ppp_ping(const struct shell *sh, size_t argc, char *argv[])
21 {
22 #if defined(CONFIG_NET_PPP)
23 if (argv[1]) {
24 int ret, idx = get_iface_idx(sh, argv[1]);
25
26 if (idx < 0) {
27 return -ENOEXEC;
28 }
29
30 ret = net_ppp_ping(idx, MSEC_PER_SEC * 1);
31 if (ret < 0) {
32 if (ret == -EAGAIN) {
33 PR_INFO("PPP Echo-Req timeout.\n");
34 } else if (ret == -ENODEV || ret == -ENOENT) {
35 PR_INFO("Not a PPP interface (%d)\n", idx);
36 } else {
37 PR_INFO("PPP Echo-Req failed (%d)\n", ret);
38 }
39 } else {
40 if (ret > 1000) {
41 PR_INFO("%s%d msec\n",
42 "Received PPP Echo-Reply in ",
43 ret / 1000);
44 } else {
45 PR_INFO("%s%d usec\n",
46 "Received PPP Echo-Reply in ", ret);
47 }
48 }
49 } else {
50 PR_INFO("PPP network interface must be given.\n");
51 return -ENOEXEC;
52 }
53 #else
54 PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_L2_PPP", "PPP");
55 #endif
56 return 0;
57 }
58
cmd_net_ppp_status(const struct shell * sh,size_t argc,char * argv[])59 static int cmd_net_ppp_status(const struct shell *sh, size_t argc, char *argv[])
60 {
61 #if defined(CONFIG_NET_PPP)
62 int idx = 0;
63 struct ppp_context *ctx;
64
65 if (argv[1]) {
66 idx = get_iface_idx(sh, argv[1]);
67 if (idx < 0) {
68 return -ENOEXEC;
69 }
70 }
71
72 ctx = net_ppp_context_get(idx);
73 if (!ctx) {
74 PR_INFO("PPP context not found.\n");
75 return -ENOEXEC;
76 }
77
78 PR("PPP phase : %s (%d)\n", ppp_phase_str(ctx->phase),
79 ctx->phase);
80 PR("LCP state : %s (%d)\n",
81 ppp_state_str(ctx->lcp.fsm.state), ctx->lcp.fsm.state);
82 PR("LCP retransmits : %u\n", ctx->lcp.fsm.retransmits);
83 PR("LCP NACK loops : %u\n", ctx->lcp.fsm.nack_loops);
84 PR("LCP NACKs recv : %u\n", ctx->lcp.fsm.recv_nack_loops);
85 PR("LCP current id : %d\n", ctx->lcp.fsm.id);
86 PR("LCP ACK received : %s\n", ctx->lcp.fsm.ack_received ?
87 "yes" : "no");
88
89 #if defined(CONFIG_NET_IPV4)
90 PR("IPCP state : %s (%d)\n",
91 ppp_state_str(ctx->ipcp.fsm.state), ctx->ipcp.fsm.state);
92 PR("IPCP retransmits : %u\n", ctx->ipcp.fsm.retransmits);
93 PR("IPCP NACK loops : %u\n", ctx->ipcp.fsm.nack_loops);
94 PR("IPCP NACKs recv : %u\n", ctx->ipcp.fsm.recv_nack_loops);
95 PR("IPCP current id : %d\n", ctx->ipcp.fsm.id);
96 PR("IPCP ACK received : %s\n", ctx->ipcp.fsm.ack_received ?
97 "yes" : "no");
98 #endif /* CONFIG_NET_IPV4 */
99
100 #if defined(CONFIG_NET_IPV6)
101 PR("IPv6CP state : %s (%d)\n",
102 ppp_state_str(ctx->ipv6cp.fsm.state), ctx->ipv6cp.fsm.state);
103 PR("IPv6CP retransmits : %u\n", ctx->ipv6cp.fsm.retransmits);
104 PR("IPv6CP NACK loops : %u\n", ctx->ipv6cp.fsm.nack_loops);
105 PR("IPv6CP NACKs recv : %u\n", ctx->ipv6cp.fsm.recv_nack_loops);
106 PR("IPv6CP current id : %d\n", ctx->ipv6cp.fsm.id);
107 PR("IPv6CP ACK received : %s\n", ctx->ipv6cp.fsm.ack_received ?
108 "yes" : "no");
109 #endif /* CONFIG_NET_IPV6 */
110
111 #if defined(CONFIG_NET_L2_PPP_PAP)
112 PR("PAP state : %s (%d)\n",
113 ppp_state_str(ctx->pap.fsm.state), ctx->pap.fsm.state);
114 PR("PAP retransmits : %u\n", ctx->pap.fsm.retransmits);
115 PR("PAP NACK loops : %u\n", ctx->pap.fsm.nack_loops);
116 PR("PAP NACKs recv : %u\n", ctx->pap.fsm.recv_nack_loops);
117 PR("PAP current id : %d\n", ctx->pap.fsm.id);
118 PR("PAP ACK received : %s\n", ctx->pap.fsm.ack_received ?
119 "yes" : "no");
120 #endif /* CONFIG_NET_L2_PPP_PAP */
121
122 #else
123 PR_INFO("Set %s to enable %s support.\n",
124 "CONFIG_NET_L2_PPP and CONFIG_NET_PPP", "PPP");
125 #endif
126 return 0;
127 }
128
129 #if defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION)
130
131 #define MAX_IFACE_HELP_STR_LEN sizeof("longbearername (0xabcd0123)")
132 #define MAX_IFACE_STR_LEN sizeof("xxx")
133
134 #if defined(CONFIG_NET_PPP)
135 static char iface_ppp_help_buffer[MAX_IFACE_COUNT][MAX_IFACE_HELP_STR_LEN];
136 static char iface_ppp_index_buffer[MAX_IFACE_COUNT][MAX_IFACE_STR_LEN];
137
set_iface_ppp_index_buffer(size_t idx)138 static char *set_iface_ppp_index_buffer(size_t idx)
139 {
140 struct net_if *iface = net_if_get_by_index(idx);
141
142 /* Network interfaces start at 1 */
143 if (idx == 0) {
144 return "";
145 }
146
147 if (!iface) {
148 return NULL;
149 }
150
151 if (net_if_l2(iface) != &NET_L2_GET_NAME(PPP)) {
152 return NULL;
153 }
154
155 snprintk(iface_ppp_index_buffer[idx], MAX_IFACE_STR_LEN, "%d", (uint8_t)idx);
156
157 return iface_ppp_index_buffer[idx];
158 }
159
set_iface_ppp_index_help(size_t idx)160 static char *set_iface_ppp_index_help(size_t idx)
161 {
162 struct net_if *iface = net_if_get_by_index(idx);
163
164 /* Network interfaces start at 1 */
165 if (idx == 0) {
166 return "";
167 }
168
169 if (!iface) {
170 return NULL;
171 }
172
173 if (net_if_l2(iface) != &NET_L2_GET_NAME(PPP)) {
174 return NULL;
175 }
176
177 #if defined(CONFIG_NET_INTERFACE_NAME)
178 char name[CONFIG_NET_INTERFACE_NAME_LEN + 1];
179
180 net_if_get_name(iface, name, CONFIG_NET_INTERFACE_NAME_LEN);
181 name[CONFIG_NET_INTERFACE_NAME_LEN] = '\0';
182
183 snprintk(iface_ppp_help_buffer[idx], MAX_IFACE_HELP_STR_LEN,
184 "%s [%s] (%p)", name, iface2str(iface, NULL), iface);
185 #else
186 snprintk(iface_ppp_help_buffer[idx], MAX_IFACE_HELP_STR_LEN,
187 "%s (%p)", iface2str(iface, NULL), iface);
188 #endif
189
190 return iface_ppp_help_buffer[idx];
191 }
192
193 static void iface_ppp_index_get(size_t idx, struct shell_static_entry *entry);
194
195 SHELL_DYNAMIC_CMD_CREATE(iface_ppp_index, iface_ppp_index_get);
196
iface_ppp_index_get(size_t idx,struct shell_static_entry * entry)197 static void iface_ppp_index_get(size_t idx, struct shell_static_entry *entry)
198 {
199 entry->handler = NULL;
200 entry->help = set_iface_ppp_index_help(idx);
201 entry->subcmd = &iface_ppp_index;
202 entry->syntax = set_iface_ppp_index_buffer(idx);
203 }
204
205 #define IFACE_PPP_DYN_CMD &iface_ppp_index
206 #else
207 #define IFACE_PPP_DYN_CMD NULL
208 #endif /* CONFIG_NET_PPP */
209
210 #else
211 #define IFACE_PPP_DYN_CMD NULL
212 #endif /* CONFIG_NET_SHELL_DYN_CMD_COMPLETION */
213
214 SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_ppp,
215 SHELL_CMD(ping, IFACE_PPP_DYN_CMD,
216 "'net ppp ping <index>' sends Echo-request to PPP interface.",
217 cmd_net_ppp_ping),
218 SHELL_CMD(status, NULL,
219 "'net ppp status' prints information about PPP.",
220 cmd_net_ppp_status),
221 SHELL_SUBCMD_SET_END
222 );
223
224 SHELL_SUBCMD_ADD((net), ppp, &net_cmd_ppp,
225 "PPP information.",
226 cmd_net_ppp_status, 1, 0);
227