telnetd: Remove CONFIGURE_MAXIMUM_PTYS

Add a rtems_telnetd_config_table::client_maximum member to the Telnet
configuration.

Close #3526.
Close #3528.
This commit is contained in:
Sebastian Huber
2018-09-26 09:04:43 +02:00
parent 2da93bcb73
commit a346ebba9c
3 changed files with 75 additions and 66 deletions

View File

@@ -155,24 +155,6 @@ extern rtems_initialization_tasks_table Initialization_tasks[];
const uint32_t rtems_libio_number_iops = RTEMS_ARRAY_SIZE(rtems_libio_iops); const uint32_t rtems_libio_number_iops = RTEMS_ARRAY_SIZE(rtems_libio_iops);
#endif #endif
/**
* This macro specifies the number of PTYs that can be concurrently
* active.
*/
#ifndef CONFIGURE_MAXIMUM_PTYS
#define CONFIGURE_MAXIMUM_PTYS 0
#endif
/**
* This variable contains the maximum number of PTYs that can be
* concurrently active.
*/
#ifdef CONFIGURE_INIT
int rtems_telnetd_maximum_ptys = CONFIGURE_MAXIMUM_PTYS;
#else
extern int rtems_telnetd_maximum_ptys;
#endif
#ifdef CONFIGURE_SMP_MAXIMUM_PROCESSORS #ifdef CONFIGURE_SMP_MAXIMUM_PROCESSORS
#warning "CONFIGURE_SMP_MAXIMUM_PROCESSORS has been renamed to CONFIGURE_MAXIMUM_PROCESSORS since RTEMS 5.1" #warning "CONFIGURE_SMP_MAXIMUM_PROCESSORS has been renamed to CONFIGURE_MAXIMUM_PROCESSORS since RTEMS 5.1"
#define CONFIGURE_MAXIMUM_PROCESSORS CONFIGURE_SMP_MAXIMUM_PROCESSORS #define CONFIGURE_MAXIMUM_PROCESSORS CONFIGURE_SMP_MAXIMUM_PROCESSORS
@@ -3474,6 +3456,10 @@ extern rtems_initialization_tasks_table Initialization_tasks[];
#warning "The CONFIGURE_MAXIMUM_POSIX_SPINLOCKS configuration option is obsolete since RTEMS 5.1" #warning "The CONFIGURE_MAXIMUM_POSIX_SPINLOCKS configuration option is obsolete since RTEMS 5.1"
#endif #endif
#ifdef CONFIGURE_MAXIMUM_PTYS
#warning "The CONFIGURE_MAXIMUM_PTYS configuration option is obsolete since RTEMS 5.1"
#endif
#ifdef CONFIGURE_TERMIOS_DISABLED #ifdef CONFIGURE_TERMIOS_DISABLED
#warning "The CONFIGURE_TERMIOS_DISABLED configuration option is obsolete since RTEMS 5.1" #warning "The CONFIGURE_TERMIOS_DISABLED configuration option is obsolete since RTEMS 5.1"
#endif #endif

View File

