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/net_core.h>
12 #include <zephyr/net/net_l2.h>
13 #include <zephyr/net/net_if.h>
14 #include <zephyr/net/net_pkt.h>
15 #include <zephyr/net/net_mgmt.h>
16 #include <zephyr/net/ppp.h>
17 #include <zephyr/sys/iterable_sections.h>
18 
19 #include "net_private.h"
20 #include "ipv4_autoconf_internal.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_NUM_COOP_PRIORITIES - 1)
30 #else
31 #define THREAD_PRIORITY K_PRIO_PREEMPT(CONFIG_NUM_PREEMPT_PRIORITIES - 1)
32 #endif
33 
34 static void tx_handler(void);
35 
36 static K_THREAD_DEFINE(tx_handler_thread, CONFIG_NET_L2_PPP_TX_STACK_SIZE,
37 		       (k_thread_entry_t)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 	ret = net_l2_send(api->send, net_if_get_device(iface), iface, pkt);
185 	if (!ret) {
186 		ret = net_pkt_get_len(pkt);
187 		ppp_update_tx_stats(iface, pkt, ret);
188 		net_pkt_unref(pkt);
189 	}
190 
191 	return ret;
192 }
193 
ppp_close(struct ppp_context * ctx)194 static void ppp_close(struct ppp_context *ctx)
195 {
196 	if (ppp_lcp) {
197 		ppp_lcp->close(ctx, "Shutdown");
198 	}
199 }
200 
ppp_lower_up(struct ppp_context * ctx)201 static void ppp_lower_up(struct ppp_context *ctx)
202 {
203 	if (ppp_lcp) {
204 		ppp_lcp->lower_up(ctx);
205 	}
206 }
207 
start_ppp(struct ppp_context * ctx)208 static void start_ppp(struct ppp_context *ctx)
209 {
210 	ppp_change_phase(ctx, PPP_ESTABLISH);
211 
212 	ppp_lower_up(ctx);
213 
214 	if (ppp_lcp) {
215 		NET_DBG("Starting LCP");
216 		ppp_lcp->open(ctx);
217 	}
218 }
219 
ppp_enable(struct net_if * iface,bool state)220 static int ppp_enable(struct net_if *iface, bool state)
221 {
222 	const struct ppp_api *ppp =
223 		net_if_get_device(iface)->api;
224 	struct ppp_context *ctx = net_if_l2_data(iface);
225 
226 
227 	if (ctx->is_enabled == state) {
228 		return 0;
229 	}
230 
231 	ctx->is_enabled = state;
232 
233 	if (!state) {
234 		ppp_close(ctx);
235 
236 		if (ppp->stop) {
237 			ppp->stop(net_if_get_device(iface));
238 		}
239 	} else {
240 		if (ppp->start) {
241 			ppp->start(net_if_get_device(iface));
242 		}
243 
244 		if (ctx->is_startup_pending) {
245 			ctx->is_enable_done = true;
246 		} else {
247 			start_ppp(ctx);
248 		}
249 	}
250 
251 	return 0;
252 }
253 
ppp_flags(struct net_if * iface)254 static enum net_l2_flags ppp_flags(struct net_if *iface)
255 {
256 	struct ppp_context *ctx = net_if_l2_data(iface);
257 
258 	return ctx->ppp_l2_flags;
259 }
260 
261 NET_L2_INIT(PPP_L2, ppp_recv, ppp_send, ppp_enable, ppp_flags);
262 
263 /* A workaround for PPP L2 not yet supporting net_if_carrier_on/off(). */
ppp_if_carrier_down(struct net_if * iface)264 void ppp_if_carrier_down(struct net_if *iface)
265 {
266 	net_if_flag_clear(iface, NET_IF_UP);
267 	net_mgmt_event_notify(NET_EVENT_IF_DOWN, iface);
268 	net_ipv4_autoconf_reset(iface);
269 }
270 
carrier_on_off(struct k_work * work)271 static void carrier_on_off(struct k_work *work)
272 {
273 	struct ppp_context *ctx = CONTAINER_OF(work, struct ppp_context,
274 					       carrier_work);
275 	bool ppp_carrier_up;
276 
277 	if (ctx->iface == NULL) {
278 		return;
279 	}
280 
281 	ppp_carrier_up = atomic_test_bit(&ctx->flags, PPP_CARRIER_UP);
282 
283 	if (ppp_carrier_up == (bool) ctx->is_net_carrier_up) {
284 		return;
285 	}
286 
287 	ctx->is_net_carrier_up = ppp_carrier_up;
288 
289 	NET_DBG("Carrier %s for interface %p", ppp_carrier_up ? "ON" : "OFF",
290 		ctx->iface);
291 
292 	if (ppp_carrier_up) {
293 		ppp_mgmt_raise_carrier_on_event(ctx->iface);
294 		net_if_up(ctx->iface);
295 	} else {
296 		if (ppp_lcp) {
297 			ppp_lcp->close(ctx, "Shutdown");
298 			/* signaling for the carrier off event is done from the LCP callback */
299 		} else {
300 			ppp_change_phase(ctx, PPP_DEAD);
301 
302 			ppp_mgmt_raise_carrier_off_event(ctx->iface);
303 			ppp_if_carrier_down(ctx->iface);
304 		}
305 	}
306 }
307 
net_ppp_carrier_on(struct net_if * iface)308 void net_ppp_carrier_on(struct net_if *iface)
309 {
310 	struct ppp_context *ctx = net_if_l2_data(iface);
311 
312 	if (!atomic_test_and_set_bit(&ctx->flags, PPP_CARRIER_UP)) {
313 		k_work_submit(&ctx->carrier_work);
314 	}
315 }
316 
net_ppp_carrier_off(struct net_if * iface)317 void net_ppp_carrier_off(struct net_if *iface)
318 {
319 	struct ppp_context *ctx = net_if_l2_data(iface);
320 
321 	if (atomic_test_and_clear_bit(&ctx->flags, PPP_CARRIER_UP)) {
322 		k_work_submit(&ctx->carrier_work);
323 	}
324 }
325 
326 #if defined(CONFIG_NET_SHELL)
get_ppp_context(int idx,struct ppp_context ** ctx,struct net_if ** iface)327 static int get_ppp_context(int idx, struct ppp_context **ctx,
328 			   struct net_if **iface)
329 {
330 	*iface = net_if_get_by_index(idx);
331 
332 	if (!*iface) {
333 		return -ENOENT;
334 	}
335 
336 	if (net_if_l2(*iface) != &NET_L2_GET_NAME(PPP)) {
337 		return -ENODEV;
338 	}
339 
340 	*ctx = net_if_l2_data(*iface);
341 
342 	return 0;
343 }
344 
echo_reply_handler(void * user_data,size_t user_data_len)345 static void echo_reply_handler(void *user_data, size_t user_data_len)
346 {
347 	struct ppp_context *ctx = user_data;
348 	uint32_t end_time = k_cycle_get_32();
349 	uint32_t time_diff;
350 
351 	time_diff = end_time - ctx->shell.echo_req_data;
352 	ctx->shell.echo_req_data =
353 		k_cyc_to_ns_floor64(time_diff) / 1000;
354 
355 	k_sem_give(&ctx->shell.wait_echo_reply);
356 }
357 
net_ppp_ping(int idx,int32_t timeout)358 int net_ppp_ping(int idx, int32_t timeout)
359 {
360 	struct ppp_context *ctx;
361 	struct net_if *iface;
362 	int ret;
363 
364 	ret = get_ppp_context(idx, &ctx, &iface);
365 	if (ret < 0) {
366 		return ret;
367 	}
368 
369 	ctx->shell.echo_req_data = k_cycle_get_32();
370 	ctx->shell.echo_reply.cb = echo_reply_handler;
371 	ctx->shell.echo_reply.user_data = ctx;
372 	ctx->shell.echo_reply.user_data_len = sizeof(ctx);
373 
374 	ret = ppp_send_pkt(&ctx->lcp.fsm, iface, PPP_ECHO_REQ, 0,
375 			   UINT_TO_POINTER(ctx->shell.echo_req_data),
376 			   sizeof(ctx->shell.echo_req_data));
377 	if (ret < 0) {
378 		return ret;
379 	}
380 
381 	ret = k_sem_take(&ctx->shell.wait_echo_reply, K_MSEC(timeout));
382 
383 	ctx->shell.echo_reply.cb = NULL;
384 
385 	if (ret < 0) {
386 		return ret;
387 	}
388 
389 	/* Returns amount of microseconds waited */
390 	return ctx->shell.echo_req_data;
391 }
392 
net_ppp_context_get(int idx)393 struct ppp_context *net_ppp_context_get(int idx)
394 {
395 	struct ppp_context *ctx;
396 	struct net_if *iface;
397 	int ret;
398 
399 	if (idx == 0) {
400 		iface = net_if_get_first_by_type(&NET_L2_GET_NAME(PPP));
401 		if (!iface) {
402 			return NULL;
403 		}
404 
405 		return net_if_l2_data(iface);
406 	}
407 
408 	ret = get_ppp_context(idx, &ctx, &iface);
409 	if (ret < 0) {
410 		return NULL;
411 	}
412 
413 	return ctx;
414 }
415 #endif
416 
ppp_lcp_get(void)417 const struct ppp_protocol_handler *ppp_lcp_get(void)
418 {
419 	return ppp_lcp;
420 }
421 
ppp_startup(struct k_work * work)422 static void ppp_startup(struct k_work *work)
423 {
424 	struct k_work_delayable *dwork = k_work_delayable_from_work(work);
425 	struct ppp_context *ctx = CONTAINER_OF(dwork, struct ppp_context,
426 					       startup);
427 	int count = 0;
428 
429 	NET_DBG("PPP %p startup for interface %p", ctx, ctx->iface);
430 
431 	STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
432 		if (proto->protocol == PPP_LCP) {
433 			ppp_lcp = proto;
434 		}
435 
436 		proto->init(ctx);
437 		count++;
438 	}
439 
440 	if (count == 0) {
441 		NET_ERR("There are no PPP protocols configured!");
442 		goto bail_out;
443 	}
444 
445 	if (ppp_lcp == NULL) {
446 		NET_ERR("No LCP found!");
447 		goto bail_out;
448 	}
449 
450 	ctx->is_ready_to_serve = true;
451 
452 bail_out:
453 	ctx->is_startup_pending = false;
454 
455 	if (ctx->is_enable_done) {
456 		start_ppp(ctx);
457 		ctx->is_enable_done = false;
458 	}
459 }
460 
ppp_queue_pkt(struct net_pkt * pkt)461 void ppp_queue_pkt(struct net_pkt *pkt)
462 {
463 	k_fifo_put(&tx_queue, pkt);
464 }
465 
tx_handler(void)466 static void tx_handler(void)
467 {
468 	struct net_pkt *pkt;
469 	int ret;
470 
471 	NET_DBG("PPP TX started");
472 
473 	k_thread_name_set(NULL, "ppp_tx");
474 
475 	while (1) {
476 		pkt = k_fifo_get(&tx_queue, K_FOREVER);
477 		if (pkt == NULL) {
478 			continue;
479 		}
480 
481 		ret = net_send_data(pkt);
482 		if (ret < 0) {
483 			net_pkt_unref(pkt);
484 		}
485 	}
486 }
487 
net_ppp_init(struct net_if * iface)488 void net_ppp_init(struct net_if *iface)
489 {
490 	struct ppp_context *ctx = net_if_l2_data(iface);
491 
492 	NET_DBG("Initializing PPP L2 %p for iface %p", ctx, iface);
493 
494 	memset(ctx, 0, sizeof(*ctx));
495 
496 	ctx->ppp_l2_flags = NET_L2_MULTICAST | NET_L2_POINT_TO_POINT;
497 	ctx->iface = iface;
498 
499 	k_work_init(&ctx->carrier_work, carrier_on_off);
500 
501 #if defined(CONFIG_NET_SHELL)
502 	k_sem_init(&ctx->shell.wait_echo_reply, 0, K_SEM_MAX_LIMIT);
503 #endif
504 
505 	/* TODO: Unify the startup worker code so that we can save
506 	 * some memory if there are more than one PPP context in the
507 	 * system. The issue is not very likely as typically there
508 	 * would be only one PPP network interface in the system.
509 	 */
510 	k_work_init_delayable(&ctx->startup, ppp_startup);
511 
512 	ctx->is_startup_pending = true;
513 
514 	k_work_reschedule(&ctx->startup,
515 			  K_MSEC(CONFIG_NET_L2_PPP_DELAY_STARTUP_MS));
516 }
517