📄 telnetdlib.c
字号:
/* * Dynamic session creation needs all elements of the structure * initialized to sane values */ pSlot->socket = -1; pSlot->inputFd = -1; pSlot->outputFd = -1; pSlot->slaveFd = -1; pSlot->outputTask = -1; pSlot->inputTask = -1; pSlot->parserControl = 0; } /* Add new entry to the list of active sessions. */ lstAdd (&telnetdSessionList, &pSlot->node); semGive (telnetdMutexSem); return (pSlot); }/********************************************************************************* telnetdSessionDisconnect - Shut down a session** This routine removes a connection and all associated resources for it.** This may be called because of login failure or end of a shell session** NOMANUAL*/LOCAL void telnetdSessionDisconnect ( TELNETD_SESSION_DATA *pSlot, BOOL pSlotDelete /* For DYNAMIC mode, should pSlot be free'd when done? */ ) { if (pSlot == NULL) return; semTake (telnetdMutexSem, WAIT_FOREVER); /* * Make sure the task is still valid. It is possible that * the connection was killed during login (telnetInTask), * failed login (telnetd) * terminated by shell (shell task) */ /* For STATIC sessions, we need to clean/sanitize all of it's resources */ if (telnetdTaskFlag) { /* Halt the i/o tasks */ if (pSlot->outputTask) taskSuspend (pSlot->outputTask); if (pSlot->inputTask) taskSuspend (pSlot->inputTask); /* Make sure the semaphores are empty */ if (pSlot->startInput) semTake (pSlot->startInput, NO_WAIT); if (pSlot->startOutput) semTake (pSlot->startOutput, NO_WAIT); /* Restart the I/O tasks, they will pend on the empty semaphores */ if (pSlot->outputTask) taskRestart (pSlot->outputTask); if (pSlot->inputTask) taskRestart (pSlot->inputTask); /* Clear out the i/o descriptors */ if ((pSlot->outputFd) > STD_ERR) ioctl (pSlot->outputFd, FIOFLUSH, 0); if ((pSlot->slaveFd) > STD_ERR) ioctl (pSlot->slaveFd, FIOFLUSH, 0); /* Close the socket connection to the client */ if ((pSlot->socket) > STD_ERR) close (pSlot->socket); /* * Re-Initialize some elements of the structure to sane values * We will not re-initialize the taskId's or the i/o file descriptors * because these resources are just reset and not removed. */ pSlot->socket = -1; pSlot->parserControl = telnetdParserControl; pSlot->loggedIn = FALSE; pSlot->busyFlag = FALSE; --telnetdCurrentClients; lstDelete (&telnetdSessionList, &pSlot->node); } else { /* For DYNAMIC sessions, we need to free all of it's resources */ /* Remove the i/o tasks */ if (pSlot->outputTask) taskDelete (pSlot->outputTask); if (pSlot->inputTask) taskDelete (pSlot->inputTask); /* Delete the semaphores */ if (pSlot->startInput) semDelete (pSlot->startInput); if (pSlot->startOutput) semDelete (pSlot->startOutput); /* Close the i/o descriptors */ if ((pSlot->outputFd) > STD_ERR) close (pSlot->outputFd); if ((pSlot->slaveFd) > STD_ERR) close (pSlot->slaveFd); /* Remove the pseudo terminal for the session. */ (void) ptyDevRemove (pSlot->ptyRemoteName); /* Close the socket connection to the client */ if ((pSlot->socket) > STD_ERR) close (pSlot->socket); /* Re-Initialize all elements of the structure to sane values */ pSlot->socket = -1; pSlot->inputFd = -1; pSlot->outputFd = -1; pSlot->slaveFd = -1; pSlot->outputTask = 0; pSlot->inputTask = 0; pSlot->parserControl = 0; pSlot->busyFlag = FALSE; --telnetdCurrentClients; lstDelete (&telnetdSessionList, &pSlot->node); /* * If we are not logged in, then the connection must have been shut down * during login. When the login routine terminates, the pSlot will be * free'd. This will be determined by the telnetd if parserControl == 0 */ if ((pSlot->loggedIn == TRUE) && (pSlotDelete == TRUE)) free (pSlot); else pSlot->loggedIn = FALSE; } semGive (telnetdMutexSem); }/********************************************************************************* telnetdSessionDisconnectFromShellJob - terminate a session from the shell** This is called from the shell context during a excTask() and is invoked * by calling telnetdSessionDisconnectFromShell.** NOTE: The inTask may also terminate the connection via * telnetdSessionDisconnectFromRemote()** RETURNS N/A** NOMANUAL*/LOCAL void telnetdSessionDisconnectFromShellJob (TELNETD_SESSION_DATA *pSlot) { /* Shut down the connection */ telnetdSessionDisconnect (pSlot, FALSE); if (*telnetdParserControl) (*telnetdParserControl) (REMOTE_STOP, pSlot, 0); if (!telnetdTaskFlag) free (pSlot); }/********************************************************************************* telnetdSessionDisconnectFromShell - terminate a session from the shell** This is called from the shell context during a logout() call * NOTE: The inTask may also terminate the connection via * telnetdSessionDisconnectFromRemote()** RETURNS N/A** NOMANUAL*/LOCAL void telnetdSessionDisconnectFromShell (TELNETD_SESSION_DATA *pSlot) { excJobAdd (telnetdSessionDisconnectFromShellJob, (int) pSlot, 0, 0, 0, 0, 0); taskDelay (sysClkRateGet()); }/********************************************************************************* telnetdSessionDisconnectFromRemote - terminate a session from the shell** This is called from the telnetInTask context if the user terminates the * connection.** RETURNS N/A** NOMANUAL*/LOCAL void telnetdSessionDisconnectFromRemote (TELNETD_SESSION_DATA *pSlot) { /* Make the shell restart locally */ (*telnetdParserControl) (REMOTE_STOP, pSlot, 0); /* The shell will terminate the connection for us */ if (pSlot->loggedIn == TRUE) { /* Shut down the connection */ telnetdSessionDisconnect (pSlot, TRUE); } taskDelay (sysClkRateGet()); }/********************************************************************************* telnetd - primary telnet server task** This routine monitors the telnet port for connection requests from clients.* It is the entry point for the primary telnet task created during the* library initialization.** The server will only accept telnet connection requests when a task is* available to handle the input and provide output to the remote user.* The default configuration uses the shell for this purpose by redirecting* the `stdin', `stdout', and `stderr' file descriptors away from the console.* When the remote user disconnects, those values are restored to their* previous settings and the shell is restarted.** RETURNS: N/A** NOMANUAL*/void telnetd (void) { struct sockaddr_in clientAddr; int clientAddrLen; int newSock; int optval; TELNETD_SESSION_DATA *pSlot; BOOL startFlag; /* Command interpreter started successfully? */ STATUS result; FOREVER { clientAddrLen = sizeof (clientAddr); pSlot = NULL; result = OK; startFlag = FALSE; newSock = accept (telnetdServerSock, (struct sockaddr *) &clientAddr, &clientAddrLen); if (newSock == ERROR) { break; /* Exit if unable to accept connection. */ } /* * Get (static) or create (dynamic) a new session entry for this * connection */ pSlot = telnetdSessionAdd (); /* Check if the maximum number of connections has been reached. */ if (pSlot == NULL) { fdprintf (newSock, "\r\nSorry, session limit reached.\r\n"); /* Prevent denial of service attack by waiting 5 seconds */ taskDelay (sysClkRateGet () * 5); close (newSock); result = ERROR; continue; } pSlot->socket = newSock; /* If we haven't created the pseudo tty device, so so now */ if (remoteInitFlag == FALSE) { /* Create pty device for all remote sessions. */ if (ptyDrv () == ERROR) { fdprintf (newSock, "\n\ntelnetd: Unable to initialize ptyDrv(). errno:%#x\n", errno, 0, 0, 0, 0, 0); /* Prevent denial of service attack by waiting 5 seconds */ taskDelay (sysClkRateGet () * 5); close (newSock); continue; result = ERROR; } remoteInitFlag = TRUE; /* Disable further device creation. */ } /* Check if we are in the dynamic mode */ if (!telnetdTaskFlag) { /* * Create the pseudo terminal for a session. The remote machine * will write to the master side and read from the slave side. * */ result = telnetdSessionPtysCreate (pSlot); if (result == OK) result = telnetdIoTasksCreate (pSlot); if (result == ERROR) { fdprintf (newSock, "\r\ntelnetd: Sorry, session limit reached. Unable to spawn tasks. errno %#x\r\n", errno); /* Prevent denial of service attack by waiting 5 seconds */ taskDelay (sysClkRateGet () * 5); telnetdSessionDisconnect (pSlot, TRUE); result = ERROR; continue; } } /* setup the slave device to act like a terminal */ (void) ioctl (pSlot->slaveFd, FIOOPTIONS, OPT_TERMINAL); /* Check if a parser has been installed */ if (!telnetdParserFlag) { fdprintf (newSock, "\r\ntelnetd: Sorry, a shell has not been installed.\r\n" ); /* Prevent denial of service attack by waiting 5 seconds */ taskDelay (sysClkRateGet () * 5); telnetdSessionDisconnect (pSlot, TRUE); continue; } /* * Spawn (or wake up) the input task which transfers data from * the client socket and the output task which transfers data to * the socket. */ if (telnetdTaskFlag) { semGive (pSlot->startInput); semGive (pSlot->startOutput); } /* turn on KEEPALIVE so if the client crashes, we'll know about it */ optval = 1; setsockopt (newSock, SOL_SOCKET, SO_KEEPALIVE, (char *) &optval, sizeof (optval)); /* 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 (pSlot->slaveFd, TELOPT_ECHO, TRUE, newSock, FALSE); /* * File descriptors are available. Save the corresponding * parser control routine. */ pSlot->parserControl = telnetdParserControl; /* * Tell the parser control function to activate the shell * for this session. */ result = (*telnetdParserControl) (REMOTE_START, (UINT32)pSlot, pSlot->slaveFd); /* * If parserControl == 0, then the connection was terminated * during login. The inTask has already cleaned up all resources * for us except the memory for pSlot. */ if (pSlot->parserControl == 0) { if (!telnetdTaskFlag) free (pSlot); continue; } /* * Was the REMOTE_START of the shell successful? * Did we fail the login or did the remote user disconnect? */ if (result == ERROR) /* No, must have failed to login */ { telnetdSessionDisconnect (pSlot, TRUE); continue; } else { /* * We must keep track of a successfull login with * 'loggedIn' element since failure to login means that the * shell was not spawned. * * Future session cleanup's will know that the login has been * a success. Therefore, the parser control will need a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -