netutils: Support telnetd in the kernel mode

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
Signed-off-by: chao an <anchao@xiaomi.com>
This commit is contained in:
Xiang Xiao 2022-10-16 19:44:38 +08:00 committed by Masayuki Ishikawa
parent 12863fbd52
commit 36a0c924f7
14 changed files with 201 additions and 451 deletions

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -10,6 +10,3 @@ config NETUTILS_TELNETD
select NETDEV_TELNET
---help---
Enable support for the Telnet daemon.
if NETUTILS_TELNETD
endif

View File

@ -22,8 +22,6 @@ include $(APPDIR)/Make.defs
# Telnet daemon
ifeq ($(CONFIG_NET_TCP),y)
CSRCS = telnetd_daemon.c
endif
include $(APPDIR)/Application.mk

View File

@ -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. */
#ifdef CONFIG_LIBC_EXECFUNCS
if (config->t_path)
{
struct sched_param param;
posix_spawnattr_t attr;
pid_t pid;
int ret;
close(0);
close(1);
close(2);
sched_getparam(0, &param);
param.sched_priority = config->t_priority;
posix_spawnattr_init(&attr);
posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSCHEDPARAM);
posix_spawnattr_setschedparam(&attr, &param);
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;
}

View File

@ -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

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -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,124 +84,44 @@ 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;
FAR struct console_stdio_s *pstate = nsh_newconsole(false);
int ret;
if (state == TELNETD_NOTRUNNING)
{
struct telnetd_config_s config;
DEBUGASSERT(pstate != NULL);
/* There is a tiny race condition here if two tasks were to try to
* start the Telnet daemon concurrently.
*/
/* Start the telnet daemon */
state = TELNETD_STARTED;
/* Configure the telnet daemon */
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;
/* 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;
}
}
if (family == AF_INET6)
{
char cmdline[] = CONFIG_SYSTEM_TELNETD_PROGNAME " -6 &";
ret = nsh_parse(&pstate->cn_vtbl, cmdline);
}
else
#endif
if (state == TELNETD_STARTED)
{
state = TELNETD_NOTRUNNING;
}
{
char cmdline[] = CONFIG_SYSTEM_TELNETD_PROGNAME " &";
ret = nsh_parse(&pstate->cn_vtbl, cmdline);
}
if (ret < 0)
{
nerr("ERROR: Failed to start the Telnet daemon: %d\n", ret);
}
nsh_release(&pstate->cn_vtbl);
return ret;
}
#endif
/****************************************************************************
* 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)
{
family = (strcmp(argv[1], "ipv6") == 0) ? AF_INET6 : AF_INET;
}
#endif
return nsh_telnetstart(family) < 0 ? ERROR : OK;
}
#endif
#endif /* CONFIG_NSH_TELNET */

View File

@ -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

View File

@ -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

View File

@ -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);
}