?? ftpdlib.c
字號(hào):
/* Copyright 1990 - 1998 Wind River Systems, Inc. */#include "copyright_wrs.h"#include "vxWorks.h"#include "ioLib.h"#include "taskLib.h"#include "lstLib.h"#include "stdio.h"#include "sys/socket.h"#include "netinet/in.h"#include "errno.h"#include "version.h"#include "string.h"#include "stdlib.h"#include "iosLib.h"#include "inetLib.h"#include "dirent.h"#include "sys/stat.h"#include "sys/times.h"#include "sockLib.h"#include "logLib.h"#include "unistd.h"#include "pathLib.h"#include "sysLib.h"#include "ftpdLib.h"#include "ctype.h"#include "time.h"#include "loginLib.h"#include "fioLib.h"#include "dosFsLib.h" #define FTPD_BINARY_TYPE 0x1#define FTPD_ASCII_TYPE 0x2#define FTPD_EBCDIC_TYPE 0x4#define FTPD_LOCAL_BYTE_TYPE 0x8#define FTPD_STREAM_MODE 0x10#define FTPD_BLOCK_MODE 0x20#define FTPD_COMPRESSED_MODE 0x40#define FTPD_NO_RECORD_STRU 0x100#define FTPD_RECORD_STRU 0x200#define FTPD_PAGE_STRU 0x400#define FTPD_USER_OK 0x1000#define FTPD_ANONYMOUS 0x2000#define FTPD_PASSIVE 0x10000#define FTPD_REPRESENTATION(slot) ( (slot)->status & 0xff)#ifdef _unused_#define FTPD_TRANS_MODE(slot) (((slot)->status >> 8) & 0xff)#define FTPD_FILE_STRUCTURE(slot) (((slot)->status >> 16) & 0xff)#define FTPD_STATUS(slot) (((slot)->status >> 24) & 0xff)#endif#define FTP_DATA_PORT 20#define FTP_DAEMON_PORT 21#define FTPD_SOCK_FREE -1#define FTPD_WORK_TASK_NAME_LEN 40#define FTPD_WAIT_MAX 90#define FTPD_WAIT_INTERVAL 5#define FTPD_CONN_TIMEOUT 200#define FTPD_UC(ch) (((int) (ch)) & 0xff)#define FTPD_MULTI_LINE 0x10000000#define FTPD_WINDOW_SIZE 10240#define FTPD_ANONYMOUS_USER_1 "anonymous"#define FTPD_ANONYMOUS_USER_2 "ftp"#define FTPD_ANONYMOUS_USER_3 "guest"/* globals */int ftpdDebug = FALSE; /* TRUE: debugging messages */int ftpdTaskPriority = 56;int ftpdTaskOptions = VX_SUPERVISOR_MODE | VX_UNBREAKABLE;int ftpdWorkTaskPriority = 152;int ftpdWorkTaskOptions = VX_SUPERVISOR_MODE | VX_UNBREAKABLE; int ftpdWorkTaskStackSize = 12000;int ftpdWindowSize = FTPD_WINDOW_SIZE;int ftpsMaxClients = 4; /* Default max. for simultaneous connections */int ftpsCurrentClients;/* locals */LOCAL BOOL ftpsActive = FALSE; /* Server started? */LOCAL BOOL ftpsShutdownFlag; /* Server halt requested? */typedef struct { NODE node; int status; int byteCount; int cmdSock; STATUS cmdSockError; int dataSock; struct sockaddr_in peerAddr; struct sockaddr_in dataAddr; caddr_t buf; int bufSize; time_t timeUsed; char curDirName [MAX_FILENAME_LENGTH+1]; char curUserName /* current user */ [MAX_LOGIN_NAME_LEN+1]; } FTPD_SESSION_DATA;LOCAL int ftpdTaskId = -1;LOCAL int ftpdServerSock = FTPD_SOCK_FREE;LOCAL LIST ftpsSessionList;LOCAL SEM_ID ftpsMutexSem;LOCAL SEM_ID ftpsSignalSem;LOCAL char ftpdWorkTaskName [FTPD_WORK_TASK_NAME_LEN];LOCAL int ftpdNumTasks;LOCAL FUNCPTR pLoginVrfyFunc = NULL ;LOCAL char defaultHomeDir /* default root directory */ [MAX_FILENAME_LENGTH+1] = {0};LOCAL char guestHomeDir /* anonymous root directory */ [MAX_FILENAME_LENGTH+1] = {0};LOCAL char writeDirName /* anonymous upload directory */ [MAX_FILENAME_LENGTH+1] = {0};/* Various messages to be told to the clients */LOCAL const char *messages [] = { "Can't open passive connection", "Parameter not accepted", "Data connection error", "Directory non existent or syntax error", "Local resource failure: %s", "VxWorks FTP server (VxWorks %s) ready.", "Password required", "User logged in", "Bye...see you later", "USER and PASS required", "No files found or invalid directory or permission problem", "Transfer complete", "File \"%s\" not found or permission problem", "Cannot create file \"%s\" or permission problem", "Changed directory to \"%s\"", "Type set to I, binary mode", "Type set to A, ASCII mode", "Port set okay", "Current directory is \"%s\"", "File structure set to NO RECORD", "Stream mode okay", "Allocate and Account not required", "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", "NOOP -- did nothing as requested...hah!", "Command not recognized", "Error in input file", "Unimplemented TYPE %d", "You could at least say goodbye.", "The following commands are recognized:", "End of command list.", "File deleted successfully.", "Login failed.", "File exists, ready for destination name.", "File renamed successfuly.", "\"%s\" directory created", "Directory %s removed", "%s: not a plain file", "UNIX Type: L8 Version: VxWorks", "\"%s\" directory could not be created", "Timeout (%d seconds): closing connection.", "Guest login ok, send your complete e-mail address as password.", "Guest login ok, access restrictions apply.", "Guest login ok, upload directory is %s.", "Guest access denied.", };#define MSG_PASSIVE_ERROR 0#define MSG_PARAM_BAD 1#define MSG_DATA_CONN_ERROR 2#define MSG_DIR_NOT_PRESENT 3#define MSG_LOCAL_RESOURCE_FAIL 4#define MSG_SERVER_READY 5#define MSG_PASSWORD_REQUIRED 6#define MSG_USER_LOGGED_IN 7#define MSG_SEE_YOU_LATER 8#define MSG_USER_PASS_REQ 9#define MSG_DIR_ERROR 10#define MSG_TRANS_COMPLETE 11#define MSG_FILE_ERROR 12#define MSG_CREATE_ERROR 13#define MSG_CHANGED_DIR 14#define MSG_TYPE_BINARY 15#define MSG_TYPE_ASCII 16#define MSG_PORT_SET 17#define MSG_CUR_DIR 18#define MSG_FILE_STRU 19#define MSG_STREAM_MODE 20#define MSG_ALLOC_ACCOUNT 21#define MSG_PASSIVE_MODE 22#define MSG_NOOP_OKAY 23#define MSG_BAD_COMMAND 24#define MSG_INPUT_FILE_ERROR 25#define MSG_TYPE_ERROR 26#define MSG_NO_GOOD_BYE 27#define MSG_COMMAND_LIST_BEGIN 28#define MSG_COMMAND_LIST_END 29#define MSG_DELE_OK 30#define MSG_USER_LOGIN_FAILED 31#define MSG_RNFR_OK 32#define MSG_RNTO_OK 33#define MSG_MKD_OK 34#define MSG_RMD_OK 35#define MSG_FILE_NOTREG 36#define MSG_SYST_REPLY 37#define MSG_MKD_ERROR 38#define MSG_CONN_TIMEOUT 39#define MSG_GUEST_PASS 40#define MSG_GUEST_OK 41#define MSG_GUEST_UPLOAD_OK 42#define MSG_GUEST_ACCESS 43LOCAL char *ftpdCommandList ="HELP USER PASS QUIT LIST NLST\n\RETR STOR CWD TYPE PORT PWD\n\STRU MODE ALLO ACCT PASV NOOP\n\DELE RNFR RNTO MKD RMD MDTM\n\SIZE SYST XCWD XPWD XMKD XRMD\n";/* forward declarations */LOCAL FTPD_SESSION_DATA *ftpdSessionAdd (void);LOCAL void ftpdSessionDelete (FTPD_SESSION_DATA *);LOCAL STATUS ftpdWorkTask (FTPD_SESSION_DATA *);LOCAL STATUS ftpdCmdSend (FTPD_SESSION_DATA *, int, int, const char *, int, int, int, int, int, int);LOCAL STATUS ftpdDataConnGet (FTPD_SESSION_DATA *);LOCAL void ftpdDataStreamSend (FTPD_SESSION_DATA *, char *);LOCAL STATUS ftpdDataStreamReceive (FTPD_SESSION_DATA *, FILE *outStream);LOCAL void ftpdSockFree (int *);LOCAL STATUS ftpdDirListGet (int, char *, BOOL);LOCAL void ftpdDebugMsg (char *, int, int, int, int);LOCAL void unImplementedType (FTPD_SESSION_DATA *pSlot);LOCAL void dataError (FTPD_SESSION_DATA *pSlot);LOCAL void fileError (FTPD_SESSION_DATA *pSlot);LOCAL void transferOkay (FTPD_SESSION_DATA *pSlot);STATUS ftpLoginUserVerify (char *name, char *passwd);void ftpdLoginInstall(FUNCPTR pLoginFunc);#define rmdir(dName) remove((dName))#define mkdir(dName) ftpMkdir((dName))LOCAL STATUS ftpMkdir ( char *dirName /* directory name */ ) { int fd; if ((fd = open (dirName, O_RDWR | O_CREAT, FSTAT_DIR | DEFAULT_DIR_PERM)) == ERROR) { return (ERROR); } return (close (fd)); }LOCAL void ftpdTask (void) { int newSock; FAST FTPD_SESSION_DATA *pSlot; int on = 1; int addrLen; struct sockaddr_in addr; char a_ip_addr [INET_ADDR_LEN]; ftpdNumTasks = 0; FOREVER { addrLen = sizeof (struct sockaddr); ftpdDebugMsg ("waiting for a new client connection...\n",0,0,0,0); newSock = accept (ftpdServerSock, (struct sockaddr *) &addr, &addrLen); if (newSock < 0) { ftpdDebugMsg ("cannot accept a new connection\n",0,0,0,0); break; } semTake (ftpsMutexSem, WAIT_FOREVER); setsockopt (newSock, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof (on)); inet_ntoa_b (addr.sin_addr, a_ip_addr); ftpdDebugMsg ("accepted a new client connection from %s\n", (int) a_ip_addr, 0, 0, 0); pSlot = (FTPD_SESSION_DATA *)lstFirst (&ftpsSessionList); while (pSlot != NULL) { FTPD_SESSION_DATA * pNext ; time_t now = time(NULL); pNext = (FTPD_SESSION_DATA *)lstNext (&pSlot->node); if( (now - pSlot->timeUsed) > FTPD_CONN_TIMEOUT ) { ftpdDebugMsg("session %x idle byteCount %d\n", (int) pSlot, pSlot->byteCount, 0, 0); if ( pSlot->byteCount == 0 ) { ftpdCmdSend (pSlot, pSlot->cmdSock, 421, messages [MSG_CONN_TIMEOUT], now - pSlot->timeUsed, 0, 0, 0, 0, 0); ftpdDebugMsg("deleting session %x\n", (int)pSlot, 0, 0, 0); /* XXX ftpdSessionDelete( pSlot ); */ ftpdSockFree (&pSlot->cmdSock); taskDelay( sysClkRateGet() / 10 ); } else pSlot->byteCount = 0 ; } pSlot = pNext ; } pSlot = ftpdSessionAdd (); if (pSlot == NULL) { ftpdCmdSend (pSlot, newSock, 421, "Session limit reached, closing control connection", 0, 0, 0, 0, 0, 0); ftpdDebugMsg ("cannot get a new connection slot\n",0,0,0,0); semGive (ftpsMutexSem); continue; } pSlot->cmdSock = newSock; bcopy ( (char *)&addr, (char *)&pSlot->peerAddr, sizeof (struct sockaddr_in)); bcopy ( (char *)&addr, (char *)&pSlot->dataAddr, sizeof (struct sockaddr_in)); pSlot->dataAddr.sin_port = htons (FTP_DATA_PORT); sprintf (ftpdWorkTaskName, "tFtpdServ%d", ftpdNumTasks); ftpdDebugMsg ("creating a new server task %s...\n", (int) ftpdWorkTaskName, 0, 0, 0); if (taskSpawn (ftpdWorkTaskName, ftpdWorkTaskPriority, ftpdWorkTaskOptions, ftpdWorkTaskStackSize, ftpdWorkTask, (int) pSlot, 0, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR) { ftpdCmdSend (pSlot, newSock, 421, "Service not available, closing control connection", 0, 0, 0, 0, 0, 0); ftpdSessionDelete (pSlot); ftpdDebugMsg ("cannot create a new work task\n",0,0,0,0); semGive (ftpsMutexSem); continue; } ftpdDebugMsg ("done.\n",0,0,0,0); semGive (ftpsMutexSem); } ftpsActive = FALSE; return; }/******************************************************************************** RETURNS:* OK if server started, or ERROR otherwise.** ERRNO: N/A*/STATUS ftpdInit ( int port, int stackSize ) { int on = 1; struct sockaddr_in ctrlAddr; if (ftpsActive) return (OK); ftpsShutdownFlag = FALSE; ftpsCurrentClients = 0; ftpdServerSock = socket (AF_INET, SOCK_STREAM, 0); if (ftpdServerSock < 0) return (ERROR); lstInit (&ftpsSessionList); ftpsMutexSem = semMCreate (SEM_Q_FIFO | SEM_DELETE_SAFE); if (ftpsMutexSem == NULL) { close (ftpdServerSock); return (ERROR); } ftpsSignalSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY); if (ftpsSignalSem == NULL) { close (ftpdServerSock); semDelete (ftpsMutexSem); return (ERROR); } if ( port == 0 ) port = FTP_DAEMON_PORT ; ctrlAddr.sin_family = AF_INET; ctrlAddr.sin_addr.s_addr = INADDR_ANY; ctrlAddr.sin_port = htons ( port ); if (setsockopt (ftpdServerSock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0) { close (ftpdServerSock); semDelete (ftpsMutexSem); semDelete (ftpsSignalSem); return (ERROR); } if (bind (ftpdServerSock, (struct sockaddr *) &ctrlAddr, sizeof (ctrlAddr)) < 0) { close (ftpdServerSock); semDelete (ftpsMutexSem); semDelete (ftpsSignalSem); return (ERROR); } if (listen (ftpdServerSock, 5) < 0) { close (ftpdServerSock); semDelete (ftpsMutexSem); semDelete (ftpsSignalSem); return (ERROR); } ftpdTaskId = taskSpawn ("tFtpdTask", ftpdTaskPriority - 1, ftpdTaskOptions, stackSize == 0 ? ftpdWorkTaskStackSize : stackSize, (FUNCPTR) ftpdTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); if (ftpdTaskId == ERROR) { ftpdDebugMsg ("ERROR: ftpdTask cannot be created\n",0,0,0,0); close (ftpdServerSock); semDelete (ftpsMutexSem); semDelete (ftpsSignalSem); return (ERROR); } ftpsActive = TRUE; ftpdLoginInstall(ftpLoginUserVerify); ftpdDebugMsg ("ftpdTask created\n",0,0,0,0); return (OK); }/********************************************************************************/STATUS ftpdDelete (void) { BOOL serverActive = FALSE; FTPD_SESSION_DATA * pData; if (! ftpsActive) return (OK); semTake (ftpsMutexSem, WAIT_FOREVER); taskDelete (ftpdTaskId); ftpdTaskId = -1;
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -