📄 telnetlib.c
字号:
/* telnetLib.c - telnet server library *//* Copyright 1984-1998 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------03e,14mar99,jdi doc: removed refs to config.h and/or configAll.h (SPR 25663).03d,05oct98,jmp doc: cleanup.03c,30oct96,dgp doc: change task names for telnetd() per SPR #590103b,09aug94,dzb fixed activeFlag race with cleanupFlag (SPR #2050). made telnetdSocket global (SPR #1941). added logFdFromRlogin (SPR #2212).03a,02may94,ms increased stack size for SIMHPPA.02z,11aug93,jmm Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h02y,01feb93,jdi documentation cleanup for 5.1.02x,18jul92,smb Changed errno.h to errnoLib.h.02w,26may92,rrr the tree shuffle -changed includes to have absolute path from h/02v,24apr92,rfs Fixed flaky shell restart upon connection termination. The functions telnetInTask() and telnetdExit() were changed. This is fixing SPR #1427. Also misc ANSI noise.02u,13dec91,gae ANSI cleanup.02t,14nov91,jpb moved remCurIdSet to shellLogout (shellLib.c).02s,04oct91,rrr passed through the ansification filter -changed functions to ansi style -changed includes to have absolute path from h/ -fixed #else and #endif -changed READ, WRITE and UPDATE to O_RDONLY O_WRONLY and ... -changed VOID to void -changed copyright notice02r,01aug91,yao fixed to pass 6 args to excJobAdd() call.02q,13may91,shl undo'ed 02o.02p,30apr91,jdi documentation tweaks.02o,29apr91,shl added call to restore original machine name, user and group ids (spr 916).02n,05apr91,jdi documentation -- removed header parens and x-ref numbers; doc review by dnw.02m,24mar91,jdi documentation cleanup.02l,05oct90,shl fixed telnetExit() to restore original user and password.02k,02oct90,hjb added a call to htons() where needed.02j,08aug90,dnw changed declaration of tnInput from void to int. added forward declaration of setMode().02i,07may90,shl changed entry point of tTelnetd back to telnetd.02h,18apr90,shl added shell security. changed telnetd name to tTelnetd.02g,20aug89,gae bumped telnetTaskStackSize from 1500 to 5000 for SPARC.02f,29sep88,gae documentation.02e,06jun88,dnw changed taskSpawn/taskCreate args.02d,30may88,dnw changed to v4 names.02c,28may88,dnw changed to use shellOrigStdSet (...) instead of shellSetOrig... changed not to use shellTaskId global variable.02b,01apr88,gae made it work with I/O system revision.02a,27jan88,jcf made kernel independent.01g,14dec87,dnw fixed bug in telnetdIn() that caused system crashes.01f,19nov87,dnw changed telnetd to wait for shell to exist before accepting remote connections.01e,17nov87,ecs lint.01d,04nov87,ecs documentation. & fixed bug in use of setsockopt(). dnw changed to call shellLogoutInstall() instead of logoutInstall.01c,24oct87,gae changed setOrig{In,Out,Err}Fd() to shellSetOrig{In,Out,Err}(). made telnetdOut() exit on EOF from master pty fd. made telnetInit() not sweat being called more than once. added shellLock() to telnetd to get exclusive use of shell.01g,20oct87,gae added logging device for telnet shell; made telnetInit() create pty device.01f,05oct87,gae made telnetdExit() from telnetdIn() - used by logout(). removed gratuitous standard I/O ioctl's. made "disconnection" cleaner by having shell do restart.01e,26jul87,dnw changed default priority of telnet tasks from 100 to 2. changed task priority and ids to be global variables so they can be accessed from outside this module.01d,04apr87,dnw de-linted.01c,27mar87,dnw documentation fixed bug causing control sequences from remote to be misinterpreted. added flushing of pty in case anything was left before remote login.01b,27feb87,dnw changed to spawn telnet tasks UNBREAKABLE.01a,20oct86,dnw written.*//*DESCRIPTIONThis library provides a remote login facility for VxWorks. It uses the telnet protocol to enable users on remote systems to log in to VxWorks.The telnet daemon, telnetd(), accepts remote telnet login requests andcauses the shell's input and output to be redirected to the remote user.The telnet daemon is started by calling telnetInit(), which is calledautomatically when the configuration macro INCLUDE_TELNET is defined.Internally, the telnet daemon provides a tty-like interface to the remote userthrough the use of the VxWorks pseudo-terminal driver, ptyDrv.INCLUDE FILES: telnetLib.hSEE ALSO:ptyDrv, rlogLib*/#include "vxWorks.h"#include "sys/types.h"#include "sys/socket.h"#include "ptyDrv.h"#include "netinet/in.h"#include "ioLib.h"#include "taskLib.h"#include "telnetLib.h"#include "stdlib.h"#include "unistd.h"#include "errnoLib.h"#include "string.h"#include "stdio.h"#include "fcntl.h"#include "sockLib.h"#include "logLib.h"#include "shellLib.h"#include "remLib.h"#include "sysLib.h"/* Defining DEBUG will make this library hook remote telnet clients up to * the routine copyStreams() instead of to the shell. This is useful for * debugging telnet without losing the shell. *//* #define DEBUG */#define TELNET_SERVICE 23 /* telnet port number */#define STDIN_BUF_SIZE 512#define STDOUT_BUF_SIZE 512#define sendToPty(fd,buf,len) write(fd,buf,len)#define sendToRem(fd,buf,len) write(fd,buf,len)/* telnet input states */#define TS_DATA 0#define TS_IAC 1#define TS_CR 2#define TS_BEGINNEG 3#define TS_ENDNEG 4#define TS_WILL 5#define TS_WONT 6#define TS_DO 7#define TS_DONT 8/* global variables */#ifndef DEBUGint telnetTaskOptions = VX_SUPERVISOR_MODE | VX_UNBREAKABLE;#elseint telnetTaskOptions = VX_SUPERVISOR_MODE;#endif#if (CPU_FAMILY == SIMHPPA) || (CPU_FAMILY == SIMSPARCSUNOS)int telnetTaskStackSize = 10000;#else /* CPU_FAMILY == SIMHPPA */int telnetTaskStackSize = 5000;#endif /* CPU_FAMILY == SIMHPPA */int telnetTaskPriority = 2; /* priority of telnet tasks */int telnetdId; /* task ID of telnetd task */int telnetInTaskId; /* task ID of telnetInTask task */int telnetOutTaskId; /* task ID of telnetOutTask task */int telnetdSocket; /* telnetd socket fd */IMPORT int logFdFromRlogin; /* fd of pty for telnet session *//* local variables */LOCAL char *telnetShellName = "tShell";LOCAL char *ptyTelnetName = "/pty/telnet.";LOCAL char *ptyTelnetNameM = "/pty/telnet.M"; /* master side */LOCAL char *ptyTelnetNameS = "/pty/telnet.S"; /* slave side */LOCAL BOOL activeFlag = FALSE; /* TRUE if there is an active connection */LOCAL BOOL cleanupFlag; /* TRUE if exit cleanup has occurred */LOCAL int telnetdM; /* telnetd master pty */LOCAL int telnetdS; /* telnetd slave pty */LOCAL int shellInFd; /* original console input */LOCAL int shellOutFd; /* original console output */LOCAL int shellErrFd; /* original console error output */LOCAL TBOOL myOpts [256]; /* current option settings - this side */LOCAL TBOOL remOpts [256]; /* current option settings - other side */LOCAL BOOL raw; /* TRUE = raw mode enabled */LOCAL BOOL echo; /* TRUE = echo enabled *//* forward static functions */static void telnetdExit (BOOL usedLogout);static int tnInput (int state, int remFd, int ptyFd, char *buf, int n);static STATUS remDoOpt (int option, BOOL enable, int remFd, int ptyFd, BOOL reqFromRem);static STATUS localDoOpt (int option, BOOL enable, int remFd, int ptyFd, BOOL reqFromRem);static void setMode (int telnetOption, BOOL enable);/********************************************************************************* telnetInit - initialize the telnet daemon** This routine initializes the telnet facility, which supports remote login* to the VxWorks shell via the telnet protocol. It creates a pty device and* spawns the telnet daemon. It is called automatically when the* configuration macro INCLUDE_TELNET is defined.** RETURNS: N/A*/void telnetInit (void) { static BOOL done; /* FALSE = not done */ if (done) { printErr ("telnetInit: already initialized.\n"); return; } if (ptyDrv () == ERROR || ptyDevCreate (ptyTelnetName, 1024, 1024) == ERROR) { printErr ("telnetInit: unable to create pty device.\n"); return; } telnetdId = taskSpawn ("tTelnetd", telnetTaskPriority, telnetTaskOptions, telnetTaskStackSize, (FUNCPTR)telnetd, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); if (telnetdId == ERROR) printErr ("telnetInit: unable to spawn telnetd.\n"); else done = TRUE; }/********************************************************************************* telnetd - VxWorks telnet daemon** This routine enables remote users to log in to VxWorks over the network via* the telnet protocol. It is spawned by telnetInit(), which should be* called at boot time.** Remote telnet requests will cause `stdin', `stdout', and `stderr' to be stolen* away from the console. When the remote user disconnects, `stdin', `stdout',* and `stderr' are restored, and the shell is restarted.** The telnet daemon requires the existence of a pseudo-terminal device,* which is created by telnetInit() before telnetd() is spawned. The telnetd()* routine creates two additional processes, `tTelnetInTask' and * `tTelnetOutTask', whenever a remote user is logged in. These processes * exit when the remote connection is terminated.** RETURNS: N/A*/void telnetd (void) { int optval; struct sockaddr_in myAddress; struct sockaddr_in clientAddress; int clientAddrLen; int client; int masterFd; int slaveFd; int sd; /* open a socket and wait for a client */ sd = socket (AF_INET, SOCK_STREAM, 0); bzero ((char *) &myAddress, sizeof (myAddress)); myAddress.sin_family = AF_INET; myAddress.sin_port = htons (TELNET_SERVICE); if (bind (sd, (struct sockaddr *) &myAddress, sizeof (myAddress)) == ERROR) { printErr ("telnetd: bind failed.\n"); return; } listen (sd, 1); FOREVER { /* wait for shell to exist */ while (taskNameToId (telnetShellName) == ERROR) taskDelay (sysClkRateGet ()); errnoSet (OK); /* clear errno for pretty i() display */ /* now accept connection */ clientAddrLen = sizeof (clientAddress); client = accept (sd, (struct sockaddr *)&clientAddress, &clientAddrLen); if (client == ERROR) { printErr ("telnetd: accept failed - status = 0x%x\n", errnoGet ()); continue; } /* check to see if there's already an active connection */ if (activeFlag) { char *msg = "\r\nSorry, this system is engaged.\r\n"; write (client, msg, strlen (msg)); close (client); continue; } /* create the pseudo terminal: * the master side is connected to the socket to the * remote machine - two processes telnetInTask & telnetOutTask * handle input and output. */ if ((masterFd = open (ptyTelnetNameM, O_RDWR, 0)) == ERROR) { char *msg = "\r\nSorry, trouble wity pty.\r\n"; printErr ("telnetd: error opening %s\n", ptyTelnetNameM); write (client, msg, strlen (msg)); close (client); continue; } if ((slaveFd = open (ptyTelnetNameS, O_RDWR, 0)) == ERROR) { char *msg = "\r\nSorry, trouble wity pty.\r\n"; printErr ("telnetd: error opening %s\n", ptyTelnetNameS); write (client, msg, strlen (msg)); close (client); close (masterFd); continue; } if (!shellLock (TRUE)) { char *msg = "\r\nSorry, shell is locked.\r\n"; printErr ("telnetd: someone tried to login.\n"); write (client, msg, strlen (msg)); close (client); close (masterFd); close (slaveFd); continue; } /* setup the slave device to act like a terminal */ (void) ioctl (slaveFd, FIOOPTIONS, OPT_TERMINAL); printErr ("\ntelnetd: This system *IN USE* via telnet.\n"); shellLogoutInstall ((FUNCPTR) telnetdExit, TRUE); activeFlag = TRUE; telnetdSocket = client; telnetdM = masterFd; telnetdS = slaveFd; /* turn on KEEPALIVE so if the client crashes, we'll know about it */ optval = 1; setsockopt (client, SOL_SOCKET, SO_KEEPALIVE, (char *) &optval, sizeof (optval)); /* flush out pty device */ (void) ioctl (slaveFd, FIOFLUSH, 0 /*XXX*/); /* get the shell's standard I/O fd's so we can restore them later */ shellInFd = ioGlobalStdGet (STD_IN); shellOutFd = ioGlobalStdGet (STD_OUT); shellErrFd = ioGlobalStdGet (STD_ERR);#ifndef DEBUG /* set shell's standard I/O to pty device; add extra logging device */ shellOrigStdSet (STD_IN, slaveFd); shellOrigStdSet (STD_OUT, slaveFd); shellOrigStdSet (STD_ERR, slaveFd); logFdAdd (slaveFd); logFdFromRlogin = slaveFd; /* store pty fd for logFdSet() */#endif /* DEBUG */ /* initialize modes and options and offer to do remote echo */ raw = FALSE; echo = TRUE; bzero ((char *) myOpts, sizeof (myOpts)); bzero ((char *) remOpts, sizeof (remOpts)); (void)localDoOpt (TELOPT_ECHO, TRUE, client, masterFd, FALSE); /* the shell is currently stuck in a read from the console, so we * restart it */#ifndef DEBUG excJobAdd (shellRestart, TRUE, 0, 0, 0, 0, 0);#else sp (copyStreams, slaveFd, slaveFd);#endif /* DEBUG */ /* spawn the output process which transfers data from the master pty * to the socket; * spawn the input process which transfers data from the client socket * to the master pty */ if (((telnetOutTaskId = taskSpawn ("tTelnetOutTask", telnetTaskPriority, telnetTaskOptions, telnetTaskStackSize, (FUNCPTR)telnetOutTask, client,masterFd, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR) || ((telnetInTaskId = taskSpawn ("tTelnetInTask", telnetTaskPriority, telnetTaskOptions, telnetTaskStackSize, (FUNCPTR)telnetInTask, client,masterFd, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR)) { printErr ("telnetd: error spawning %s child - status = 0x%x\n", (telnetOutTaskId != ERROR) ? "output" : "input", errnoGet ());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -