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 #include <zephyr/net/net_if.h>
13 
14 #include <zephyr/net/ppp.h>
15 #include <zephyr/random/random.h>
16 
17 #include "net_private.h"
18 
19 #include "ppp_internal.h"
20 
21 /* This timeout is in milliseconds */
22 #define FSM_TIMEOUT K_MSEC(CONFIG_NET_L2_PPP_TIMEOUT)
23 
24 #define MAX_NACK_LOOPS CONFIG_NET_L2_PPP_MAX_NACK_LOOPS
25 
ppp_fsm_ctx(struct ppp_fsm * fsm)26 struct ppp_context *ppp_fsm_ctx(struct ppp_fsm *fsm)
27 {
28 	if (fsm->protocol == PPP_LCP) {
29 		return CONTAINER_OF(fsm, struct ppp_context, lcp.fsm);
30 #if defined(CONFIG_NET_IPV4)
31 	} else if (fsm->protocol == PPP_IPCP) {
32 		return CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm);
33 #endif
34 #if defined(CONFIG_NET_IPV6)
35 	} else if (fsm->protocol == PPP_IPV6CP) {
36 		return CONTAINER_OF(fsm, struct ppp_context, ipv6cp.fsm);
37 #endif
38 #if defined(CONFIG_NET_L2_PPP_PAP)
39 	} else if (fsm->protocol == PPP_PAP) {
40 		return CONTAINER_OF(fsm, struct ppp_context, pap.fsm);
41 #endif
42 	}
43 
44 	return NULL;
45 }
46 
ppp_fsm_iface(struct ppp_fsm * fsm)47 struct net_if *ppp_fsm_iface(struct ppp_fsm *fsm)
48 {
49 	struct ppp_context *ctx = ppp_fsm_ctx(fsm);
50 
51 	NET_ASSERT(ctx->iface);
52 
53 	return ctx->iface;
54 }
55 
fsm_send_configure_req(struct ppp_fsm * fsm,bool retransmit)56 static void fsm_send_configure_req(struct ppp_fsm *fsm, bool retransmit)
57 {
58 	struct net_pkt *pkt = NULL;
59 
60 	if (fsm->state != PPP_ACK_RECEIVED &&
61 	    fsm->state != PPP_ACK_SENT &&
62 	    fsm->state != PPP_REQUEST_SENT) {
63 		/* If we are not negotiating options, then reset them */
64 		if (fsm->cb.config_info_reset) {
65 			fsm->cb.config_info_reset(fsm);
66 		}
67 
68 		fsm->recv_nack_loops = 0;
69 		fsm->nack_loops = 0;
70 	}
71 
72 	if (!retransmit) {
73 		fsm->retransmits = MAX_CONFIGURE_REQ;
74 		fsm->req_id = ++fsm->id;
75 	}
76 
77 	fsm->ack_received = false;
78 
79 	if (fsm->cb.config_info_add) {
80 		pkt = fsm->cb.config_info_add(fsm);
81 	}
82 
83 	NET_DBG("[%s/%p] Sending %s (%d) id %d to peer while in %s (%d)",
84 		fsm->name, fsm, ppp_pkt_type2str(PPP_CONFIGURE_REQ),
85 		PPP_CONFIGURE_REQ, fsm->req_id, ppp_state_str(fsm->state),
86 		fsm->state);
87 
88 	(void)ppp_send_pkt(fsm, NULL, PPP_CONFIGURE_REQ, fsm->req_id,
89 			   pkt, pkt ? net_pkt_get_len(pkt) : 0);
90 
91 	fsm->retransmits--;
92 
93 	(void)k_work_reschedule(&fsm->timer, FSM_TIMEOUT);
94 }
95 
ppp_fsm_timeout(struct k_work * work)96 static void ppp_fsm_timeout(struct k_work *work)
97 {
98 	struct k_work_delayable *dwork = k_work_delayable_from_work(work);
99 	struct ppp_fsm *fsm = CONTAINER_OF(dwork, struct ppp_fsm, timer);
100 
101 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
102 		ppp_state_str(fsm->state), fsm->state);
103 
104 	switch (fsm->state) {
105 	case PPP_ACK_RECEIVED:
106 	case PPP_ACK_SENT:
107 	case PPP_REQUEST_SENT:
108 		if (fsm->retransmits <= 0) {
109 			NET_DBG("[%s/%p] %s retransmit limit %d reached",
110 				fsm->name, fsm,
111 				ppp_pkt_type2str(PPP_CONFIGURE_REQ),
112 				fsm->retransmits);
113 
114 			ppp_change_state(fsm, PPP_STOPPED);
115 
116 			if (fsm->cb.finished) {
117 				fsm->cb.finished(fsm);
118 			}
119 		} else {
120 			if (fsm->cb.retransmit) {
121 				fsm->cb.retransmit(fsm);
122 			}
123 
124 			fsm_send_configure_req(fsm, true);
125 
126 			if (fsm->state == PPP_ACK_RECEIVED) {
127 				ppp_change_state(fsm, PPP_REQUEST_SENT);
128 			}
129 		}
130 
131 		break;
132 
133 	case PPP_CLOSING:
134 	case PPP_STOPPING:
135 		if (fsm->retransmits <= 0) {
136 			ppp_change_state(fsm,
137 					 fsm->state == PPP_CLOSING ?
138 					 PPP_CLOSED : PPP_STOPPED);
139 
140 			if (fsm->cb.finished) {
141 				fsm->cb.finished(fsm);
142 			}
143 		} else {
144 			fsm->req_id = ++fsm->id;
145 
146 			ppp_send_pkt(fsm, NULL, PPP_TERMINATE_REQ, fsm->req_id,
147 				     fsm->terminate_reason,
148 				     strlen(fsm->terminate_reason));
149 
150 			fsm->retransmits--;
151 
152 			(void)k_work_reschedule(&fsm->timer, FSM_TIMEOUT);
153 		}
154 
155 		break;
156 
157 	default:
158 		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
159 			ppp_state_str(fsm->state), fsm->state);
160 		break;
161 	}
162 }
163 
ppp_fsm_init(struct ppp_fsm * fsm,uint16_t protocol)164 void ppp_fsm_init(struct ppp_fsm *fsm, uint16_t protocol)
165 {
166 	fsm->protocol = protocol;
167 	fsm->state = PPP_INITIAL;
168 	fsm->flags = 0U;
169 
170 	k_work_init_delayable(&fsm->timer, ppp_fsm_timeout);
171 }
172 
fsm_down(struct ppp_fsm * fsm)173 static void fsm_down(struct ppp_fsm *fsm)
174 {
175 	size_t i;
176 
177 	for (i = 0; i < fsm->my_options.count; i++) {
178 		fsm->my_options.data[i].flags = 0;
179 	}
180 
181 	if (fsm->cb.down) {
182 		fsm->cb.down(fsm);
183 	}
184 }
185 
terminate(struct ppp_fsm * fsm,enum ppp_state next_state)186 static void terminate(struct ppp_fsm *fsm, enum ppp_state next_state)
187 {
188 	if (fsm->state != PPP_OPENED) {
189 		k_work_cancel_delayable(&fsm->timer);
190 	} else {
191 		fsm_down(fsm);
192 	}
193 
194 	fsm->retransmits = MAX_TERMINATE_REQ;
195 	fsm->req_id = ++fsm->id;
196 
197 	(void)ppp_send_pkt(fsm, NULL, PPP_TERMINATE_REQ, fsm->req_id,
198 			   fsm->terminate_reason,
199 			   strlen(fsm->terminate_reason));
200 
201 	if (fsm->retransmits == 0) {
202 		ppp_change_state(fsm, next_state);
203 
204 		if (fsm->cb.finished) {
205 			fsm->cb.finished(fsm);
206 		}
207 
208 		return;
209 	}
210 
211 	(void)k_work_reschedule(&fsm->timer, FSM_TIMEOUT);
212 
213 	fsm->retransmits--;
214 
215 	ppp_change_state(fsm, next_state);
216 }
217 
ppp_fsm_close(struct ppp_fsm * fsm,const uint8_t * reason)218 void ppp_fsm_close(struct ppp_fsm *fsm, const uint8_t *reason)
219 {
220 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
221 		ppp_state_str(fsm->state), fsm->state);
222 
223 	switch (fsm->state) {
224 	case PPP_ACK_RECEIVED:
225 	case PPP_ACK_SENT:
226 	case PPP_OPENED:
227 	case PPP_REQUEST_SENT:
228 		if (reason) {
229 			int len = strlen(reason);
230 
231 			len = MIN(sizeof(fsm->terminate_reason) - 1, len);
232 			strncpy(fsm->terminate_reason, reason, len);
233 		}
234 
235 		terminate(fsm, PPP_CLOSING);
236 		break;
237 
238 	case PPP_INITIAL:
239 	case PPP_STARTING:
240 		ppp_change_state(fsm, PPP_INITIAL);
241 		break;
242 
243 	case PPP_STOPPED:
244 		ppp_change_state(fsm, PPP_CLOSED);
245 		break;
246 
247 	case PPP_STOPPING:
248 		ppp_change_state(fsm, PPP_CLOSING);
249 		break;
250 
251 	default:
252 		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
253 			ppp_state_str(fsm->state), fsm->state);
254 		break;
255 	}
256 }
257 
ppp_fsm_lower_down(struct ppp_fsm * fsm)258 void ppp_fsm_lower_down(struct ppp_fsm *fsm)
259 {
260 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
261 		ppp_state_str(fsm->state), fsm->state);
262 
263 	switch (fsm->state) {
264 	case PPP_ACK_RECEIVED:
265 	case PPP_ACK_SENT:
266 	case PPP_REQUEST_SENT:
267 	case PPP_STOPPING:
268 		ppp_change_state(fsm, PPP_STARTING);
269 		k_work_cancel_delayable(&fsm->timer);
270 		break;
271 
272 	case PPP_CLOSED:
273 		ppp_change_state(fsm, PPP_INITIAL);
274 		break;
275 
276 	case PPP_CLOSING:
277 		ppp_change_state(fsm, PPP_INITIAL);
278 		k_work_cancel_delayable(&fsm->timer);
279 		break;
280 
281 	case PPP_OPENED:
282 		ppp_change_state(fsm, PPP_STARTING);
283 		fsm_down(fsm);
284 
285 		break;
286 
287 	case PPP_STOPPED:
288 		ppp_change_state(fsm, PPP_STARTING);
289 		if (fsm->cb.starting) {
290 			fsm->cb.starting(fsm);
291 		}
292 
293 		break;
294 
295 	default:
296 		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
297 			ppp_state_str(fsm->state), fsm->state);
298 		break;
299 	}
300 }
301 
ppp_fsm_lower_up(struct ppp_fsm * fsm)302 void ppp_fsm_lower_up(struct ppp_fsm *fsm)
303 {
304 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
305 		ppp_state_str(fsm->state), fsm->state);
306 
307 	switch (fsm->state) {
308 	case PPP_CLOSED:
309 		break;
310 
311 	case PPP_INITIAL:
312 		ppp_change_state(fsm, PPP_CLOSED);
313 		break;
314 
315 	case PPP_STARTING:
316 		fsm_send_configure_req(fsm, false);
317 		ppp_change_state(fsm, PPP_REQUEST_SENT);
318 
319 		break;
320 
321 	default:
322 		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
323 			ppp_state_str(fsm->state), fsm->state);
324 		break;
325 	}
326 }
327 
ppp_fsm_open(struct ppp_fsm * fsm)328 void ppp_fsm_open(struct ppp_fsm *fsm)
329 {
330 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
331 		ppp_state_str(fsm->state), fsm->state);
332 
333 	switch (fsm->state) {
334 	case PPP_CLOSED:
335 		ppp_change_state(fsm, PPP_REQUEST_SENT);
336 		fsm_send_configure_req(fsm, false);
337 		break;
338 
339 	case PPP_CLOSING:
340 		ppp_change_state(fsm, PPP_STOPPING);
341 		if (fsm->flags & FSM_RESTART) {
342 			ppp_fsm_lower_down(fsm);
343 			ppp_fsm_lower_up(fsm);
344 		}
345 
346 		break;
347 
348 	case PPP_INITIAL:
349 		ppp_change_state(fsm, PPP_STARTING);
350 		if (fsm->cb.starting) {
351 			fsm->cb.starting(fsm);
352 		}
353 
354 		break;
355 
356 	case PPP_OPENED:
357 	case PPP_STOPPED:
358 		if (fsm->flags & FSM_RESTART) {
359 			ppp_fsm_lower_down(fsm);
360 			ppp_fsm_lower_up(fsm);
361 		}
362 
363 		break;
364 
365 	default:
366 		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
367 			ppp_state_str(fsm->state), fsm->state);
368 		break;
369 	}
370 }
371 
ppp_send_pkt(struct ppp_fsm * fsm,struct net_if * iface,enum ppp_packet_type type,uint8_t id,void * data,uint32_t data_len)372 int ppp_send_pkt(struct ppp_fsm *fsm, struct net_if *iface,
373 		 enum ppp_packet_type type, uint8_t id,
374 		 void *data, uint32_t data_len)
375 {
376 	/* Note that the data parameter is the received PPP packet if
377 	 * we want to send PROTOCOL or CODE reject packet.
378 	 */
379 	struct net_pkt *req_pkt = data;
380 	uint16_t protocol = 0;
381 	size_t len = 0;
382 	struct ppp_packet ppp;
383 	struct net_pkt *pkt = NULL;
384 	int ret;
385 
386 	if (!iface) {
387 		if (!fsm) {
388 			return -ENOENT;
389 		}
390 
391 		iface = ppp_fsm_iface(fsm);
392 	}
393 
394 	if (!net_if_is_carrier_ok(iface)) {
395 		return -ENETDOWN;
396 	}
397 
398 	if (fsm) {
399 		protocol = fsm->protocol;
400 	}
401 
402 	switch (type) {
403 	case PPP_CODE_REJ: {
404 		struct ppp_context *ctx = ppp_fsm_ctx(fsm);
405 
406 		len = net_pkt_get_len(req_pkt);
407 		len = MIN(len, ctx->lcp.my_options.mru);
408 		break;
409 	}
410 
411 	case PPP_CONFIGURE_ACK:
412 	case PPP_CONFIGURE_NACK:
413 	case PPP_CONFIGURE_REJ:
414 	case PPP_CONFIGURE_REQ:
415 		pkt = data;
416 		/* 2 + 1 + 1 (configure-[req|ack|nack|rej]) +
417 		 * data_len (options)
418 		 */
419 		len = sizeof(ppp) + data_len;
420 		break;
421 
422 	case PPP_DISCARD_REQ:
423 		break;
424 
425 	case PPP_ECHO_REQ:
426 		len = sizeof(ppp) + sizeof(uint32_t) + data_len;
427 		break;
428 
429 	case PPP_ECHO_REPLY:
430 		len = sizeof(ppp) + net_pkt_remaining_data(req_pkt);
431 		break;
432 
433 	case PPP_PROTOCOL_REJ:
434 		len = sizeof(ppp) + sizeof(uint16_t) +
435 			net_pkt_remaining_data(req_pkt);
436 		protocol = PPP_LCP;
437 		break;
438 
439 	case PPP_TERMINATE_REQ:
440 	case PPP_TERMINATE_ACK:
441 		len = sizeof(ppp);
442 		break;
443 
444 	default:
445 		break;
446 	}
447 
448 	if (len < sizeof(ppp)) {
449 		return -EINVAL;
450 	}
451 
452 	ppp.code = type;
453 	ppp.id = id;
454 	ppp.length = htons(len);
455 
456 	if (!pkt) {
457 		pkt = net_pkt_alloc_with_buffer(iface,
458 						sizeof(uint16_t) + len,
459 						AF_UNSPEC, 0,
460 						PPP_BUF_ALLOC_TIMEOUT);
461 		if (!pkt) {
462 			goto out_of_mem;
463 		}
464 	} else {
465 		struct net_buf *buf;
466 
467 		buf = net_pkt_get_reserve_tx_data(sizeof(uint16_t) + len,
468 						  PPP_BUF_ALLOC_TIMEOUT);
469 		if (!buf) {
470 			LOG_ERR("failed to allocate buffer");
471 			goto out_of_mem;
472 		}
473 
474 		net_pkt_frag_insert(pkt, buf);
475 		net_pkt_cursor_init(pkt);
476 	}
477 
478 	ret = net_pkt_write_be16(pkt, protocol);
479 	if (ret < 0) {
480 		goto out_of_mem;
481 	}
482 
483 	ret = net_pkt_write(pkt, &ppp, sizeof(ppp));
484 	if (ret < 0) {
485 		goto out_of_mem;
486 	}
487 
488 	if (type == PPP_CODE_REJ) {
489 		if (!req_pkt) {
490 			goto out_of_mem;
491 		}
492 
493 		net_pkt_cursor_init(req_pkt);
494 		net_pkt_copy(pkt, req_pkt, len);
495 
496 	} else if (type == PPP_ECHO_REQ) {
497 		struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
498 						       lcp.fsm);
499 		if (ctx->lcp.magic) {
500 			ctx->lcp.magic = sys_rand32_get();
501 		}
502 
503 		ret = net_pkt_write_be32(pkt, ctx->lcp.magic);
504 		if (ret < 0) {
505 			goto out_of_mem;
506 		}
507 
508 		data_len = MIN(data_len, ctx->lcp.my_options.mru);
509 		if (data_len > 0) {
510 			if (data_len == sizeof(uint32_t)) {
511 				ret = net_pkt_write_be32(pkt,
512 						       POINTER_TO_UINT(data));
513 			} else {
514 				ret = net_pkt_write(pkt, data, data_len);
515 			}
516 
517 			if (ret < 0) {
518 				goto out_of_mem;
519 			}
520 		}
521 	} else if (type == PPP_ECHO_REPLY) {
522 		net_pkt_copy(pkt, req_pkt, len);
523 	} else if (type == PPP_PROTOCOL_REJ) {
524 		net_pkt_cursor_init(req_pkt);
525 		net_pkt_copy(pkt, req_pkt, len);
526 	}
527 
528 	NET_DBG("[%s/%p] Sending %zd bytes pkt %p (options len %d)",
529 		fsm ? fsm->name : "?", fsm, net_pkt_get_len(pkt), pkt,
530 		data_len);
531 
532 	net_pkt_set_ppp(pkt, true);
533 
534 	if (fsm) {
535 		/* Do not call net_send_data() directly in order to make this
536 		 * thread run before the sending happens. If we call the
537 		 * net_send_data() from this thread, then in fast link (like
538 		 * when running inside QEMU) the reply might arrive before we
539 		 * have returned from this function. That is bad because the
540 		 * fsm would be in wrong state and the received pkt is dropped.
541 		 */
542 		ppp_queue_pkt(pkt);
543 	} else {
544 		ret = net_send_data(pkt);
545 		if (ret < 0) {
546 			net_pkt_unref(pkt);
547 		}
548 	}
549 
550 	return 0;
551 
552 out_of_mem:
553 	if (pkt) {
554 		net_pkt_unref(pkt);
555 	}
556 
557 	return -ENOMEM;
558 }
559 
fsm_recv_configure_req(struct ppp_fsm * fsm,uint8_t id,struct net_pkt * pkt,uint16_t remaining_len)560 static enum net_verdict fsm_recv_configure_req(struct ppp_fsm *fsm,
561 					       uint8_t id,
562 					       struct net_pkt *pkt,
563 					       uint16_t remaining_len)
564 {
565 	struct net_pkt *out = NULL;
566 	int len = 0;
567 	enum ppp_packet_type code;
568 
569 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
570 		ppp_state_str(fsm->state), fsm->state);
571 
572 	switch (fsm->state) {
573 	case PPP_ACK_SENT:
574 	case PPP_ACK_RECEIVED:
575 		break;
576 
577 	case PPP_CLOSED:
578 		(void)ppp_send_pkt(fsm, net_pkt_iface(pkt), PPP_TERMINATE_ACK,
579 				   id, NULL, 0);
580 		return NET_OK;
581 
582 	case PPP_CLOSING:
583 	case PPP_STOPPING:
584 		return NET_OK;
585 
586 	case PPP_OPENED:
587 		fsm_down(fsm);
588 
589 		fsm_send_configure_req(fsm, false);
590 		ppp_change_state(fsm, PPP_REQUEST_SENT);
591 		break;
592 
593 	case PPP_REQUEST_SENT:
594 		/* Received request while waiting ACK */
595 		break;
596 
597 	case PPP_STOPPED:
598 		fsm_send_configure_req(fsm, false);
599 		ppp_change_state(fsm, PPP_REQUEST_SENT);
600 		break;
601 
602 	default:
603 		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
604 			ppp_state_str(fsm->state), fsm->state);
605 		return NET_DROP;
606 	}
607 
608 	out = net_pkt_alloc_with_buffer(net_pkt_iface(pkt),
609 					sizeof(uint16_t) + sizeof(uint16_t) +
610 						sizeof(uint8_t) + sizeof(uint8_t) +
611 						remaining_len,
612 					AF_UNSPEC, 0, PPP_BUF_ALLOC_TIMEOUT);
613 	if (!out) {
614 		return NET_DROP;
615 	}
616 
617 	net_pkt_cursor_init(out);
618 
619 	if (fsm->cb.config_info_req) {
620 		int ret;
621 
622 		ret = fsm->cb.config_info_req(fsm, pkt, remaining_len, out);
623 		if (ret < 0) {
624 			goto unref_out_pkt;
625 		}
626 
627 		if (fsm->nack_loops >= MAX_NACK_LOOPS &&
628 		    ret == PPP_CONFIGURE_NACK) {
629 			ret = PPP_CONFIGURE_REJ;
630 		}
631 
632 		code = ret;
633 		len = net_pkt_get_len(out);
634 	} else if (remaining_len) {
635 		code = PPP_CONFIGURE_REJ;
636 
637 		net_pkt_copy(out, pkt, remaining_len);
638 		len = remaining_len;
639 	} else {
640 		code = PPP_CONFIGURE_ACK;
641 	}
642 
643 	NET_DBG("[%s/%p] Sending %s (%d) id %d to peer while in %s (%d)",
644 		fsm->name, fsm, ppp_pkt_type2str(code), code, id,
645 		ppp_state_str(fsm->state), fsm->state);
646 
647 	(void)ppp_send_pkt(fsm, NULL, code, id, out, len);
648 
649 	if (code == PPP_CONFIGURE_ACK) {
650 		if (fsm->state == PPP_ACK_RECEIVED) {
651 			k_work_cancel_delayable(&fsm->timer);
652 
653 			ppp_change_state(fsm, PPP_OPENED);
654 
655 			if (fsm->cb.up) {
656 				fsm->cb.up(fsm);
657 			}
658 		} else {
659 			ppp_change_state(fsm, PPP_ACK_SENT);
660 		}
661 
662 		fsm->nack_loops = 0;
663 	} else {
664 		if (fsm->state != PPP_ACK_RECEIVED) {
665 			ppp_change_state(fsm, PPP_REQUEST_SENT);
666 		}
667 
668 		if (code == PPP_CONFIGURE_NACK) {
669 			fsm->nack_loops++;
670 		}
671 	}
672 
673 	return NET_OK;
674 
675 unref_out_pkt:
676 	net_pkt_unref(out);
677 
678 	return NET_DROP;
679 }
680 
fsm_recv_configure_ack(struct ppp_fsm * fsm,uint8_t id,struct net_pkt * pkt,uint16_t remaining_len)681 static enum net_verdict fsm_recv_configure_ack(struct ppp_fsm *fsm, uint8_t id,
682 					       struct net_pkt *pkt,
683 					       uint16_t remaining_len)
684 {
685 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
686 		ppp_state_str(fsm->state), fsm->state);
687 
688 	if (id != fsm->req_id || fsm->ack_received) {
689 		return NET_DROP;
690 	}
691 
692 	if (fsm->cb.config_info_ack) {
693 		if (fsm->cb.config_info_ack(fsm, pkt, remaining_len) < 0) {
694 			NET_DBG("[%s/%p] %s %s received", fsm->name, fsm,
695 				"Invalid",
696 				ppp_pkt_type2str(PPP_CONFIGURE_ACK));
697 			return NET_DROP;
698 		}
699 	}
700 
701 	fsm->ack_received = true;
702 	fsm->recv_nack_loops = 0;
703 
704 	switch (fsm->state) {
705 	case PPP_ACK_RECEIVED:
706 		k_work_cancel_delayable(&fsm->timer);
707 		fsm_send_configure_req(fsm, false);
708 		ppp_change_state(fsm, PPP_REQUEST_SENT);
709 		break;
710 
711 	case PPP_ACK_SENT:
712 		k_work_cancel_delayable(&fsm->timer);
713 		ppp_change_state(fsm, PPP_OPENED);
714 		fsm->retransmits = MAX_CONFIGURE_REQ;
715 		if (fsm->cb.up) {
716 			fsm->cb.up(fsm);
717 		}
718 
719 		break;
720 
721 	case PPP_CLOSED:
722 	case PPP_STOPPED:
723 		(void)ppp_send_pkt(fsm, net_pkt_iface(pkt), PPP_TERMINATE_ACK,
724 				   id, NULL, 0);
725 		break;
726 
727 	case PPP_OPENED:
728 		fsm_down(fsm);
729 
730 		fsm_send_configure_req(fsm, false);
731 		ppp_change_state(fsm, PPP_REQUEST_SENT);
732 		break;
733 
734 	case PPP_REQUEST_SENT:
735 		ppp_change_state(fsm, PPP_ACK_RECEIVED);
736 		fsm->retransmits = MAX_CONFIGURE_REQ;
737 		break;
738 
739 	default:
740 		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
741 			ppp_state_str(fsm->state), fsm->state);
742 		return NET_DROP;
743 	}
744 
745 	return NET_OK;
746 }
747 
fsm_recv_configure_nack_rej(struct ppp_fsm * fsm,enum ppp_packet_type code,uint8_t id,struct net_pkt * pkt,uint16_t length)748 static enum net_verdict fsm_recv_configure_nack_rej(struct ppp_fsm *fsm,
749 						    enum ppp_packet_type code,
750 						    uint8_t id,
751 						    struct net_pkt *pkt,
752 						    uint16_t length)
753 {
754 	bool ret = false;
755 
756 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
757 		ppp_state_str(fsm->state), fsm->state);
758 
759 	if (id != fsm->req_id || fsm->ack_received) {
760 		return NET_DROP;
761 	}
762 
763 	if (code == PPP_CONFIGURE_NACK) {
764 		bool rejected = false;
765 
766 		fsm->recv_nack_loops++;
767 
768 		if (fsm->recv_nack_loops >= MAX_NACK_LOOPS) {
769 			rejected = true;
770 		}
771 
772 		if (fsm->cb.config_info_nack) {
773 			int err;
774 
775 			err = fsm->cb.config_info_nack(fsm, pkt, length,
776 						       rejected);
777 			if (err < 0) {
778 				NET_DBG("[%s/%p] %s failed (%d)",
779 					fsm->name, fsm, "Nack", err);
780 			} else {
781 				ret = true;
782 			}
783 		}
784 
785 		if (!ret) {
786 			NET_DBG("[%s/%p] %s %s (id %d)", fsm->name, fsm,
787 				"Invalid", ppp_pkt_type2str(code), id);
788 			return NET_DROP;
789 		}
790 	} else {
791 		fsm->recv_nack_loops = 0;
792 
793 		if (fsm->cb.config_info_rej) {
794 			int err;
795 
796 			err = fsm->cb.config_info_rej(fsm, pkt, length);
797 			if (err < 0) {
798 				NET_DBG("[%s/%p] %s failed (%d)",
799 					fsm->name, fsm, "Reject", err);
800 			} else {
801 				ret = true;
802 			}
803 		}
804 
805 		if (!ret) {
806 			NET_DBG("[%s/%p] %s %s (id %d)", fsm->name, fsm,
807 				"Invalid", ppp_pkt_type2str(code), id);
808 			return NET_DROP;
809 		}
810 	}
811 
812 	fsm->ack_received = true;
813 
814 	switch (fsm->state) {
815 	case PPP_ACK_RECEIVED:
816 		k_work_cancel_delayable(&fsm->timer);
817 		fsm_send_configure_req(fsm, false);
818 		ppp_change_state(fsm, PPP_REQUEST_SENT);
819 		break;
820 
821 	case PPP_ACK_SENT:
822 	case PPP_REQUEST_SENT:
823 		k_work_cancel_delayable(&fsm->timer);
824 		fsm_send_configure_req(fsm, false);
825 		break;
826 
827 	case PPP_CLOSED:
828 	case PPP_STOPPED:
829 		(void)ppp_send_pkt(fsm, net_pkt_iface(pkt), PPP_TERMINATE_ACK,
830 				   id, NULL, 0);
831 		break;
832 
833 	case PPP_OPENED:
834 		fsm_down(fsm);
835 
836 		fsm_send_configure_req(fsm, false);
837 		ppp_change_state(fsm, PPP_REQUEST_SENT);
838 		break;
839 
840 	default:
841 		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
842 			ppp_state_str(fsm->state), fsm->state);
843 		return NET_DROP;
844 	}
845 
846 	return NET_OK;
847 }
848 
fsm_recv_terminate_req(struct ppp_fsm * fsm,uint8_t id,struct net_pkt * pkt,uint16_t length)849 static enum net_verdict fsm_recv_terminate_req(struct ppp_fsm *fsm, uint8_t id,
850 					       struct net_pkt *pkt,
851 					       uint16_t length)
852 {
853 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
854 		ppp_state_str(fsm->state), fsm->state);
855 
856 	switch (fsm->state) {
857 	case PPP_ACK_RECEIVED:
858 	case PPP_ACK_SENT:
859 		ppp_change_state(fsm, PPP_REQUEST_SENT);
860 		break;
861 
862 	case PPP_OPENED:
863 		if (length > 0) {
864 			net_pkt_read(pkt, fsm->terminate_reason,
865 				     MIN(length,
866 					 sizeof(fsm->terminate_reason) - 1));
867 
868 			NET_DBG("[%s/%p] %s (%s)",
869 				fsm->name, fsm, "Terminated by peer",
870 				fsm->terminate_reason);
871 		} else {
872 			NET_DBG("[%s/%p] Terminated by peer",
873 				fsm->name, fsm);
874 		}
875 
876 		fsm->retransmits = 0;
877 		ppp_change_state(fsm, PPP_STOPPING);
878 
879 		fsm_down(fsm);
880 
881 		(void)k_work_reschedule(&fsm->timer, FSM_TIMEOUT);
882 		break;
883 
884 	default:
885 		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
886 			ppp_state_str(fsm->state), fsm->state);
887 		return NET_DROP;
888 	}
889 
890 	(void)ppp_send_pkt(fsm, net_pkt_iface(pkt), PPP_TERMINATE_ACK, id,
891 			   NULL, 0);
892 
893 	return NET_OK;
894 }
895 
fsm_recv_terminate_ack(struct ppp_fsm * fsm,uint8_t id,struct net_pkt * pkt,uint16_t length)896 static enum net_verdict fsm_recv_terminate_ack(struct ppp_fsm *fsm, uint8_t id,
897 					       struct net_pkt *pkt,
898 					       uint16_t length)
899 {
900 	enum ppp_state new_state;
901 
902 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
903 		ppp_state_str(fsm->state), fsm->state);
904 
905 	switch (fsm->state) {
906 	case PPP_CLOSING:
907 		new_state = PPP_CLOSED;
908 		goto stopped;
909 
910 	case PPP_OPENED:
911 		fsm_down(fsm);
912 
913 		fsm_send_configure_req(fsm, false);
914 		ppp_change_state(fsm, PPP_REQUEST_SENT);
915 		break;
916 
917 	case PPP_STOPPING:
918 		new_state = PPP_STOPPED;
919 		goto stopped;
920 
921 	case PPP_ACK_RECEIVED:
922 		ppp_change_state(fsm, PPP_REQUEST_SENT);
923 		break;
924 
925 	default:
926 		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
927 			ppp_state_str(fsm->state), fsm->state);
928 		return NET_DROP;
929 	}
930 
931 	return NET_OK;
932 
933 stopped:
934 	k_work_cancel_delayable(&fsm->timer);
935 	ppp_change_state(fsm, new_state);
936 
937 	if (fsm->cb.finished) {
938 		fsm->cb.finished(fsm);
939 	}
940 
941 	return NET_OK;
942 }
943 
fsm_recv_code_rej(struct ppp_fsm * fsm,struct net_pkt * pkt)944 static enum net_verdict fsm_recv_code_rej(struct ppp_fsm *fsm,
945 					  struct net_pkt *pkt)
946 {
947 	uint8_t code, id;
948 	int ret;
949 
950 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
951 		ppp_state_str(fsm->state), fsm->state);
952 
953 	ret = net_pkt_read_u8(pkt, &code);
954 	if (ret < 0) {
955 		return NET_DROP;
956 	}
957 
958 	ret = net_pkt_read_u8(pkt, &id);
959 	if (ret < 0) {
960 		return NET_DROP;
961 	}
962 
963 	NET_DBG("[%s/%p] Received Code-Rej code %d id %d", fsm->name, fsm,
964 		code, id);
965 
966 	if (fsm->state == PPP_ACK_RECEIVED) {
967 		ppp_change_state(fsm, PPP_REQUEST_SENT);
968 	}
969 
970 	return NET_OK;
971 }
972 
ppp_fsm_proto_reject(struct ppp_fsm * fsm)973 void ppp_fsm_proto_reject(struct ppp_fsm *fsm)
974 {
975 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
976 		ppp_state_str(fsm->state), fsm->state);
977 
978 	switch (fsm->state) {
979 	case PPP_ACK_RECEIVED:
980 	case PPP_ACK_SENT:
981 	case PPP_STOPPING:
982 	case PPP_REQUEST_SENT:
983 		k_work_cancel_delayable(&fsm->timer);
984 		ppp_change_state(fsm, PPP_STOPPED);
985 		if (fsm->cb.finished) {
986 			fsm->cb.finished(fsm);
987 		}
988 
989 		break;
990 
991 	case PPP_CLOSED:
992 		ppp_change_state(fsm, PPP_CLOSED);
993 		if (fsm->cb.finished) {
994 			fsm->cb.finished(fsm);
995 		}
996 
997 		break;
998 
999 	case PPP_CLOSING:
1000 		k_work_cancel_delayable(&fsm->timer);
1001 		ppp_change_state(fsm, PPP_CLOSED);
1002 		if (fsm->cb.finished) {
1003 			fsm->cb.finished(fsm);
1004 		}
1005 
1006 		break;
1007 
1008 	case PPP_OPENED:
1009 		terminate(fsm, PPP_STOPPING);
1010 		break;
1011 
1012 	case PPP_STOPPED:
1013 		ppp_change_state(fsm, PPP_STOPPED);
1014 		if (fsm->cb.finished) {
1015 			fsm->cb.finished(fsm);
1016 		}
1017 
1018 		break;
1019 
1020 	default:
1021 		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
1022 			ppp_state_str(fsm->state), fsm->state);
1023 		break;
1024 	}
1025 }
1026 
ppp_fsm_input(struct ppp_fsm * fsm,uint16_t proto,struct net_pkt * pkt)1027 enum net_verdict ppp_fsm_input(struct ppp_fsm *fsm, uint16_t proto,
1028 			       struct net_pkt *pkt)
1029 {
1030 	uint8_t code, id;
1031 	uint16_t length;
1032 	int ret;
1033 	struct ppp_context *ctx = ppp_fsm_ctx(fsm);
1034 
1035 	ret = net_pkt_read_u8(pkt, &code);
1036 	if (ret < 0) {
1037 		NET_DBG("[%s/%p] Cannot read %s (pkt len %zd)",
1038 			fsm->name, fsm, "code", net_pkt_get_len(pkt));
1039 		return NET_DROP;
1040 	}
1041 
1042 	ret = net_pkt_read_u8(pkt, &id);
1043 	if (ret < 0) {
1044 		NET_DBG("[%s/%p] Cannot read %s (pkt len %zd)",
1045 			fsm->name, fsm, "id", net_pkt_get_len(pkt));
1046 		return NET_DROP;
1047 	}
1048 
1049 	ret = net_pkt_read_be16(pkt, &length);
1050 	if (ret < 0) {
1051 		NET_DBG("[%s/%p] Cannot read %s (pkt len %zd)",
1052 			fsm->name, fsm, "length", net_pkt_get_len(pkt));
1053 		return NET_DROP;
1054 	}
1055 
1056 	if (length > ctx->lcp.my_options.mru) {
1057 		NET_DBG("[%s/%p] Too long msg %d", fsm->name, fsm, length);
1058 		return NET_DROP;
1059 	}
1060 
1061 	if (fsm->state == PPP_INITIAL || fsm->state == PPP_STARTING) {
1062 		NET_DBG("[%s/%p] Received %s packet in wrong state %s (%d)",
1063 			fsm->name, fsm, ppp_proto2str(proto),
1064 			ppp_state_str(fsm->state), fsm->state);
1065 		return NET_DROP;
1066 	}
1067 
1068 	/* Length will only contain payload/data length */
1069 	length -= sizeof(code) + sizeof(id) + sizeof(length);
1070 
1071 	NET_DBG("[%s/%p] %s %s (%d) id %d payload len %d", fsm->name, fsm,
1072 		ppp_proto2str(proto), ppp_pkt_type2str(code), code, id,
1073 		length);
1074 
1075 	switch (code) {
1076 	case PPP_CODE_REJ:
1077 		return fsm_recv_code_rej(fsm, pkt);
1078 
1079 	case PPP_CONFIGURE_ACK:
1080 		return fsm_recv_configure_ack(fsm, id, pkt, length);
1081 
1082 	case PPP_CONFIGURE_NACK:
1083 		return fsm_recv_configure_nack_rej(fsm, code, id, pkt, length);
1084 
1085 	case PPP_CONFIGURE_REQ:
1086 		return fsm_recv_configure_req(fsm, id, pkt, length);
1087 
1088 	case PPP_CONFIGURE_REJ:
1089 		return fsm_recv_configure_nack_rej(fsm, code, id, pkt, length);
1090 
1091 	case PPP_TERMINATE_ACK:
1092 		return fsm_recv_terminate_ack(fsm, id, pkt, length);
1093 
1094 	case PPP_TERMINATE_REQ:
1095 		return fsm_recv_terminate_req(fsm, id, pkt, length);
1096 
1097 	default:
1098 		if (fsm->cb.proto_extension) {
1099 			enum net_verdict verdict;
1100 
1101 			verdict = fsm->cb.proto_extension(fsm, code, id, pkt);
1102 			if (verdict != NET_DROP) {
1103 				return verdict;
1104 			}
1105 		}
1106 
1107 		(void)ppp_send_pkt(fsm, net_pkt_iface(pkt), PPP_CODE_REJ,
1108 				   id, pkt, 0);
1109 	}
1110 
1111 	return NET_DROP;
1112 }
1113 
ppp_fsm_recv_protocol_rej(struct ppp_fsm * fsm,uint8_t id,struct net_pkt * pkt)1114 enum net_verdict ppp_fsm_recv_protocol_rej(struct ppp_fsm *fsm,
1115 					   uint8_t id,
1116 					   struct net_pkt *pkt)
1117 {
1118 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
1119 		ppp_state_str(fsm->state), fsm->state);
1120 
1121 	return NET_DROP;
1122 }
1123 
ppp_fsm_recv_echo_req(struct ppp_fsm * fsm,uint8_t id,struct net_pkt * pkt)1124 enum net_verdict ppp_fsm_recv_echo_req(struct ppp_fsm *fsm,
1125 				       uint8_t id,
1126 				       struct net_pkt *pkt)
1127 {
1128 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
1129 		ppp_state_str(fsm->state), fsm->state);
1130 
1131 	(void)ppp_send_pkt(fsm, net_pkt_iface(pkt), PPP_ECHO_REPLY,
1132 		id, pkt, 0);
1133 
1134 	return NET_OK;
1135 }
1136 
ppp_fsm_recv_echo_reply(struct ppp_fsm * fsm,uint8_t id,struct net_pkt * pkt)1137 enum net_verdict ppp_fsm_recv_echo_reply(struct ppp_fsm *fsm,
1138 					 uint8_t id,
1139 					 struct net_pkt *pkt)
1140 {
1141 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
1142 		ppp_state_str(fsm->state), fsm->state);
1143 
1144 #if defined(CONFIG_NET_SHELL)
1145 	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
1146 					       lcp.fsm);
1147 	if (ctx->shell.echo_reply.cb) {
1148 		ctx->shell.echo_reply.cb(ctx->shell.echo_reply.user_data,
1149 					 ctx->shell.echo_reply.user_data_len);
1150 	}
1151 #endif /* CONFIG_NET_SHELL */
1152 
1153 	return NET_OK;
1154 }
1155 
ppp_fsm_recv_discard_req(struct ppp_fsm * fsm,uint8_t id,struct net_pkt * pkt)1156 enum net_verdict ppp_fsm_recv_discard_req(struct ppp_fsm *fsm,
1157 					  uint8_t id,
1158 					  struct net_pkt *pkt)
1159 {
1160 	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
1161 		ppp_state_str(fsm->state), fsm->state);
1162 
1163 	return NET_OK;
1164 }
1165 
ppp_send_proto_rej(struct net_if * iface,struct net_pkt * pkt,uint16_t protocol)1166 void ppp_send_proto_rej(struct net_if *iface, struct net_pkt *pkt,
1167 			uint16_t protocol)
1168 {
1169 	uint8_t code, id;
1170 	int ret;
1171 
1172 	ret = net_pkt_read_u8(pkt, &code);
1173 	if (ret < 0) {
1174 		goto quit;
1175 	}
1176 
1177 	ret = net_pkt_read_u8(pkt, &id);
1178 	if (ret < 0) {
1179 		goto quit;
1180 	}
1181 
1182 	(void)ppp_send_pkt(NULL, iface, PPP_PROTOCOL_REJ, id, pkt, 0);
1183 
1184 quit:
1185 	return;
1186 }
1187