1 /*
2  * Copyright (c) 2017 Intel Corporation
3  * Copyright (c) 2019 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/init.h>
9 
10 #include <zephyr/logging/log.h>
11 #include <zephyr/net/socket.h>
12 #include <zephyr/net/socket_service.h>
13 #include <zephyr/shell/shell_telnet.h>
14 
15 #include "shell_telnet_protocol.h"
16 
17 SHELL_TELNET_DEFINE(shell_transport_telnet);
18 SHELL_DEFINE(shell_telnet, CONFIG_SHELL_PROMPT_TELNET, &shell_transport_telnet,
19 	     CONFIG_SHELL_TELNET_LOG_MESSAGE_QUEUE_SIZE,
20 	     CONFIG_SHELL_TELNET_LOG_MESSAGE_QUEUE_TIMEOUT,
21 	     SHELL_FLAG_OLF_CRLF);
22 
23 LOG_MODULE_REGISTER(shell_telnet, CONFIG_SHELL_TELNET_LOG_LEVEL);
24 
25 struct shell_telnet *sh_telnet;
26 
27 /* Various definitions mapping the TELNET service configuration options */
28 #define TELNET_PORT      CONFIG_SHELL_TELNET_PORT
29 #define TELNET_LINE_SIZE CONFIG_SHELL_TELNET_LINE_BUF_SIZE
30 #define TELNET_TIMEOUT   CONFIG_SHELL_TELNET_SEND_TIMEOUT
31 
32 #define TELNET_MIN_COMMAND_LEN 2
33 #define TELNET_WILL_DO_COMMAND_LEN 3
34 
35 #define SOCK_ID_IPV4_LISTEN 0
36 #define SOCK_ID_IPV6_LISTEN 1
37 #define SOCK_ID_CLIENT      2
38 #define SOCK_ID_MAX         3
39 
40 /* Basic TELNET implementation. */
41 
42 static void telnet_server_cb(struct net_socket_service_event *evt);
43 static int telnet_init(struct shell_telnet *ctx);
44 
45 NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC(telnet_server, telnet_server_cb,
46 				      SHELL_TELNET_POLLFD_COUNT);
47 
48 
telnet_end_client_connection(void)49 static void telnet_end_client_connection(void)
50 {
51 	int ret;
52 
53 	(void)zsock_close(sh_telnet->fds[SOCK_ID_CLIENT].fd);
54 
55 	sh_telnet->fds[SOCK_ID_CLIENT].fd = -1;
56 	sh_telnet->output_lock = false;
57 
58 	k_work_cancel_delayable_sync(&sh_telnet->send_work,
59 				     &sh_telnet->work_sync);
60 
61 	ret = net_socket_service_register(&telnet_server, sh_telnet->fds,
62 					  ARRAY_SIZE(sh_telnet->fds), NULL);
63 	if (ret < 0) {
64 		LOG_ERR("Failed to register socket service, %d", ret);
65 	}
66 }
67 
telnet_command_send_reply(uint8_t * msg,uint16_t len)68 static void telnet_command_send_reply(uint8_t *msg, uint16_t len)
69 {
70 	if (sh_telnet->fds[SOCK_ID_CLIENT].fd < 0) {
71 		return;
72 	}
73 
74 	while (len > 0) {
75 		int ret;
76 
77 		ret = zsock_send(sh_telnet->fds[SOCK_ID_CLIENT].fd, msg, len, 0);
78 		if (ret < 0) {
79 			LOG_ERR("Failed to send command %d, shutting down", ret);
80 			telnet_end_client_connection();
81 			break;
82 		}
83 
84 		msg += ret;
85 		len -= ret;
86 	}
87 }
88 
telnet_reply_ay_command(void)89 static void telnet_reply_ay_command(void)
90 {
91 	static const char alive[] = "Zephyr at your service\r\n";
92 
93 	telnet_command_send_reply((uint8_t *)alive, strlen(alive));
94 }
95 
telnet_echo_set(const struct shell * sh,bool val)96 static int telnet_echo_set(const struct shell *sh, bool val)
97 {
98 	int ret = shell_echo_set(sh_telnet->shell_context, val);
99 
100 	if (ret < 0) {
101 		LOG_ERR("Failed to set echo to: %d, err: %d", val, ret);
102 	}
103 	return ret;
104 }
105 
telnet_reply_dont_command(struct telnet_simple_command * cmd)106 static void telnet_reply_dont_command(struct telnet_simple_command *cmd)
107 {
108 	switch (cmd->opt) {
109 	case NVT_OPT_ECHO:
110 	{
111 		int ret = telnet_echo_set(sh_telnet->shell_context, false);
112 
113 		if (ret >= 0) {
114 			cmd->op = NVT_CMD_WILL_NOT;
115 		} else {
116 			cmd->op = NVT_CMD_WILL;
117 		}
118 		break;
119 	}
120 	default:
121 		cmd->op = NVT_CMD_WILL_NOT;
122 		break;
123 	}
124 
125 	telnet_command_send_reply((uint8_t *)cmd,
126 				  sizeof(struct telnet_simple_command));
127 }
128 
telnet_reply_do_command(struct telnet_simple_command * cmd)129 static void telnet_reply_do_command(struct telnet_simple_command *cmd)
130 {
131 	switch (cmd->opt) {
132 	case NVT_OPT_SUPR_GA:
133 		cmd->op = NVT_CMD_WILL;
134 		break;
135 	case NVT_OPT_ECHO:
136 	{
137 		int ret = telnet_echo_set(sh_telnet->shell_context, true);
138 
139 		if (ret >= 0) {
140 			cmd->op = NVT_CMD_WILL;
141 		} else {
142 			cmd->op = NVT_CMD_WILL_NOT;
143 		}
144 		break;
145 	}
146 	default:
147 		cmd->op = NVT_CMD_WILL_NOT;
148 		break;
149 	}
150 
151 	telnet_command_send_reply((uint8_t *)cmd,
152 				  sizeof(struct telnet_simple_command));
153 }
154 
telnet_reply_command(struct telnet_simple_command * cmd)155 static void telnet_reply_command(struct telnet_simple_command *cmd)
156 {
157 	if (!cmd->iac) {
158 		return;
159 	}
160 
161 	switch (cmd->op) {
162 	case NVT_CMD_AO:
163 		/* OK, no output then */
164 		sh_telnet->output_lock = true;
165 		sh_telnet->line_out.len = 0;
166 		k_work_cancel_delayable_sync(&sh_telnet->send_work,
167 					     &sh_telnet->work_sync);
168 		break;
169 	case NVT_CMD_AYT:
170 		telnet_reply_ay_command();
171 		break;
172 	case NVT_CMD_DO:
173 		telnet_reply_do_command(cmd);
174 		break;
175 	case NVT_CMD_DO_NOT:
176 		telnet_reply_dont_command(cmd);
177 		break;
178 	default:
179 		LOG_DBG("Operation %u not handled", cmd->op);
180 		break;
181 	}
182 }
183 
telnet_send(bool block)184 static int telnet_send(bool block)
185 {
186 	int ret;
187 	uint8_t *msg = sh_telnet->line_out.buf;
188 	uint16_t len = sh_telnet->line_out.len;
189 
190 	if (sh_telnet->line_out.len == 0) {
191 		return 0;
192 	}
193 
194 	if (sh_telnet->fds[SOCK_ID_CLIENT].fd < 0) {
195 		return -ENOTCONN;
196 	}
197 
198 	while (len > 0) {
199 		ret = zsock_send(sh_telnet->fds[SOCK_ID_CLIENT].fd, msg, len,
200 				 block ? 0 : ZSOCK_MSG_DONTWAIT);
201 		if (!block && (ret < 0) && (errno == EAGAIN)) {
202 			/* Not all data was sent - move the remaining data and
203 			 * update length.
204 			 */
205 			memmove(sh_telnet->line_out.buf, msg, len);
206 			sh_telnet->line_out.len = len;
207 			return -EAGAIN;
208 		}
209 
210 		if (ret < 0) {
211 			ret = -errno;
212 			LOG_ERR("Failed to send %d, shutting down", -ret);
213 			telnet_end_client_connection();
214 			return ret;
215 		}
216 
217 		msg += ret;
218 		len -= ret;
219 	}
220 
221 	/* We reinitialize the line buffer */
222 	sh_telnet->line_out.len = 0;
223 
224 	return 0;
225 }
226 
telnet_send_prematurely(struct k_work * work)227 static void telnet_send_prematurely(struct k_work *work)
228 {
229 	int ret;
230 
231 	/* Use non-blocking send to prevent system workqueue blocking. */
232 	ret = telnet_send(false);
233 	if (ret == -EAGAIN) {
234 		/* Not all data was sent, reschedule the work. */
235 		k_work_reschedule(&sh_telnet->send_work, K_MSEC(TELNET_TIMEOUT));
236 	}
237 }
238 
telnet_command_length(uint8_t op)239 static int telnet_command_length(uint8_t op)
240 {
241 	if (op == NVT_CMD_SB || op == NVT_CMD_WILL || op == NVT_CMD_WILL_NOT ||
242 	    op == NVT_CMD_DO || op == NVT_CMD_DO_NOT) {
243 		return TELNET_WILL_DO_COMMAND_LEN;
244 	}
245 
246 	return TELNET_MIN_COMMAND_LEN;
247 }
248 
telnet_handle_command(struct telnet_simple_command * cmd)249 static inline int telnet_handle_command(struct telnet_simple_command *cmd)
250 {
251 	/* Commands are two or three bytes. */
252 	if (cmd->iac != NVT_CMD_IAC) {
253 		return 0;
254 	}
255 
256 	if (IS_ENABLED(CONFIG_SHELL_TELNET_SUPPORT_COMMAND)) {
257 		LOG_DBG("Got a command %u/%u/%u", cmd->iac, cmd->op, cmd->opt);
258 		telnet_reply_command(cmd);
259 	}
260 
261 	if (cmd->op == NVT_CMD_SB) {
262 		/* TODO Add subnegotiation support. */
263 		return -EOPNOTSUPP;
264 	}
265 
266 	return 0;
267 }
268 
telnet_recv(struct zsock_pollfd * pollfd)269 static void telnet_recv(struct zsock_pollfd *pollfd)
270 {
271 	struct telnet_simple_command *cmd =
272 			(struct telnet_simple_command *)sh_telnet->cmd_buf;
273 	size_t len, off, buf_left, cmd_total_len;
274 	uint8_t *buf;
275 	int ret;
276 
277 	k_mutex_lock(&sh_telnet->rx_lock, K_FOREVER);
278 
279 	buf_left = sizeof(sh_telnet->rx_buf) - sh_telnet->rx_len;
280 	if (buf_left == 0) {
281 		/* No space left to read TCP stream, try again later. */
282 		k_mutex_unlock(&sh_telnet->rx_lock);
283 		k_msleep(10);
284 		return;
285 	}
286 
287 	buf = sh_telnet->rx_buf + sh_telnet->rx_len;
288 
289 	ret = zsock_recv(pollfd->fd, buf, buf_left, 0);
290 	if (ret < 0) {
291 		LOG_DBG("Telnet client error %d", ret);
292 		goto error;
293 	} else if (ret == 0) {
294 		LOG_DBG("Telnet client closed connection");
295 		goto error;
296 	}
297 
298 	off = 0;
299 	len = ret;
300 	cmd_total_len = 0;
301 	/* Filter out and process commands from the data buffer. */
302 	while (off < len) {
303 		if (sh_telnet->cmd_len > 0) {
304 			/* Command mode */
305 			if (sh_telnet->cmd_len == 1) {
306 				/* Operation */
307 				cmd->op = *(buf + off);
308 				sh_telnet->cmd_len++;
309 				cmd_total_len++;
310 				off++;
311 
312 				if (telnet_command_length(cmd->op) >
313 							TELNET_MIN_COMMAND_LEN) {
314 					continue;
315 				}
316 			} else if (sh_telnet->cmd_len == 2) {
317 				/* Option */
318 				cmd->opt = *(buf + off);
319 				sh_telnet->cmd_len++;
320 				cmd_total_len++;
321 				off++;
322 			}
323 
324 			ret = telnet_handle_command(cmd);
325 			if (ret < 0) {
326 				goto error;
327 			} else {
328 				LOG_DBG("Handled command");
329 			}
330 
331 			memset(cmd, 0, sizeof(*cmd));
332 			sh_telnet->cmd_len = 0;
333 
334 			continue;
335 		}
336 
337 		if (*(buf + off) == NVT_CMD_IAC) {
338 			cmd->iac = *(buf + off);
339 			sh_telnet->cmd_len++;
340 			cmd_total_len++;
341 			off++;
342 			continue;
343 		}
344 
345 		/* Data byte, remove command bytes from the buffer, if any. */
346 		if (cmd_total_len > 0) {
347 			size_t data_off = off;
348 
349 			off -= cmd_total_len;
350 			len -= cmd_total_len;
351 			cmd_total_len = 0;
352 
353 			memmove(buf + off, buf + data_off, len);
354 		}
355 
356 		off++;
357 	}
358 
359 	if (cmd_total_len > 0) {
360 		/* In case the buffer ended with command, trim the buffer size
361 		 * here.
362 		 */
363 		len -=	cmd_total_len;
364 	}
365 
366 	if (len == 0) {
367 		k_mutex_unlock(&sh_telnet->rx_lock);
368 		return;
369 	}
370 
371 	sh_telnet->rx_len += len;
372 
373 	k_mutex_unlock(&sh_telnet->rx_lock);
374 
375 	sh_telnet->shell_handler(SHELL_TRANSPORT_EVT_RX_RDY,
376 				 sh_telnet->shell_context);
377 
378 	return;
379 
380 error:
381 	k_mutex_unlock(&sh_telnet->rx_lock);
382 	telnet_end_client_connection();
383 }
384 
telnet_restart_server(void)385 static void telnet_restart_server(void)
386 {
387 	int ret;
388 
389 	if (sh_telnet->fds[SOCK_ID_IPV4_LISTEN].fd >= 0) {
390 		(void)zsock_close(sh_telnet->fds[SOCK_ID_IPV4_LISTEN].fd);
391 		sh_telnet->fds[SOCK_ID_IPV4_LISTEN].fd = -1;
392 	}
393 
394 	if (sh_telnet->fds[SOCK_ID_IPV6_LISTEN].fd >= 0) {
395 		(void)zsock_close(sh_telnet->fds[SOCK_ID_IPV6_LISTEN].fd);
396 		sh_telnet->fds[SOCK_ID_IPV6_LISTEN].fd = -1;
397 	}
398 
399 	if (sh_telnet->fds[SOCK_ID_CLIENT].fd >= 0) {
400 		(void)zsock_close(sh_telnet->fds[SOCK_ID_CLIENT].fd);
401 		sh_telnet->fds[SOCK_ID_CLIENT].fd = -1;
402 	}
403 
404 	ret = telnet_init(sh_telnet);
405 	if (ret < 0) {
406 		LOG_ERR("Telnet fatal error, failed to restart server (%d)", ret);
407 		(void)net_socket_service_unregister(&telnet_server);
408 	}
409 }
410 
telnet_accept(struct zsock_pollfd * pollfd)411 static void telnet_accept(struct zsock_pollfd *pollfd)
412 {
413 	int sock, ret = 0;
414 	struct sockaddr addr;
415 	socklen_t addrlen = sizeof(struct sockaddr);
416 
417 	sock = zsock_accept(pollfd->fd, &addr, &addrlen);
418 	if (sock < 0) {
419 		ret = -errno;
420 		NET_ERR("Telnet accept error (%d)", ret);
421 		return;
422 	}
423 
424 	if (sh_telnet->fds[SOCK_ID_CLIENT].fd > 0) {
425 		/* Too many connections. */
426 		ret = 0;
427 		NET_ERR("Telnet client already connected.");
428 		goto error;
429 	}
430 
431 	sh_telnet->fds[SOCK_ID_CLIENT].fd = sock;
432 	sh_telnet->fds[SOCK_ID_CLIENT].events = ZSOCK_POLLIN;
433 	sh_telnet->rx_len = 0;
434 	sh_telnet->cmd_len = 0;
435 	sh_telnet->line_out.len = 0;
436 
437 	ret = net_socket_service_register(&telnet_server, sh_telnet->fds,
438 					  ARRAY_SIZE(sh_telnet->fds), NULL);
439 	if (ret < 0) {
440 		LOG_ERR("Failed to register socket service, (%d)", ret);
441 		sh_telnet->fds[SOCK_ID_CLIENT].fd = -1;
442 		goto error;
443 	}
444 
445 	LOG_DBG("Telnet client connected (family AF_INET%s)",
446 		addr.sa_family == AF_INET ? "" : "6");
447 
448 	/* Disable echo - if command handling is enabled we reply that we
449 	 * support echo.
450 	 */
451 	(void)telnet_echo_set(sh_telnet->shell_context, false);
452 
453 	return;
454 
455 error:
456 	if (sock > 0) {
457 		(void)zsock_close(sock);
458 	}
459 
460 	if (ret < 0) {
461 		telnet_restart_server();
462 	}
463 }
464 
telnet_server_cb(struct net_socket_service_event * evt)465 static void telnet_server_cb(struct net_socket_service_event *evt)
466 {
467 	int sock_error;
468 	socklen_t optlen = sizeof(int);
469 
470 	if (sh_telnet == NULL) {
471 		return;
472 	}
473 
474 	if ((evt->event.revents & ZSOCK_POLLERR) ||
475 	    (evt->event.revents & ZSOCK_POLLNVAL)) {
476 		(void)zsock_getsockopt(evt->event.fd, SOL_SOCKET,
477 				       SO_ERROR, &sock_error, &optlen);
478 		NET_ERR("Telnet socket %d error (%d)", evt->event.fd, sock_error);
479 
480 		if (evt->event.fd == sh_telnet->fds[SOCK_ID_CLIENT].fd) {
481 			telnet_end_client_connection();
482 			return;
483 		}
484 
485 		goto error;
486 	}
487 
488 	if (!(evt->event.revents & ZSOCK_POLLIN)) {
489 		return;
490 	}
491 
492 	if (evt->event.fd == sh_telnet->fds[SOCK_ID_IPV4_LISTEN].fd) {
493 		telnet_accept(&sh_telnet->fds[SOCK_ID_IPV4_LISTEN]);
494 		return;
495 	} else if (evt->event.fd == sh_telnet->fds[SOCK_ID_IPV6_LISTEN].fd) {
496 		telnet_accept(&sh_telnet->fds[SOCK_ID_IPV6_LISTEN]);
497 		return;
498 	} else if (evt->event.fd == sh_telnet->fds[SOCK_ID_CLIENT].fd) {
499 		telnet_recv(&sh_telnet->fds[SOCK_ID_CLIENT]);
500 		return;
501 	}
502 
503 	NET_ERR("Unexpected FD received for telnet, restarting service.");
504 
505 error:
506 	telnet_restart_server();
507 }
508 
telnet_setup_server(struct zsock_pollfd * pollfd,sa_family_t family,struct sockaddr * addr,socklen_t addrlen)509 static int telnet_setup_server(struct zsock_pollfd *pollfd, sa_family_t family,
510 			       struct sockaddr *addr, socklen_t addrlen)
511 {
512 	int ret = 0;
513 
514 	pollfd->fd = zsock_socket(family, SOCK_STREAM, IPPROTO_TCP);
515 	if (pollfd->fd < 0) {
516 		ret = -errno;
517 		LOG_ERR("Failed to create telnet AF_INET%s socket",
518 			family == AF_INET ? "" : "6");
519 		goto error;
520 	}
521 
522 	if (zsock_bind(pollfd->fd, addr, addrlen) < 0) {
523 		ret = -errno;
524 		LOG_ERR("Cannot bind on family AF_INET%s (%d)",
525 			family == AF_INET ? "" : "6", ret);
526 		goto error;
527 	}
528 
529 	if (zsock_listen(pollfd->fd, 1)) {
530 		ret = -errno;
531 		LOG_ERR("Cannot listen on family AF_INET%s (%d)",
532 			family == AF_INET ? "" : "6", ret);
533 		goto error;
534 	}
535 
536 	pollfd->events = ZSOCK_POLLIN;
537 
538 	LOG_DBG("Telnet console enabled on AF_INET%s",
539 		family == AF_INET ? "" : "6");
540 
541 	return 0;
542 
543 error:
544 	LOG_ERR("Unable to start telnet on AF_INET%s (%d)",
545 		family == AF_INET ? "" : "6", ret);
546 
547 	if (pollfd->fd >= 0) {
548 		(void)zsock_close(pollfd->fd);
549 		pollfd->fd = -1;
550 	}
551 
552 	return ret;
553 }
554 
telnet_init(struct shell_telnet * ctx)555 static int telnet_init(struct shell_telnet *ctx)
556 {
557 	int ret;
558 
559 	if (IS_ENABLED(CONFIG_NET_IPV4)) {
560 		struct sockaddr_in any_addr4 = {
561 			.sin_family = AF_INET,
562 			.sin_port = htons(TELNET_PORT),
563 			.sin_addr = INADDR_ANY_INIT
564 		};
565 
566 		ret = telnet_setup_server(&ctx->fds[SOCK_ID_IPV4_LISTEN],
567 					  AF_INET, (struct sockaddr *)&any_addr4,
568 					  sizeof(any_addr4));
569 		if (ret < 0) {
570 			goto error;
571 		}
572 	}
573 
574 	if (IS_ENABLED(CONFIG_NET_IPV6)) {
575 		struct sockaddr_in6 any_addr6 = {
576 			.sin6_family = AF_INET6,
577 			.sin6_port = htons(TELNET_PORT),
578 			.sin6_addr = IN6ADDR_ANY_INIT
579 		};
580 
581 		ret = telnet_setup_server(&ctx->fds[SOCK_ID_IPV6_LISTEN],
582 					  AF_INET6, (struct sockaddr *)&any_addr6,
583 					  sizeof(any_addr6));
584 		if (ret < 0) {
585 			goto error;
586 		}
587 	}
588 
589 	ret = net_socket_service_register(&telnet_server, ctx->fds,
590 					  ARRAY_SIZE(ctx->fds), NULL);
591 	if (ret < 0) {
592 		LOG_ERR("Failed to register socket service, %d", ret);
593 		goto error;
594 	}
595 
596 	LOG_INF("Telnet shell backend initialized");
597 
598 	return 0;
599 
600 error:
601 	if (ctx->fds[SOCK_ID_IPV4_LISTEN].fd >= 0) {
602 		(void)zsock_close(ctx->fds[SOCK_ID_IPV4_LISTEN].fd);
603 		ctx->fds[SOCK_ID_IPV4_LISTEN].fd = -1;
604 	}
605 
606 	if (ctx->fds[SOCK_ID_IPV6_LISTEN].fd >= 0) {
607 		(void)zsock_close(ctx->fds[SOCK_ID_IPV6_LISTEN].fd);
608 		ctx->fds[SOCK_ID_IPV6_LISTEN].fd = -1;
609 	}
610 
611 	return ret;
612 }
613 
614 /* Shell API */
615 
init(const struct shell_transport * transport,const void * config,shell_transport_handler_t evt_handler,void * context)616 static int init(const struct shell_transport *transport,
617 		const void *config,
618 		shell_transport_handler_t evt_handler,
619 		void *context)
620 {
621 	int err;
622 
623 	sh_telnet = (struct shell_telnet *)transport->ctx;
624 
625 	memset(sh_telnet, 0, sizeof(struct shell_telnet));
626 	for (int i = 0; i < ARRAY_SIZE(sh_telnet->fds); i++) {
627 		sh_telnet->fds[i].fd = -1;
628 	}
629 
630 	sh_telnet->shell_handler = evt_handler;
631 	sh_telnet->shell_context = context;
632 
633 	err = telnet_init(sh_telnet);
634 	if (err != 0) {
635 		return err;
636 	}
637 
638 	k_work_init_delayable(&sh_telnet->send_work, telnet_send_prematurely);
639 	k_mutex_init(&sh_telnet->rx_lock);
640 
641 	return 0;
642 }
643 
uninit(const struct shell_transport * transport)644 static int uninit(const struct shell_transport *transport)
645 {
646 	if (sh_telnet == NULL) {
647 		return -ENODEV;
648 	}
649 
650 	return 0;
651 }
652 
enable(const struct shell_transport * transport,bool blocking)653 static int enable(const struct shell_transport *transport, bool blocking)
654 {
655 	if (sh_telnet == NULL) {
656 		return -ENODEV;
657 	}
658 
659 	return 0;
660 }
661 
telnet_write(const struct shell_transport * transport,const void * data,size_t length,size_t * cnt)662 static int telnet_write(const struct shell_transport *transport,
663 			const void *data, size_t length, size_t *cnt)
664 {
665 	struct shell_telnet_line_buf *lb;
666 	size_t copy_len;
667 	int err;
668 	uint32_t timeout;
669 	bool was_running;
670 
671 	if (sh_telnet == NULL) {
672 		*cnt = 0;
673 		return -ENODEV;
674 	}
675 
676 	if (sh_telnet->fds[SOCK_ID_CLIENT].fd < 0 || sh_telnet->output_lock) {
677 		*cnt = length;
678 		return 0;
679 	}
680 
681 	*cnt = 0;
682 	lb = &sh_telnet->line_out;
683 
684 	/* Stop the transmission timer, so it does not interrupt the operation.
685 	 */
686 	timeout = k_ticks_to_ms_ceil32(
687 			k_work_delayable_remaining_get(&sh_telnet->send_work));
688 	was_running = k_work_cancel_delayable_sync(&sh_telnet->send_work,
689 						   &sh_telnet->work_sync);
690 
691 	do {
692 		if (lb->len + length - *cnt > TELNET_LINE_SIZE) {
693 			copy_len = TELNET_LINE_SIZE - lb->len;
694 		} else {
695 			copy_len = length - *cnt;
696 		}
697 
698 		memcpy(lb->buf + lb->len, (uint8_t *)data + *cnt, copy_len);
699 		lb->len += copy_len;
700 
701 		/* Send the data immediately if the buffer is full or line feed
702 		 * is recognized.
703 		 */
704 		if (lb->buf[lb->len - 1] == '\n' ||
705 		    lb->len == TELNET_LINE_SIZE) {
706 			err = telnet_send(true);
707 			if (err != 0) {
708 				*cnt = length;
709 				if ((err == -ENOTCONN) || (err == -ENETDOWN)) {
710 					LOG_ERR("Network disconnected, shutting down");
711 				} else {
712 					LOG_ERR("Error %d, shutting down", err);
713 				}
714 				return 0; /* Return 0 to not trigger ASSERT in shell_ops.c */
715 			}
716 		}
717 
718 		*cnt += copy_len;
719 	} while (*cnt < length);
720 
721 	if (lb->len > 0) {
722 		/* Check if the timer was already running, initialize otherwise.
723 		 */
724 		timeout = was_running ? timeout : TELNET_TIMEOUT;
725 
726 		k_work_reschedule(&sh_telnet->send_work, K_MSEC(timeout));
727 	}
728 
729 	sh_telnet->shell_handler(SHELL_TRANSPORT_EVT_TX_RDY,
730 				 sh_telnet->shell_context);
731 
732 	return 0;
733 }
734 
telnet_read(const struct shell_transport * transport,void * data,size_t length,size_t * cnt)735 static int telnet_read(const struct shell_transport *transport,
736 		       void *data, size_t length, size_t *cnt)
737 {
738 	size_t read_len;
739 
740 	if (sh_telnet == NULL) {
741 		return -ENODEV;
742 	}
743 
744 	if (sh_telnet->fds[SOCK_ID_CLIENT].fd < 0) {
745 		goto no_data;
746 	}
747 
748 	k_mutex_lock(&sh_telnet->rx_lock, K_FOREVER);
749 
750 	if (sh_telnet->rx_len == 0) {
751 		k_mutex_unlock(&sh_telnet->rx_lock);
752 		goto no_data;
753 	}
754 
755 	read_len = sh_telnet->rx_len;
756 	if (read_len > length) {
757 		read_len = length;
758 	}
759 
760 	memcpy(data, sh_telnet->rx_buf, read_len);
761 	*cnt = read_len;
762 
763 	sh_telnet->rx_len -= read_len;
764 	if (sh_telnet->rx_len > 0) {
765 		memmove(sh_telnet->rx_buf, sh_telnet->rx_buf + read_len,
766 			sh_telnet->rx_len);
767 	}
768 
769 	k_mutex_unlock(&sh_telnet->rx_lock);
770 
771 	return 0;
772 
773 no_data:
774 	*cnt = 0;
775 	return 0;
776 }
777 
778 const struct shell_transport_api shell_telnet_transport_api = {
779 	.init = init,
780 	.uninit = uninit,
781 	.enable = enable,
782 	.write = telnet_write,
783 	.read = telnet_read
784 };
785 
enable_shell_telnet(void)786 static int enable_shell_telnet(void)
787 {
788 	bool log_backend = CONFIG_SHELL_TELNET_INIT_LOG_LEVEL > 0;
789 	uint32_t level = (CONFIG_SHELL_TELNET_INIT_LOG_LEVEL > LOG_LEVEL_DBG) ?
790 		      CONFIG_LOG_MAX_LEVEL : CONFIG_SHELL_TELNET_INIT_LOG_LEVEL;
791 	static const struct shell_backend_config_flags cfg_flags =
792 					SHELL_DEFAULT_BACKEND_CONFIG_FLAGS;
793 
794 	return shell_init(&shell_telnet, NULL, cfg_flags, log_backend, level);
795 }
796 
797 SYS_INIT(enable_shell_telnet, APPLICATION, CONFIG_SHELL_TELNET_INIT_PRIORITY);
798 
shell_backend_telnet_get_ptr(void)799 const struct shell *shell_backend_telnet_get_ptr(void)
800 {
801 	return &shell_telnet;
802 }
803