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/sys/iterable_sections.h>
13 #include <zephyr/net/ppp.h>
14 
15 #include "net_private.h"
16 
17 #include "ppp_internal.h"
18 
lcp_up(struct ppp_context * ctx)19 static void lcp_up(struct ppp_context *ctx)
20 {
21 	STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
22 		if (proto->protocol == PPP_LCP) {
23 			continue;
24 		}
25 
26 		if (proto->lower_up) {
27 			proto->lower_up(ctx);
28 		}
29 	}
30 }
31 
do_network(struct ppp_context * ctx)32 static void do_network(struct ppp_context *ctx)
33 {
34 	ppp_change_phase(ctx, PPP_NETWORK);
35 
36 	STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
37 		if (proto->protocol == PPP_CCP || proto->protocol == PPP_ECP) {
38 			if (proto->open) {
39 				proto->open(ctx);
40 			}
41 		}
42 	}
43 
44 	/* Do the other network protocols if encryption is not needed for
45 	 * them.
46 	 */
47 	/* TODO possible encryption stuff here*/
48 
49 	STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
50 		if (proto->protocol == PPP_CCP || proto->protocol == PPP_ECP ||
51 		    proto->protocol >= 0xC000) {
52 			continue;
53 		}
54 
55 		if (proto->open) {
56 			ctx->network_protos_open++;
57 			proto->open(ctx);
58 		}
59 	}
60 
61 	if (ctx->network_protos_open == 0) {
62 		const struct ppp_protocol_handler *proto = ppp_lcp_get();
63 
64 		if (proto) {
65 			proto->close(ctx, "No network protocols open");
66 		}
67 	}
68 }
69 
do_auth(struct ppp_context * ctx)70 static void do_auth(struct ppp_context *ctx)
71 {
72 	uint16_t auth_proto = 0;
73 
74 	ppp_change_phase(ctx, PPP_AUTH);
75 
76 	if (IS_ENABLED(CONFIG_NET_L2_PPP_AUTH_SUPPORT)) {
77 		auth_proto = ctx->lcp.peer_options.auth_proto;
78 	}
79 
80 	/* If no authentication is need, then we are done */
81 	if (!auth_proto) {
82 		ppp_link_authenticated(ctx);
83 		return;
84 	}
85 
86 	STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
87 		if (proto->protocol == auth_proto) {
88 			if (proto->open) {
89 				proto->open(ctx);
90 			}
91 
92 			break;
93 		}
94 	}
95 }
96 
ppp_link_established(struct ppp_context * ctx,struct ppp_fsm * fsm)97 void ppp_link_established(struct ppp_context *ctx, struct ppp_fsm *fsm)
98 {
99 	NET_DBG("[%p] Link established", ctx);
100 
101 	ppp_change_phase(ctx, PPP_ESTABLISH);
102 
103 	do_auth(ctx);
104 
105 	lcp_up(ctx);
106 }
107 
ppp_link_authenticated(struct ppp_context * ctx)108 void ppp_link_authenticated(struct ppp_context *ctx)
109 {
110 	NET_DBG("[%p] Link authenticated", ctx);
111 
112 	do_network(ctx);
113 }
114 
ppp_link_terminated(struct ppp_context * ctx)115 void ppp_link_terminated(struct ppp_context *ctx)
116 {
117 	k_sem_give(&ctx->wait_ppp_link_terminated);
118 
119 	if (ctx->phase == PPP_DEAD) {
120 		return;
121 	}
122 
123 	/* TODO: cleanup things etc here if needed */
124 
125 	ppp_change_phase(ctx, PPP_DEAD);
126 
127 	NET_DBG("[%p] Link terminated", ctx);
128 }
129 
ppp_link_down(struct ppp_context * ctx)130 void ppp_link_down(struct ppp_context *ctx)
131 {
132 	k_sem_give(&ctx->wait_ppp_link_down);
133 
134 	if (ctx->phase == PPP_DEAD) {
135 		return;
136 	}
137 
138 	ppp_network_all_down(ctx);
139 
140 	ppp_change_phase(ctx, PPP_DEAD);
141 }
142 
ppp_link_needed(struct ppp_context * ctx)143 void ppp_link_needed(struct ppp_context *ctx)
144 {
145 	/* TODO: Try to create link if needed. */
146 }
147