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