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