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