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_REGISTER(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL);
9 
10 #include <stdlib.h>
11 #include <zephyr/net/ethernet.h>
12 #include <zephyr/net/net_core.h>
13 #include <zephyr/net/net_l2.h>
14 #include <zephyr/net/net_if.h>
15 #include <zephyr/net/net_pkt.h>
16 #include <zephyr/net/net_mgmt.h>
17 #include <zephyr/net/ppp.h>
18 #include <zephyr/sys/iterable_sections.h>
19 
20 #include "net_private.h"
21 
22 #include "ppp_stats.h"
23 #include "ppp_internal.h"
24 
25 static K_FIFO_DEFINE(tx_queue);
26 
27 #if defined(CONFIG_NET_TC_THREAD_COOPERATIVE)
28 /* Lowest priority cooperative thread */
29 #define THREAD_PRIORITY K_PRIO_COOP(CONFIG_NET_L2_PPP_THREAD_PRIO)
30 #else
31 #define THREAD_PRIORITY K_PRIO_PREEMPT(CONFIG_NET_L2_PPP_THREAD_PRIO)
32 #endif
33 
34 static void tx_handler(void *p1, void *p2, void *p3);
35 
36 static K_THREAD_DEFINE(tx_handler_thread, CONFIG_NET_L2_PPP_TX_STACK_SIZE,
37 		       tx_handler, NULL, NULL, NULL,
38 		       THREAD_PRIORITY, 0, 0);
39 
40 static const struct ppp_protocol_handler *ppp_lcp;
41 
ppp_update_rx_stats(struct net_if * iface,struct net_pkt * pkt,size_t length)42 static void ppp_update_rx_stats(struct net_if *iface,
43 				struct net_pkt *pkt, size_t length)
44 {
45 #if defined(CONFIG_NET_STATISTICS_PPP)
46 	ppp_stats_update_bytes_rx(iface, length);
47 	ppp_stats_update_pkts_rx(iface);
48 #endif /* CONFIG_NET_STATISTICS_PPP */
49 }
50 
ppp_update_tx_stats(struct net_if * iface,struct net_pkt * pkt,size_t length)51 static void ppp_update_tx_stats(struct net_if *iface,
52 				struct net_pkt *pkt, size_t length)
53 {
54 #if defined(CONFIG_NET_STATISTICS_PPP)
55 	ppp_stats_update_bytes_tx(iface, length);
56 	ppp_stats_update_pkts_tx(iface);
57 #endif /* CONFIG_NET_STATISTICS_PPP */
58 }
59 
60 #if defined(CONFIG_NET_TEST)
61 typedef enum net_verdict (*ppp_l2_callback_t)(struct net_if *iface,
62 					      struct net_pkt *pkt);
63 
64 static ppp_l2_callback_t testing_cb;
65 
ppp_l2_register_pkt_cb(ppp_l2_callback_t cb)66 void ppp_l2_register_pkt_cb(ppp_l2_callback_t cb)
67 {
68 	testing_cb = cb;
69 }
70 #endif
71 
process_ppp_msg(struct net_if * iface,struct net_pkt * pkt)72 static enum net_verdict process_ppp_msg(struct net_if *iface,
73 					struct net_pkt *pkt)
74 {
75 	struct ppp_context *ctx = net_if_l2_data(iface);
76 	enum net_verdict verdict = NET_DROP;
77 	uint16_t protocol;
78 	int ret;
79 
80 	if (!ctx->is_ready_to_serve) {
81 		goto quit;
82 	}
83 
84 	ret = net_pkt_read_be16(pkt, &protocol);
85 	if (ret < 0) {
86 		goto quit;
87 	}
88 
89 	if ((IS_ENABLED(CONFIG_NET_IPV4) && protocol == PPP_IP) ||
90 	    (IS_ENABLED(CONFIG_NET_IPV6) && protocol == PPP_IPV6)) {
91 		/* Remove the protocol field so that IP packet processing
92 		 * continues properly in net_core.c:process_data()
93 		 */
94 		(void)net_buf_pull_be16(pkt->buffer);
95 		net_pkt_cursor_init(pkt);
96 		return NET_CONTINUE;
97 	}
98 
99 	STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
100 		if (proto->protocol != protocol) {
101 			continue;
102 		}
103 
104 		return proto->handler(ctx, iface, pkt);
105 	}
106 
107 	switch (protocol) {
108 	case PPP_IP:
109 	case PPP_IPV6:
110 	case PPP_ECP:
111 	case PPP_CCP:
112 	case PPP_LCP:
113 	case PPP_IPCP:
114 	case PPP_IPV6CP:
115 		ppp_send_proto_rej(iface, pkt, protocol);
116 		break;
117 	default:
118 		break;
119 	}
120 
121 	NET_DBG("%s protocol %s%s(0x%02x)",
122 		ppp_proto2str(protocol) ? "Unhandled" : "Unknown",
123 		ppp_proto2str(protocol),
124 		ppp_proto2str(protocol) ? " " : "",
125 		protocol);
126 
127 quit:
128 	return verdict;
129 }
130 
ppp_recv(struct net_if * iface,struct net_pkt * pkt)131 static enum net_verdict ppp_recv(struct net_if *iface,
132 				 struct net_pkt *pkt)
133 {
134 	enum net_verdict verdict;
135 
136 #if defined(CONFIG_NET_TEST)
137 	/* If we are running a PPP unit test, then feed the packet
138 	 * back to test app for verification.
139 	 */
140 	if (testing_cb) {
141 		return testing_cb(iface, pkt);
142 	}
143 #endif
144 
145 	ppp_update_rx_stats(iface, pkt, net_pkt_get_len(pkt));
146 
147 	if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) {
148 		net_pkt_hexdump(pkt, "recv L2");
149 	}
150 
151 	verdict = process_ppp_msg(iface, pkt);
152 
153 	switch (verdict) {
154 	case NET_OK:
155 		net_pkt_unref(pkt);
156 		break;
157 	case NET_DROP:
158 		ppp_stats_update_drop_rx(iface);
159 		break;
160 	case NET_CONTINUE:
161 		break;
162 	}
163 
164 	return verdict;
165 }
166 
ppp_send(struct net_if * iface,struct net_pkt * pkt)167 static int ppp_send(struct net_if *iface, struct net_pkt *pkt)
168 {
169 	const struct ppp_api *api = net_if_get_device(iface)->api;
170 	struct ppp_context *ctx = net_if_l2_data(iface);
171 	int ret;
172 
173 	if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) {
174 		net_pkt_hexdump(pkt, "send L2");
175 	}
176 
177 	/* If PPP is not yet ready, then just give error to caller as there
178 	 * is no way to send before the PPP handshake is finished.
179 	 */
180 	if (ctx->phase != PPP_RUNNING && !net_pkt_is_ppp(pkt)) {
181 		return -ENETDOWN;
182 	}
183 
184 	/* PPP drivers only support IP packet types, therefore in order to be
185 	 * able to use AF_PACKET family sockets with PPP, we need to translate
186 	 * L2 proto type to packet family.
187 	 */
188 	if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
189 	    net_pkt_family(pkt) == AF_PACKET) {
190 		switch (net_pkt_ll_proto_type(pkt)) {
191 		case ETH_P_IP:
192 			net_pkt_set_family(pkt, AF_INET);
193 			break;
194 		case ETH_P_IPV6:
195 			net_pkt_set_family(pkt, AF_INET6);
196 			break;
197 		default:
198 			return -EPROTONOSUPPORT;
199 		}
200 	}
201 
202 	ret = net_l2_send(api->send, net_if_get_device(iface), iface, pkt);
203 	if (!ret) {
204 		ret = net_pkt_get_len(pkt);
205 		ppp_update_tx_stats(iface, pkt, ret);
206 		net_pkt_unref(pkt);
207 	}
208 
209 	return ret;
210 }
211 
ppp_flags(struct net_if * iface)212 static enum net_l2_flags ppp_flags(struct net_if *iface)
213 {
214 	struct ppp_context *ctx = net_if_l2_data(iface);
215 
216 	return ctx->ppp_l2_flags;
217 }
218 
ppp_open_async(struct ppp_context * ctx)219 static void ppp_open_async(struct ppp_context *ctx)
220 {
221 	ppp_change_phase(ctx, PPP_ESTABLISH);
222 
223 	if (ppp_lcp) {
224 		NET_DBG("Starting LCP");
225 		ppp_lcp->lower_up(ctx);
226 		ppp_lcp->open(ctx);
227 	}
228 }
229 
ppp_up(struct net_if * iface)230 static int ppp_up(struct net_if *iface)
231 {
232 	const struct ppp_api *ppp = net_if_get_device(iface)->api;
233 
234 	if (ppp->start) {
235 		ppp->start(net_if_get_device(iface));
236 	}
237 
238 	return 0;
239 }
240 
ppp_lcp_close_async(struct ppp_context * ctx)241 static void ppp_lcp_close_async(struct ppp_context *ctx)
242 {
243 	if (ppp_lcp == NULL) {
244 		ppp_change_phase(ctx, PPP_DEAD);
245 	}
246 
247 	if (ctx->phase == PPP_DEAD) {
248 		return;
249 	}
250 
251 	ppp_lcp->close(ctx, "L2 Disabled");
252 }
253 
ppp_lcp_close(struct ppp_context * ctx)254 static int ppp_lcp_close(struct ppp_context *ctx)
255 {
256 	if (ppp_lcp == NULL) {
257 		ppp_change_phase(ctx, PPP_DEAD);
258 	}
259 
260 	if (ctx->phase == PPP_DEAD) {
261 		return 0;
262 	}
263 
264 	k_sem_reset(&ctx->wait_ppp_link_terminated);
265 	ppp_lcp->close(ctx, "L2 Disabled");
266 	return k_sem_take(&ctx->wait_ppp_link_terminated,
267 			  K_MSEC(CONFIG_NET_L2_PPP_TIMEOUT *
268 				 (1 + CONFIG_NET_L2_PPP_MAX_TERMINATE_REQ_RETRANSMITS)));
269 }
270 
ppp_lcp_lower_down_async(struct ppp_context * ctx)271 static void ppp_lcp_lower_down_async(struct ppp_context *ctx)
272 {
273 	if (ctx->phase == PPP_DEAD) {
274 		return;
275 	}
276 
277 	if (ppp_lcp == NULL) {
278 		ppp_change_phase(ctx, PPP_DEAD);
279 	} else {
280 		ppp_lcp->lower_down(ctx);
281 	}
282 }
283 
ppp_lcp_lower_down(struct ppp_context * ctx)284 static int ppp_lcp_lower_down(struct ppp_context *ctx)
285 {
286 	if (ppp_lcp == NULL) {
287 		ppp_change_phase(ctx, PPP_DEAD);
288 	}
289 
290 	if (ctx->phase == PPP_DEAD) {
291 		return 0;
292 	}
293 
294 	k_sem_reset(&ctx->wait_ppp_link_down);
295 	ppp_lcp->lower_down(ctx);
296 	return k_sem_take(&ctx->wait_ppp_link_down, K_MSEC(CONFIG_NET_L2_PPP_TIMEOUT));
297 }
298 
299 /* Bring down network interface by terminating all protocols */
ppp_down(struct net_if * iface)300 static int ppp_down(struct net_if *iface)
301 {
302 	const struct ppp_api *ppp = net_if_get_device(iface)->api;
303 	struct ppp_context *ctx = net_if_l2_data(iface);
304 
305 	if (net_if_is_carrier_ok(iface)) {
306 		/* Terminate protocols and close LCP */
307 		if (ppp_lcp_close(ctx) < 0) {
308 			return -EAGAIN;
309 		}
310 	} else {
311 		/* Terminate protocols */
312 		if (ppp_lcp_lower_down(ctx) < 0) {
313 			return -EAGAIN;
314 		}
315 	}
316 
317 	if (ppp->stop) {
318 		/* Inform L2 PPP device that PPP link is down */
319 		ppp->stop(net_if_get_device(iface));
320 	}
321 
322 	return 0;
323 }
324 
ppp_enable(struct net_if * iface,bool state)325 static int ppp_enable(struct net_if *iface, bool state)
326 {
327 	struct ppp_context *ctx = net_if_l2_data(iface);
328 	int ret;
329 
330 	/* Set the desired network interface state */
331 	ctx->is_enabled = state;
332 
333 	/* Attempt to enter desired state */
334 	if (state) {
335 		ret = ppp_up(iface);
336 	} else {
337 		ret = ppp_down(iface);
338 	}
339 
340 	if (ret < 0) {
341 		/* Reset the desired state */
342 		ctx->is_enabled = !state;
343 	}
344 
345 	return ret;
346 }
347 
348 NET_L2_INIT(PPP_L2, ppp_recv, ppp_send, ppp_enable, ppp_flags);
349 
350 #if defined(CONFIG_NET_SHELL)
get_ppp_context(int idx,struct ppp_context ** ctx,struct net_if ** iface)351 static int get_ppp_context(int idx, struct ppp_context **ctx,
352 			   struct net_if **iface)
353 {
354 	*iface = net_if_get_by_index(idx);
355 
356 	if (!*iface) {
357 		return -ENOENT;
358 	}
359 
360 	if (net_if_l2(*iface) != &NET_L2_GET_NAME(PPP)) {
361 		return -ENODEV;
362 	}
363 
364 	*ctx = net_if_l2_data(*iface);
365 
366 	return 0;
367 }
368 
echo_reply_handler(void * user_data,size_t user_data_len)369 static void echo_reply_handler(void *user_data, size_t user_data_len)
370 {
371 	struct ppp_context *ctx = user_data;
372 	uint32_t end_time = k_cycle_get_32();
373 	uint32_t time_diff;
374 
375 	time_diff = end_time - ctx->shell.echo_req_data;
376 	ctx->shell.echo_req_data =
377 		k_cyc_to_ns_floor64(time_diff) / 1000;
378 
379 	k_sem_give(&ctx->shell.wait_echo_reply);
380 }
381 
net_ppp_ping(int idx,int32_t timeout)382 int net_ppp_ping(int idx, int32_t timeout)
383 {
384 	struct ppp_context *ctx;
385 	struct net_if *iface;
386 	int ret;
387 
388 	ret = get_ppp_context(idx, &ctx, &iface);
389 	if (ret < 0) {
390 		return ret;
391 	}
392 
393 	ctx->shell.echo_req_data = k_cycle_get_32();
394 	ctx->shell.echo_reply.cb = echo_reply_handler;
395 	ctx->shell.echo_reply.user_data = ctx;
396 	ctx->shell.echo_reply.user_data_len = sizeof(ctx);
397 
398 	ret = ppp_send_pkt(&ctx->lcp.fsm, iface, PPP_ECHO_REQ, 0,
399 			   UINT_TO_POINTER(ctx->shell.echo_req_data),
400 			   sizeof(ctx->shell.echo_req_data));
401 	if (ret < 0) {
402 		return ret;
403 	}
404 
405 	ret = k_sem_take(&ctx->shell.wait_echo_reply, K_MSEC(timeout));
406 
407 	ctx->shell.echo_reply.cb = NULL;
408 
409 	if (ret < 0) {
410 		return ret;
411 	}
412 
413 	/* Returns amount of microseconds waited */
414 	return ctx->shell.echo_req_data;
415 }
416 
net_ppp_context_get(int idx)417 struct ppp_context *net_ppp_context_get(int idx)
418 {
419 	struct ppp_context *ctx;
420 	struct net_if *iface;
421 	int ret;
422 
423 	if (idx == 0) {
424 		iface = net_if_get_first_by_type(&NET_L2_GET_NAME(PPP));
425 		if (!iface) {
426 			return NULL;
427 		}
428 
429 		return net_if_l2_data(iface);
430 	}
431 
432 	ret = get_ppp_context(idx, &ctx, &iface);
433 	if (ret < 0) {
434 		return NULL;
435 	}
436 
437 	return ctx;
438 }
439 #endif
440 
ppp_lcp_get(void)441 const struct ppp_protocol_handler *ppp_lcp_get(void)
442 {
443 	return ppp_lcp;
444 }
445 
ppp_queue_pkt(struct net_pkt * pkt)446 void ppp_queue_pkt(struct net_pkt *pkt)
447 {
448 	k_fifo_put(&tx_queue, pkt);
449 }
450 
tx_handler(void * p1,void * p2,void * p3)451 static void tx_handler(void *p1, void *p2, void *p3)
452 {
453 	ARG_UNUSED(p1);
454 	ARG_UNUSED(p2);
455 	ARG_UNUSED(p3);
456 
457 	struct net_pkt *pkt;
458 	int ret;
459 
460 	NET_DBG("PPP TX started");
461 
462 	k_thread_name_set(NULL, "ppp_tx");
463 
464 	while (1) {
465 		pkt = k_fifo_get(&tx_queue, K_FOREVER);
466 		if (pkt == NULL) {
467 			continue;
468 		}
469 
470 		ret = net_send_data(pkt);
471 		if (ret < 0) {
472 			net_pkt_unref(pkt);
473 		}
474 	}
475 }
476 
net_ppp_mgmt_evt_handler(struct net_mgmt_event_callback * cb,uint64_t mgmt_event,struct net_if * iface)477 static void net_ppp_mgmt_evt_handler(struct net_mgmt_event_callback *cb, uint64_t mgmt_event,
478 				     struct net_if *iface)
479 {
480 	struct ppp_context *ctx;
481 
482 	if (net_if_l2(iface) != &NET_L2_GET_NAME(PPP)) {
483 		return;
484 	}
485 
486 	ctx = net_if_l2_data(iface);
487 
488 	if (net_if_is_carrier_ok(iface)) {
489 		ppp_mgmt_raise_carrier_on_event(iface);
490 	} else {
491 		ppp_mgmt_raise_carrier_off_event(iface);
492 	}
493 
494 	if (mgmt_event == NET_EVENT_IF_UP) {
495 		ppp_open_async(ctx);
496 		return;
497 	}
498 
499 	if ((mgmt_event == NET_EVENT_IF_DOWN) && (!net_if_is_carrier_ok(iface))) {
500 		ppp_lcp_lower_down_async(ctx);
501 	}
502 	if ((mgmt_event == NET_EVENT_IF_DOWN && net_if_is_carrier_ok(iface) &&
503 	     net_if_is_dormant(iface))) {
504 		ppp_lcp_close_async(ctx);
505 	}
506 }
507 
net_ppp_init(struct net_if * iface)508 void net_ppp_init(struct net_if *iface)
509 {
510 	struct ppp_context *ctx = net_if_l2_data(iface);
511 	uint8_t count = 0;
512 
513 	NET_DBG("Initializing PPP L2 %p for iface %p", ctx, iface);
514 
515 	memset(ctx, 0, sizeof(*ctx));
516 
517 	ctx->ppp_l2_flags = NET_L2_MULTICAST | NET_L2_POINT_TO_POINT;
518 	ctx->iface = iface;
519 	k_sem_init(&ctx->wait_ppp_link_terminated, 0, 1);
520 	k_sem_init(&ctx->wait_ppp_link_down, 0, 1);
521 
522 #if defined(CONFIG_NET_SHELL)
523 	k_sem_init(&ctx->shell.wait_echo_reply, 0, K_SEM_MAX_LIMIT);
524 #endif
525 
526 	net_mgmt_init_event_callback(&ctx->mgmt_evt_cb, net_ppp_mgmt_evt_handler,
527 				     (NET_EVENT_IF_UP | NET_EVENT_IF_DOWN));
528 
529 	net_mgmt_add_event_callback(&ctx->mgmt_evt_cb);
530 
531 	STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
532 		if (proto->protocol == PPP_LCP) {
533 			ppp_lcp = proto;
534 		}
535 
536 		proto->init(ctx);
537 		count++;
538 	}
539 
540 	if (count == 0) {
541 		NET_ERR("There are no PPP protocols configured!");
542 		return;
543 	}
544 
545 	if (ppp_lcp == NULL) {
546 		NET_ERR("No LCP found!");
547 		return;
548 	}
549 
550 	ctx->is_ready_to_serve = true;
551 }
552