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