Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
ftpd.c
00001 /* 00002 * Copyright (c) 2002 Florian Schulze. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 3. Neither the name of the authors nor the names of the contributors 00015 * may be used to endorse or promote products derived from this software 00016 * without specific prior written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 00019 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00021 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 00022 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00023 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00024 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00025 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00026 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00027 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00028 * SUCH DAMAGE. 00029 * 00030 * ftpd.c - This file is part of the FTP daemon for lwIP 00031 * 00032 */ 00033 00034 #include "mbed.h" // DRB 00035 #include "SDFileSystem.h" // DRB 00036 #include "EthernetNetIf.h" 00037 #include "HTTPServer.h" 00038 00039 #include "lwip/debug.h" 00040 00041 #include "lwip/stats.h" 00042 00043 #include "ftpd.h" 00044 00045 #include "lwip/tcp.h" 00046 00047 #include <stdio.h> 00048 #include <stdarg.h> 00049 //..#include <malloc.h> 00050 #ifdef _WIN32 00051 #include <string.h> 00052 #endif 00053 #include <ctype.h> 00054 #include <errno.h> 00055 #include <time.h> 00056 00057 #include "vfs.h" 00058 } 00059 00060 00061 extern void printit( char *p_buf ); 00062 00063 00064 #ifdef FTPD_DEBUG 00065 int dbg_printf(const char *fmt, ...); 00066 #else 00067 #ifdef _MSC_VER 00068 #define dbg_printf(x) /* x */ 00069 #else 00070 #define dbg_printf(f, ...) /* */ 00071 #endif 00072 #endif 00073 00074 #define msg110 "110 MARK %s = %s." 00075 /* 00076 110 Restart marker reply. 00077 In this case, the text is exact and not left to the 00078 particular implementation; it must read: 00079 MARK yyyy = mmmm 00080 Where yyyy is User-process data stream marker, and mmmm 00081 server's equivalent marker (note the spaces between markers 00082 and "="). 00083 */ 00084 #define msg120 "120 Service ready in nnn minutes." 00085 #define msg125 "125 Data connection already open; transfer starting." 00086 #define msg150 "150 File status okay; about to open data connection." 00087 #define msg150recv "150 Opening BINARY mode data connection for %s (%i bytes)." 00088 #define msg150stor "150 Opening BINARY mode data connection for %s." 00089 #define msg200 "200 Command okay." 00090 #define msg202 "202 Command not implemented, superfluous at this site." 00091 #define msg211 "211 System status, or system help reply." 00092 #define msg212 "212 Directory status." 00093 #define msg213 "213 File status." 00094 #define msg214 "214 %s." 00095 /* 00096 214 Help message. 00097 On how to use the server or the meaning of a particular 00098 non-standard command. This reply is useful only to the 00099 human user. 00100 */ 00101 #define msg214SYST "214 %s system type." 00102 /* 00103 215 NAME system type. 00104 Where NAME is an official system name from the list in the 00105 Assigned Numbers document. 00106 */ 00107 #define msg220 "220 lwIP FTP Server ready." 00108 /* 00109 220 Service ready for new user. 00110 */ 00111 #define msg221 "221 Goodbye." 00112 /* 00113 221 Service closing control connection. 00114 Logged out if appropriate. 00115 */ 00116 #define msg225 "225 Data connection open; no transfer in progress." 00117 #define msg226 "226 Closing data connection." 00118 /* 00119 Requested file action successful (for example, file 00120 transfer or file abort). 00121 */ 00122 #define msg227 "227 Entering Passive Mode (%i,%i,%i,%i,%i,%i)." 00123 /* 00124 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). 00125 */ 00126 #define msg230 "230 User logged in, proceed." 00127 #define msg250 "250 Requested file action okay, completed." 00128 #define msg257PWD "257 \"%s\" is current directory." 00129 #define msg257 "257 \"%s\" created." 00130 /* 00131 257 "PATHNAME" created. 00132 */ 00133 #define msg331 "331 User name okay, need password." 00134 #define msg332 "332 Need account for login." 00135 #define msg350 "350 Requested file action pending further information." 00136 #define msg421 "421 Service not available, closing control connection." 00137 /* 00138 This may be a reply to any command if the service knows it 00139 must shut down. 00140 */ 00141 #define msg425 "425 Can't open data connection." 00142 #define msg426 "426 Connection closed; transfer aborted." 00143 #define msg450 "450 Requested file action not taken." 00144 /* 00145 File unavailable (e.g., file busy). 00146 */ 00147 #define msg451 "451 Requested action aborted: local error in processing." 00148 #define msg452 "452 Requested action not taken." 00149 /* 00150 Insufficient storage space in system. 00151 */ 00152 #define msg500 "500 Syntax error, command unrecognized." 00153 /* 00154 This may include errors such as command line too long. 00155 */ 00156 #define msg501 "501 Syntax error in parameters or arguments." 00157 #define msg502 "502 Command not implemented." 00158 #define msg503 "503 Bad sequence of commands." 00159 #define msg504 "504 Command not implemented for that parameter." 00160 #define msg530 "530 Not logged in." 00161 #define msg532 "532 Need account for storing files." 00162 #define msg550 "550 Requested action not taken." 00163 /* 00164 File unavailable (e.g., file not found, no access). 00165 */ 00166 #define msg551 "551 Requested action aborted: page type unknown." 00167 #define msg552 "552 Requested file action aborted." 00168 /* 00169 Exceeded storage allocation (for current directory or 00170 dataset). 00171 */ 00172 #define msg553 "553 Requested action not taken." 00173 /* 00174 File name not allowed. 00175 */ 00176 00177 enum ftpd_state_e { 00178 FTPD_USER, 00179 FTPD_PASS, 00180 FTPD_IDLE, 00181 FTPD_NLST, 00182 FTPD_LIST, 00183 FTPD_RETR, 00184 FTPD_RNFR, 00185 FTPD_STOR, 00186 FTPD_QUIT 00187 }; 00188 00189 static const char *month_table[12] = { 00190 "Jan", 00191 "Feb", 00192 "Mar", 00193 "Apr", 00194 "May", 00195 "Jun", 00196 "Jul", 00197 "Aug", 00198 "Sep", 00199 "Oct", 00200 "Nov", 00201 "Dez" 00202 }; 00203 00204 /* 00205 ------------------------------------------------------------ 00206 SFIFO 1.3 00207 ------------------------------------------------------------ 00208 * Simple portable lock-free FIFO 00209 * (c) 2000-2002, David Olofson 00210 * 00211 * Platform support: 00212 * gcc / Linux / x86: Works 00213 * gcc / Linux / x86 kernel: Works 00214 * gcc / FreeBSD / x86: Works 00215 * gcc / NetBSD / x86: Works 00216 * gcc / Mac OS X / PPC: Works 00217 * gcc / Win32 / x86: Works 00218 * Borland C++ / DOS / x86RM: Works 00219 * Borland C++ / Win32 / x86PM16: Untested 00220 * ? / Various Un*ces / ?: Untested 00221 * ? / Mac OS / PPC: Untested 00222 * gcc / BeOS / x86: Untested 00223 * gcc / BeOS / PPC: Untested 00224 * ? / ? / Alpha: Untested 00225 * 00226 * 1.2: Max buffer size halved, to avoid problems with 00227 * the sign bit... 00228 * 00229 * 1.3: Critical buffer allocation bug fixed! For certain 00230 * requested buffer sizes, older version would 00231 * allocate a buffer of insufficient size, which 00232 * would result in memory thrashing. (Amazing that 00233 * I've manage to use this to the extent I have 00234 * without running into this... *heh*) 00235 */ 00236 00237 /* 00238 * Porting note: 00239 * Reads and writes of a variable of this type in memory 00240 * must be *atomic*! 'int' is *not* atomic on all platforms. 00241 * A safe type should be used, and sfifo should limit the 00242 * maximum buffer size accordingly. 00243 */ 00244 typedef int sfifo_atomic_t; 00245 #ifdef __TURBOC__ 00246 # define SFIFO_MAX_BUFFER_SIZE 0x7fff 00247 #else /* Kludge: Assume 32 bit platform */ 00248 # define SFIFO_MAX_BUFFER_SIZE 0x7fffffff 00249 #endif 00250 00251 typedef struct sfifo_t 00252 { 00253 char *buffer; 00254 int size; /* Number of bytes */ 00255 sfifo_atomic_t readpos; /* Read position */ 00256 sfifo_atomic_t writepos; /* Write position */ 00257 } sfifo_t; 00258 00259 #define SFIFO_SIZEMASK(x) ((x)->size - 1) 00260 00261 #define sfifo_used(x) (((x)->writepos - (x)->readpos) & SFIFO_SIZEMASK(x)) 00262 #define sfifo_space(x) ((x)->size - 1 - sfifo_used(x)) 00263 00264 //..DRB #define DBG(x) 00265 00266 /* 00267 * Alloc buffer, init FIFO etc... 00268 */ 00269 static int sfifo_init(sfifo_t *f, int size) 00270 { 00271 memset(f, 0, sizeof(sfifo_t)); 00272 00273 if(size > SFIFO_MAX_BUFFER_SIZE) 00274 return -EINVAL; 00275 00276 /* 00277 * Set sufficient power-of-2 size. 00278 * 00279 * No, there's no bug. If you need 00280 * room for N bytes, the buffer must 00281 * be at least N+1 bytes. (The fifo 00282 * can't tell 'empty' from 'full' 00283 * without unsafe index manipulations 00284 * otherwise.) 00285 */ 00286 f->size = 1; 00287 for(; f->size <= size; f->size <<= 1) 00288 ; 00289 00290 /* Get buffer */ 00291 if( 0 == (f->buffer = (char *)malloc(f->size)) ) 00292 return -ENOMEM; 00293 00294 return 0; 00295 } 00296 00297 /* 00298 * Dealloc buffer etc... 00299 */ 00300 static void sfifo_close(sfifo_t *f) 00301 { 00302 if(f->buffer) 00303 free(f->buffer); 00304 } 00305 00306 /* 00307 * Empty FIFO buffer 00308 */ 00309 static void sfifo_flush(sfifo_t *f) 00310 { 00311 /* Reset positions */ 00312 f->readpos = 0; 00313 f->writepos = 0; 00314 } 00315 00316 /* 00317 * Write bytes to a FIFO 00318 * Return number of bytes written, or an error code 00319 */ 00320 static int sfifo_write(sfifo_t *f, const void *_buf, int len) 00321 { 00322 int total; 00323 int i; 00324 const char *buf = (const char *)_buf; 00325 00326 if(!f->buffer) 00327 return -ENODEV; /* No buffer! */ 00328 00329 /* total = len = min(space, len) */ 00330 total = sfifo_space(f); 00331 DBG(dbg_printf("sfifo_space() = %d\n",total)); 00332 if(len > total) 00333 len = total; 00334 else 00335 total = len; 00336 00337 i = f->writepos; 00338 if(i + len > f->size) 00339 { 00340 memcpy(f->buffer + i, buf, f->size - i); 00341 buf += f->size - i; 00342 len -= f->size - i; 00343 i = 0; 00344 } 00345 memcpy(f->buffer + i, buf, len); 00346 f->writepos = i + len; 00347 00348 return total; 00349 } 00350 00351 /* 00352 * Read bytes from a FIFO 00353 * Return number of bytes read, or an error code 00354 */ 00355 static int sfifo_read(sfifo_t *f, void *_buf, int len) 00356 { 00357 int total; 00358 int i; 00359 char *buf = (char *)_buf; 00360 00361 if(!f->buffer) 00362 return -ENODEV; /* No buffer! */ 00363 00364 /* total = len = min(used, len) */ 00365 total = sfifo_used(f); 00366 DBG(dbg_printf("sfifo_used() = %d\n",total)); 00367 if(len > total) 00368 len = total; 00369 else 00370 total = len; 00371 00372 i = f->readpos; 00373 if(i + len > f->size) 00374 { 00375 memcpy(buf, f->buffer + i, f->size - i); 00376 buf += f->size - i; 00377 len -= f->size - i; 00378 i = 0; 00379 } 00380 memcpy(buf, f->buffer + i, len); 00381 f->readpos = i + len; 00382 00383 return total; 00384 } 00385 00386 struct ftpd_datastate { 00387 int connected; 00388 vfs_dir_t *vfs_dir; 00389 vfs_dirent_t *vfs_dirent; 00390 vfs_file_t *vfs_file; 00391 sfifo_t fifo; 00392 struct tcp_pcb *msgpcb; 00393 struct ftpd_msgstate *msgfs; 00394 }; 00395 00396 struct ftpd_msgstate { 00397 enum ftpd_state_e state; 00398 sfifo_t fifo; 00399 vfs_t *vfs; 00400 struct ip_addr dataip; 00401 u16_t dataport; 00402 struct tcp_pcb *datapcb; 00403 struct ftpd_datastate *datafs; 00404 int passive; 00405 char *renamefrom; 00406 }; 00407 00408 static void send_msg(struct tcp_pcb *pcb, struct ftpd_msgstate *fsm, char *msg, ...); 00409 00410 static void ftpd_dataerr(void *arg, err_t err) 00411 { 00412 struct ftpd_datastate *fsd = (struct ftpd_datastate*)arg; 00413 00414 dbg_printf("ftpd_dataerr: %s (%i)\n", lwip_strerr(err), err); 00415 if (fsd == NULL) 00416 return; 00417 fsd->msgfs->datafs = NULL; 00418 fsd->msgfs->state = FTPD_IDLE; 00419 free(fsd); 00420 } 00421 00422 static void ftpd_dataclose(struct tcp_pcb *pcb, struct ftpd_datastate *fsd) 00423 { 00424 tcp_arg(pcb, NULL); 00425 tcp_sent(pcb, NULL); 00426 tcp_recv(pcb, NULL); 00427 fsd->msgfs->datafs = NULL; 00428 sfifo_close(&fsd->fifo); 00429 free(fsd); 00430 tcp_arg(pcb, NULL); 00431 tcp_close(pcb); 00432 } 00433 00434 static void send_data(struct tcp_pcb *pcb, struct ftpd_datastate *fsd) 00435 { 00436 err_t err; 00437 u16_t len; 00438 00439 if (sfifo_used(&fsd->fifo) > 0) { 00440 int i; 00441 00442 /* We cannot send more data than space available in the send 00443 buffer. */ 00444 if (tcp_sndbuf(pcb) < sfifo_used(&fsd->fifo)) { 00445 len = tcp_sndbuf(pcb); 00446 } else { 00447 len = (u16_t) sfifo_used(&fsd->fifo); 00448 } 00449 00450 i = fsd->fifo.readpos; 00451 if ((i + len) > fsd->fifo.size) { 00452 err = tcp_write(pcb, fsd->fifo.buffer + i, (u16_t)(fsd->fifo.size - i), 1); 00453 if (err != ERR_OK) { 00454 dbg_printf("send_data: error writing!\n"); 00455 return; 00456 } 00457 len -= fsd->fifo.size - i; 00458 fsd->fifo.readpos = 0; 00459 i = 0; 00460 } 00461 00462 err = tcp_write(pcb, fsd->fifo.buffer + i, len, 1); 00463 if (err != ERR_OK) { 00464 dbg_printf("send_data: error writing!\n"); 00465 return; 00466 } 00467 fsd->fifo.readpos += len; 00468 } 00469 } 00470 00471 static void send_file( struct ftpd_datastate *fsd, struct tcp_pcb *pcb ) 00472 { 00473 if (!fsd->connected) 00474 return; 00475 00476 if (fsd->vfs_file) 00477 { 00478 char buffer[ 2048 ]; 00479 int len; 00480 00481 len = sfifo_space( &fsd->fifo ); 00482 if (len == 0) 00483 { 00484 send_data(pcb, fsd); 00485 return; 00486 } 00487 if (len > 2048) 00488 len = 2048; 00489 len = vfs_read( buffer, 1, len, fsd->vfs_file ); 00490 if( len == 0 ) 00491 { 00492 if( vfs_eof( fsd->vfs_file ) == 0) 00493 return; 00494 vfs_close( fsd->vfs_file ); 00495 fsd->vfs_file = NULL; 00496 return; 00497 } 00498 sfifo_write( &fsd->fifo, buffer, len ); 00499 send_data( pcb, fsd ); 00500 } else { 00501 struct ftpd_msgstate *fsm; 00502 struct tcp_pcb *msgpcb; 00503 00504 if (sfifo_used(&fsd->fifo) > 0) { 00505 send_data(pcb, fsd); 00506 return; 00507 } 00508 fsm = fsd->msgfs; 00509 msgpcb = fsd->msgpcb; 00510 00511 vfs_close( fsd->vfs_file ); 00512 fsd->vfs_file = NULL; 00513 ftpd_dataclose( pcb, fsd ); 00514 fsm->datapcb = NULL; 00515 fsm->datafs = NULL; 00516 fsm->state = FTPD_IDLE; 00517 send_msg( msgpcb, fsm, msg226 ); 00518 // printit( msg226 ); 00519 return; 00520 } 00521 } 00522 00523 static void send_next_directory(struct ftpd_datastate *fsd, struct tcp_pcb *pcb, int shortlist) 00524 { 00525 char buffer[1024]; 00526 int len; 00527 00528 while (1) { 00529 if (fsd->vfs_dirent == NULL) 00530 fsd->vfs_dirent = vfs_readdir(fsd->vfs_dir); 00531 00532 if (fsd->vfs_dirent) { 00533 if (shortlist) { 00534 len = sprintf(buffer, "%s\r\n", fsd->vfs_dirent->name); 00535 if (sfifo_space(&fsd->fifo) < len) { 00536 send_data(pcb, fsd); 00537 return; 00538 } 00539 sfifo_write(&fsd->fifo, buffer, len); 00540 fsd->vfs_dirent = NULL; 00541 } else { 00542 vfs_stat_t st; 00543 time_t current_time; 00544 int current_year; 00545 struct tm *s_time; 00546 00547 time(¤t_time); 00548 s_time = gmtime(¤t_time); 00549 current_year = s_time->tm_year; 00550 00551 //..DRB vfs_stat(fsd->msgfs->vfs, fsd->vfs_dirent->name, &st); 00552 s_time = gmtime(&st.st_mtime); 00553 if (s_time->tm_year == current_year) 00554 len = sprintf(buffer, "-rw-rw-rw- 1 user ftp %11ld %s %02i %02i:%02i %s\r\n", st.st_size, month_table[s_time->tm_mon], s_time->tm_mday, s_time->tm_hour, s_time->tm_min, fsd->vfs_dirent->name); 00555 else 00556 len = sprintf(buffer, "-rw-rw-rw- 1 user ftp %11ld %s %02i %5i %s\r\n", st.st_size, month_table[s_time->tm_mon], s_time->tm_mday, s_time->tm_year + 1900, fsd->vfs_dirent->name); 00557 if (VFS_ISDIR(st.st_mode)) 00558 buffer[0] = 'd'; 00559 if (sfifo_space(&fsd->fifo) < len) { 00560 send_data(pcb, fsd); 00561 return; 00562 } 00563 sfifo_write(&fsd->fifo, buffer, len); 00564 fsd->vfs_dirent = NULL; 00565 } 00566 } else { 00567 struct ftpd_msgstate *fsm; 00568 struct tcp_pcb *msgpcb; 00569 00570 if (sfifo_used(&fsd->fifo) > 0) { 00571 send_data(pcb, fsd); 00572 return; 00573 } 00574 fsm = fsd->msgfs; 00575 msgpcb = fsd->msgpcb; 00576 00577 vfs_closedir(fsd->vfs_dir); 00578 fsd->vfs_dir = NULL; 00579 ftpd_dataclose(pcb, fsd); 00580 fsm->datapcb = NULL; 00581 fsm->datafs = NULL; 00582 fsm->state = FTPD_IDLE; 00583 send_msg(msgpcb, fsm, msg226); 00584 return; 00585 } 00586 } 00587 } 00588 00589 static err_t ftpd_datasent(void *arg, struct tcp_pcb *pcb, u16_t len) 00590 { 00591 struct ftpd_datastate *fsd = (struct ftpd_datastate*)arg; 00592 00593 switch (fsd->msgfs->state) { 00594 case FTPD_LIST: 00595 send_next_directory(fsd, pcb, 0); 00596 break; 00597 case FTPD_NLST: 00598 send_next_directory(fsd, pcb, 1); 00599 break; 00600 case FTPD_RETR: 00601 send_file(fsd, pcb); 00602 break; 00603 default: 00604 break; 00605 } 00606 00607 return ERR_OK; 00608 } 00609 00610 static err_t ftpd_datarecv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) 00611 { 00612 struct ftpd_datastate *fsd = (struct ftpd_datastate*)arg; 00613 00614 if (err == ERR_OK && p != NULL) { 00615 struct pbuf *q; 00616 u16_t tot_len = 0; 00617 00618 for (q = p; q != NULL; q = q->next) { 00619 int len; 00620 00621 len = vfs_write(q->payload, 1, q->len, fsd->vfs_file); 00622 tot_len += len; 00623 if (len != q->len) 00624 break; 00625 } 00626 00627 /* Inform TCP that we have taken the data. */ 00628 tcp_recved(pcb, tot_len); 00629 00630 pbuf_free(p); 00631 } 00632 if (err == ERR_OK && p == NULL) { 00633 struct ftpd_msgstate *fsm; 00634 struct tcp_pcb *msgpcb; 00635 00636 fsm = fsd->msgfs; 00637 msgpcb = fsd->msgpcb; 00638 00639 vfs_close(fsd->vfs_file); 00640 fsd->vfs_file = NULL; 00641 ftpd_dataclose(pcb, fsd); 00642 fsm->datapcb = NULL; 00643 fsm->datafs = NULL; 00644 fsm->state = FTPD_IDLE; 00645 send_msg(msgpcb, fsm, msg226); 00646 } 00647 00648 return ERR_OK; 00649 } 00650 00651 static err_t ftpd_dataconnected(void *arg, struct tcp_pcb *pcb, err_t err) 00652 { 00653 struct ftpd_datastate *fsd = (struct ftpd_datastate*)arg; 00654 00655 fsd->msgfs->datapcb = pcb; 00656 fsd->connected = 1; 00657 00658 /* Tell TCP that we wish to be informed of incoming data by a call 00659 to the http_recv() function. */ 00660 tcp_recv(pcb, ftpd_datarecv); 00661 00662 /* Tell TCP that we wish be to informed of data that has been 00663 successfully sent by a call to the ftpd_sent() function. */ 00664 tcp_sent(pcb, ftpd_datasent); 00665 00666 tcp_err(pcb, ftpd_dataerr); 00667 00668 switch (fsd->msgfs->state) { 00669 case FTPD_LIST: 00670 send_next_directory(fsd, pcb, 0); 00671 break; 00672 case FTPD_NLST: 00673 send_next_directory(fsd, pcb, 1); 00674 break; 00675 case FTPD_RETR: 00676 send_file(fsd, pcb); 00677 break; 00678 default: 00679 break; 00680 } 00681 00682 return ERR_OK; 00683 } 00684 00685 static err_t ftpd_dataaccept(void *arg, struct tcp_pcb *pcb, err_t err) 00686 { 00687 struct ftpd_datastate *fsd = (struct ftpd_datastate*)arg; 00688 00689 fsd->msgfs->datapcb = pcb; 00690 fsd->connected = 1; 00691 00692 /* Tell TCP that we wish to be informed of incoming data by a call 00693 to the http_recv() function. */ 00694 tcp_recv(pcb, ftpd_datarecv); 00695 00696 /* Tell TCP that we wish be to informed of data that has been 00697 successfully sent by a call to the ftpd_sent() function. */ 00698 tcp_sent(pcb, ftpd_datasent); 00699 00700 tcp_err(pcb, ftpd_dataerr); 00701 00702 switch (fsd->msgfs->state) { 00703 case FTPD_LIST: 00704 send_next_directory(fsd, pcb, 0); 00705 break; 00706 case FTPD_NLST: 00707 send_next_directory(fsd, pcb, 1); 00708 break; 00709 case FTPD_RETR: 00710 send_file(fsd, pcb); 00711 break; 00712 default: 00713 break; 00714 } 00715 00716 return ERR_OK; 00717 } 00718 00719 static int open_dataconnection(struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 00720 { 00721 if (fsm->passive) 00722 return 0; 00723 00724 /* Allocate memory for the structure that holds the state of the connection. */ 00725 fsm->datafs = (struct ftpd_datastate*)malloc(sizeof(struct ftpd_datastate)); 00726 00727 if (fsm->datafs == NULL) { 00728 send_msg(pcb, fsm, msg451); 00729 return 1; 00730 } 00731 memset(fsm->datafs, 0, sizeof(struct ftpd_datastate)); 00732 fsm->datafs->msgfs = fsm; 00733 fsm->datafs->msgpcb = pcb; 00734 sfifo_init(&fsm->datafs->fifo, 2000); 00735 00736 fsm->datapcb = tcp_new(); 00737 tcp_bind(fsm->datapcb, &pcb->local_ip, 20); 00738 /* Tell TCP that this is the structure we wish to be passed for our 00739 callbacks. */ 00740 tcp_arg(fsm->datapcb, fsm->datafs); 00741 tcp_connect(fsm->datapcb, &fsm->dataip, fsm->dataport, ftpd_dataconnected); 00742 00743 return 0; 00744 } 00745 00746 static void cmd_user(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 00747 { 00748 send_msg(pcb, fsm, msg331); 00749 fsm->state = FTPD_PASS; 00750 /* 00751 send_msg(pcb, fs, msgLoginFailed); 00752 fs->state = FTPD_QUIT; 00753 */ 00754 } 00755 00756 static void cmd_pass(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 00757 { 00758 send_msg(pcb, fsm, msg230); 00759 fsm->state = FTPD_IDLE; 00760 /* 00761 send_msg(pcb, fs, msgLoginFailed); 00762 fs->state = FTPD_QUIT; 00763 */ 00764 } 00765 00766 static void cmd_port(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 00767 { 00768 int nr; 00769 unsigned pHi, pLo; 00770 unsigned ip[4]; 00771 00772 nr = sscanf(arg, "%u,%u,%u,%u,%u,%u", &(ip[0]), &(ip[1]), &(ip[2]), &(ip[3]), &pHi, &pLo); 00773 if (nr != 6) { 00774 send_msg(pcb, fsm, msg501); 00775 } else { 00776 IP4_ADDR(&fsm->dataip, (u8_t) ip[0], (u8_t) ip[1], (u8_t) ip[2], (u8_t) ip[3]); 00777 fsm->dataport = ((u16_t) pHi << 8) | (u16_t) pLo; 00778 send_msg(pcb, fsm, msg200); 00779 } 00780 } 00781 00782 static void cmd_quit(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 00783 { 00784 send_msg(pcb, fsm, msg221); 00785 fsm->state = FTPD_QUIT; 00786 } 00787 00788 static void cmd_cwd(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 00789 { 00790 if (!vfs_chdir(fsm->vfs, arg)) { 00791 send_msg(pcb, fsm, msg250); 00792 } else { 00793 send_msg(pcb, fsm, msg550); 00794 } 00795 } 00796 00797 static void cmd_cdup(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 00798 { 00799 if (!vfs_chdir(fsm->vfs, "..")) { 00800 send_msg(pcb, fsm, msg250); 00801 } else { 00802 send_msg(pcb, fsm, msg550); 00803 } 00804 } 00805 00806 static void cmd_pwd(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 00807 { 00808 char *path; 00809 00810 path = vfs_getcwd( fsm->vfs, NULL, 0 ); 00811 if( path ) 00812 { 00813 send_msg(pcb, fsm, msg257PWD, path); 00814 free(path); 00815 } 00816 } 00817 00818 static void cmd_list_common(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm, int shortlist) 00819 { 00820 vfs_dir_t *vfs_dir; 00821 char *cwd; 00822 00823 #if 0 00824 cwd = vfs_getcwd(fsm->vfs, NULL, 0); 00825 if ((!cwd)) { 00826 send_msg(pcb, fsm, msg451); 00827 return; 00828 } 00829 #endif 00830 vfs_dir = vfs_opendir(fsm->vfs, cwd); 00831 free(cwd); 00832 if (!vfs_dir) { 00833 send_msg(pcb, fsm, msg451); 00834 return; 00835 } 00836 00837 if( open_dataconnection(pcb, fsm) != 0) 00838 { 00839 vfs_closedir(vfs_dir); 00840 return; 00841 } 00842 00843 fsm->datafs->vfs_dir = vfs_dir; 00844 fsm->datafs->vfs_dirent = NULL; 00845 if (shortlist != 0) 00846 { 00847 fsm->state = FTPD_NLST; 00848 } 00849 else 00850 { 00851 fsm->state = FTPD_LIST; 00852 } 00853 send_msg(pcb, fsm, msg150); 00854 } 00855 00856 00857 static void cmd_nlst(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 00858 { 00859 cmd_list_common(arg, pcb, fsm, 1); 00860 } 00861 00862 static void cmd_list(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 00863 { 00864 cmd_list_common(arg, pcb, fsm, 0); 00865 } 00866 00867 static void cmd_retr(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 00868 { 00869 vfs_file_t *vfs_file; 00870 vfs_stat_t st; 00871 00872 #if 0 00873 vfs_stat(fsm->vfs, arg, &st); 00874 if (!VFS_ISREG(st.st_mode)) 00875 { 00876 send_msg(pcb, fsm, msg550); 00877 return; 00878 } 00879 #endif 00880 vfs_file = vfs_open(fsm->vfs, arg, "rb"); 00881 if (!vfs_file) { 00882 send_msg(pcb, fsm, msg550); 00883 return; 00884 } 00885 00886 send_msg(pcb, fsm, msg150recv, arg, st.st_size); 00887 00888 if (open_dataconnection(pcb, fsm) != 0) { 00889 vfs_close(vfs_file); 00890 return; 00891 } 00892 00893 fsm->datafs->vfs_file = vfs_file; 00894 fsm->state = FTPD_RETR; 00895 } 00896 00897 static void cmd_stor(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 00898 { 00899 vfs_file_t *vfs_file; 00900 00901 vfs_file = vfs_open(fsm->vfs, arg, "wb"); 00902 if (!vfs_file) { 00903 send_msg(pcb, fsm, msg550); 00904 return; 00905 } 00906 00907 send_msg(pcb, fsm, msg150stor, arg); 00908 00909 if (open_dataconnection(pcb, fsm) != 0) { 00910 vfs_close(vfs_file); 00911 return; 00912 } 00913 00914 fsm->datafs->vfs_file = vfs_file; 00915 fsm->state = FTPD_STOR; 00916 } 00917 00918 static void cmd_noop(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 00919 { 00920 send_msg(pcb, fsm, msg200); 00921 } 00922 00923 static void cmd_syst(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 00924 { 00925 send_msg(pcb, fsm, msg214SYST, "UNIX"); 00926 } 00927 00928 static void cmd_pasv(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 00929 { 00930 static u16_t port = 4096; 00931 static u16_t start_port = 4096; 00932 struct tcp_pcb *temppcb; 00933 00934 /* Allocate memory for the structure that holds the state of the connection. */ 00935 fsm->datafs = (struct ftpd_datastate*)malloc(sizeof(struct ftpd_datastate)); 00936 00937 if (fsm->datafs == NULL) { 00938 send_msg(pcb, fsm, msg451); 00939 return; 00940 } 00941 memset(fsm->datafs, 0, sizeof(struct ftpd_datastate)); 00942 00943 fsm->datapcb = tcp_new(); 00944 if (!fsm->datapcb) { 00945 free(fsm->datafs); 00946 send_msg(pcb, fsm, msg451); 00947 return; 00948 } 00949 00950 sfifo_init(&fsm->datafs->fifo, 2000); 00951 00952 start_port = port; 00953 00954 while (1) { 00955 err_t err; 00956 00957 if(++port > 0x7fff) 00958 port = 4096; 00959 00960 fsm->dataport = port; 00961 err = tcp_bind(fsm->datapcb, &pcb->local_ip, fsm->dataport); 00962 if (err == ERR_OK) 00963 break; 00964 if (start_port == port) 00965 err = ERR_CLSD; 00966 if (err == ERR_USE) 00967 continue; 00968 if (err != ERR_OK) { 00969 ftpd_dataclose(fsm->datapcb, fsm->datafs); 00970 fsm->datapcb = NULL; 00971 fsm->datafs = NULL; 00972 return; 00973 } 00974 } 00975 00976 temppcb = tcp_listen(fsm->datapcb); 00977 if (!temppcb) { 00978 ftpd_dataclose(fsm->datapcb, fsm->datafs); 00979 fsm->datapcb = NULL; 00980 fsm->datafs = NULL; 00981 return; 00982 } 00983 fsm->datapcb = temppcb; 00984 00985 fsm->passive = 1; 00986 fsm->datafs->connected = 0; 00987 fsm->datafs->msgfs = fsm; 00988 fsm->datafs->msgpcb = pcb; 00989 00990 /* Tell TCP that this is the structure we wish to be passed for our 00991 callbacks. */ 00992 tcp_arg(fsm->datapcb, fsm->datafs); 00993 00994 tcp_accept(fsm->datapcb, ftpd_dataaccept); 00995 send_msg(pcb, fsm, msg227, ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip), ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), (fsm->dataport >> 8) & 0xff, (fsm->dataport) & 0xff); 00996 } 00997 00998 static void cmd_abrt(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 00999 { 01000 if (fsm->datafs != NULL) { 01001 tcp_arg(fsm->datapcb, NULL); 01002 tcp_sent(fsm->datapcb, NULL); 01003 tcp_recv(fsm->datapcb, NULL); 01004 tcp_arg(fsm->datapcb, NULL); 01005 tcp_abort(pcb); 01006 sfifo_close(&fsm->datafs->fifo); 01007 free(fsm->datafs); 01008 fsm->datafs = NULL; 01009 } 01010 fsm->state = FTPD_IDLE; 01011 } 01012 01013 static void cmd_type(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 01014 { 01015 dbg_printf("Got TYPE -%s-\n", arg); 01016 //printit( "Got TYPE -" ); 01017 //printit( (char*)arg ); // ASCII text 01018 01019 if( *arg == 'A' ) 01020 { 01021 send_msg(pcb, fsm, "200 Type set to A." ); 01022 } 01023 else 01024 { 01025 send_msg(pcb, fsm, msg502); 01026 } 01027 } 01028 01029 static void cmd_mode(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 01030 { 01031 dbg_printf("Got MODE -%s-\n", arg); 01032 //printit( "Got MODE -" ); 01033 //printit( (char*)arg ); 01034 send_msg(pcb, fsm, msg502); 01035 } 01036 01037 static void cmd_rnfr(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 01038 { 01039 if (arg == NULL) { 01040 send_msg(pcb, fsm, msg501); 01041 return; 01042 } 01043 if (*arg == '\0') { 01044 send_msg(pcb, fsm, msg501); 01045 return; 01046 } 01047 if (fsm->renamefrom) 01048 free(fsm->renamefrom); 01049 fsm->renamefrom = (char*)malloc(strlen(arg) + 1); 01050 if (fsm->renamefrom == NULL) { 01051 send_msg(pcb, fsm, msg451); 01052 return; 01053 } 01054 strcpy(fsm->renamefrom, arg); 01055 fsm->state = FTPD_RNFR; 01056 send_msg(pcb, fsm, msg350); 01057 } 01058 01059 static void cmd_rnto(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 01060 { 01061 if (fsm->state != FTPD_RNFR) { 01062 send_msg(pcb, fsm, msg503); 01063 return; 01064 } 01065 fsm->state = FTPD_IDLE; 01066 if (arg == NULL) { 01067 send_msg(pcb, fsm, msg501); 01068 return; 01069 } 01070 if (*arg == '\0') { 01071 send_msg(pcb, fsm, msg501); 01072 return; 01073 } 01074 if (vfs_rename(fsm->vfs, fsm->renamefrom, arg)) { 01075 send_msg(pcb, fsm, msg450); 01076 } else { 01077 send_msg(pcb, fsm, msg250); 01078 } 01079 } 01080 01081 static void cmd_mkd(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 01082 { 01083 if (arg == NULL) { 01084 send_msg(pcb, fsm, msg501); 01085 return; 01086 } 01087 if (*arg == '\0') { 01088 send_msg(pcb, fsm, msg501); 01089 return; 01090 } 01091 if (vfs_mkdir(fsm->vfs, arg, VFS_IRWXU | VFS_IRWXG | VFS_IRWXO) != 0) { 01092 send_msg(pcb, fsm, msg550); 01093 } else { 01094 send_msg(pcb, fsm, msg257, arg); 01095 } 01096 } 01097 01098 static void cmd_nill(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 01099 { 01100 printit( "cmd_nill" ); 01101 } 01102 01103 01104 static void cmd_rmd(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 01105 { 01106 vfs_stat_t st; 01107 01108 if (arg == NULL) { 01109 send_msg(pcb, fsm, msg501); 01110 return; 01111 } 01112 if (*arg == '\0') { 01113 send_msg(pcb, fsm, msg501); 01114 return; 01115 } 01116 if (vfs_stat(fsm->vfs, arg, &st) != 0) { 01117 send_msg(pcb, fsm, msg550); 01118 return; 01119 } 01120 if (!VFS_ISDIR(st.st_mode)) { 01121 send_msg(pcb, fsm, msg550); 01122 return; 01123 } 01124 if (vfs_rmdir(fsm->vfs, arg) != 0) { 01125 send_msg(pcb, fsm, msg550); 01126 } else { 01127 send_msg(pcb, fsm, msg250); 01128 } 01129 } 01130 01131 static void cmd_dele(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 01132 { 01133 vfs_stat_t st; 01134 01135 if (arg == NULL) { 01136 send_msg(pcb, fsm, msg501); 01137 return; 01138 } 01139 if (*arg == '\0') { 01140 send_msg(pcb, fsm, msg501); 01141 return; 01142 } 01143 #if 0 01144 if (vfs_stat(fsm->vfs, arg, &st) != 0) 01145 { 01146 send_msg(pcb, fsm, msg550); 01147 return; 01148 } 01149 if (!VFS_ISREG(st.st_mode)) 01150 { 01151 send_msg(pcb, fsm, msg550); 01152 return; 01153 } 01154 #endif 01155 if (vfs_remove(fsm->vfs, arg) != 0) 01156 { 01157 send_msg(pcb, fsm, msg550); 01158 } 01159 else 01160 { 01161 send_msg(pcb, fsm, msg250); 01162 } 01163 } 01164 01165 01166 struct ftpd_command { 01167 char *cmd; 01168 void (*func) (const char *arg, struct tcp_pcb * pcb, struct ftpd_msgstate * fsm); 01169 }; 01170 01171 static struct ftpd_command ftpd_commands[] = { 01172 "USER", cmd_user, 01173 "PASS", cmd_pass, 01174 "PORT", cmd_port, 01175 "QUIT", cmd_quit, 01176 "CWD", cmd_cwd, 01177 "CDUP", cmd_cdup, 01178 "PWD", cmd_pwd, 01179 "XPWD", cmd_pwd, 01180 "NLST", cmd_nlst, 01181 "LIST", cmd_list, 01182 "RETR", cmd_retr, 01183 "STOR", cmd_stor, 01184 "NOOP", cmd_noop, 01185 "SYST", cmd_syst, 01186 "ABOR", cmd_abrt, 01187 "TYPE", cmd_type, 01188 "MODE", cmd_mode, 01189 "RNFR", cmd_rnfr, 01190 "RNTO", cmd_rnto, 01191 "MKD", cmd_mkd, 01192 "XMKD", cmd_mkd, 01193 "RMD", cmd_rmd, 01194 "XRMD", cmd_rmd, 01195 "DELE", cmd_dele, 01196 //"PASV", cmd_pasv, 01197 NULL 01198 }; 01199 01200 static void send_msgdata(struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 01201 { 01202 err_t err; 01203 u16_t len; 01204 01205 if (sfifo_used(&fsm->fifo) > 0) { 01206 int i; 01207 01208 /* We cannot send more data than space available in the send 01209 buffer. */ 01210 if (tcp_sndbuf(pcb) < sfifo_used(&fsm->fifo)) { 01211 len = tcp_sndbuf(pcb); 01212 } else { 01213 len = (u16_t) sfifo_used(&fsm->fifo); 01214 } 01215 01216 i = fsm->fifo.readpos; 01217 if ((i + len) > fsm->fifo.size) { 01218 err = tcp_write(pcb, fsm->fifo.buffer + i, (u16_t)(fsm->fifo.size - i), 1); 01219 if (err != ERR_OK) { 01220 dbg_printf("send_msgdata: error writing!\n"); 01221 return; 01222 } 01223 len -= fsm->fifo.size - i; 01224 fsm->fifo.readpos = 0; 01225 i = 0; 01226 } 01227 01228 err = tcp_write(pcb, fsm->fifo.buffer + i, len, 1); 01229 if (err != ERR_OK) { 01230 dbg_printf("send_msgdata: error writing!\n"); 01231 return; 01232 } 01233 fsm->fifo.readpos += len; 01234 } 01235 } 01236 01237 static void send_msg(struct tcp_pcb *pcb, struct ftpd_msgstate *fsm, char *msg, ...) 01238 { 01239 va_list arg; 01240 char buffer[1024]; 01241 int len; 01242 01243 va_start(arg, msg); 01244 vsprintf(buffer, msg, arg); 01245 va_end(arg); 01246 strcat(buffer, "\r\n"); 01247 len = strlen(buffer); 01248 if (sfifo_space(&fsm->fifo) < len) 01249 return; 01250 sfifo_write(&fsm->fifo, buffer, len); 01251 dbg_printf("response: %s", buffer); 01252 //printit( buffer ); 01253 send_msgdata(pcb, fsm); 01254 } 01255 01256 static void ftpd_msgerr(void *arg, err_t err) 01257 { 01258 struct ftpd_msgstate *fsm = (struct ftpd_msgstate*)arg; 01259 01260 // printit( "ftpd_msgerr" ); 01261 dbg_printf("ftpd_msgerr: %s (%i)\n", lwip_strerr(err), err); 01262 if (fsm == NULL) 01263 return; 01264 if (fsm->datafs) 01265 ftpd_dataclose(fsm->datapcb, fsm->datafs); 01266 sfifo_close(&fsm->fifo); 01267 vfs_close( (vfs_file_t*)fsm->vfs); 01268 fsm->vfs = NULL; 01269 if (fsm->renamefrom) 01270 free(fsm->renamefrom); 01271 fsm->renamefrom = NULL; 01272 free(fsm); 01273 } 01274 01275 static void ftpd_msgclose(struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) 01276 { 01277 //printit( "ftpd_msgclose" ); 01278 tcp_arg(pcb, NULL); 01279 tcp_sent(pcb, NULL); 01280 tcp_recv(pcb, NULL); 01281 if (fsm->datafs) 01282 ftpd_dataclose(fsm->datapcb, fsm->datafs); 01283 sfifo_close(&fsm->fifo); 01284 vfs_close( (vfs_file_t*)fsm->vfs); 01285 fsm->vfs = NULL; 01286 if (fsm->renamefrom) 01287 free(fsm->renamefrom); 01288 fsm->renamefrom = NULL; 01289 free(fsm); 01290 tcp_arg(pcb, NULL); 01291 tcp_close(pcb); 01292 } 01293 01294 static err_t ftpd_msgsent(void *arg, struct tcp_pcb *pcb, u16_t len) 01295 { 01296 struct ftpd_msgstate *fsm = (struct ftpd_msgstate*)arg; 01297 01298 // printit( "ftpd_msgsent" ); 01299 if (pcb->state > ESTABLISHED) 01300 return ERR_OK; 01301 01302 if ((sfifo_used(&fsm->fifo) == 0) && (fsm->state == FTPD_QUIT)) 01303 ftpd_msgclose(pcb, fsm); 01304 01305 send_msgdata(pcb, fsm); 01306 01307 return ERR_OK; 01308 } 01309 01310 01311 void bcopy (char *src, char *dest, int len) 01312 { 01313 if (dest < src) 01314 while (len--) 01315 *dest++ = *src++; 01316 else 01317 { 01318 char *lasts = src + (len-1); 01319 char *lastd = dest + (len-1); 01320 while (len--) 01321 *(char *)lastd-- = *(char *)lasts--; 01322 } 01323 } 01324 01325 static err_t ftpd_msgrecv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) 01326 { 01327 char *text; 01328 struct ftpd_msgstate *fsm = (struct ftpd_msgstate*)arg; 01329 01330 // printit( "ftpd_msgrecv" ); 01331 //printit( arg ); 01332 if (err == ERR_OK && p != NULL) { 01333 01334 /* Inform TCP that we have taken the data. */ 01335 tcp_recved(pcb, p->tot_len); 01336 01337 text = (char*)malloc(p->tot_len + 1); 01338 if (text) { 01339 char cmd[5]; 01340 struct pbuf *q; 01341 char *pt = text; 01342 struct ftpd_command *ftpd_cmd; 01343 01344 for (q = p; q != NULL; q = q->next) 01345 { 01346 bcopy( (char*)q->payload, pt, q->len); 01347 pt += q->len; 01348 } 01349 *pt = '\0'; 01350 01351 pt = &text[strlen(text) - 1]; 01352 while (((*pt == '\r') || (*pt == '\n')) && pt >= text) 01353 *pt-- = '\0'; 01354 01355 dbg_printf("query: %s\n", text); 01356 //printit( "query: " ); 01357 //printit( text ); 01358 01359 strncpy(cmd, text, 4); 01360 for (pt = cmd; isalpha(*pt) && pt < &cmd[4]; pt++) 01361 *pt = toupper(*pt); 01362 *pt = '\0'; 01363 01364 for (ftpd_cmd = ftpd_commands; ftpd_cmd->cmd != NULL; ftpd_cmd++) { 01365 if (!strcmp(ftpd_cmd->cmd, cmd)) 01366 break; 01367 } 01368 01369 if (strlen(text) < (strlen(cmd) + 1)) 01370 pt = ""; 01371 else 01372 pt = &text[strlen(cmd) + 1]; 01373 01374 if (ftpd_cmd->func) 01375 ftpd_cmd->func(pt, pcb, fsm); 01376 else 01377 send_msg(pcb, fsm, msg502); 01378 01379 free(text); 01380 } 01381 pbuf_free(p); 01382 } 01383 01384 return ERR_OK; 01385 } 01386 01387 static err_t ftpd_msgpoll(void *arg, struct tcp_pcb *pcb) 01388 { 01389 struct ftpd_msgstate *fsm = (struct ftpd_msgstate*)arg; 01390 01391 //printit( "ftpd_msgpoll" ); 01392 if (fsm == NULL) 01393 return ERR_OK; 01394 01395 if (fsm->datafs) { 01396 if (fsm->datafs->connected) { 01397 switch (fsm->state) { 01398 case FTPD_LIST: 01399 send_next_directory(fsm->datafs, fsm->datapcb, 0); 01400 break; 01401 case FTPD_NLST: 01402 send_next_directory(fsm->datafs, fsm->datapcb, 1); 01403 break; 01404 case FTPD_RETR: 01405 send_file(fsm->datafs, fsm->datapcb); 01406 break; 01407 default: 01408 break; 01409 } 01410 } 01411 } 01412 01413 return ERR_OK; 01414 } 01415 01416 static err_t ftpd_msgaccept(void *arg, struct tcp_pcb *pcb, err_t err) 01417 { 01418 struct ftpd_msgstate *fsm; 01419 01420 01421 //printit( "FTP call" ); 01422 /* Allocate memory for the structure that holds the state of the 01423 connection. */ 01424 fsm = (struct ftpd_msgstate*)malloc(sizeof(struct ftpd_msgstate)); 01425 01426 if (fsm == NULL) { 01427 dbg_printf("ftpd_msgaccept: Out of memory\n"); 01428 return ERR_MEM; 01429 } 01430 memset(fsm, 0, sizeof(struct ftpd_msgstate)); 01431 01432 /* Initialize the structure. */ 01433 sfifo_init(&fsm->fifo, 2000); 01434 fsm->state = FTPD_IDLE; 01435 fsm->vfs = vfs_openfs(); 01436 #if 0 01437 if (!fsm->vfs) 01438 { 01439 free(fsm); 01440 return ERR_CLSD; 01441 } 01442 #endif 01443 /* Tell TCP that this is the structure we wish to be passed for our 01444 callbacks. */ 01445 tcp_arg( pcb, fsm ); 01446 01447 /* Tell TCP that we wish to be informed of incoming data by a call 01448 to the http_recv() function. */ 01449 tcp_recv( pcb, ftpd_msgrecv ); 01450 01451 /* Tell TCP that we wish be to informed of data that has been 01452 successfully sent by a call to the ftpd_sent() function. */ 01453 tcp_sent( pcb, ftpd_msgsent ); 01454 01455 tcp_err( pcb, ftpd_msgerr ); 01456 01457 tcp_poll(pcb, ftpd_msgpoll, 1); 01458 01459 send_msg(pcb, fsm, msg220); 01460 01461 return ERR_OK; 01462 } 01463 01464 01465 void ftpd_init(void) 01466 { 01467 struct tcp_pcb *pcb; 01468 01469 //.. vfs_load_plugin(vfs_default_fs); 01470 01471 pcb = tcp_new(); 01472 tcp_bind( pcb, IP_ADDR_ANY, 21 ); 01473 pcb = tcp_listen( pcb ); 01474 tcp_accept( pcb, ftpd_msgaccept ); 01475 } 01476 01477 01478
Generated on Tue Jul 12 2022 22:52:20 by
