📄 tinyftp.c
字号:
/*-----------------------------------------------------------------------------*//* */ /* tinyftp.c - user ftp built on tinytcp.c */ /* *//* Written March 31, 1986 by Geoffrey Cooper *//* *//* Copyright (C) 1986, IMAGEN Corporation *//* "This code may be duplicated in whole or in part provided that [1] there *//* is no commercial gain involved in the duplication, and [2] that this *//* copyright notice is preserved on all copies. Any other duplication *//* requires written notice of the author." *//*-----------------------------------------------------------------------------*/#include "_stdio.h"#include "env.h"#include "tinyip.h"#include "support.h"#include "flashop.h"#include "srloader.h"#include "shell.h"#include "revision.h"tcp_Socket ftp_ctl, ftp_data;static byte ftp_cmdbuf[128];static int ftp_cmdbufi;static byte ftp_outbuf[ftp_MaxData];static int ftp_outbufix, ftp_outbuflen;#ifdef FTP_SERVER_SUPPORT#define USERNAME_LEN 16#define REC_GET_TAG 0#define REC_GET_LEN 1#define REC_GET_ADDR 2#define REC_GET_DATA 3#define REC_GET_CHECKSUM 4#define REC_GET_ABORT 5#define REC_GET_DONE 6#define CFG_MAGIC_NUMBER 0x434D4D4C /* CMML */// by Oleg can be 0x0300 #define CFG_VERSION_NUMBER 0x0200int ftpServerStatus = STATUS_NONE;int rebootFlag = FALSE;static char buffer[ftp_MaxData];static longword ftpRemoteHost;static longword ftpRemotePort;static int dlen;static bit32 flashAddress;static bit32u flashOffset;static bit32 endAddress;static bit32u ramAddress;static bit32u recState, recLen, recAddr, recChecksum;static short ftpMedia;static short ftpType;static FTPCommand commandList[] = { {TOK_ABOR, "ABOR", FALSE},/*Abort transfer: ABOR.*//* {TOK_BYE, "BYE", FALSE}, Logout or break connection: BYE.*/ {TOK_QUIT, "QUIT", FALSE},/*Logout or break connection: QUIT.*/ {TOK_PORT, "PORT", TRUE}, /*Specify the client port number: PORT a0,a1,a2,a3,a4,a5.*/ {TOK_USER, "USER", TRUE}, /*Supply a username: USER username.*/ {TOK_PASS, "PASS", TRUE}, /*Supply a user password: PASS password.*//* #if 0 */ {TOK_HELP, "HELP", FALSE},/*Show help: HELP*//* #endif *//* {TOK_SYST, "SYST", FALSE}, Get operating system type: SYST.*/ {TOK_PASV, "PASV", FALSE},/*Set server in passive mode: PASV.*//* {TOK_PASW, "P@SW", FALSE}, Set server in passive mode: P@SV.*/#if 0 {TOK_NLST, "NLST", FALSE},/*List filenames only: NLST.*/ {TOK_LIST, "LIST", FALSE},/*Get directory listing: LIST.*/#endif {TOK_STOR, "STOR", TRUE}, /*Store file: STOR file-name.*/ {TOK_TYPE, "TYPE", TRUE}, /*Set filetype: TYPE [A | I].*/ {TOK_RETR, "RETR", TRUE}, /*Get file: RETR file-name.*/ {TOK_MEDIA, "MEDIA", TRUE}, /*Set storage media - Flash/SDRAM: MEDIA [FLSH | SDRM].*/ {TOK_GETENV, "GETENV",TRUE}, /*Retreive the value for an env variable: GET env-name.*/ {TOK_SETENV, "SETENV",TRUE}, /*Set an env value-variable pair: SET env-name,value.*/ {TOK_UNSETENV,"UNSETENV",TRUE}, /*Unset an env value-variable pair: UNSET env-name.*/ {TOK_FIXENV, "FIXENV",FALSE},/*rebuild env: FIXENV.*/ {TOK_PRINTENV,"PRINTENV",FALSE},/*print env variables: PRINTENV.*/ {TOK_REBOOT, "REBOOT",FALSE},/*Reboot the server: REBOOT.*/ {TOK_ERROR, "", FALSE},};void FlushICache(void);int RetrConfigSpace(tcp_Socket *s);int RetrMtdSpace(tcp_Socket *s);void FTPSend (tcp_Socket *s, char *data, int len){ char *sr; char *dp; sr = data; dp = (char *)ftp_outbuf; if (len == 0) len = strlen(data); if (len > ftp_MaxData) len = ftp_MaxData; sys_memcpy(dp, data, len); ftp_outbuflen = len; ftp_outbufix = 0; if ( len > 0 ) { len = tcp_Write(s, &ftp_outbuf[ftp_outbufix], len); ftp_outbufix += len; tcp_Flush(s); }}int flashStore (byte *dp, int len){ if ((dlen == 0) && (dp)) { if (FWBValid((bit32u)flashAddress) == 0) { return FALSE; } if (FWBOpen((bit32u)flashAddress) == 0) { return FALSE; } /* The code assumes that every time you want to start writing to the flash you want * to start at the beginning of the block. Since the env var and cfgman data are * sharing the same block, this is no longer true. Therefore, we include this * hack here to adjust the offset on the first write */ flashAddress+=flashOffset; sys_printf("WriteToFlash\n"); } if ((flashAddress + len) > endAddress) return FALSE; if ((dp) && (len)) { WriteToFlash((UINT8 *)flashAddress, (UINT8 *)dp, len); dlen += len; flashAddress += len; } return TRUE;}int ramStore (byte *dp, int len){ bit32u recTag, newChecksum; static UINT32 TotalBytes = 0; while (len) { switch (recState) { case REC_GET_TAG: if (getf32((bit32u)dp, &recTag, FALSE) == 4) { if (recTag != TAG_WANTED) { recState = REC_GET_ABORT; sys_printf("Error: File for wrong endian.\n"); } else recState = REC_GET_LEN; } ramAddress = 0; len -= 4; dp += 4; sys_printf("\n"); break; case REC_GET_LEN: if (getf32((bit32u)dp, &recLen, FALSE) == 4) { recChecksum = recLen; recState = REC_GET_ADDR; } len -= 4; dp += 4; break; case REC_GET_ADDR: if (getf32((bit32u)dp, &recAddr, FALSE) == 4) { if (recLen == 0) { ramAddress = recAddr; recState = REC_GET_DONE; } else { recChecksum += recAddr; recState = REC_GET_DATA; } } len -= 4; dp += 4; break; case REC_GET_DATA: while ((recLen != 0) && (len != 0)) { recChecksum += ((bit32u)*dp)&0x0ff; *(char *)recAddr++ = *dp++; recLen--; len--; if ((TotalBytes++ % INDICATE_WRITE) == 0) sys_printf("."); } if (recLen == 0) recState = REC_GET_CHECKSUM; break; case REC_GET_CHECKSUM: if (getf32((bit32u)dp, &newChecksum, FALSE) == 4) { recChecksum += newChecksum; if (recChecksum != 0) { sys_printf("Error: Bad Checksum.\n"); recState = REC_GET_ABORT; } else recState = REC_GET_LEN; } dp += 4; len -= 4; break; case REC_GET_ABORT: case REC_GET_DONE: len = 0; break; } } if (recState == REC_GET_ABORT) return FALSE; return TRUE;}void FTPDataHandler (tcp_Socket *s, byte *dp, int len, int state){ int ret = FALSE; switch (state) { case SOPEN: dlen = 0; flashOffset=0; recState = REC_GET_TAG; recChecksum = 0; recLen = recAddr = 0; break; case SDATA: if (ftpServerStatus == STATUS_DOWNLOAD) { if (s->dataSize == 0) {// by Oleg if ((RetrConfigSpace(&ftp_data) == FALSE)&&(RetrMtdSpace(&ftp_data) == FALSE)) { dlen = 0; flashOffset=0; tcp_Close(&ftp_data); FTPSend(&ftp_ctl, "226 complete.\r\n", 0); ftpServerStatus = STATUS_IDLE; } } break; } else if (ftpServerStatus != STATUS_UPLOAD) break; if (ftpMedia == MEDIA_FLASH) {// sys_printf("\nflashStore 0x%x to 0x%x offset 0x%x length %d\n", flashAddress, endAddress, flashOffset, len); // by Oleg for debug ret = flashStore(dp, len); } else if (ftpMedia == MEDIA_SDRAM) { ret = ramStore(dp, len); } if (ret == FALSE) { sys_printf("ERROR: Store to media failed\n"); tcp_Close(&ftp_data); FTPSend(&ftp_ctl, "426 Connection close; transfer aborted.\r\n", 0); ftpServerStatus = STATUS_IDLE; } break; case SCLOSE: case SABORT: if (ftpServerStatus != STATUS_UPLOAD) break; if (dlen && (ftpMedia == MEDIA_FLASH)) { if (!FWBClose()) sys_printf("ERROR: Could not close flash block, dlen = %d\n", dlen); } dlen = 0; flashOffset=0; tcp_Close(&ftp_data); FTPSend(&ftp_ctl, "226 Transfer complete.\r\n", 0); ftpServerStatus = STATUS_IDLE; sys_printf("\n"); if ((ftpMedia == MEDIA_SDRAM) && (ramAddress != 0)) { FlushICache(); sys_printf("\nExecuting the RAM image at 0x%x.\n", ramAddress); if (executeProgram(0, ramAddress, 0, NULL) == 0) FTPSend(&ftp_ctl, "200 Execution successful.\r\n", 0); else FTPSend(&ftp_ctl, "214 Execution failed.\r\n", 0); ramAddress = 0; } break; }}int ftpCheckState (void){ if (ftp_data.state != tcp_StateESTAB) return 0; if ((ftpServerStatus != STATUS_PASSIVE) && (ftpServerStatus != STATUS_ACTIVE)) return 0; return 1;}int RetrEnvSpace(tcp_Socket *s){ int i; char *cp,*cp2; for(i=0;i<256;i++) { cp=sys_getienv(i); if (cp) { cp2=sys_getenv(cp); if (!cp2) cp2 = ""; sys_sprintf(buffer, "%-20s %s\r\n", cp, cp2); FTPSend(s, buffer, 0); } } return TRUE;}int RetrMtdSpace(tcp_Socket *s){ int len = (ftp_MaxData - 1); static bit32u size = 0x0; static bit32 configAddress = 0x0; if (dlen == 0) { sys_printf("RetrMtdSpace: 0x%x; 0x%x\r\n", flashAddress, endAddress); configAddress = flashAddress; configAddress &= 0x1fffffff; configAddress |= 0xa0000000; // by Oleg 0xB------- size = endAddress-flashAddress; } if ((configAddress == 0x0) || (size == 0x0)) return FALSE; if (size < len) len = size; sys_memset(buffer, 0, ftp_MaxData); sys_memcpy(buffer, (void *) configAddress, len); FTPSend(s, buffer, len); configAddress += len; // by Oleg : this is static variable=> preserve state dlen += len; size -= len; // by Oleg : this is static variable=> preserve state return TRUE;}int RetrConfigSpace(tcp_Socket *s){ char *cp; bit32u magicNumber, versionNumber; char cfgman_mtd_name[FLASH_ENV_ENTRY_SIZE]; int len = (ftp_MaxData - 1); static bit32u size = 0x0; static bit32 configAddress = 0x0; if (dlen == 0) { /* calculate the address for the config block */ sys_sprintf(cfgman_mtd_name,"mtd%d", CFGMAN_MTD); cp = sys_getenv(cfgman_mtd_name); if ((cp == NULL) || (myatox(cp,&configAddress) == 0)) return FALSE; configAddress &= 0x1fffffff; configAddress |= 0xa0000000; /* adjust for the offset */ configAddress += CFGMAN_MTD_OFFSET; /* Get magic number, version and size, but leave configAddress as it is. */ if ((getf32((bit32u)configAddress, &magicNumber, FALSE) != 4) || (magicNumber != CFG_MAGIC_NUMBER)) return FALSE; configAddress += 4; // by Oleg remove if ((getf32((bit32u)configAddress, &versionNumber, FALSE) != 4) || (versionNumber != CFG_VERSION_NUMBER)) return FALSE; configAddress += 4; if ((getf32((bit32u)configAddress, &size, FALSE) != 4) || (size >= 0xFFFF)) return FALSE;/* by Oleg configAddress += 8; Leaving size and crc; No need to read the crc */ configAddress -= 8; // by Oleg to read config with headrer, to be able "put config.xml" size +=8; } if ((configAddress == 0x0) || (size == 0x0)) return FALSE; if (size < len) len = size; sys_memset(buffer, 0, ftp_MaxData); sys_memcpy(buffer, (void *)configAddress, len); FTPSend(s, buffer, len); configAddress += len; // by Oleg : this is static variable=> preserve state dlen += len; size -= len; // by Oleg : this is static variable=> preserve state return TRUE;}void FTPCommandLine(tcp_Socket *s){ char *cmdstr, *argstr; int ncmd, i, port; char *cp, *start, *end; char *strArr[10]; static char username[USERNAME_LEN]; char ipaddr[USERNAME_LEN]; cmdstr = (char *)ftp_cmdbuf; argstr = strtok(cmdstr, ' '); for (ncmd = TOK_ABOR; ncmd < TOK_ERROR; ncmd++) { if (strcmp(cmdstr, commandList[ncmd].commandName) == 0) { if ((commandList[ncmd].argFlag == TRUE) && (argstr == NULL)) { FTPSend(s, "501 Invalid number of parameters.\r\n", 0); return; } break; } } if ((ncmd != TOK_USER && ncmd != TOK_PASS) && (ftpServerStatus == STATUS_LOGIN)) { FTPSend(s, "530 Please login with USER and PASS.\r\n", 0); sys_memset(username, 0, USERNAME_LEN); return; } switch(ncmd) { case TOK_ABOR: if (ftpServerStatus != STATUS_IDLE) FTPSend(s, "426 Data connection closed.\r\n", 0); FTPSend(s, "226 ABOR command successful.\r\n", 0); if (ftp_data.state != tcp_StateCLOSED) tcp_Abort(&ftp_data); break; // case TOK_BYE: case TOK_QUIT:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -