From e82f3f21bff1cf021e036ce3e67d5cc12eb41ebe Mon Sep 17 00:00:00 2001 From: patacongo Date: Sat, 4 Feb 2012 21:02:45 +0000 Subject: Add the beginnings of an FTP server git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4368 42af7a65-404d-4744-a932-0658087f49c3 --- apps/netutils/ftpd/ftpd.c | 4523 +++++++++++++++++++++++++++++++++++++++++++++ apps/netutils/ftpd/ftpd.h | 204 ++ 2 files changed, 4727 insertions(+) create mode 100755 apps/netutils/ftpd/ftpd.c create mode 100755 apps/netutils/ftpd/ftpd.h (limited to 'apps/netutils/ftpd') diff --git a/apps/netutils/ftpd/ftpd.c b/apps/netutils/ftpd/ftpd.c new file mode 100755 index 000000000..fa15afeec --- /dev/null +++ b/apps/netutils/ftpd/ftpd.c @@ -0,0 +1,4523 @@ +/**************************************************************************** + * apps/n etutils/ftpd.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Includes original code as well as logic adapted from hwport_ftpd, written + * by Jaehyuk Cho which is released under a BSD license. + * + * Copyright (C) HWPORT.COM. All rights reserved. + * Author: JAEHYUK CHO + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include + +#include + +#include "ftpd.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* Account functions */ + +static FAR struct ftpd_account_s *ftpd_account_new(FAR const char *user, + uint8_t accountflags); +static void ftpd_account_free(FAR struct ftpd_account_s *account); +static int ftpd_account_setpassord(FAR struct ftpd_account_s *account, + FAR const char *passwd); +static int ftpd_account_add(FAR struct ftpd_server_s *server, + FAR struct ftpd_account_s *account); +static int ftpd_account_sethome(FAR struct ftpd_account_s *account, + FAR const char *home); +static FAR struct ftpd_account_s * + ftpd_account_search_user(FAR struct ftpd_session_s *session, + FAR const char *user, FAR struct ftpd_account_s **dupaccount); +static FAR struct ftpd_account_s * + ftpd_account_login(FAR struct ftpd_session_s *session, + FAR const char *user, FAR const char *passwd); + +/* Parsing functions */ + +static FAR char *ftpd_strtok(bool skipspace, FAR const char *delimiters, + FAR char **str); +static FAR char *ftpd_strtok_alloc(bool skipspace, + FAR const char *delimiters, FAR const char **str); +static int ftpd_patternmatch(FAR const char *pattern, FAR const char *str); + +/* Socket helpers */ + +static int ftpd_getprotocol(FAR const char *protocol) +static int ftpd_rxpoll(int sd, int timeout); +static int ftpd_txpoll(int sd, int timeout); +static int ftpd_accept(int sd, FAR void *addr, FAR socklen_t *addrlen, + int timeout); +static ssize_t ftpd_recv(int sd, FAR void *data, size_t size, int timeout); +static ssize_t ftpd_send(int sd, FAR const void *data, size_t size, + int timeout); +static ssize_t ftpd_response(int sd, int timeout, FAR const char *fmt, ...); + +static int ftpd_dataopen(FAR struct ftpd_session_s *session); +static int ftpd_dataclose(FAR struct ftpd_session_s *session); +static FAR struct ftpd_server_s *ftpd_openserver(int port); + +/* Path helpers */ + +static int ftpd_pathignore(FAR struct ftpd_pathnode_s *currpath); +static void ftpd_nodefree(FAR struct ftpd_pathnode_s *node); +static FAR struct ftpd_pathnode_s *ftpd_path2node(FAR const char *path); +static FAR char *ftpd_node2path(FAR struct ftpd_pathnode_s *node, + bool strip); +static FAR struct ftpd_pathnode_s * + ftpd_nodeappend(FAR struct ftpd_pathnode_s *head, + FAR struct ftpd_pathnode_s *node, bool override); +static int ftpd_getpath(FAR struct ftpd_session_s *session, + FAR const char *chdirectory, FAR char **abspath, + FAR char **workpath); + +/* Commmand helpers */ + +static int ftpd_changedir(FAR struct ftpd_session_s *session, + FAR char *rempath); +static off_t ftpd_offsatoi(FAR const char *filename, off_t offset); +static int ftpd_stream(FAR struct ftpd_session_s *session, int cmdtype); +static uint8_t ftpd_listoption(FAR char **param); +static int ftpd_listbuffer(FAR struct ftpd_session_s *session, + FAR char *path, FAR struct stat *st, FAR char *buffer, + size_t buflen, unsigned int opton); +static int fptd_listscan(FAR struct ftpd_session_s *session, + FAR char *path, unsigned int opton); +static int ftpd_list(FAR struct ftpd_session_s *session, + unsigned int opton); + +/* Command handlers */ + +static int ftpd_command_user(FAR struct ftpd_session_s *session); +static int ftpd_command_pass(FAR struct ftpd_session_s *session); +static int ftpd_command_syst(FAR struct ftpd_session_s *session); +static int ftpd_command_type(FAR struct ftpd_session_s *session); +static int ftpd_command_mode(FAR struct ftpd_session_s *session); +static int ftpd_command_abor(FAR struct ftpd_session_s *session); +static int ftpd_command_quit(FAR struct ftpd_session_s *session); +static int ftpd_command_noop(FAR struct ftpd_session_s *session); +static int ftpd_command_port(FAR struct ftpd_session_s *session); +static int ftpd_command_eprt(FAR struct ftpd_session_s *session); +static int ftpd_command_pwd(FAR struct ftpd_session_s *session); +static int ftpd_command_cwd(FAR struct ftpd_session_s *session); +static int ftpd_command_cdup(FAR struct ftpd_session_s *session); +static int ftpd_command_rmd(FAR struct ftpd_session_s *session); +static int ftpd_command_mkd(FAR struct ftpd_session_s *session); +static int ftpd_command_dele(FAR struct ftpd_session_s *session); +static int ftpd_command_pasv(FAR struct ftpd_session_s *session); +static int ftpd_command_epsv(FAR struct ftpd_session_s *session); +static int ftpd_command_list(FAR struct ftpd_session_s *session); +static int ftpd_command_nlst(FAR struct ftpd_session_s *session); +static int ftpd_command_acct(FAR struct ftpd_session_s *session); +static int ftpd_command_size(FAR struct ftpd_session_s *session); +static int ftpd_command_stru(FAR struct ftpd_session_s *session); +static int ftpd_command_rnfr(FAR struct ftpd_session_s *session); +static int ftpd_command_rnto(FAR struct ftpd_session_s *session); +static int ftpd_command_retr(FAR struct ftpd_session_s *session); +static int ftpd_command_stor(FAR struct ftpd_session_s *session); +static int ftpd_command_appe(FAR struct ftpd_session_s *session); +static int ftpd_command_rest(FAR struct ftpd_session_s *session); +static int ftpd_command_mdtm(FAR struct ftpd_session_s *session); +static int ftpd_command_opts(FAR struct ftpd_session_s *session); +static int ftpd_command_site(FAR struct ftpd_session_s *session); +static int ftpd_command_help(FAR struct ftpd_session_s *session); + +static int ftpd_command(FAR struct ftpd_session_s *session); + +/* Worker thread */ + +static int ftpd_startworker(pthread_startroutine_t handler, FAR void *arg, + size_t stacksize); +static void ftpd_freesession(FAR struct ftpd_session_s *session); +static void ftpd_workersetup(FAR struct ftpd_session_s *session); +static FAR void *ftpd_worker(FAR void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct ftpd_cmd_s g_ftpdcmdtab[] = +{ + {"USER", ftpd_command_user, 0}, /* USER */ + {"PASS", ftpd_command_pass, 0}, /* PASS */ + {"SYST", ftpd_command_syst, FTPD_CMDFLAG_LOGIN}, /* SYST */ + {"TYPE", ftpd_command_type, FTPD_CMDFLAG_LOGIN}, /* TYPE */ + {"MODE", ftpd_command_mode, FTPD_CMDFLAG_LOGIN}, /* MODE */ + {"ABOR", ftpd_command_abor, FTPD_CMDFLAG_LOGIN}, /* ABOR */ + {"QUIT", ftpd_command_quit, 0}, /* QUIT */ + {"NOOP", ftpd_command_noop, FTPD_CMDFLAG_LOGIN}, /* NOOP */ + {"PORT", ftpd_command_port, FTPD_CMDFLAG_LOGIN}, /* PORT */ + {"EPRT", ftpd_command_eprt, FTPD_CMDFLAG_LOGIN}, /* EPRT */ + {"PWD" , ftpd_command_pwd , FTPD_CMDFLAG_LOGIN}, /* PWD */ + {"XPWD", ftpd_command_pwd , FTPD_CMDFLAG_LOGIN}, /* XPWD */ + {"CWD" , ftpd_command_cwd , FTPD_CMDFLAG_LOGIN}, /* CWD */ + {"XCWD", ftpd_command_cwd , FTPD_CMDFLAG_LOGIN}, /* XCWD */ + {"CDUP", ftpd_command_cdup, FTPD_CMDFLAG_LOGIN}, /* CDUP */ + {"XCUP", ftpd_command_cdup, FTPD_CMDFLAG_LOGIN}, /* XCUP */ + {"RMD" , ftpd_command_rmd , FTPD_CMDFLAG_LOGIN}, /* RMD */ + {"XRMD", ftpd_command_rmd , FTPD_CMDFLAG_LOGIN}, /* XRMD */ + {"MKD" , ftpd_command_mkd , FTPD_CMDFLAG_LOGIN}, /* MKD */ + {"XMKD", ftpd_command_mkd , FTPD_CMDFLAG_LOGIN}, /* XMKD */ + {"DELE", ftpd_command_dele, FTPD_CMDFLAG_LOGIN}, /* DELE */ + {"PASV", ftpd_command_pasv, FTPD_CMDFLAG_LOGIN}, /* PASV */ + {"EPSV", ftpd_command_epsv, FTPD_CMDFLAG_LOGIN}, /* EPSV OR EPSV ALL */ + {"LPSV", ftpd_command_epsv, FTPD_CMDFLAG_LOGIN}, /* LPSV ??? */ + {"LIST", ftpd_command_list, FTPD_CMDFLAG_LOGIN}, /* LIST [ ] */ + {"NLST", ftpd_command_nlst, FTPD_CMDFLAG_LOGIN}, /* NLST [ ] */ + {"ACCT", ftpd_command_acct, FTPD_CMDFLAG_LOGIN}, /* ACCT */ + {"SIZE", ftpd_command_size, FTPD_CMDFLAG_LOGIN}, /* SIZE */ + {"STRU", ftpd_command_stru, FTPD_CMDFLAG_LOGIN}, /* STRU */ + {"RNFR", ftpd_command_rnfr, FTPD_CMDFLAG_LOGIN}, /* RNFR */ + {"RNTO", ftpd_command_rnto, FTPD_CMDFLAG_LOGIN}, /* RNTO */ + {"RETR", ftpd_command_retr, FTPD_CMDFLAG_LOGIN}, /* RETR */ + {"STOR", ftpd_command_stor, FTPD_CMDFLAG_LOGIN}, /* STOR */ + {"APPE", ftpd_command_appe, FTPD_CMDFLAG_LOGIN}, /* APPE */ + {"REST", ftpd_command_rest, FTPD_CMDFLAG_LOGIN}, /* REST */ + {"MDTM", ftpd_command_mdtm, FTPD_CMDFLAG_LOGIN}, /* MDTM */ + {"OPTS", ftpd_command_opts, FTPD_CMDFLAG_LOGIN}, /* OPTS