@@ -85,6 +85,14 @@ typedef struct {
* create other tasks for the shell which listen on sockets. * create other tasks for the shell which listen on sockets.
*/ */
bool keep_stdio; bool keep_stdio;
/**
* @brief Maximum number of clients which can connect to the system at a
* time.
*
* Use 0 for the default value.
*/
uint16_t client_maximum;
} rtems_telnetd_config_table; } rtems_telnetd_config_table;
/** /**

View File

@@ -62,11 +62,17 @@
#define PARANOIA #define PARANOIA
typedef struct telnetd_context telnetd_context;
struct shell_args { struct shell_args {
rtems_pty_context pty; rtems_pty_context pty;
void *arg;
char peername[16]; char peername[16];
char delete_myself; telnetd_context *ctx;
};
struct telnetd_context {
rtems_telnetd_config_table config;
uint16_t active_clients;
}; };
typedef union uni_sa { typedef union uni_sa {
@@ -85,7 +91,7 @@ rtems_id telnetd_dflt_spawn(
); );
/***********************************************************/ /***********************************************************/
static rtems_telnetd_config_table *telnetd_config; static telnetd_context telnetd_instance;
/* /*
* chrisj: this variable was global and with no declared interface in a header * chrisj: this variable was global and with no declared interface in a header
@@ -102,33 +108,39 @@ static const rtems_id (*telnetd_spawn_task)(
) = telnetd_dflt_spawn; ) = telnetd_dflt_spawn;
static struct shell_args *grab_a_Connection( static struct shell_args *grab_a_Connection(
telnetd_context *ctx,
int des_socket, int des_socket,
uni_sa *srv, uni_sa *srv,
char *peername, char *peername,
int sz int sz
) )
{ {
struct shell_args *args = NULL; struct shell_args *args;
socklen_t size_adr = sizeof(srv->sin); socklen_t size_adr = sizeof(srv->sin);
int acp_sock; int acp_sock;
if (ctx->active_clients >= ctx->config.client_maximum) {
return NULL;
}
args = malloc(sizeof(*args)); args = malloc(sizeof(*args));
if (args == NULL) { if (args == NULL) {
perror("telnetd:malloc"); perror("telnetd:malloc");
goto bailout; return NULL;
} }
acp_sock = accept(des_socket,&srv->sa,&size_adr); acp_sock = accept(des_socket,&srv->sa,&size_adr);
if (acp_sock<0) { if (acp_sock<0) {
perror("telnetd:accept"); perror("telnetd:accept");
goto bailout; free(args);
return NULL;
}; };
if (telnet_get_pty(&args->pty, acp_sock) == NULL) { if (telnet_get_pty(&args->pty, acp_sock) == NULL) {
syslog( LOG_DAEMON | LOG_ERR, "telnetd: unable to obtain PTY"); syslog( LOG_DAEMON | LOG_ERR, "telnetd: unable to obtain PTY");
/* NOTE: failing 'do_get_pty()' closed the socket */ /* NOTE: failing 'do_get_pty()' closed the socket */
goto bailout; free(args);
return NULL;
} }
if (sockpeername(acp_sock, peername, sz)) if (sockpeername(acp_sock, peername, sz))
@@ -141,13 +153,14 @@ static struct shell_args *grab_a_Connection(
args->pty.name); args->pty.name);
#endif #endif
bailout: ++ctx->active_clients;
args->ctx = ctx;
return args; return args;
} }
static void release_a_Connection(char *devname, char *peername, FILE **pstd, int n) static void release_a_Connection(telnetd_context *ctx, const char *devname,
const char *peername, FILE **pstd, int n)
{ {
#ifdef PARANOIA #ifdef PARANOIA
@@ -157,6 +170,8 @@ static void release_a_Connection(char *devname, char *peername, FILE **pstd, int
devname ); devname );
#endif #endif
--ctx->active_clients;
while (--n>=0) while (--n>=0)
if (pstd[n]) fclose(pstd[n]); if (pstd[n]) fclose(pstd[n]);
@@ -192,6 +207,7 @@ rtems_task_telnetd(void *task_argument)
int size_adr; int size_adr;
struct shell_args *arg = NULL; struct shell_args *arg = NULL;
rtems_id task_id; rtems_id task_id;
telnetd_context *ctx = task_argument;
if ((des_socket=socket(PF_INET,SOCK_STREAM,0))<0) { if ((des_socket=socket(PF_INET,SOCK_STREAM,0))<0) {
perror("telnetd:socket"); perror("telnetd:socket");
@@ -218,21 +234,21 @@ rtems_task_telnetd(void *task_argument)
* was started from the console anyway .. * was started from the console anyway ..
*/ */
do { do {
if (telnetd_config->keep_stdio) { if (ctx->config.keep_stdio) {
bool start = true; bool start = true;
char device_name [32]; char device_name [32];
ttyname_r( 1, device_name, sizeof( device_name)); ttyname_r( 1, device_name, sizeof( device_name));
if (telnetd_config->login_check != NULL) { if (ctx->config.login_check != NULL) {
start = rtems_shell_login_prompt( start = rtems_shell_login_prompt(
stdin, stdin,
stderr, stderr,
device_name, device_name,
telnetd_config->login_check ctx->config.login_check
); );
} }
if (start) { if (start) {
telnetd_config->command( device_name, arg->arg); ctx->config.command( device_name, ctx->config.arg);
} else { } else {
syslog( syslog(
LOG_AUTHPRIV | LOG_WARNING, LOG_AUTHPRIV | LOG_WARNING,
@@ -241,7 +257,8 @@ rtems_task_telnetd(void *task_argument)
); );
} }
} else { } else {
arg = grab_a_Connection(des_socket, &srv, peername, sizeof(peername)); arg = grab_a_Connection(ctx, des_socket, &srv, peername,
sizeof(peername));
if (arg == NULL) { if (arg == NULL) {
/* if something went wrong, sleep for some time */ /* if something went wrong, sleep for some time */
@@ -249,13 +266,12 @@ rtems_task_telnetd(void *task_argument)
continue; continue;
} }
arg->arg = telnetd_config->arg;
strncpy(arg->peername, peername, sizeof(arg->peername)); strncpy(arg->peername, peername, sizeof(arg->peername));
task_id = telnetd_spawn_task( task_id = telnetd_spawn_task(
arg->pty.name, arg->pty.name,
telnetd_config->priority, ctx->config.priority,
telnetd_config->stack_size, ctx->config.stack_size,
spawned_shell, spawned_shell,
arg arg
); );
@@ -275,7 +291,7 @@ rtems_task_telnetd(void *task_argument)
if ( !(dummy=fopen(arg->pty.name,"r+")) ) if ( !(dummy=fopen(arg->pty.name,"r+")) )
perror("Unable to dummy open the pty, losing a slot :-("); perror("Unable to dummy open the pty, losing a slot :-(");
release_a_Connection(arg->pty.name, peername, &dummy, 1); release_a_Connection(ctx, arg->pty.name, peername, &dummy, 1);
free(arg); free(arg);
sleep(2); /* don't accept connections too fast */ sleep(2); /* don't accept connections too fast */
} }
@@ -293,62 +309,60 @@ rtems_task_telnetd(void *task_argument)
rtems_status_code rtems_telnetd_start(const rtems_telnetd_config_table* config) rtems_status_code rtems_telnetd_start(const rtems_telnetd_config_table* config)
{ {
telnetd_context *ctx = &telnetd_instance;
rtems_id task_id; rtems_id task_id;
if (telnetd_config != NULL) {
fprintf(stderr, "telnetd already started\n");
return RTEMS_RESOURCE_IN_USE;
}
if (config->command == NULL) { if (config->command == NULL) {
fprintf(stderr, "telnetd setup with invalid command\n"); fprintf(stderr, "telnetd setup with invalid command\n");
return RTEMS_IO_ERROR; return RTEMS_IO_ERROR;
} }
telnetd_config = calloc(1, sizeof(*telnetd_config)); if (ctx->config.command != NULL) {
if (telnetd_config == NULL) { fprintf(stderr, "telnetd already started\n");
fprintf(stderr, "telnetd cannot alloc telnetd config table\n"); return RTEMS_RESOURCE_IN_USE;
return RTEMS_NO_MEMORY;
} }
*telnetd_config = *config; ctx->config = *config;
/* Check priority */ /* Check priority */
#ifdef RTEMS_NETWORKING #ifdef RTEMS_NETWORKING
if (telnetd_config->priority <= 0) { if (ctx->config.priority == 0) {
telnetd_config->priority = rtems_bsdnet_config.network_task_priority; ctx->config.priority = rtems_bsdnet_config.network_task_priority;
} }
#endif #endif
if (telnetd_config->priority < 2) { if (ctx->config.priority == 0) {
telnetd_config->priority = 100; ctx->config.priority = 100;
} }
/* Check stack size */ /* Check stack size */
if (telnetd_config->stack_size <= 0) { if (ctx->config.stack_size == 0) {
telnetd_config->stack_size = (size_t)32 * 1024; ctx->config.stack_size = (size_t)32 * 1024;
}
if (ctx->config.client_maximum == 0) {
ctx->config.client_maximum = 5;
} }
/* Spawn task */ /* Spawn task */
task_id = telnetd_spawn_task( task_id = telnetd_spawn_task(
"TNTD", "TNTD",
telnetd_config->priority, ctx->config.priority,
telnetd_config->stack_size, ctx->config.stack_size,
rtems_task_telnetd, rtems_task_telnetd,
0 ctx
); );
if (task_id == RTEMS_ID_NONE) { if (task_id == RTEMS_ID_NONE) {
free(telnetd_config); ctx->config.command = NULL;
telnetd_config = NULL;
return RTEMS_IO_ERROR; return RTEMS_IO_ERROR;
} }
/* Print status */ /* Print status */
if (!telnetd_config->keep_stdio) { if (!ctx->config.keep_stdio) {
fprintf( fprintf(
stderr, stderr,
"telnetd started with stacksize = %u and priority = %d\n", "telnetd started with stacksize = %u and priority = %d\n",
(unsigned) telnetd_config->stack_size, (unsigned) ctx->config.stack_size,
(unsigned) telnetd_config->priority (unsigned) ctx->config.priority
); );
} }
@@ -364,6 +378,7 @@ spawned_shell(void *targ)
FILE *ostd[3]={ stdin, stdout, stderr }; FILE *ostd[3]={ stdin, stdout, stderr };
int i=0; int i=0;
struct shell_args *arg = targ; struct shell_args *arg = targ;
telnetd_context *ctx = arg->ctx;
bool login_failed = false; bool login_failed = false;
bool start = true; bool start = true;
@@ -395,17 +410,17 @@ spawned_shell(void *targ)
stderr = nstd[2]; stderr = nstd[2];
/* call their routine */ /* call their routine */
if (telnetd_config->login_check != NULL) { if (ctx->config.login_check != NULL) {
start = rtems_shell_login_prompt( start = rtems_shell_login_prompt(
stdin, stdin,
stderr, stderr,
arg->pty.name, arg->pty.name,
telnetd_config->login_check ctx->config.login_check
); );
login_failed = !start; login_failed = !start;
} }
if (start) { if (start) {
telnetd_config->command( arg->pty.name, arg->arg); ctx->config.command( arg->pty.name, ctx->config.arg);
} }
stdin = ostd[0]; stdin = ostd[0];
@@ -421,7 +436,7 @@ spawned_shell(void *targ)
} }
cleanup: cleanup:
release_a_Connection(arg->pty.name, arg->peername, nstd, i); release_a_Connection(ctx, arg->pty.name, arg->peername, nstd, i);
free(arg); free(arg);
} }