forked from Imagelibrary/rtems
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:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user