This is an automated email from the ASF dual-hosted git repository. masayuki pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx-apps.git
commit 36a0c924f7ff210a8d203e80b8468561c842b992 Author: Xiang Xiao <[email protected]> AuthorDate: Sun Oct 16 19:44:38 2022 +0800 netutils: Support telnetd in the kernel mode Signed-off-by: Xiang Xiao <[email protected]> Signed-off-by: chao an <[email protected]> --- examples/telnetd/Makefile | 4 +- examples/telnetd/telnetd.c | 5 +- include/netutils/telnetd.h | 48 ++++---- netutils/telnetd/Kconfig | 3 - netutils/telnetd/Makefile | 2 - netutils/telnetd/telnetd_daemon.c | 230 ++++++++++++-------------------------- nshlib/Kconfig | 51 +-------- nshlib/README.md | 18 ++- nshlib/nsh.h | 41 ------- nshlib/nsh_command.c | 8 -- nshlib/nsh_telnetd.c | 153 +++++-------------------- system/telnet/telnet_client.c | 4 +- system/telnetd/Kconfig | 9 +- system/telnetd/telnetd.c | 74 +++++++++--- 14 files changed, 200 insertions(+), 450 deletions(-) diff --git a/examples/telnetd/Makefile b/examples/telnetd/Makefile index b121c1f75..f12fec619 100644 --- a/examples/telnetd/Makefile +++ b/examples/telnetd/Makefile @@ -27,8 +27,8 @@ MAINSRC = telnetd.c # Buttons built-in application info PROGNAME = telnetd -PRIORITY = SCHED_PRIORITY_DEFAULT -STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE) +PRIORITY = $(CONFIG_EXAMPLES_TELNETD_DAEMONPRIO) +STACKSIZE = $(CONFIG_EXAMPLES_TELNETD_DAEMONSTACKSIZE) MODULE = $(CONFIG_EXAMPLES_TELNETD) include $(APPDIR)/Application.mk diff --git a/examples/telnetd/telnetd.c b/examples/telnetd/telnetd.c index e51af2d79..971c4cb7e 100644 --- a/examples/telnetd/telnetd.c +++ b/examples/telnetd/telnetd.c @@ -239,10 +239,9 @@ int main(int argc, FAR char *argv[]) /* Configure the telnet daemon */ + memset(&config, 0, sizeof(config)); config.d_port = HTONS(23); config.d_family = AF_INET; - config.d_priority = CONFIG_EXAMPLES_TELNETD_DAEMONPRIO; - config.d_stacksize = CONFIG_EXAMPLES_TELNETD_DAEMONSTACKSIZE; config.t_priority = CONFIG_EXAMPLES_TELNETD_CLIENTPRIO; config.t_stacksize = CONFIG_EXAMPLES_TELNETD_CLIENTSTACKSIZE; config.t_entry = telnetd_session; @@ -250,7 +249,7 @@ int main(int argc, FAR char *argv[]) /* Start the telnet daemon */ printf("telnetd_main: Starting the Telnet daemon\n"); - ret = telnetd_start(&config); + ret = telnetd_daemon(&config); if (ret < 0) { printf("Failed to start the Telnet daemon\n"); diff --git a/include/netutils/telnetd.h b/include/netutils/telnetd.h index 11fb39f58..1183d4ffc 100644 --- a/include/netutils/telnetd.h +++ b/include/netutils/telnetd.h @@ -25,44 +25,38 @@ * Included Files ****************************************************************************/ -#include <nuttx/config.h> - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* CONFIG_TELNETD_CONSOLE - Use the first Telnet session as the default - * console. - */ +#include <sys/types.h> /**************************************************************************** * Public Types ****************************************************************************/ /* An instance of the struct telnetd_config_s structure must be passed to - * telnetd_start in order to configure the new Telnet daemon. + * telnetd_daemon in order to configure the new Telnet daemon. */ struct telnetd_config_s { - /* These fields describe the telnet daemon */ - - uint8_t d_priority; /* The execution priority of the Telnet daemon task */ - size_t d_stacksize; /* The stack size needed by the Telnet daemon task */ - /* These fields describe the network connection */ - uint16_t d_port; /* The port to listen on (in network byte order) */ - sa_family_t d_family; /* Address family */ + uint16_t d_port; /* The port to listen on (in network byte order) */ + sa_family_t d_family; /* Address family */ - /* These fields describe the priority of each thread created by the Telnet + /* These fields describe the priority of each task created by the Telnet * daemon. */ - uint8_t t_priority; /* The execution priority of the spawned task, */ - size_t t_stacksize; /* The stack size needed by the spawned task */ - main_t t_entry; /* The entrypoint of the task to spawn when a new - * connection is accepted. */ + uint8_t t_priority; /* The execution priority of the spawned task, */ + size_t t_stacksize; /* The stack size needed by the spawned task */ +#ifndef CONFIG_BUILD_KERNEL + main_t t_entry; /* The entrypoint of the task to spawn when a new + * connection is accepted. */ +#endif +#ifdef CONFIG_LIBC_EXECFUNCS + FAR const char *t_path; /* The binary path of the task to spawn when a new + * connection is accepted. */ +#endif + FAR char * const *t_argv; /* The argument pass to the spawned task */ }; /**************************************************************************** @@ -78,10 +72,10 @@ extern "C" #endif /**************************************************************************** - * Name: telnetd_start + * Name: telnetd_daemon * * Description: - * Start the Telnet daemon. + * Run the Telnet daemon loop. * * Parameters: * config A pointer to a configuration structure that characterizes the @@ -90,13 +84,11 @@ extern "C" * daemon. * * Return: - * The process ID (pid) of the new Telnet daemon is returned on - * success; A negated errno is returned if the daemon was not successfully - * started. + * A negated errno is returned if the daemon was not successfully started. * ****************************************************************************/ -int telnetd_start(FAR struct telnetd_config_s *config); +int telnetd_daemon(FAR const struct telnetd_config_s *config); #undef EXTERN #ifdef __cplusplus diff --git a/netutils/telnetd/Kconfig b/netutils/telnetd/Kconfig index eff726523..896bbd62f 100644 --- a/netutils/telnetd/Kconfig +++ b/netutils/telnetd/Kconfig @@ -10,6 +10,3 @@ config NETUTILS_TELNETD select NETDEV_TELNET ---help--- Enable support for the Telnet daemon. - -if NETUTILS_TELNETD -endif diff --git a/netutils/telnetd/Makefile b/netutils/telnetd/Makefile index 201cefca5..9eab6856e 100644 --- a/netutils/telnetd/Makefile +++ b/netutils/telnetd/Makefile @@ -22,8 +22,6 @@ include $(APPDIR)/Make.defs # Telnet daemon -ifeq ($(CONFIG_NET_TCP),y) CSRCS = telnetd_daemon.c -endif include $(APPDIR)/Application.mk diff --git a/netutils/telnetd/telnetd_daemon.c b/netutils/telnetd/telnetd_daemon.c index 5a5d9b35f..8d544b52d 100644 --- a/netutils/telnetd/telnetd_daemon.c +++ b/netutils/telnetd/telnetd_daemon.c @@ -24,52 +24,24 @@ #include <nuttx/config.h> -#include <sys/types.h> #include <sys/socket.h> #include <sys/ioctl.h> -#include <inttypes.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> #include <unistd.h> #include <fcntl.h> -#include <string.h> #include <signal.h> -#include <semaphore.h> #include <sched.h> -#include <assert.h> +#include <spawn.h> #include <errno.h> #include <debug.h> -#include <netinet/in.h> -#include <arpa/inet.h> - #include <nuttx/net/telnet.h> #include "netutils/telnetd.h" #include "netutils/netlib.h" /**************************************************************************** - * Private Types - ****************************************************************************/ - -/* This structure represents the overall state of one telnet daemon instance - * (Yes, multiple telnet daemons are supported). - */ - -struct telnetd_s -{ - uint16_t port; /* The port to listen on (in network byte order) */ - sa_family_t family; /* Address family */ - uint8_t priority; /* The execution priority of the spawned task, */ - size_t stacksize; /* The stack size needed by the spawned task */ - main_t entry; /* The entrypoint of the task to spawn when a new - * connection is accepted. */ -}; - -/**************************************************************************** - * Private Functions + * Public Functions ****************************************************************************/ /**************************************************************************** @@ -87,11 +59,8 @@ struct telnetd_s * ****************************************************************************/ -static int telnetd_daemon(int argc, FAR char *argv[]) +int telnetd_daemon(FAR const struct telnetd_config_s *config) { - UNUSED(argc); - - FAR struct telnetd_s *daemon; union { struct sockaddr generic; @@ -103,29 +72,16 @@ static int telnetd_daemon(int argc, FAR char *argv[]) #endif } addr; - struct telnet_session_s session; -#ifdef CONFIG_NET_SOLINGER - struct linger ling; -#endif #ifdef CONFIG_SCHED_HAVE_PARENT struct sigaction sa; sigset_t blockset; #endif socklen_t addrlen; - pid_t pid; int listensd; int acceptsd; - int drvrfd; #ifdef CONFIG_NET_SOCKOPTS int optval; #endif - int ret; - int fd; - - /* Get daemon startup info */ - - daemon = (FAR struct telnetd_s *)((uintptr_t)strtoul(argv[1], NULL, 0)); - DEBUGASSERT(daemon != NULL); #ifdef CONFIG_SCHED_HAVE_PARENT /* Call sigaction with the SA_NOCLDWAIT flag so that we do not transform @@ -143,7 +99,7 @@ static int telnetd_daemon(int argc, FAR char *argv[]) if (sigaction(SIGCHLD, &sa, NULL) < 0) { nerr("ERROR: sigaction failed: %d\n", errno); - goto errout_with_daemon; + goto errout; } /* Block receipt of the SIGCHLD signal */ @@ -153,18 +109,18 @@ static int telnetd_daemon(int argc, FAR char *argv[]) if (sigprocmask(SIG_BLOCK, &blockset, NULL) < 0) { nerr("ERROR: sigprocmask failed: %d\n", errno); - goto errout_with_daemon; + goto errout; } #endif /* CONFIG_SCHED_HAVE_PARENT */ /* Create a new TCP socket to use to listen for connections */ - listensd = socket(daemon->family, SOCK_STREAM | SOCK_CLOEXEC, 0); + listensd = socket(config->d_family, SOCK_STREAM | SOCK_CLOEXEC, 0); if (listensd < 0) { nerr("ERROR: socket() failed for family %u: %d\n", - daemon->family, errno); - goto errout_with_daemon; + config->d_family, errno); + goto errout; } #ifdef CONFIG_NET_SOCKOPTS @@ -172,7 +128,7 @@ static int telnetd_daemon(int argc, FAR char *argv[]) optval = 1; if (setsockopt(listensd, SOL_SOCKET, SO_REUSEADDR, - (FAR void *)&optval, sizeof(int)) < 0) + &optval, sizeof(int)) < 0) { nerr("ERROR: setsockopt SO_REUSEADDR failure: %d\n", errno); goto errout_with_socket; @@ -182,20 +138,20 @@ static int telnetd_daemon(int argc, FAR char *argv[]) /* Bind the socket to a local address */ #ifdef CONFIG_NET_IPv4 - if (daemon->family == AF_INET) + if (config->d_family == AF_INET) { addr.ipv4.sin_family = AF_INET; - addr.ipv4.sin_port = daemon->port; + addr.ipv4.sin_port = config->d_port; addr.ipv4.sin_addr.s_addr = INADDR_ANY; addrlen = sizeof(struct sockaddr_in); } else #endif #ifdef CONFIG_NET_IPv6 - if (daemon->family == AF_INET6) + if (config->d_family == AF_INET6) { addr.ipv6.sin6_family = AF_INET6; - addr.ipv6.sin6_port = daemon->port; + addr.ipv6.sin6_port = config->d_port; addrlen = sizeof(struct sockaddr_in6); memset(addr.ipv6.sin6_addr.s6_addr, 0, @@ -204,7 +160,7 @@ static int telnetd_daemon(int argc, FAR char *argv[]) else #endif { - nerr("ERROR: Unsupported address family: %u", daemon->family); + nerr("ERROR: Unsupported address family: %u", config->d_family); goto errout_with_socket; } @@ -222,24 +178,26 @@ static int telnetd_daemon(int argc, FAR char *argv[]) goto errout_with_socket; } - /* Now go silent. */ - -#ifndef CONFIG_DEBUG_FEATURES - close(0); - close(1); - close(2); -#endif - /* Begin accepting connections */ for (; ; ) { - socklen_t accptlen; + struct telnet_session_s session; +#ifdef CONFIG_NET_SOLINGER + struct linger ling; +#endif + int drvrfd; - ninfo("Accepting connections on port %d\n", ntohs(daemon->port)); + /* Now go silent. */ - accptlen = sizeof(addr); - acceptsd = accept(listensd, &addr.generic, &accptlen); + close(0); + close(1); + close(2); + + ninfo("Accepting connections on port %d\n", ntohs(config->d_port)); + + addrlen = sizeof(addr); + acceptsd = accept(listensd, &addr.generic, &addrlen); if (acceptsd < 0) { /* Just continue if a signal was received */ @@ -272,8 +230,8 @@ static int telnetd_daemon(int argc, FAR char *argv[]) /* Open the Telnet factory */ - fd = open("/dev/telnet", O_RDONLY); - if (fd < 0) + drvrfd = open("/dev/telnet", O_RDONLY); + if (drvrfd < 0) { nerr("ERROR: open(/dev/telnet) failed: %d\n", errno); goto errout_with_acceptsd; @@ -286,15 +244,16 @@ static int telnetd_daemon(int argc, FAR char *argv[]) session.ts_sd = acceptsd; session.ts_devpath[0] = '\0'; - ret = ioctl(fd, SIOCTELNET, (unsigned long)((uintptr_t)&session)); - close(fd); - - if (ret < 0) + if (ioctl(drvrfd, SIOCTELNET, + (unsigned long)((uintptr_t)&session)) < 0) { nerr("ERROR: open(/dev/telnet) failed: %d\n", errno); + close(drvrfd); goto errout_with_acceptsd; } + close(drvrfd); + /* Open the driver */ ninfo("Opening the telnet driver at %s\n", session.ts_devpath); @@ -323,19 +282,46 @@ static int telnetd_daemon(int argc, FAR char *argv[]) */ ninfo("Starting the telnet session\n"); - pid = task_create("Telnet session", daemon->priority, - daemon->stacksize, daemon->entry, NULL); - if (pid < 0) + +#ifndef CONFIG_BUILD_KERNEL + if (config->t_entry) { - nerr("ERROR: Failed start the telnet session: %d\n", errno); - goto errout_with_socket; + pid_t pid = task_create("Telnet session", + config->t_priority, config->t_stacksize, + config->t_entry, NULL); + if (pid >= 0) + { + continue; + } } +#endif - /* Forget about the connection. */ - - close(0); - close(1); - close(2); +#ifdef CONFIG_LIBC_EXECFUNCS + if (config->t_path) + { + struct sched_param param; + posix_spawnattr_t attr; + pid_t pid; + int ret; + + sched_getparam(0, ¶m); + param.sched_priority = config->t_priority; + + posix_spawnattr_init(&attr); + posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSCHEDPARAM); + posix_spawnattr_setschedparam(&attr, ¶m); + posix_spawnattr_setstacksize(&attr, config->t_stacksize); + + ret = posix_spawnp(&pid, config->t_path, NULL, + &attr, config->t_argv, NULL); + if (ret > 0) + { + nerr("ERROR: Failed start the telnet session: %d\n", ret); + errno = ret; + goto errout_with_socket; + } + } +#endif } errout_with_acceptsd: @@ -343,74 +329,6 @@ errout_with_acceptsd: errout_with_socket: close(listensd); -errout_with_daemon: - free(daemon); - return 1; -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: telnetd_start - * - * Description: - * Start the telnet daemon. - * - * Parameters: - * config A pointer to a configuration structure that characterizes the - * telnet daemon. This configuration structure may be defined - * on the caller's stack because it is not retained by the - * daemon. - * - * Return: - * The process ID (pid) of the new telnet daemon is returned on - * success; A negated errno is returned if the daemon was not successfully - * started. - * - ****************************************************************************/ - -int telnetd_start(FAR struct telnetd_config_s *config) -{ - FAR struct telnetd_s *daemon; - FAR char *argv[2]; - char arg0[sizeof("0x1234567812345678")]; - pid_t pid; - - /* Allocate a state structure for the new daemon */ - - daemon = (FAR struct telnetd_s *)malloc(sizeof(struct telnetd_s)); - if (!daemon) - { - return -ENOMEM; - } - - /* Initialize the daemon structure */ - - daemon->port = config->d_port; - daemon->family = config->d_family; - daemon->priority = config->t_priority; - daemon->stacksize = config->t_stacksize; - daemon->entry = config->t_entry; - - /* Then start the new daemon */ - - snprintf(arg0, sizeof(arg0), "0x%" PRIxPTR, (uintptr_t)daemon); - argv[0] = arg0; - argv[1] = NULL; - - pid = task_create("Telnet daemon", config->d_priority, config->d_stacksize, - telnetd_daemon, argv); - if (pid < 0) - { - int errval = errno; - free(daemon); - nerr("ERROR: Failed to start the telnet daemon: %d\n", errval); - return -errval; - } - - /* Return success */ - - return pid; +errout: + return errno; } diff --git a/nshlib/Kconfig b/nshlib/Kconfig index f3b914edf..98993e317 100644 --- a/nshlib/Kconfig +++ b/nshlib/Kconfig @@ -546,10 +546,6 @@ config NSH_DISABLE_TEST bool "Disable test" default DEFAULT_SMALL -config NSH_DISABLE_TELNETD - bool "Disable telnetd" - default DEFAULT_SMALL || NSH_NETLOCAL - config NSH_DISABLE_TRUNCATE bool "Disable truncate" default DEFAULT_SMALL @@ -1156,65 +1152,24 @@ endif # NSH_DISABLE_WGET endmenu # Networking Configuration" menu "Telnet Configuration" - depends on NETUTILS_TELNETD config NSH_TELNET bool "Use Telnet console" default !DEFAULT_SMALL - depends on NETUTILS_TELNETD + depends on SYSTEM_TELNETD ---help--- If NSH_TELNET is set to 'y', then a TELENET server front-end is selected. When this option is provided, you may log into NuttX remotely using telnet in order to access NSH. -if NSH_TELNET - -config NSH_TELNETD_PORT - int "Telnet port number" - default 23 - ---help--- - The telnet daemon will listen on this TCP port number for connections. - Default: 23 - -config NSH_TELNETD_DAEMONPRIO - int "Telnet daemon priority" - default 100 - ---help--- - Priority of the Telnet daemon. Default: 100 - -config NSH_TELNETD_DAEMONSTACKSIZE - int "Telnet daemon stack size" - default DEFAULT_TASK_STACKSIZE - ---help--- - Stack size allocated for the Telnet daemon. Default: 2048 - -config NSH_TELNETD_CLIENTPRIO - int "Telnet client priority" - default 100 - ---help--- - Priority of the Telnet client. Default: 100 - -config NSH_TELNETD_CLIENTSTACKSIZE - int "Telnet client stack size" - default DEFAULT_TASK_STACKSIZE - ---help--- - Stack size allocated for the Telnet client. Default: 2048 - -config NSH_IOBUFFER_SIZE - int "Telnet I/O buffer size" - default 512 - ---help--- - Determines the size of the I/O buffer to use for sending/ - receiving TELNET commands/responses. Default: 512 - config NSH_DISABLE_TELNETSTART bool "Disable to start telnetd" - default false + default DEFAULT_SMALL + depends on NSH_TELNET ---help--- Determines if the nsh starts telnetd automatically -endif # NSH_TELNET endmenu # Telnet Configuration config NSH_LOGIN diff --git a/nshlib/README.md b/nshlib/README.md index 8c52c7a99..efbc885cd 100644 --- a/nshlib/README.md +++ b/nshlib/README.md @@ -1343,7 +1343,7 @@ system image. `nsh_telnetstart()` or it may be started from the NSH command line using this `telnetd` command. - Normally this command would be suppressed with `CONFIG_NSH_DISABLE_TELNETD` + Normally this command would be suppressed without `CONFIG_SYSTEM_TELNETD` because the Telnet daemon is automatically started in `nsh_main.c`. The exception is when `CONFIG_NETINIT_NETLOCAL` is selected. IN that case, the network is not enabled at initialization but rather must be enabled from the @@ -1618,7 +1618,7 @@ shutdown | `CONFIG_BOARDCTL_POWEROFF` || `CONFIG_BOARDCTL_RESET` sleep | - source | `CONFIG_FILE_STREAM` && !`CONFIG_NSH_DISABLESCRIPT` test | !`CONFIG_NSH_DISABLESCRIPT` -telnetd | `CONFIG_NSH_TELNET` && !`CONFIG_NSH_DISABLE_TELNETD` +telnetd | `CONFIG_NSH_TELNET` && `CONFIG_SYSTEM_TELNETD` time | - truncate | !`CONFIG_DISABLE_MOUNTPOINT` umount | !`CONFIG_DISABLE_MOUNTPOINT` @@ -1915,16 +1915,16 @@ The behavior of NSH can be modified with the following settings in the If Telnet is selected for the NSH console, then we must configure the resources used by the Telnet daemon and by the Telnet clients. -- `CONFIG_NSH_TELNETD_PORT` – The telnet daemon will listen on this TCP port +- `CONFIG_SYSTEM_TELNETD_PORT` – The telnet daemon will listen on this TCP port number for connections. Default: `23` -- `CONFIG_NSH_TELNETD_DAEMONPRIO` – Priority of the Telnet daemon. Default: +- `CONFIG_SYSTEM_TELNETD_PRIORITY` – Priority of the Telnet daemon. Default: `SCHED_PRIORITY_DEFAULT` -- `CONFIG_NSH_TELNETD_DAEMONSTACKSIZE` – Stack size allocated for the Telnet +- `CONFIG_SYSTEM_TELNETD_STACKSIZE` – Stack size allocated for the Telnet daemon. Default: `2048` -- `CONFIG_NSH_TELNETD_CLIENTPRIO` – Priority of the Telnet client. Default: +- `CONFIG_SYSTEM_TELNETD_SESSION_PRIORITY` – Priority of the Telnet client. Default: `SCHED_PRIORITY_DEFAULT` -- `CONFIG_NSH_TELNETD_CLIENTSTACKSIZE` – Stack size allocated for the Telnet - client. Default: `2048` +- `CONFIG_SYSTEM_TELNETD_SESSION_STACKSIZE` – Stack size allocated for the Telnet + client. Default: `3072` One or both of CONFIG_NSH_CONSOLE and `CONFIG_NSH_TELNET` must be defined. If `CONFIG_NSH_TELNET` is selected, then there some other configuration settings @@ -1933,8 +1933,6 @@ that apply: - `CONFIG_NET=y` – Of course, networking must be enabled - `CONFIG_NET_TCP=y` – TCP/IP support is required for telnet (as well as various other TCP-related configuration settings). -- `CONFIG_NSH_IOBUFFER_SIZE` – Determines the size of the I/O buffer to use for - sending/ receiving TELNET commands/responses. - `CONFIG_NETINIT_DHCPC` – Obtain the IP address via DHCP. - `CONFIG_NETINIT_IPADDR` – If `CONFIG_NETINIT_DHCPC` is NOT set, then the static IP address must be provided. diff --git a/nshlib/nsh.h b/nshlib/nsh.h index 494887542..12aeb4604 100644 --- a/nshlib/nsh.h +++ b/nshlib/nsh.h @@ -264,16 +264,6 @@ /* If Telnet is selected for the NSH console, then we must configure * the resources used by the Telnet daemon and by the Telnet clients. * - * CONFIG_NSH_TELNETD_PORT - The telnet daemon will listen on this. - * port. Default: 23 - * CONFIG_NSH_TELNETD_DAEMONPRIO - Priority of the Telnet daemon. - * Default: SCHED_PRIORITY_DEFAULT - * CONFIG_NSH_TELNETD_DAEMONSTACKSIZE - Stack size allocated for the - * Telnet daemon. Default: 2048 - * CONFIG_NSH_TELNETD_CLIENTPRIO - Priority of the Telnet client. - * Default: SCHED_PRIORITY_DEFAULT - * CONFIG_NSH_TELNETD_CLIENTSTACKSIZE - Stack size allocated for the - * Telnet client. Default: 2048 * CONFIG_NSH_TELNET_LOGIN - Support a simple Telnet login. * * If CONFIG_NSH_TELNET_LOGIN is defined, then these additional @@ -285,26 +275,6 @@ * Default 3. */ -#ifndef CONFIG_NSH_TELNETD_PORT -# define CONFIG_NSH_TELNETD_PORT 23 -#endif - -#ifndef CONFIG_NSH_TELNETD_DAEMONPRIO -# define CONFIG_NSH_TELNETD_DAEMONPRIO SCHED_PRIORITY_DEFAULT -#endif - -#ifndef CONFIG_NSH_TELNETD_DAEMONSTACKSIZE -# define CONFIG_NSH_TELNETD_DAEMONSTACKSIZE 2048 -#endif - -#ifndef CONFIG_NSH_TELNETD_CLIENTPRIO -# define CONFIG_NSH_TELNETD_CLIENTPRIO SCHED_PRIORITY_DEFAULT -#endif - -#ifndef CONFIG_NSH_TELNETD_CLIENTSTACKSIZE -# define CONFIG_NSH_TELNETD_CLIENTSTACKSIZE 2048 -#endif - #ifdef CONFIG_NSH_TELNET_LOGIN # ifndef CONFIG_NSH_LOGIN_USERNAME @@ -447,12 +417,6 @@ # define CONFIG_NSH_LINELEN 80 #endif -/* The following two settings are used only in the telnetd interface */ - -#ifndef CONFIG_NSH_IOBUFFER_SIZE -# define CONFIG_NSH_IOBUFFER_SIZE 512 -#endif - /* The maximum number of nested if-then[-else]-fi sequences that * are permissible. */ @@ -1152,11 +1116,6 @@ int cmd_irqinfo(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv); # ifndef CONFIG_NSH_DISABLE_ROUTE int cmd_route(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv); # endif -# if defined(CONFIG_NSH_TELNET) -# ifndef CONFIG_NSH_DISABLE_TELNETD - int cmd_telnetd(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv); -# endif -# endif #endif /* CONFIG_NET */ #if defined(CONFIG_LIBC_NETDB) && !defined(CONFIG_NSH_DISABLE_NSLOOKUP) diff --git a/nshlib/nsh_command.c b/nshlib/nsh_command.c index 189bad7b1..fa73d6b93 100644 --- a/nshlib/nsh_command.c +++ b/nshlib/nsh_command.c @@ -521,14 +521,6 @@ static const struct cmdmap_s g_cmdmap[] = { "test", cmd_test, 3, CONFIG_NSH_MAXARGUMENTS, "<expression>" }, #endif -#if defined(CONFIG_NSH_TELNET) && !defined(CONFIG_NSH_DISABLE_TELNETD) -#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) - {"telnetd", cmd_telnetd, 2, 2, "[ipv4|ipv6]" }, -#else - {"telnetd", cmd_telnetd, 1, 1, NULL }, -#endif -#endif - #ifndef CONFIG_NSH_DISABLE_TIME { "time", cmd_time, 2, 2, "\"<command>\"" }, #endif diff --git a/nshlib/nsh_telnetd.c b/nshlib/nsh_telnetd.c index a773b3ec9..371993474 100644 --- a/nshlib/nsh_telnetd.c +++ b/nshlib/nsh_telnetd.c @@ -24,39 +24,16 @@ #include <nuttx/config.h> -#include <stdio.h> -#include <string.h> #include <assert.h> #include <debug.h> -#include <arpa/inet.h> - -#include "netutils/telnetd.h" - -#ifdef CONFIG_TELNET_CHARACTER_MODE -#ifdef CONFIG_NSH_CLE -# include "system/cle.h" -#else -# include "system/readline.h" -#endif -#endif +#include <sys/socket.h> #include "nsh.h" #include "nsh_console.h" #ifdef CONFIG_NSH_TELNET -/**************************************************************************** - * Private Types - ****************************************************************************/ - -enum telnetd_state_e -{ - TELNETD_NOTRUNNING = 0, - TELNETD_STARTED, - TELNETD_RUNNING -}; - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -107,123 +84,43 @@ int nsh_telnetmain(int argc, FAR char *argv[]) #ifndef CONFIG_NSH_DISABLE_TELNETSTART int nsh_telnetstart(sa_family_t family) { - static enum telnetd_state_e state = TELNETD_NOTRUNNING; - int ret = OK; - - if (state == TELNETD_NOTRUNNING) - { - struct telnetd_config_s config; - - /* There is a tiny race condition here if two tasks were to try to - * start the Telnet daemon concurrently. - */ - - state = TELNETD_STARTED; - - /* Configure the telnet daemon */ + FAR struct console_stdio_s *pstate = nsh_newconsole(false); + int ret; - config.d_port = HTONS(CONFIG_NSH_TELNETD_PORT); - config.d_priority = CONFIG_NSH_TELNETD_DAEMONPRIO; - config.d_stacksize = CONFIG_NSH_TELNETD_DAEMONSTACKSIZE; - config.t_priority = CONFIG_NSH_TELNETD_CLIENTPRIO; - config.t_stacksize = CONFIG_NSH_TELNETD_CLIENTSTACKSIZE; - config.t_entry = nsh_telnetmain; + DEBUGASSERT(pstate != NULL); - /* Start the telnet daemon */ + /* Start the telnet daemon */ - ninfo("Starting the Telnet daemon\n"); + ninfo("Starting the Telnet daemon\n"); #ifdef CONFIG_NET_IPv4 - if (family == AF_UNSPEC || family == AF_INET) - { - config.d_family = AF_INET; - ret = telnetd_start(&config); - if (ret < 0) - { - _err("ERROR: Failed to start the Telnet IPv4 daemon: %d\n", - ret); - } - else - { - state = TELNETD_RUNNING; - } - } + if (family == AF_INET) + { + char cmdline[] = CONFIG_SYSTEM_TELNETD_PROGNAME " -4 &"; + ret = nsh_parse(&pstate->cn_vtbl, cmdline); + } + else #endif - #ifdef CONFIG_NET_IPv6 - if (family == AF_UNSPEC || family == AF_INET6) - { - config.d_family = AF_INET6; - ret = telnetd_start(&config); - if (ret < 0) - { - _err("ERROR: Failed to start the Telnet IPv6 daemon: %d\n", - ret); - } - else - { - state = TELNETD_RUNNING; - } - } -#endif - - if (state == TELNETD_STARTED) - { - state = TELNETD_NOTRUNNING; - } + if (family == AF_INET6) + { + char cmdline[] = CONFIG_SYSTEM_TELNETD_PROGNAME " -6 &"; + ret = nsh_parse(&pstate->cn_vtbl, cmdline); } - - return ret; -} + else #endif + { + char cmdline[] = CONFIG_SYSTEM_TELNETD_PROGNAME " &"; + ret = nsh_parse(&pstate->cn_vtbl, cmdline); + } -/**************************************************************************** - * Name: cmd_telnetd - * - * Description: - * The Telnet daemon may be started either programmatically by calling - * nsh_telnetstart() or it may be started from the NSH command line using - * this telnetd command. - * - * This command would be suppressed with CONFIG_NSH_DISABLE_TELNETD - * normally because the Telnet daemon is automatically started in - * nsh_main.c. The exception is when CONFIG_NETINIT_NETLOCAL is selected. - * IN that case, the network is not enabled at initialization but rather - * must be enabled from the NSH command line or via other applications. - * - * In that case, calling nsh_telnetstart() before the the network is - * initialized will fail. - * - * Input Parameters: - * None. All of the properties of the Telnet daemon are controlled by - * NuttX configuration setting. - * - * Returned Values: - * OK is returned on success; ERROR is return on failure. - * - ****************************************************************************/ - -#ifndef CONFIG_NSH_DISABLE_TELNETD -int cmd_telnetd(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv) -{ - UNUSED(vtbl); - UNUSED(argc); - UNUSED(argv); - - sa_family_t family = AF_UNSPEC; - - /* If both IPv6 and IPv4 are enabled, then the address family must - * be specified on the command line. - */ - -#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) - if (argc >= 2) + if (ret < 0) { - family = (strcmp(argv[1], "ipv6") == 0) ? AF_INET6 : AF_INET; + nerr("ERROR: Failed to start the Telnet daemon: %d\n", ret); } -#endif - return nsh_telnetstart(family) < 0 ? ERROR : OK; + nsh_release(&pstate->cn_vtbl); + return ret; } #endif diff --git a/system/telnet/telnet_client.c b/system/telnet/telnet_client.c index 4ac2622d0..14ef9f923 100644 --- a/system/telnet/telnet_client.c +++ b/system/telnet/telnet_client.c @@ -77,8 +77,8 @@ * Pre-processor Definitions ****************************************************************************/ -#ifdef CONFIG_NSH_TELNETD_PORT -# define DEFAULT_PORT CONFIG_NSH_TELNETD_PORT +#ifdef CONFIG_SYSTEM_TELNETD_PORT +# define DEFAULT_PORT CONFIG_SYSTEM_TELNETD_PORT #else # define DEFAULT_PORT 23 #endif diff --git a/system/telnetd/Kconfig b/system/telnetd/Kconfig index 46eb2181e..bca37cb87 100644 --- a/system/telnetd/Kconfig +++ b/system/telnetd/Kconfig @@ -5,7 +5,7 @@ config SYSTEM_TELNETD tristate "Telnet daemon application" - default n + default !DEFAULT_SMALL depends on NETUTILS_TELNETD ---help--- Enable the Telnet daemon application @@ -28,6 +28,13 @@ config SYSTEM_TELNETD_STACKSIZE default DEFAULT_TASK_STACKSIZE depends on SYSTEM_TELNETD +config SYSTEM_TELNETD_PORT + int "Telnetd port number" + default 23 + ---help--- + The telnet daemon will listen on this TCP port number for connections. + Default: 23 + config SYSTEM_TELNETD_SESSION_PRIORITY int "Telnetd session task priority" default 100 diff --git a/system/telnetd/telnetd.c b/system/telnetd/telnetd.c index 674f94160..8f536f2eb 100644 --- a/system/telnetd/telnetd.c +++ b/system/telnetd/telnetd.c @@ -24,10 +24,12 @@ #include <stdio.h> #include <stdlib.h> -#include <string.h> +#include <unistd.h> + +#include <netinet/in.h> +#include <sys/socket.h> #include "netutils/telnetd.h" -#include "netutils/netlib.h" #include "nshlib/nshlib.h" /**************************************************************************** @@ -36,26 +38,62 @@ int main(int argc, FAR char *argv[]) { - FAR char *argv1[3]; - char arg0[sizeof("0x1234567812345678")]; - struct telnetd_s daemon; + FAR char *argv_[] = + { + CONFIG_SYSTEM_TELNETD_PROGNAME, + "-c", + NULL, + }; - /* Initialize the daemon structure */ + struct telnetd_config_s config = + { + HTONS(CONFIG_SYSTEM_TELNETD_PORT), +#ifdef CONFIG_NET_IPv4 + AF_INET, +#else + AF_INET6, +#endif + CONFIG_SYSTEM_TELNETD_SESSION_PRIORITY, + CONFIG_SYSTEM_TELNETD_SESSION_STACKSIZE, +#ifndef CONFIG_BUILD_KERNEL + nsh_telnetmain, +#endif +#ifdef CONFIG_LIBC_EXECFUNCS + CONFIG_SYSTEM_TELNETD_PROGNAME, +#endif + argv_, + }; - daemon.port = HTONS(23); - daemon.family = AF_INET; - daemon.entry = nsh_telnetmain; + int daemon = 1; + int opt; - /* NOTE: Settings for telnet session task */ + while ((opt = getopt(argc, argv, "46cp:")) != ERROR) + { + switch (opt) + { +#ifdef CONFIG_NET_IPv4 + case '4': + config.d_family = AF_INET; + break; +#endif +#ifdef CONFIG_NET_IPv6 + case '6': + config.d_family = AF_INET6; + break; +#endif + case 'c': + daemon = 0; + break; - daemon.priority = CONFIG_SYSTEM_TELNETD_SESSION_PRIORITY; - daemon.stacksize = CONFIG_SYSTEM_TELNETD_SESSION_STACKSIZE; + case 'p': + config.d_port = atoi(optarg); + break; - snprintf(arg0, sizeof(arg0), "0x%" PRIxPTR, (uintptr_t)&daemon); - argv1[0] = "telnetd"; - argv1[1] = arg0; - argv1[2] = NULL; + default: + fprintf(stderr, "Usage: %s [-4|-6] [-p port]\n", argv[0]); + exit(EXIT_FAILURE); + } + } - telnetd_daemon(2, argv1); - return 0; + return daemon ? telnetd_daemon(&config) : nsh_telnetmain(1, argv); }
