1 /*
2  * Copyright (c) 2019 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_DECLARE(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL);
9 
10 #include <zephyr/net/net_core.h>
11 #include <zephyr/net/net_pkt.h>
12 
13 #include <zephyr/net/ppp.h>
14 
15 #include "net_private.h"
16 
17 #include "ppp_internal.h"
18 
ppp_phase_str(enum ppp_phase phase)19 const char *ppp_phase_str(enum ppp_phase phase)
20 {
21 #if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) || defined(CONFIG_NET_SHELL)
22 	switch (phase) {
23 	case PPP_DEAD:
24 		return "DEAD";
25 	case PPP_ESTABLISH:
26 		return "ESTABLISH";
27 	case PPP_AUTH:
28 		return "AUTH";
29 	case PPP_NETWORK:
30 		return "NETWORK";
31 	case PPP_RUNNING:
32 		return "RUNNING";
33 	case PPP_TERMINATE:
34 		return "TERMINATE";
35 	}
36 #else
37 	ARG_UNUSED(phase);
38 #endif
39 
40 	return "";
41 }
42 
43 #if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
validate_phase_transition(enum ppp_phase current,enum ppp_phase new)44 static void validate_phase_transition(enum ppp_phase current,
45 				      enum ppp_phase new)
46 {
47 	static const uint8_t valid_transitions[] = {
48 		[PPP_DEAD] = 1 << PPP_ESTABLISH,
49 		[PPP_ESTABLISH] = 1 << PPP_DEAD |
50 				1 << PPP_AUTH |
51 				1 << PPP_TERMINATE,
52 		[PPP_AUTH] = 1 << PPP_TERMINATE |
53 				1 << PPP_NETWORK,
54 		[PPP_NETWORK] = 1 << PPP_TERMINATE |
55 				1 << PPP_RUNNING,
56 		[PPP_RUNNING] = 1 << PPP_TERMINATE |
57 				1 << PPP_NETWORK,
58 		[PPP_TERMINATE] = 1 << PPP_DEAD,
59 	};
60 
61 	if (!(valid_transitions[current] & 1 << new)) {
62 		NET_DBG("Invalid phase transition: %s (%d) => %s (%d)",
63 			ppp_phase_str(current), current,
64 			ppp_phase_str(new), new);
65 	}
66 }
67 #else
validate_phase_transition(enum ppp_phase current,enum ppp_phase new)68 static inline void validate_phase_transition(enum ppp_phase current,
69 					     enum ppp_phase new)
70 {
71 	ARG_UNUSED(current);
72 	ARG_UNUSED(new);
73 }
74 #endif
75 
76 #if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
ppp_change_phase_debug(struct ppp_context * ctx,enum ppp_phase new_phase,const char * caller,int line)77 void ppp_change_phase_debug(struct ppp_context *ctx, enum ppp_phase new_phase,
78 			    const char *caller, int line)
79 #else
80 void ppp_change_phase(struct ppp_context *ctx, enum ppp_phase new_phase)
81 #endif
82 {
83 	NET_ASSERT(ctx);
84 
85 	if (ctx->phase == new_phase) {
86 		return;
87 	}
88 
89 	NET_ASSERT(new_phase >= PPP_DEAD &&
90 		   new_phase <= PPP_TERMINATE);
91 
92 #if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
93 	NET_DBG("[%p] phase %s (%d) => %s (%d) (%s():%d)",
94 		ctx, ppp_phase_str(ctx->phase), ctx->phase,
95 		ppp_phase_str(new_phase), new_phase, caller, line);
96 #endif
97 
98 	validate_phase_transition(ctx->phase, new_phase);
99 
100 	ctx->phase = new_phase;
101 
102 	if (ctx->phase == PPP_DEAD) {
103 		ppp_mgmt_raise_phase_dead_event(ctx->iface);
104 	} else if (ctx->phase == PPP_RUNNING) {
105 		ppp_mgmt_raise_phase_running_event(ctx->iface);
106 	}
107 }
108 
ppp_state_str(enum ppp_state state)109 const char *ppp_state_str(enum ppp_state state)
110 {
111 #if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) || defined(CONFIG_NET_SHELL)
112 	switch (state) {
113 	case PPP_INITIAL:
114 		return "INITIAL";
115 	case PPP_STARTING:
116 		return "STARTING";
117 	case PPP_CLOSED:
118 		return "CLOSED";
119 	case PPP_STOPPED:
120 		return "STOPPED";
121 	case PPP_CLOSING:
122 		return "CLOSING";
123 	case PPP_STOPPING:
124 		return "STOPPING";
125 	case PPP_REQUEST_SENT:
126 		return "REQUEST_SENT";
127 	case PPP_ACK_RECEIVED:
128 		return "ACK_RECEIVED";
129 	case PPP_ACK_SENT:
130 		return "ACK_SENT";
131 	case PPP_OPENED:
132 		return "OPENED";
133 	}
134 #else
135 	ARG_UNUSED(state);
136 #endif
137 
138 	return "";
139 }
140 
ppp_pkt_type2str(enum ppp_packet_type type)141 const char *ppp_pkt_type2str(enum ppp_packet_type type)
142 {
143 #if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) || defined(CONFIG_NET_SHELL)
144 	switch (type) {
145 	case PPP_CONFIGURE_REQ:
146 		return "Configure-Req";
147 	case PPP_CONFIGURE_ACK:
148 		return "Configure-Ack";
149 	case PPP_CONFIGURE_NACK:
150 		return "Configure-Nack";
151 	case PPP_CONFIGURE_REJ:
152 		return "Configure-Rej";
153 	case PPP_TERMINATE_REQ:
154 		return "Terminate-Req";
155 	case PPP_TERMINATE_ACK:
156 		return "Terminate-Ack";
157 	case PPP_CODE_REJ:
158 		return "Code-Rej";
159 	case PPP_PROTOCOL_REJ:
160 		return "Protocol-Rej";
161 	case PPP_ECHO_REQ:
162 		return "Echo-Req";
163 	case PPP_ECHO_REPLY:
164 		return "Echo-Reply";
165 	case PPP_DISCARD_REQ:
166 		return "Discard-Req";
167 	}
168 #else
169 	ARG_UNUSED(type);
170 #endif
171 
172 	return "";
173 }
174 
ppp_proto2str(uint16_t proto)175 const char *ppp_proto2str(uint16_t proto)
176 {
177 #if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG)
178 	switch (proto) {
179 	case PPP_IP:
180 		return "IPv4";
181 	case PPP_IPV6:
182 		return "IPv6";
183 	case PPP_ECP:
184 		return "ECP";
185 	case PPP_CCP:
186 		return "CCP";
187 	case PPP_LCP:
188 		return "LCP";
189 	case PPP_IPCP:
190 		return "IPCP";
191 	case PPP_IPV6CP:
192 		return "IPV6CP";
193 	case PPP_PAP:
194 		return "PAP";
195 	case PPP_CHAP:
196 		return "CHAP";
197 	case PPP_EAP:
198 		return "EAP";
199 	}
200 #else
201 	ARG_UNUSED(proto);
202 #endif
203 
204 	return "";
205 }
206 
207 #if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
validate_state_transition(enum ppp_state current,enum ppp_state new)208 static void validate_state_transition(enum ppp_state current,
209 				      enum ppp_state new)
210 {
211 	/* See RFC 1661 ch. 4.1 */
212 	static const uint16_t valid_transitions[] = {
213 		[PPP_INITIAL] = 1 << PPP_CLOSED |
214 				1 << PPP_STARTING,
215 		[PPP_STARTING] = 1 << PPP_INITIAL |
216 				1 << PPP_REQUEST_SENT,
217 		[PPP_CLOSED] = 1 << PPP_INITIAL |
218 				1 << PPP_REQUEST_SENT,
219 		[PPP_STOPPED] = 1 << PPP_STARTING |
220 				1 << PPP_CLOSED |
221 				1 << PPP_ACK_RECEIVED |
222 				1 << PPP_REQUEST_SENT,
223 		[PPP_CLOSING] = 1 << PPP_INITIAL |
224 				1 << PPP_STOPPING |
225 				1 << PPP_CLOSED,
226 		[PPP_STOPPING] = 1 << PPP_STARTING |
227 				1 << PPP_CLOSING |
228 				1 << PPP_STOPPED,
229 		[PPP_REQUEST_SENT] = 1 << PPP_STARTING |
230 				1 << PPP_CLOSING |
231 				1 << PPP_STOPPED |
232 				1 << PPP_ACK_SENT |
233 				1 << PPP_ACK_RECEIVED,
234 		[PPP_ACK_RECEIVED] = 1 << PPP_STARTING |
235 				1 << PPP_CLOSING |
236 				1 << PPP_OPENED |
237 				1 << PPP_REQUEST_SENT |
238 				1 << PPP_STOPPED,
239 		[PPP_ACK_SENT] = 1 << PPP_STARTING |
240 				1 << PPP_CLOSING |
241 				1 << PPP_STOPPED |
242 				1 << PPP_REQUEST_SENT |
243 				1 << PPP_OPENED,
244 		[PPP_OPENED] = 1 << PPP_STARTING |
245 				1 << PPP_CLOSING |
246 				1 << PPP_ACK_SENT |
247 				1 << PPP_REQUEST_SENT |
248 				1 << PPP_CLOSING |
249 				1 << PPP_STOPPING,
250 	};
251 
252 	if (!(valid_transitions[current] & 1 << new)) {
253 		NET_DBG("Invalid state transition: %s (%d) => %s (%d)",
254 			ppp_state_str(current), current,
255 			ppp_state_str(new), new);
256 	}
257 }
258 #else
validate_state_transition(enum ppp_state current,enum ppp_state new)259 static inline void validate_state_transition(enum ppp_state current,
260 					     enum ppp_state new)
261 {
262 	ARG_UNUSED(current);
263 	ARG_UNUSED(new);
264 }
265 #endif
266 
267 #if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
ppp_change_state_debug(struct ppp_fsm * fsm,enum ppp_state new_state,const char * caller,int line)268 void ppp_change_state_debug(struct ppp_fsm *fsm, enum ppp_state new_state,
269 			    const char *caller, int line)
270 #else
271 void ppp_change_state(struct ppp_fsm *fsm, enum ppp_state new_state)
272 #endif
273 {
274 	NET_ASSERT(fsm);
275 
276 	if (fsm->state == new_state) {
277 		return;
278 	}
279 
280 	NET_ASSERT(new_state >= PPP_INITIAL &&
281 		   new_state <= PPP_OPENED);
282 
283 #if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
284 	NET_DBG("[%s/%p] state %s (%d) => %s (%d) (%s():%d)",
285 		fsm->name, fsm, ppp_state_str(fsm->state), fsm->state,
286 		ppp_state_str(new_state), new_state, caller, line);
287 #endif
288 
289 	validate_state_transition(fsm->state, new_state);
290 
291 	fsm->state = new_state;
292 }
293 
ppp_option2str(enum ppp_protocol_type protocol,int type)294 const char *ppp_option2str(enum ppp_protocol_type protocol,
295 			   int type)
296 {
297 #if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) || defined(CONFIG_NET_SHELL)
298 	switch (protocol) {
299 	case PPP_LCP:
300 		switch (type) {
301 		case LCP_OPTION_RESERVED:
302 			return "RESERVED";
303 		case LCP_OPTION_MRU:
304 			return "MRU";
305 		case LCP_OPTION_ASYNC_CTRL_CHAR_MAP:
306 			return "ASYNC_CTRL_CHAR_MAP";
307 		case LCP_OPTION_AUTH_PROTO:
308 			return "AUTH_PROTO";
309 		case LCP_OPTION_QUALITY_PROTO:
310 			return "QUALITY_PROTO";
311 		case LCP_OPTION_MAGIC_NUMBER:
312 			return "MAGIC_NUMBER";
313 		case LCP_OPTION_PROTO_COMPRESS:
314 			return "PROTO_COMPRESS";
315 		case LCP_OPTION_ADDR_CTRL_COMPRESS:
316 			return "ADDR_CTRL_COMPRESS";
317 		}
318 
319 		break;
320 
321 #if defined(CONFIG_NET_IPV4)
322 	case PPP_IPCP:
323 		switch (type) {
324 		case IPCP_OPTION_RESERVED:
325 			return "RESERVED";
326 		case IPCP_OPTION_IP_ADDRESSES:
327 			return "IP_ADDRESSES";
328 		case IPCP_OPTION_IP_COMP_PROTO:
329 			return "IP_COMPRESSION_PROTOCOL";
330 		case IPCP_OPTION_IP_ADDRESS:
331 			return "IP_ADDRESS";
332 		case IPCP_OPTION_DNS1:
333 			return "DNS1";
334 		case IPCP_OPTION_NBNS1:
335 			return "NBNS1";
336 		case IPCP_OPTION_DNS2:
337 			return "DNS2";
338 		case IPCP_OPTION_NBNS2:
339 			return "NBNS2";
340 		}
341 
342 		break;
343 #endif
344 
345 #if defined(CONFIG_NET_IPV6)
346 	case PPP_IPV6CP:
347 		switch (type) {
348 		case IPV6CP_OPTION_RESERVED:
349 			return "RESERVED";
350 		case IPV6CP_OPTION_INTERFACE_IDENTIFIER:
351 			return "INTERFACE_IDENTIFIER";
352 		}
353 
354 		break;
355 #endif
356 
357 	default:
358 		break;
359 	}
360 #else
361 	ARG_UNUSED(type);
362 #endif
363 
364 	return "";
365 }
366 
ppp_fsm_name_set(struct ppp_fsm * fsm,const char * name)367 void ppp_fsm_name_set(struct ppp_fsm *fsm, const char *name)
368 {
369 #if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
370 	fsm->name = name;
371 #else
372 	ARG_UNUSED(fsm);
373 	ARG_UNUSED(name);
374 #endif
375 }
376