diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-30 11:07:05 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-30 13:42:18 +0200 |
commit | 443a058db4ee8032221da84823f39f411796ff63 (patch) | |
tree | db5850817d66462ff2f869dfb19c0f0840282cc8 /rtemsbsd/telnetd/telnetd.c | |
parent | Add DHCP clientid to test default network init (diff) | |
download | rtems-libbsd-443a058db4ee8032221da84823f39f411796ff63.tar.bz2 |
Use network services from RTEMS
Close #3419.
Diffstat (limited to '')
-rw-r--r-- | rtemsbsd/telnetd/telnetd.c | 517 |
1 files changed, 0 insertions, 517 deletions
diff --git a/rtemsbsd/telnetd/telnetd.c b/rtemsbsd/telnetd/telnetd.c deleted file mode 100644 index 7fe603fa..00000000 --- a/rtemsbsd/telnetd/telnetd.c +++ /dev/null @@ -1,517 +0,0 @@ -/***********************************************************/ -/* - * - * The telnet DAEMON - * - * Author: 17,may 2001 - * - * WORK: fernando.ruiz@ctv.es - * HOME: correo@fernando-ruiz.com - * - * After start the net you can start this daemon. - * It uses the previously inited pseudo-terminales (pty.c) - * getting a new terminal with getpty(). This function - * gives a terminal name passing a opened socket like parameter. - * - * With register_telnetd() you add a new command in the shell to start - * this daemon interactively. (Login in /dev/console of course) - * - * Sorry but OOB is not still implemented. (This is the first version) - * - * Till Straumann <strauman@slac.stanford.edu> - * - made the 'shell' interface more generic, i.e. it is now - * possible to have 'telnetd' run an arbitrary 'shell' - * program. - * - * Copyright (c) 2009 embedded brains GmbH and others. - * - * embedded brains GmbH - * Obere Lagerstr. 30 - * D-82178 Puchheim - * Germany - * <rtems@embedded-brains.de> - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <rtems.h> -#include <rtems/error.h> -#include <rtems/pty.h> -#include <rtems/shell.h> -#include <rtems/telnetd.h> -#include <rtems/bspIo.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <syslog.h> - -#include <rtems/userenv.h> -#include <rtems/error.h> -#include <rtems/rtems_bsdnet.h> - -#define PARANOIA - -extern char *telnet_get_pty(int socket); -extern int telnet_pty_initialize(void); - -struct shell_args { - char *devname; - void *arg; - char peername[16]; - char delete_myself; -}; - -typedef union uni_sa { - struct sockaddr_in sin; - struct sockaddr sa; -} uni_sa; - -static int sockpeername(int sock, char *buf, int bufsz); - -rtems_id telnetd_dflt_spawn( - const char *name, - unsigned priority, - unsigned stackSize, - void (*fn)(void*), - void *fnarg -); - -/***********************************************************/ -static rtems_telnetd_config_table* telnetd_config; -static rtems_id telnetd_task_id; - -/* - * chrisj: this variable was global and with no declared interface in a header - * file and with no means to set it so I have stopped it being global; - * if this breaks any user they will have be to provide a formal - * interface to get this change reverted. - */ -static const rtems_id (*telnetd_spawn_task)( - const char *, - unsigned, - unsigned, - void (*)(void*), - void * -) = telnetd_dflt_spawn; - -static char *grab_a_Connection( - int des_socket, - uni_sa *srv, - char *peername, - int sz -) -{ - char *rval = 0; - socklen_t size_adr = sizeof(srv->sin); - int acp_sock; - - acp_sock = accept(des_socket,&srv->sa,&size_adr); - - if (acp_sock<0) { - perror("telnetd:accept"); - goto bailout; - }; - - if ( !(rval=telnet_get_pty(acp_sock)) ) { - syslog( LOG_DAEMON | LOG_ERR, "telnetd: unable to obtain PTY"); - /* NOTE: failing 'do_get_pty()' closed the socket */ - goto bailout; - } - - if (sockpeername(acp_sock, peername, sz)) - strncpy(peername, "<UNKNOWN>", sz); - -#ifdef PARANOIA - syslog(LOG_DAEMON | LOG_INFO, - "telnetd: accepted connection from %s on %s", - peername, - rval); -#endif - -bailout: - - return rval; -} - - -static void release_a_Connection(char *devname, char *peername, FILE **pstd, int n) -{ - -#ifdef PARANOIA - syslog( LOG_DAEMON | LOG_INFO, - "telnetd: releasing connection from %s on %s", - peername, - devname ); -#endif - - while (--n>=0) - if (pstd[n]) fclose(pstd[n]); - -} - -static int sockpeername(int sock, char *buf, int bufsz) -{ - uni_sa peer; - int rval = sock < 0; - socklen_t len = sizeof(peer.sin); - - if ( !rval ) - rval = getpeername(sock, &peer.sa, &len); - - if ( !rval ) - rval = !inet_ntop( AF_INET, &peer.sin.sin_addr, buf, bufsz ); - - return rval; -} - -static void -spawned_shell(void *arg); - -/***********************************************************/ -static void -rtems_task_telnetd(void *task_argument) -{ - int des_socket; - uni_sa srv; - char *devname; - char peername[16]; - int i=1; - int size_adr; - struct shell_args *arg = NULL; - - if ((des_socket=socket(PF_INET,SOCK_STREAM,0))<0) { - perror("telnetd:socket"); - telnetd_task_id = RTEMS_ID_NONE; - rtems_task_delete(RTEMS_SELF); - }; - setsockopt(des_socket,SOL_SOCKET,SO_KEEPALIVE,&i,sizeof(i)); - - memset(&srv,0,sizeof(srv)); - srv.sin.sin_family=AF_INET; - srv.sin.sin_port=htons(23); - size_adr=sizeof(srv.sin); - if ((bind(des_socket,&srv.sa,size_adr))<0) { - perror("telnetd:bind"); - close(des_socket); - telnetd_task_id = RTEMS_ID_NONE; - rtems_task_delete(RTEMS_SELF); - }; - if ((listen(des_socket,5))<0) { - perror("telnetd:listen"); - close(des_socket); - telnetd_task_id = RTEMS_ID_NONE; - rtems_task_delete(RTEMS_SELF); - }; - - /* we don't redirect stdio as this probably - * was started from the console anyway .. - */ - do { - if (telnetd_config->keep_stdio) { - bool start = true; - char device_name [32]; - - ttyname_r( 1, device_name, sizeof( device_name)); - if (telnetd_config->login_check != NULL) { - start = rtems_shell_login_prompt( - stdin, - stderr, - device_name, - telnetd_config->login_check - ); - } - if (start) { - telnetd_config->command( device_name, arg->arg); - } else { - syslog( - LOG_AUTHPRIV | LOG_WARNING, - "telnetd: to many wrong passwords entered from %s", - device_name - ); - } - } else { - devname = grab_a_Connection(des_socket, &srv, peername, sizeof(peername)); - - if ( !devname ) { - /* if something went wrong, sleep for some time */ - sleep(10); - continue; - } - - arg = malloc( sizeof(*arg) ); - - arg->devname = devname; - arg->arg = telnetd_config->arg; - strncpy(arg->peername, peername, sizeof(arg->peername)); - - telnetd_task_id = telnetd_spawn_task( - devname, - telnetd_config->priority, - telnetd_config->stack_size, - spawned_shell, - arg - ); - if (telnetd_task_id == RTEMS_ID_NONE) { - FILE *dummy; - - if ( telnetd_spawn_task != telnetd_dflt_spawn ) { - fprintf(stderr,"Telnetd: Unable to spawn child task\n"); - } - - /* hmm - the pty driver slot can only be - * released by opening and subsequently - * closing the PTY - this also closes - * the underlying socket. So we mock up - * a stream... - */ - - if ( !(dummy=fopen(devname,"r+")) ) - perror("Unable to dummy open the pty, losing a slot :-("); - release_a_Connection(devname, peername, &dummy, 1); - free(arg); - sleep(2); /* don't accept connections too fast */ - } - } - } while(1); - - /* TODO: how to free the connection semaphore? But then - - * stopping the daemon is probably only needed during - * development/debugging. - * Finalizer code should collect all the connection semaphore - * counts and eventually clean up... - */ - close(des_socket); - telnetd_task_id = RTEMS_ID_NONE; -} - -rtems_status_code rtems_telnetd_start(const rtems_telnetd_config_table* config) -{ - if (telnetd_config != NULL) { - fprintf(stderr, "telnetd already started\n"); - return RTEMS_RESOURCE_IN_USE; - } - - if (config->command == NULL) { - fprintf(stderr, "telnetd setup with invalid command\n"); - return RTEMS_IO_ERROR; - } - - telnetd_config = calloc(1, sizeof(*telnetd_config)); - if (telnetd_config == NULL) { - fprintf(stderr, "telnetd cannot alloc telnetd config table\n"); - return RTEMS_NO_MEMORY; - } - - - if ( !telnet_pty_initialize() ) { - fprintf(stderr, "telnetd cannot initialize PTY driver\n"); - free(telnetd_config); - telnetd_config = NULL; - return RTEMS_IO_ERROR; - } - - *telnetd_config = *config; - - /* Check priority */ - if (telnetd_config->priority < 2) { - telnetd_config->priority = 100; - } - - /* Check stack size */ - if (telnetd_config->stack_size <= 0) { - telnetd_config->stack_size = (size_t)32 * 1024; - } - - /* Spawn task */ - telnetd_task_id = telnetd_spawn_task( - "TNTD", - telnetd_config->priority, - telnetd_config->stack_size, - rtems_task_telnetd, - 0 - ); - if (telnetd_task_id == RTEMS_ID_NONE) { - free(telnetd_config); - telnetd_config = NULL; - return RTEMS_IO_ERROR; - } - - /* Print status */ - if (!telnetd_config->keep_stdio) { - fprintf( - stderr, - "telnetd started with stacksize = %u and priority = %d\n", - (unsigned) telnetd_config->stack_size, - (unsigned) telnetd_config->priority - ); - } - - return RTEMS_SUCCESSFUL; -} - -/* utility wrapper */ -static void -spawned_shell(void *targ) -{ - rtems_status_code sc; - FILE *nstd[3]={0}; - FILE *ostd[3]={ stdin, stdout, stderr }; - int i=0; - struct shell_args *arg = targ; - bool login_failed = false; - bool start = true; - - sc=rtems_libio_set_private_env(); - - /* newlib hack/workaround. Before we change stdin/out/err we must make - * sure the internal data are initialized (fileno(stdout) has this sideeffect). - * This should probably be done from RTEMS' libc support layer... - * (T.S., newlibc-1.13; 2005/10) - */ - - fileno(stdout); - - if (RTEMS_SUCCESSFUL != sc) { - rtems_error(sc,"rtems_libio_set_private_env"); - goto cleanup; - } - - /* redirect stdio */ - for (i=0; i<3; i++) { - if ( !(nstd[i]=fopen(arg->devname,"r+")) ) { - perror("unable to open stdio"); - goto cleanup; - } - } - - stdin = nstd[0]; - stdout = nstd[1]; - stderr = nstd[2]; - - #if 0 - printk("STDOUT is now %x (%x) (FD %i/%i)\n", - stdout,nstd[1],fileno(stdout),fileno(nstd[1])); - printf("hello\n"); - write(fileno(stdout),"hellofd\n",8); - #endif - - /* call their routine */ - if (telnetd_config->login_check != NULL) { - start = rtems_shell_login_prompt( - stdin, - stderr, - arg->devname, - telnetd_config->login_check - ); - login_failed = !start; - } - if (start) { - telnetd_config->command( arg->devname, arg->arg); - } - - stdin = ostd[0]; - stdout = ostd[1]; - stderr = ostd[2]; - - if (login_failed) { - syslog( - LOG_AUTHPRIV | LOG_WARNING, - "telnetd: to many wrong passwords entered from %s", - arg->peername - ); - } - -cleanup: - release_a_Connection(arg->devname, arg->peername, nstd, i); - free(arg); -} - -struct wrap_delete_args { - void (*t)(void *); - void *a; -}; - -static rtems_task -wrap_delete(rtems_task_argument arg) -{ - struct wrap_delete_args *pwa = (struct wrap_delete_args *)arg; - register void (*t)(void *) = pwa->t; - register void *a = pwa->a; - - /* free argument before calling function (which may never return if - * they choose to delete themselves) - */ - free(pwa); - t(a); - rtems_task_delete(RTEMS_SELF); -} - -rtems_id -telnetd_dflt_spawn(const char *name, unsigned int priority, unsigned int stackSize, void (*fn)(void *), void* fnarg) -{ - rtems_status_code sc; - rtems_id task_id = RTEMS_ID_NONE; - char nm[4] = {'X','X','X','X' }; - struct wrap_delete_args *pwa = malloc(sizeof(*pwa)); - - strncpy(nm, name, 4); - - if ( !pwa ) { - perror("Telnetd: no memory\n"); - return RTEMS_ID_NONE; - } - - pwa->t = fn; - pwa->a = fnarg; - - if ((sc=rtems_task_create( - rtems_build_name(nm[0], nm[1], nm[2], nm[3]), - (rtems_task_priority)priority, - stackSize, - RTEMS_DEFAULT_MODES, - RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, - &task_id)) || - (sc=rtems_task_start( - task_id, - wrap_delete, - (rtems_task_argument)pwa))) { - free(pwa); - rtems_error(sc,"Telnetd: spawning task failed"); - return RTEMS_ID_NONE; - } - return task_id; -} - -/* convenience routines for CEXP (retrieve stdio descriptors - * from reent structure) - */ -#ifdef stdin -static __inline__ FILE * -_stdin(void) { return stdin; } -#undef stdin -FILE *stdin(void) { return _stdin(); } -#endif -#ifdef stdout -static __inline__ FILE * -_stdout(void) { return stdout; } -#undef stdout -FILE *stdout(void) { return _stdout(); } -#endif -#ifdef stderr -static __inline__ FILE * -_stderr(void) { return stderr; } -#undef stderr -FILE *stderr(void) { return _stderr(); } -#endif - -/* MUST NOT USE stdin & friends below here !!!!!!!!!!!!! */ |