Webserver+3d print

Dependents:   Nucleo

Committer:
Sergunb
Date:
Sat Feb 04 18:15:49 2017 +0000
Revision:
0:8918a71cdbe9
nothing else

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sergunb 0:8918a71cdbe9 1 /**
Sergunb 0:8918a71cdbe9 2 * @file ftp_server_commands.c
Sergunb 0:8918a71cdbe9 3 * @brief FTP server (command processing)
Sergunb 0:8918a71cdbe9 4 *
Sergunb 0:8918a71cdbe9 5 * @section License
Sergunb 0:8918a71cdbe9 6 *
Sergunb 0:8918a71cdbe9 7 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
Sergunb 0:8918a71cdbe9 8 *
Sergunb 0:8918a71cdbe9 9 * This file is part of CycloneTCP Open.
Sergunb 0:8918a71cdbe9 10 *
Sergunb 0:8918a71cdbe9 11 * This program is free software; you can redistribute it and/or
Sergunb 0:8918a71cdbe9 12 * modify it under the terms of the GNU General Public License
Sergunb 0:8918a71cdbe9 13 * as published by the Free Software Foundation; either version 2
Sergunb 0:8918a71cdbe9 14 * of the License, or (at your option) any later version.
Sergunb 0:8918a71cdbe9 15 *
Sergunb 0:8918a71cdbe9 16 * This program is distributed in the hope that it will be useful,
Sergunb 0:8918a71cdbe9 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Sergunb 0:8918a71cdbe9 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Sergunb 0:8918a71cdbe9 19 * GNU General Public License for more details.
Sergunb 0:8918a71cdbe9 20 *
Sergunb 0:8918a71cdbe9 21 * You should have received a copy of the GNU General Public License
Sergunb 0:8918a71cdbe9 22 * along with this program; if not, write to the Free Software Foundation,
Sergunb 0:8918a71cdbe9 23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Sergunb 0:8918a71cdbe9 24 *
Sergunb 0:8918a71cdbe9 25 * @author Oryx Embedded SARL (www.oryx-embedded.com)
Sergunb 0:8918a71cdbe9 26 * @version 1.7.6
Sergunb 0:8918a71cdbe9 27 **/
Sergunb 0:8918a71cdbe9 28
Sergunb 0:8918a71cdbe9 29 //Switch to the appropriate trace level
Sergunb 0:8918a71cdbe9 30 #define TRACE_LEVEL FTP_TRACE_LEVEL
Sergunb 0:8918a71cdbe9 31
Sergunb 0:8918a71cdbe9 32 //Dependencies
Sergunb 0:8918a71cdbe9 33 #include <stdlib.h>
Sergunb 0:8918a71cdbe9 34 #include "ftp/ftp_server.h"
Sergunb 0:8918a71cdbe9 35 #include "ftp/ftp_server_events.h"
Sergunb 0:8918a71cdbe9 36 #include "ftp/ftp_server_commands.h"
Sergunb 0:8918a71cdbe9 37 #include "ftp/ftp_server_misc.h"
Sergunb 0:8918a71cdbe9 38 #include "str.h"
Sergunb 0:8918a71cdbe9 39 #include "path.h"
Sergunb 0:8918a71cdbe9 40 #include "error.h"
Sergunb 0:8918a71cdbe9 41 #include "debug.h"
Sergunb 0:8918a71cdbe9 42
Sergunb 0:8918a71cdbe9 43 //Check TCP/IP stack configuration
Sergunb 0:8918a71cdbe9 44 #if (FTP_SERVER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 45
Sergunb 0:8918a71cdbe9 46
Sergunb 0:8918a71cdbe9 47 /**
Sergunb 0:8918a71cdbe9 48 * @brief FTP command processing
Sergunb 0:8918a71cdbe9 49 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 50 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 51 **/
Sergunb 0:8918a71cdbe9 52
Sergunb 0:8918a71cdbe9 53 void ftpServerProcessCmd(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 54 FtpClientConnection *connection)
Sergunb 0:8918a71cdbe9 55 {
Sergunb 0:8918a71cdbe9 56 size_t n;
Sergunb 0:8918a71cdbe9 57 char_t *p;
Sergunb 0:8918a71cdbe9 58
Sergunb 0:8918a71cdbe9 59 //The <CRLF> sequence should be used to terminate the command line
Sergunb 0:8918a71cdbe9 60 for(n = 0; n < connection->commandLength; n++)
Sergunb 0:8918a71cdbe9 61 {
Sergunb 0:8918a71cdbe9 62 if(connection->command[n] == '\n')
Sergunb 0:8918a71cdbe9 63 break;
Sergunb 0:8918a71cdbe9 64 }
Sergunb 0:8918a71cdbe9 65
Sergunb 0:8918a71cdbe9 66 //Any command to process?
Sergunb 0:8918a71cdbe9 67 if(n < connection->commandLength)
Sergunb 0:8918a71cdbe9 68 {
Sergunb 0:8918a71cdbe9 69 //Properly terminate the string with a NULL character
Sergunb 0:8918a71cdbe9 70 connection->command[n] = '\0';
Sergunb 0:8918a71cdbe9 71 //Remove trailing whitespace from the command line
Sergunb 0:8918a71cdbe9 72 strRemoveTrailingSpace(connection->command);
Sergunb 0:8918a71cdbe9 73
Sergunb 0:8918a71cdbe9 74 //Debug message
Sergunb 0:8918a71cdbe9 75 TRACE_DEBUG("FTP client: %s\r\n", connection->command);
Sergunb 0:8918a71cdbe9 76
Sergunb 0:8918a71cdbe9 77 //Command line too long?
Sergunb 0:8918a71cdbe9 78 if(connection->controlState == FTP_CONTROL_STATE_DISCARD)
Sergunb 0:8918a71cdbe9 79 {
Sergunb 0:8918a71cdbe9 80 //Switch to idle state
Sergunb 0:8918a71cdbe9 81 connection->controlState = FTP_CONTROL_STATE_IDLE;
Sergunb 0:8918a71cdbe9 82 //Format response message
Sergunb 0:8918a71cdbe9 83 strcpy(connection->response, "500 Command line too long\r\n");
Sergunb 0:8918a71cdbe9 84 }
Sergunb 0:8918a71cdbe9 85 else
Sergunb 0:8918a71cdbe9 86 {
Sergunb 0:8918a71cdbe9 87 //The command name and the arguments are separated by one or more spaces
Sergunb 0:8918a71cdbe9 88 for(p = connection->command; *p != '\0' && *p != ' '; p++);
Sergunb 0:8918a71cdbe9 89
Sergunb 0:8918a71cdbe9 90 //Space character found?
Sergunb 0:8918a71cdbe9 91 if(*p == ' ')
Sergunb 0:8918a71cdbe9 92 {
Sergunb 0:8918a71cdbe9 93 //Split the string at the first occurrence of the space character
Sergunb 0:8918a71cdbe9 94 *(p++) = '\0';
Sergunb 0:8918a71cdbe9 95 //Skip extra whitespace
Sergunb 0:8918a71cdbe9 96 while(*p == ' ') p++;
Sergunb 0:8918a71cdbe9 97 }
Sergunb 0:8918a71cdbe9 98
Sergunb 0:8918a71cdbe9 99 //NOOP command received
Sergunb 0:8918a71cdbe9 100 if(!strcasecmp(connection->command, "NOOP"))
Sergunb 0:8918a71cdbe9 101 ftpServerProcessNoop(context, connection, p);
Sergunb 0:8918a71cdbe9 102 //SYST command received
Sergunb 0:8918a71cdbe9 103 else if(!strcasecmp(connection->command, "SYST"))
Sergunb 0:8918a71cdbe9 104 ftpServerProcessSyst(context, connection, p);
Sergunb 0:8918a71cdbe9 105 //FEAT command received?
Sergunb 0:8918a71cdbe9 106 else if(!strcasecmp(connection->command, "FEAT"))
Sergunb 0:8918a71cdbe9 107 ftpServerProcessFeat(context, connection, p);
Sergunb 0:8918a71cdbe9 108 //TYPE command received?
Sergunb 0:8918a71cdbe9 109 else if(!strcasecmp(connection->command, "TYPE"))
Sergunb 0:8918a71cdbe9 110 ftpServerProcessType(context, connection, p);
Sergunb 0:8918a71cdbe9 111 //STRU command received?
Sergunb 0:8918a71cdbe9 112 else if(!strcasecmp(connection->command, "STRU"))
Sergunb 0:8918a71cdbe9 113 ftpServerProcessStru(context, connection, p);
Sergunb 0:8918a71cdbe9 114 //MODE command received?
Sergunb 0:8918a71cdbe9 115 else if(!strcasecmp(connection->command, "MODE"))
Sergunb 0:8918a71cdbe9 116 ftpServerProcessMode(context, connection, p);
Sergunb 0:8918a71cdbe9 117 //USER command received?
Sergunb 0:8918a71cdbe9 118 else if(!strcasecmp(connection->command, "USER"))
Sergunb 0:8918a71cdbe9 119 ftpServerProcessUser(context, connection, p);
Sergunb 0:8918a71cdbe9 120 //PASS command received?
Sergunb 0:8918a71cdbe9 121 else if(!strcasecmp(connection->command, "PASS"))
Sergunb 0:8918a71cdbe9 122 ftpServerProcessPass(context, connection, p);
Sergunb 0:8918a71cdbe9 123 //REIN command received?
Sergunb 0:8918a71cdbe9 124 else if(!strcasecmp(connection->command, "REIN"))
Sergunb 0:8918a71cdbe9 125 ftpServerProcessRein(context, connection, p);
Sergunb 0:8918a71cdbe9 126 //QUIT command received?
Sergunb 0:8918a71cdbe9 127 else if(!strcasecmp(connection->command, "QUIT"))
Sergunb 0:8918a71cdbe9 128 ftpServerProcessQuit(context, connection, p);
Sergunb 0:8918a71cdbe9 129 //PORT command received?
Sergunb 0:8918a71cdbe9 130 else if(!strcasecmp(connection->command, "PORT"))
Sergunb 0:8918a71cdbe9 131 ftpServerProcessPort(context, connection, p);
Sergunb 0:8918a71cdbe9 132 //EPRT command received?
Sergunb 0:8918a71cdbe9 133 else if(!strcasecmp(connection->command, "EPRT"))
Sergunb 0:8918a71cdbe9 134 ftpServerProcessEprt(context, connection, p);
Sergunb 0:8918a71cdbe9 135 //PASV command received?
Sergunb 0:8918a71cdbe9 136 else if(!strcasecmp(connection->command, "PASV"))
Sergunb 0:8918a71cdbe9 137 ftpServerProcessPasv(context, connection, p);
Sergunb 0:8918a71cdbe9 138 //EPSV command received?
Sergunb 0:8918a71cdbe9 139 else if(!strcasecmp(connection->command, "EPSV"))
Sergunb 0:8918a71cdbe9 140 ftpServerProcessEpsv(context, connection, p);
Sergunb 0:8918a71cdbe9 141 //ABOR command received?
Sergunb 0:8918a71cdbe9 142 else if(!strcasecmp(connection->command, "ABOR"))
Sergunb 0:8918a71cdbe9 143 ftpServerProcessAbor(context, connection, p);
Sergunb 0:8918a71cdbe9 144 //PWD command received?
Sergunb 0:8918a71cdbe9 145 else if(!strcasecmp(connection->command, "PWD"))
Sergunb 0:8918a71cdbe9 146 ftpServerProcessPwd(context, connection, p);
Sergunb 0:8918a71cdbe9 147 //LIST command received?
Sergunb 0:8918a71cdbe9 148 else if(!strcasecmp(connection->command, "LIST"))
Sergunb 0:8918a71cdbe9 149 ftpServerProcessList(context, connection, p);
Sergunb 0:8918a71cdbe9 150 //CWD command received?
Sergunb 0:8918a71cdbe9 151 else if(!strcasecmp(connection->command, "CWD"))
Sergunb 0:8918a71cdbe9 152 ftpServerProcessCwd(context, connection, p);
Sergunb 0:8918a71cdbe9 153 //CDUP command received?
Sergunb 0:8918a71cdbe9 154 else if(!strcasecmp(connection->command, "CDUP"))
Sergunb 0:8918a71cdbe9 155 ftpServerProcessCdup(context, connection, p);
Sergunb 0:8918a71cdbe9 156 //MKD command received?
Sergunb 0:8918a71cdbe9 157 else if(!strcasecmp(connection->command, "MKD"))
Sergunb 0:8918a71cdbe9 158 ftpServerProcessMkd(context, connection, p);
Sergunb 0:8918a71cdbe9 159 //RMD command received?
Sergunb 0:8918a71cdbe9 160 else if(!strcasecmp(connection->command, "RMD"))
Sergunb 0:8918a71cdbe9 161 ftpServerProcessRmd(context, connection, p);
Sergunb 0:8918a71cdbe9 162 //SIZE command received?
Sergunb 0:8918a71cdbe9 163 else if(!strcasecmp(connection->command, "SIZE"))
Sergunb 0:8918a71cdbe9 164 ftpServerProcessSize(context, connection, p);
Sergunb 0:8918a71cdbe9 165 //RETR command received?
Sergunb 0:8918a71cdbe9 166 else if(!strcasecmp(connection->command, "RETR"))
Sergunb 0:8918a71cdbe9 167 ftpServerProcessRetr(context, connection, p);
Sergunb 0:8918a71cdbe9 168 //STOR command received?
Sergunb 0:8918a71cdbe9 169 else if(!strcasecmp(connection->command, "STOR"))
Sergunb 0:8918a71cdbe9 170 ftpServerProcessStor(context, connection, p);
Sergunb 0:8918a71cdbe9 171 //APPE command received?
Sergunb 0:8918a71cdbe9 172 else if(!strcasecmp(connection->command, "APPE"))
Sergunb 0:8918a71cdbe9 173 ftpServerProcessAppe(context, connection, p);
Sergunb 0:8918a71cdbe9 174 //RNFR command received?
Sergunb 0:8918a71cdbe9 175 else if(!strcasecmp(connection->command, "RNFR"))
Sergunb 0:8918a71cdbe9 176 ftpServerProcessRnfr(context, connection, p);
Sergunb 0:8918a71cdbe9 177 //RNTO command received?
Sergunb 0:8918a71cdbe9 178 else if(!strcasecmp(connection->command, "RNTO"))
Sergunb 0:8918a71cdbe9 179 ftpServerProcessRnto(context, connection, p);
Sergunb 0:8918a71cdbe9 180 //DELE command received?
Sergunb 0:8918a71cdbe9 181 else if(!strcasecmp(connection->command, "DELE"))
Sergunb 0:8918a71cdbe9 182 ftpServerProcessDele(context, connection, p);
Sergunb 0:8918a71cdbe9 183 //Unknown command received?
Sergunb 0:8918a71cdbe9 184 else
Sergunb 0:8918a71cdbe9 185 ftpServerProcessUnknownCmd(context, connection, p);
Sergunb 0:8918a71cdbe9 186 }
Sergunb 0:8918a71cdbe9 187
Sergunb 0:8918a71cdbe9 188 //Debug message
Sergunb 0:8918a71cdbe9 189 TRACE_DEBUG("FTP server: %s", connection->response);
Sergunb 0:8918a71cdbe9 190
Sergunb 0:8918a71cdbe9 191 //Number of bytes in the response buffer
Sergunb 0:8918a71cdbe9 192 connection->responseLength = strlen(connection->response);
Sergunb 0:8918a71cdbe9 193 connection->responsePos = 0;
Sergunb 0:8918a71cdbe9 194
Sergunb 0:8918a71cdbe9 195 //Clear command line
Sergunb 0:8918a71cdbe9 196 connection->commandLength = 0;
Sergunb 0:8918a71cdbe9 197 }
Sergunb 0:8918a71cdbe9 198 else if(connection->commandLength >= FTP_SERVER_MAX_LINE_LEN)
Sergunb 0:8918a71cdbe9 199 {
Sergunb 0:8918a71cdbe9 200 //The command line is too long...
Sergunb 0:8918a71cdbe9 201 connection->controlState = FTP_CONTROL_STATE_DISCARD;
Sergunb 0:8918a71cdbe9 202 //Drop incoming data
Sergunb 0:8918a71cdbe9 203 connection->commandLength = 0;
Sergunb 0:8918a71cdbe9 204 }
Sergunb 0:8918a71cdbe9 205 }
Sergunb 0:8918a71cdbe9 206
Sergunb 0:8918a71cdbe9 207
Sergunb 0:8918a71cdbe9 208 /**
Sergunb 0:8918a71cdbe9 209 * @brief Unknown command processing
Sergunb 0:8918a71cdbe9 210 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 211 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 212 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 213 **/
Sergunb 0:8918a71cdbe9 214
Sergunb 0:8918a71cdbe9 215 void ftpServerProcessUnknownCmd(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 216 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 217 {
Sergunb 0:8918a71cdbe9 218 error_t error;
Sergunb 0:8918a71cdbe9 219
Sergunb 0:8918a71cdbe9 220 //Invoke user-defined callback, if any
Sergunb 0:8918a71cdbe9 221 if(context->settings.unknownCommandCallback != NULL)
Sergunb 0:8918a71cdbe9 222 {
Sergunb 0:8918a71cdbe9 223 //Custom command processing
Sergunb 0:8918a71cdbe9 224 error = context->settings.unknownCommandCallback(connection,
Sergunb 0:8918a71cdbe9 225 connection->command, param);
Sergunb 0:8918a71cdbe9 226 }
Sergunb 0:8918a71cdbe9 227 else
Sergunb 0:8918a71cdbe9 228 {
Sergunb 0:8918a71cdbe9 229 //Report an error
Sergunb 0:8918a71cdbe9 230 error = ERROR_INVALID_COMMAND;
Sergunb 0:8918a71cdbe9 231 }
Sergunb 0:8918a71cdbe9 232
Sergunb 0:8918a71cdbe9 233 //Invalid command received?
Sergunb 0:8918a71cdbe9 234 if(error == ERROR_INVALID_COMMAND)
Sergunb 0:8918a71cdbe9 235 {
Sergunb 0:8918a71cdbe9 236 //Format response message
Sergunb 0:8918a71cdbe9 237 strcpy(connection->response, "500 Command unrecognized\r\n");
Sergunb 0:8918a71cdbe9 238 }
Sergunb 0:8918a71cdbe9 239 }
Sergunb 0:8918a71cdbe9 240
Sergunb 0:8918a71cdbe9 241
Sergunb 0:8918a71cdbe9 242 /**
Sergunb 0:8918a71cdbe9 243 * @brief NOOP command processing
Sergunb 0:8918a71cdbe9 244 *
Sergunb 0:8918a71cdbe9 245 * The NOOP command does not affect any parameters or previously entered
Sergunb 0:8918a71cdbe9 246 * commands. It specifies no action other than that the server send an OK reply
Sergunb 0:8918a71cdbe9 247 *
Sergunb 0:8918a71cdbe9 248 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 249 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 250 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 251 **/
Sergunb 0:8918a71cdbe9 252
Sergunb 0:8918a71cdbe9 253 void ftpServerProcessNoop(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 254 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 255 {
Sergunb 0:8918a71cdbe9 256 //Send an OK reply
Sergunb 0:8918a71cdbe9 257 strcpy(connection->response, "200 Command okay\r\n");
Sergunb 0:8918a71cdbe9 258 }
Sergunb 0:8918a71cdbe9 259
Sergunb 0:8918a71cdbe9 260
Sergunb 0:8918a71cdbe9 261 /**
Sergunb 0:8918a71cdbe9 262 * @brief SYST command processing
Sergunb 0:8918a71cdbe9 263 *
Sergunb 0:8918a71cdbe9 264 * The SYST command is used to find out the type of operating system
Sergunb 0:8918a71cdbe9 265 * at the server side
Sergunb 0:8918a71cdbe9 266 *
Sergunb 0:8918a71cdbe9 267 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 268 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 269 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 270 **/
Sergunb 0:8918a71cdbe9 271
Sergunb 0:8918a71cdbe9 272 void ftpServerProcessSyst(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 273 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 274 {
Sergunb 0:8918a71cdbe9 275 //Format the response to the SYST command
Sergunb 0:8918a71cdbe9 276 strcpy(connection->response, "215 UNIX Type: L8\r\n");
Sergunb 0:8918a71cdbe9 277 }
Sergunb 0:8918a71cdbe9 278
Sergunb 0:8918a71cdbe9 279
Sergunb 0:8918a71cdbe9 280 /**
Sergunb 0:8918a71cdbe9 281 * @brief FEAT command processing
Sergunb 0:8918a71cdbe9 282 *
Sergunb 0:8918a71cdbe9 283 * The FEAT command allows a client to discover which optional
Sergunb 0:8918a71cdbe9 284 * commands a server supports
Sergunb 0:8918a71cdbe9 285 *
Sergunb 0:8918a71cdbe9 286 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 287 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 288 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 289 **/
Sergunb 0:8918a71cdbe9 290
Sergunb 0:8918a71cdbe9 291 void ftpServerProcessFeat(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 292 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 293 {
Sergunb 0:8918a71cdbe9 294 //Format the response to the FEAT command
Sergunb 0:8918a71cdbe9 295 strcpy(connection->response, "211-Features supported:\r\n");
Sergunb 0:8918a71cdbe9 296 strcat(connection->response, " SIZE\r\n");
Sergunb 0:8918a71cdbe9 297 strcat(connection->response, " EPRT\r\n");
Sergunb 0:8918a71cdbe9 298 strcat(connection->response, " EPSV\r\n");
Sergunb 0:8918a71cdbe9 299 strcat(connection->response, "211 End\r\n");
Sergunb 0:8918a71cdbe9 300 }
Sergunb 0:8918a71cdbe9 301
Sergunb 0:8918a71cdbe9 302
Sergunb 0:8918a71cdbe9 303 /**
Sergunb 0:8918a71cdbe9 304 * @brief TYPE command processing
Sergunb 0:8918a71cdbe9 305 *
Sergunb 0:8918a71cdbe9 306 * The TYPE command specifies the representation type
Sergunb 0:8918a71cdbe9 307 *
Sergunb 0:8918a71cdbe9 308 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 309 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 310 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 311 **/
Sergunb 0:8918a71cdbe9 312
Sergunb 0:8918a71cdbe9 313 void ftpServerProcessType(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 314 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 315 {
Sergunb 0:8918a71cdbe9 316 //The argument specifies the representation type
Sergunb 0:8918a71cdbe9 317 if(*param != '\0')
Sergunb 0:8918a71cdbe9 318 {
Sergunb 0:8918a71cdbe9 319 //ASCII type?
Sergunb 0:8918a71cdbe9 320 if(!strcasecmp(param, "A"))
Sergunb 0:8918a71cdbe9 321 {
Sergunb 0:8918a71cdbe9 322 //Format the response to the TYPE command
Sergunb 0:8918a71cdbe9 323 strcpy(connection->response, "200 Type set to A\r\n");
Sergunb 0:8918a71cdbe9 324 }
Sergunb 0:8918a71cdbe9 325 //Image type?
Sergunb 0:8918a71cdbe9 326 else if(!strcasecmp(param, "I"))
Sergunb 0:8918a71cdbe9 327 {
Sergunb 0:8918a71cdbe9 328 //Format the response to the TYPE command
Sergunb 0:8918a71cdbe9 329 strcpy(connection->response, "200 Type set to I\r\n");
Sergunb 0:8918a71cdbe9 330 }
Sergunb 0:8918a71cdbe9 331 //Unknown type?
Sergunb 0:8918a71cdbe9 332 else
Sergunb 0:8918a71cdbe9 333 {
Sergunb 0:8918a71cdbe9 334 //Report an error
Sergunb 0:8918a71cdbe9 335 strcpy(connection->response, "504 Unknown type\r\n");
Sergunb 0:8918a71cdbe9 336 }
Sergunb 0:8918a71cdbe9 337 }
Sergunb 0:8918a71cdbe9 338 else
Sergunb 0:8918a71cdbe9 339 {
Sergunb 0:8918a71cdbe9 340 //The argument is missing...
Sergunb 0:8918a71cdbe9 341 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 342 }
Sergunb 0:8918a71cdbe9 343 }
Sergunb 0:8918a71cdbe9 344
Sergunb 0:8918a71cdbe9 345
Sergunb 0:8918a71cdbe9 346 /**
Sergunb 0:8918a71cdbe9 347 * @brief STRU command processing
Sergunb 0:8918a71cdbe9 348 *
Sergunb 0:8918a71cdbe9 349 * The STRU command specifies the file structure
Sergunb 0:8918a71cdbe9 350 *
Sergunb 0:8918a71cdbe9 351 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 352 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 353 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 354 **/
Sergunb 0:8918a71cdbe9 355
Sergunb 0:8918a71cdbe9 356 void ftpServerProcessStru(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 357 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 358 {
Sergunb 0:8918a71cdbe9 359 //The argument specifies the file structure
Sergunb 0:8918a71cdbe9 360 if(*param != '\0')
Sergunb 0:8918a71cdbe9 361 {
Sergunb 0:8918a71cdbe9 362 //No record structure?
Sergunb 0:8918a71cdbe9 363 if(!strcasecmp(param, "F"))
Sergunb 0:8918a71cdbe9 364 {
Sergunb 0:8918a71cdbe9 365 //Format the response to the STRU command
Sergunb 0:8918a71cdbe9 366 strcpy(connection->response, "200 Structure set to F\r\n");
Sergunb 0:8918a71cdbe9 367 }
Sergunb 0:8918a71cdbe9 368 //Unknown file structure?
Sergunb 0:8918a71cdbe9 369 else
Sergunb 0:8918a71cdbe9 370 {
Sergunb 0:8918a71cdbe9 371 //Report an error
Sergunb 0:8918a71cdbe9 372 strcpy(connection->response, "504 Unknown structure\r\n");
Sergunb 0:8918a71cdbe9 373 }
Sergunb 0:8918a71cdbe9 374 }
Sergunb 0:8918a71cdbe9 375 else
Sergunb 0:8918a71cdbe9 376 {
Sergunb 0:8918a71cdbe9 377 //The argument is missing...
Sergunb 0:8918a71cdbe9 378 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 379 }
Sergunb 0:8918a71cdbe9 380 }
Sergunb 0:8918a71cdbe9 381
Sergunb 0:8918a71cdbe9 382
Sergunb 0:8918a71cdbe9 383 /**
Sergunb 0:8918a71cdbe9 384 * @brief MODE command processing
Sergunb 0:8918a71cdbe9 385 *
Sergunb 0:8918a71cdbe9 386 * The MODE command specifies the data transfer mode
Sergunb 0:8918a71cdbe9 387 *
Sergunb 0:8918a71cdbe9 388 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 389 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 390 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 391 **/
Sergunb 0:8918a71cdbe9 392
Sergunb 0:8918a71cdbe9 393 void ftpServerProcessMode(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 394 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 395 {
Sergunb 0:8918a71cdbe9 396 //The argument specifies the data transfer mode
Sergunb 0:8918a71cdbe9 397 if(*param != '\0')
Sergunb 0:8918a71cdbe9 398 {
Sergunb 0:8918a71cdbe9 399 //Stream mode?
Sergunb 0:8918a71cdbe9 400 if(!strcasecmp(param, "S"))
Sergunb 0:8918a71cdbe9 401 {
Sergunb 0:8918a71cdbe9 402 //Format the response to the MODE command
Sergunb 0:8918a71cdbe9 403 strcpy(connection->response, "200 Mode set to S\r\n");
Sergunb 0:8918a71cdbe9 404 }
Sergunb 0:8918a71cdbe9 405 //Unknown data transfer mode?
Sergunb 0:8918a71cdbe9 406 else
Sergunb 0:8918a71cdbe9 407 {
Sergunb 0:8918a71cdbe9 408 //Report an error
Sergunb 0:8918a71cdbe9 409 strcpy(connection->response, "504 Unknown mode\r\n");
Sergunb 0:8918a71cdbe9 410 }
Sergunb 0:8918a71cdbe9 411 }
Sergunb 0:8918a71cdbe9 412 else
Sergunb 0:8918a71cdbe9 413 {
Sergunb 0:8918a71cdbe9 414 //The argument is missing...
Sergunb 0:8918a71cdbe9 415 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 416 }
Sergunb 0:8918a71cdbe9 417 }
Sergunb 0:8918a71cdbe9 418
Sergunb 0:8918a71cdbe9 419
Sergunb 0:8918a71cdbe9 420 /**
Sergunb 0:8918a71cdbe9 421 * @brief USER command processing
Sergunb 0:8918a71cdbe9 422 *
Sergunb 0:8918a71cdbe9 423 * The USER command is used to identify the user
Sergunb 0:8918a71cdbe9 424 *
Sergunb 0:8918a71cdbe9 425 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 426 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 427 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 428 **/
Sergunb 0:8918a71cdbe9 429
Sergunb 0:8918a71cdbe9 430 void ftpServerProcessUser(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 431 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 432 {
Sergunb 0:8918a71cdbe9 433 uint_t status;
Sergunb 0:8918a71cdbe9 434
Sergunb 0:8918a71cdbe9 435 //The argument specifies the user name
Sergunb 0:8918a71cdbe9 436 if(*param == '\0')
Sergunb 0:8918a71cdbe9 437 {
Sergunb 0:8918a71cdbe9 438 //The argument is missing...
Sergunb 0:8918a71cdbe9 439 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 440 //Exit immediately
Sergunb 0:8918a71cdbe9 441 return;
Sergunb 0:8918a71cdbe9 442 }
Sergunb 0:8918a71cdbe9 443
Sergunb 0:8918a71cdbe9 444 //Check the length of the user name
Sergunb 0:8918a71cdbe9 445 if(strlen(param) > FTP_SERVER_MAX_USERNAME_LEN)
Sergunb 0:8918a71cdbe9 446 {
Sergunb 0:8918a71cdbe9 447 //The specified user name is not valid...
Sergunb 0:8918a71cdbe9 448 strcpy(connection->response, "501 Invalid parameter\r\n");
Sergunb 0:8918a71cdbe9 449 //Exit immediately
Sergunb 0:8918a71cdbe9 450 return;
Sergunb 0:8918a71cdbe9 451 }
Sergunb 0:8918a71cdbe9 452
Sergunb 0:8918a71cdbe9 453 //Save user name
Sergunb 0:8918a71cdbe9 454 strcpy(connection->user, param);
Sergunb 0:8918a71cdbe9 455 //Log out the user
Sergunb 0:8918a71cdbe9 456 connection->userLoggedIn = FALSE;
Sergunb 0:8918a71cdbe9 457 //Set home directory
Sergunb 0:8918a71cdbe9 458 strcpy(connection->homeDir, context->settings.rootDir);
Sergunb 0:8918a71cdbe9 459 //Set current directory
Sergunb 0:8918a71cdbe9 460 strcpy(connection->currentDir, context->settings.rootDir);
Sergunb 0:8918a71cdbe9 461
Sergunb 0:8918a71cdbe9 462 //Invoke user-defined callback, if any
Sergunb 0:8918a71cdbe9 463 if(context->settings.checkUserCallback != NULL)
Sergunb 0:8918a71cdbe9 464 status = context->settings.checkUserCallback(connection, param);
Sergunb 0:8918a71cdbe9 465 else
Sergunb 0:8918a71cdbe9 466 status = FTP_ACCESS_ALLOWED;
Sergunb 0:8918a71cdbe9 467
Sergunb 0:8918a71cdbe9 468 //Access allowed?
Sergunb 0:8918a71cdbe9 469 if(status == FTP_ACCESS_ALLOWED)
Sergunb 0:8918a71cdbe9 470 {
Sergunb 0:8918a71cdbe9 471 //The user is now logged in
Sergunb 0:8918a71cdbe9 472 connection->userLoggedIn = TRUE;
Sergunb 0:8918a71cdbe9 473 //Format response message
Sergunb 0:8918a71cdbe9 474 strcpy(connection->response, "230 User logged in, proceed\r\n");
Sergunb 0:8918a71cdbe9 475 }
Sergunb 0:8918a71cdbe9 476 //Password required?
Sergunb 0:8918a71cdbe9 477 else if(status == FTP_PASSWORD_REQUIRED)
Sergunb 0:8918a71cdbe9 478 {
Sergunb 0:8918a71cdbe9 479 //This command must be immediately followed by a PASS command
Sergunb 0:8918a71cdbe9 480 connection->controlState = FTP_CONTROL_STATE_USER;
Sergunb 0:8918a71cdbe9 481 //Format response message
Sergunb 0:8918a71cdbe9 482 strcpy(connection->response, "331 User name okay, need password\r\n");
Sergunb 0:8918a71cdbe9 483 }
Sergunb 0:8918a71cdbe9 484 //Access denied?
Sergunb 0:8918a71cdbe9 485 else
Sergunb 0:8918a71cdbe9 486 {
Sergunb 0:8918a71cdbe9 487 //Format response message
Sergunb 0:8918a71cdbe9 488 strcpy(connection->response, "530 Login authentication failed\r\n");
Sergunb 0:8918a71cdbe9 489 }
Sergunb 0:8918a71cdbe9 490 }
Sergunb 0:8918a71cdbe9 491
Sergunb 0:8918a71cdbe9 492
Sergunb 0:8918a71cdbe9 493 /**
Sergunb 0:8918a71cdbe9 494 * @brief PASS command processing
Sergunb 0:8918a71cdbe9 495 *
Sergunb 0:8918a71cdbe9 496 * The USER command specifies the user's password
Sergunb 0:8918a71cdbe9 497 *
Sergunb 0:8918a71cdbe9 498 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 499 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 500 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 501 **/
Sergunb 0:8918a71cdbe9 502
Sergunb 0:8918a71cdbe9 503 void ftpServerProcessPass(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 504 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 505 {
Sergunb 0:8918a71cdbe9 506 uint_t status;
Sergunb 0:8918a71cdbe9 507
Sergunb 0:8918a71cdbe9 508 //This command must immediately follow a USER command
Sergunb 0:8918a71cdbe9 509 if(connection->controlState != FTP_CONTROL_STATE_USER)
Sergunb 0:8918a71cdbe9 510 {
Sergunb 0:8918a71cdbe9 511 //Switch to idle state
Sergunb 0:8918a71cdbe9 512 connection->controlState = FTP_CONTROL_STATE_IDLE;
Sergunb 0:8918a71cdbe9 513 //Report an error
Sergunb 0:8918a71cdbe9 514 strcpy(connection->response, "503 Bad sequence of commands\r\n");
Sergunb 0:8918a71cdbe9 515 //Exit immediately
Sergunb 0:8918a71cdbe9 516 return;
Sergunb 0:8918a71cdbe9 517 }
Sergunb 0:8918a71cdbe9 518
Sergunb 0:8918a71cdbe9 519 //Switch to idle state
Sergunb 0:8918a71cdbe9 520 connection->controlState = FTP_CONTROL_STATE_IDLE;
Sergunb 0:8918a71cdbe9 521
Sergunb 0:8918a71cdbe9 522 //The argument specifies the password
Sergunb 0:8918a71cdbe9 523 if(*param == '\0')
Sergunb 0:8918a71cdbe9 524 {
Sergunb 0:8918a71cdbe9 525 //The argument is missing...
Sergunb 0:8918a71cdbe9 526 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 527 //Exit immediately
Sergunb 0:8918a71cdbe9 528 return;
Sergunb 0:8918a71cdbe9 529 }
Sergunb 0:8918a71cdbe9 530
Sergunb 0:8918a71cdbe9 531 //Invoke user-defined callback, if any
Sergunb 0:8918a71cdbe9 532 if(context->settings.checkPasswordCallback != NULL)
Sergunb 0:8918a71cdbe9 533 status = context->settings.checkPasswordCallback(connection, connection->user, param);
Sergunb 0:8918a71cdbe9 534 else
Sergunb 0:8918a71cdbe9 535 status = FTP_ACCESS_ALLOWED;
Sergunb 0:8918a71cdbe9 536
Sergunb 0:8918a71cdbe9 537 //Access allowed?
Sergunb 0:8918a71cdbe9 538 if(status == FTP_ACCESS_ALLOWED)
Sergunb 0:8918a71cdbe9 539 {
Sergunb 0:8918a71cdbe9 540 //The user is now logged in
Sergunb 0:8918a71cdbe9 541 connection->userLoggedIn = TRUE;
Sergunb 0:8918a71cdbe9 542 //Format response message
Sergunb 0:8918a71cdbe9 543 strcpy(connection->response, "230 User logged in, proceed\r\n");
Sergunb 0:8918a71cdbe9 544 }
Sergunb 0:8918a71cdbe9 545 //Access denied?
Sergunb 0:8918a71cdbe9 546 else
Sergunb 0:8918a71cdbe9 547 {
Sergunb 0:8918a71cdbe9 548 //Format response message
Sergunb 0:8918a71cdbe9 549 strcpy(connection->response, "530 Login authentication failed\r\n");
Sergunb 0:8918a71cdbe9 550 }
Sergunb 0:8918a71cdbe9 551 }
Sergunb 0:8918a71cdbe9 552
Sergunb 0:8918a71cdbe9 553
Sergunb 0:8918a71cdbe9 554 /**
Sergunb 0:8918a71cdbe9 555 * @brief REIN command processing
Sergunb 0:8918a71cdbe9 556 *
Sergunb 0:8918a71cdbe9 557 * The REIN command is used to reinitialize a user session
Sergunb 0:8918a71cdbe9 558 *
Sergunb 0:8918a71cdbe9 559 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 560 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 561 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 562 **/
Sergunb 0:8918a71cdbe9 563
Sergunb 0:8918a71cdbe9 564 void ftpServerProcessRein(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 565 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 566 {
Sergunb 0:8918a71cdbe9 567 //Close data connection
Sergunb 0:8918a71cdbe9 568 ftpServerCloseDataConnection(connection);
Sergunb 0:8918a71cdbe9 569
Sergunb 0:8918a71cdbe9 570 //Release previously allocated resources
Sergunb 0:8918a71cdbe9 571 if(connection->file != NULL)
Sergunb 0:8918a71cdbe9 572 {
Sergunb 0:8918a71cdbe9 573 fsCloseFile(connection->file);
Sergunb 0:8918a71cdbe9 574 connection->file = NULL;
Sergunb 0:8918a71cdbe9 575 }
Sergunb 0:8918a71cdbe9 576 if(connection->dir != NULL)
Sergunb 0:8918a71cdbe9 577 {
Sergunb 0:8918a71cdbe9 578 fsCloseDir(connection->dir);
Sergunb 0:8918a71cdbe9 579 connection->dir = NULL;
Sergunb 0:8918a71cdbe9 580 }
Sergunb 0:8918a71cdbe9 581
Sergunb 0:8918a71cdbe9 582 //Clear account information
Sergunb 0:8918a71cdbe9 583 connection->userLoggedIn = FALSE;
Sergunb 0:8918a71cdbe9 584
Sergunb 0:8918a71cdbe9 585 //Format response message
Sergunb 0:8918a71cdbe9 586 strcpy(connection->response, "220 Service ready for new user\r\n");
Sergunb 0:8918a71cdbe9 587 }
Sergunb 0:8918a71cdbe9 588
Sergunb 0:8918a71cdbe9 589
Sergunb 0:8918a71cdbe9 590 /**
Sergunb 0:8918a71cdbe9 591 * @brief QUIT command processing
Sergunb 0:8918a71cdbe9 592 *
Sergunb 0:8918a71cdbe9 593 * The QUIT command is used to terminate a user session
Sergunb 0:8918a71cdbe9 594 *
Sergunb 0:8918a71cdbe9 595 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 596 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 597 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 598 **/
Sergunb 0:8918a71cdbe9 599
Sergunb 0:8918a71cdbe9 600 void ftpServerProcessQuit(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 601 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 602 {
Sergunb 0:8918a71cdbe9 603 //There are two cases to consider upon receipt of this command
Sergunb 0:8918a71cdbe9 604 if(connection->dataState == FTP_DATA_STATE_CLOSED)
Sergunb 0:8918a71cdbe9 605 {
Sergunb 0:8918a71cdbe9 606 //If the FTP service command was already completed, the server closes
Sergunb 0:8918a71cdbe9 607 //the data connection (if it is open)...
Sergunb 0:8918a71cdbe9 608 ftpServerCloseDataConnection(connection);
Sergunb 0:8918a71cdbe9 609
Sergunb 0:8918a71cdbe9 610 //...and responds with a 221 reply
Sergunb 0:8918a71cdbe9 611 strcpy(connection->response, "221 Service closing control connection\r\n");
Sergunb 0:8918a71cdbe9 612 }
Sergunb 0:8918a71cdbe9 613 else
Sergunb 0:8918a71cdbe9 614 {
Sergunb 0:8918a71cdbe9 615 //If the FTP service command is still in progress, the server aborts
Sergunb 0:8918a71cdbe9 616 //the FTP service in progress and closes the data connection...
Sergunb 0:8918a71cdbe9 617 ftpServerCloseDataConnection(connection);
Sergunb 0:8918a71cdbe9 618
Sergunb 0:8918a71cdbe9 619 //...returning a 426 reply to indicate that the service request
Sergunb 0:8918a71cdbe9 620 //terminated abnormally
Sergunb 0:8918a71cdbe9 621 strcpy(connection->response, "426 Connection closed; transfer aborted\r\n");
Sergunb 0:8918a71cdbe9 622
Sergunb 0:8918a71cdbe9 623 //The server then sends a 221 reply
Sergunb 0:8918a71cdbe9 624 strcat(connection->response, "221 Service closing control connection\r\n");
Sergunb 0:8918a71cdbe9 625 }
Sergunb 0:8918a71cdbe9 626
Sergunb 0:8918a71cdbe9 627 //Release previously allocated resources
Sergunb 0:8918a71cdbe9 628 if(connection->file != NULL)
Sergunb 0:8918a71cdbe9 629 {
Sergunb 0:8918a71cdbe9 630 fsCloseFile(connection->file);
Sergunb 0:8918a71cdbe9 631 connection->file = NULL;
Sergunb 0:8918a71cdbe9 632 }
Sergunb 0:8918a71cdbe9 633 if(connection->dir != NULL)
Sergunb 0:8918a71cdbe9 634 {
Sergunb 0:8918a71cdbe9 635 fsCloseDir(connection->dir);
Sergunb 0:8918a71cdbe9 636 connection->dir = NULL;
Sergunb 0:8918a71cdbe9 637 }
Sergunb 0:8918a71cdbe9 638
Sergunb 0:8918a71cdbe9 639 //Clear account information
Sergunb 0:8918a71cdbe9 640 connection->userLoggedIn = FALSE;
Sergunb 0:8918a71cdbe9 641 //Gracefully disconnect from the remote host
Sergunb 0:8918a71cdbe9 642 connection->controlState = FTP_CONTROL_STATE_WAIT_ACK;
Sergunb 0:8918a71cdbe9 643 }
Sergunb 0:8918a71cdbe9 644
Sergunb 0:8918a71cdbe9 645
Sergunb 0:8918a71cdbe9 646 /**
Sergunb 0:8918a71cdbe9 647 * @brief PORT command processing
Sergunb 0:8918a71cdbe9 648 *
Sergunb 0:8918a71cdbe9 649 * The PORT command specifies the data port to be used for the data connection
Sergunb 0:8918a71cdbe9 650 *
Sergunb 0:8918a71cdbe9 651 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 652 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 653 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 654 **/
Sergunb 0:8918a71cdbe9 655
Sergunb 0:8918a71cdbe9 656 void ftpServerProcessPort(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 657 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 658 {
Sergunb 0:8918a71cdbe9 659 error_t error;
Sergunb 0:8918a71cdbe9 660 size_t i;
Sergunb 0:8918a71cdbe9 661 size_t j;
Sergunb 0:8918a71cdbe9 662 char_t *p;
Sergunb 0:8918a71cdbe9 663 char_t *token;
Sergunb 0:8918a71cdbe9 664 char_t *end;
Sergunb 0:8918a71cdbe9 665
Sergunb 0:8918a71cdbe9 666 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 667 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 668 {
Sergunb 0:8918a71cdbe9 669 //Format response message
Sergunb 0:8918a71cdbe9 670 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 671 //Exit immediately
Sergunb 0:8918a71cdbe9 672 return;
Sergunb 0:8918a71cdbe9 673 }
Sergunb 0:8918a71cdbe9 674
Sergunb 0:8918a71cdbe9 675 //The argument is the concatenation of the IP address and the 16-bit port number
Sergunb 0:8918a71cdbe9 676 if(*param == '\0')
Sergunb 0:8918a71cdbe9 677 {
Sergunb 0:8918a71cdbe9 678 //The argument is missing...
Sergunb 0:8918a71cdbe9 679 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 680 //Exit immediately
Sergunb 0:8918a71cdbe9 681 return;
Sergunb 0:8918a71cdbe9 682 }
Sergunb 0:8918a71cdbe9 683
Sergunb 0:8918a71cdbe9 684 //Close the data connection, if any
Sergunb 0:8918a71cdbe9 685 ftpServerCloseDataConnection(connection);
Sergunb 0:8918a71cdbe9 686
Sergunb 0:8918a71cdbe9 687 //Start of exception handling block
Sergunb 0:8918a71cdbe9 688 do
Sergunb 0:8918a71cdbe9 689 {
Sergunb 0:8918a71cdbe9 690 //Assume an error condition...
Sergunb 0:8918a71cdbe9 691 error = ERROR_INVALID_SYNTAX;
Sergunb 0:8918a71cdbe9 692
Sergunb 0:8918a71cdbe9 693 //Parse the string
Sergunb 0:8918a71cdbe9 694 for(i = 0, j = 1; param[i] != '\0'; i++)
Sergunb 0:8918a71cdbe9 695 {
Sergunb 0:8918a71cdbe9 696 //Change commas to dots
Sergunb 0:8918a71cdbe9 697 if(param[i] == ',' && j < sizeof(Ipv4Addr))
Sergunb 0:8918a71cdbe9 698 {
Sergunb 0:8918a71cdbe9 699 param[i] = '.';
Sergunb 0:8918a71cdbe9 700 j++;
Sergunb 0:8918a71cdbe9 701 }
Sergunb 0:8918a71cdbe9 702 }
Sergunb 0:8918a71cdbe9 703
Sergunb 0:8918a71cdbe9 704 //Get the IP address to be used
Sergunb 0:8918a71cdbe9 705 token = strtok_r(param, ",", &p);
Sergunb 0:8918a71cdbe9 706 //Syntax error?
Sergunb 0:8918a71cdbe9 707 if(token == NULL)
Sergunb 0:8918a71cdbe9 708 break;
Sergunb 0:8918a71cdbe9 709
Sergunb 0:8918a71cdbe9 710 //Convert the dot-decimal string to a binary IP address
Sergunb 0:8918a71cdbe9 711 error = ipStringToAddr(token, &connection->remoteIpAddr);
Sergunb 0:8918a71cdbe9 712 //Invalid IP address?
Sergunb 0:8918a71cdbe9 713 if(error)
Sergunb 0:8918a71cdbe9 714 break;
Sergunb 0:8918a71cdbe9 715
Sergunb 0:8918a71cdbe9 716 //Assume an error condition...
Sergunb 0:8918a71cdbe9 717 error = ERROR_INVALID_SYNTAX;
Sergunb 0:8918a71cdbe9 718
Sergunb 0:8918a71cdbe9 719 //Get the most significant byte of the port number
Sergunb 0:8918a71cdbe9 720 token = strtok_r(NULL, ",", &p);
Sergunb 0:8918a71cdbe9 721 //Syntax error?
Sergunb 0:8918a71cdbe9 722 if(token == NULL)
Sergunb 0:8918a71cdbe9 723 break;
Sergunb 0:8918a71cdbe9 724
Sergunb 0:8918a71cdbe9 725 //Convert the string representation to integer
Sergunb 0:8918a71cdbe9 726 connection->remotePort = strtoul(token, &end, 10) << 8;
Sergunb 0:8918a71cdbe9 727 //Syntax error?
Sergunb 0:8918a71cdbe9 728 if(*end != '\0')
Sergunb 0:8918a71cdbe9 729 break;
Sergunb 0:8918a71cdbe9 730
Sergunb 0:8918a71cdbe9 731 //Get the least significant byte of the port number
Sergunb 0:8918a71cdbe9 732 token = strtok_r(NULL, ",", &p);
Sergunb 0:8918a71cdbe9 733 //Syntax error?
Sergunb 0:8918a71cdbe9 734 if(token == NULL)
Sergunb 0:8918a71cdbe9 735 break;
Sergunb 0:8918a71cdbe9 736
Sergunb 0:8918a71cdbe9 737 //Convert the string representation to integer
Sergunb 0:8918a71cdbe9 738 connection->remotePort |= strtoul(token, &end, 10) & 0xFF;
Sergunb 0:8918a71cdbe9 739 //Syntax error?
Sergunb 0:8918a71cdbe9 740 if(*end != '\0')
Sergunb 0:8918a71cdbe9 741 break;
Sergunb 0:8918a71cdbe9 742
Sergunb 0:8918a71cdbe9 743 //Successful processing
Sergunb 0:8918a71cdbe9 744 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 745
Sergunb 0:8918a71cdbe9 746 //End of exception handling block
Sergunb 0:8918a71cdbe9 747 } while(0);
Sergunb 0:8918a71cdbe9 748
Sergunb 0:8918a71cdbe9 749 //Any error to report?
Sergunb 0:8918a71cdbe9 750 if(error)
Sergunb 0:8918a71cdbe9 751 {
Sergunb 0:8918a71cdbe9 752 //Re initialize data connection
Sergunb 0:8918a71cdbe9 753 connection->passiveMode = FALSE;
Sergunb 0:8918a71cdbe9 754 connection->remotePort = 0;
Sergunb 0:8918a71cdbe9 755
Sergunb 0:8918a71cdbe9 756 //Format response message
Sergunb 0:8918a71cdbe9 757 strcpy(connection->response, "501 Syntax error in parameters or arguments\r\n");
Sergunb 0:8918a71cdbe9 758 //Exit immediately
Sergunb 0:8918a71cdbe9 759 return;
Sergunb 0:8918a71cdbe9 760 }
Sergunb 0:8918a71cdbe9 761
Sergunb 0:8918a71cdbe9 762 //Successful processing
Sergunb 0:8918a71cdbe9 763 strcpy(connection->response, "200 Command okay\r\n");
Sergunb 0:8918a71cdbe9 764 }
Sergunb 0:8918a71cdbe9 765
Sergunb 0:8918a71cdbe9 766
Sergunb 0:8918a71cdbe9 767 /**
Sergunb 0:8918a71cdbe9 768 * @brief EPRT command processing
Sergunb 0:8918a71cdbe9 769 *
Sergunb 0:8918a71cdbe9 770 * The EPRT command allows for the specification of an extended address
Sergunb 0:8918a71cdbe9 771 * for the data connection
Sergunb 0:8918a71cdbe9 772 *
Sergunb 0:8918a71cdbe9 773 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 774 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 775 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 776 **/
Sergunb 0:8918a71cdbe9 777
Sergunb 0:8918a71cdbe9 778 void ftpServerProcessEprt(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 779 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 780 {
Sergunb 0:8918a71cdbe9 781 error_t error;
Sergunb 0:8918a71cdbe9 782 uint_t protocol;
Sergunb 0:8918a71cdbe9 783 char_t *p;
Sergunb 0:8918a71cdbe9 784 char_t *token;
Sergunb 0:8918a71cdbe9 785 char_t *end;
Sergunb 0:8918a71cdbe9 786 char_t delimiter[2];
Sergunb 0:8918a71cdbe9 787
Sergunb 0:8918a71cdbe9 788 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 789 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 790 {
Sergunb 0:8918a71cdbe9 791 //Format response message
Sergunb 0:8918a71cdbe9 792 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 793 //Exit immediately
Sergunb 0:8918a71cdbe9 794 return;
Sergunb 0:8918a71cdbe9 795 }
Sergunb 0:8918a71cdbe9 796
Sergunb 0:8918a71cdbe9 797 //The extended address must consist of the network protocol
Sergunb 0:8918a71cdbe9 798 //as well as the IP address and the 16-bit port number
Sergunb 0:8918a71cdbe9 799 if(*param == '\0')
Sergunb 0:8918a71cdbe9 800 {
Sergunb 0:8918a71cdbe9 801 //The argument is missing...
Sergunb 0:8918a71cdbe9 802 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 803 //Exit immediately
Sergunb 0:8918a71cdbe9 804 return;
Sergunb 0:8918a71cdbe9 805 }
Sergunb 0:8918a71cdbe9 806
Sergunb 0:8918a71cdbe9 807 //Close the data connection, if any
Sergunb 0:8918a71cdbe9 808 ftpServerCloseDataConnection(connection);
Sergunb 0:8918a71cdbe9 809
Sergunb 0:8918a71cdbe9 810 //Start of exception handling block
Sergunb 0:8918a71cdbe9 811 do
Sergunb 0:8918a71cdbe9 812 {
Sergunb 0:8918a71cdbe9 813 //A delimiter character must be specified
Sergunb 0:8918a71cdbe9 814 delimiter[0] = param[0];
Sergunb 0:8918a71cdbe9 815 delimiter[1] = '\0';
Sergunb 0:8918a71cdbe9 816 //Skip delimiter character
Sergunb 0:8918a71cdbe9 817 param++;
Sergunb 0:8918a71cdbe9 818
Sergunb 0:8918a71cdbe9 819 //Assume an error condition...
Sergunb 0:8918a71cdbe9 820 error = ERROR_INVALID_SYNTAX;
Sergunb 0:8918a71cdbe9 821
Sergunb 0:8918a71cdbe9 822 //Retrieve the network protocol to be used
Sergunb 0:8918a71cdbe9 823 token = strtok_r(param, delimiter, &p);
Sergunb 0:8918a71cdbe9 824 //Syntax error?
Sergunb 0:8918a71cdbe9 825 if(token == NULL)
Sergunb 0:8918a71cdbe9 826 break;
Sergunb 0:8918a71cdbe9 827
Sergunb 0:8918a71cdbe9 828 //Convert the string representation to integer
Sergunb 0:8918a71cdbe9 829 protocol = strtoul(token, &end, 10);
Sergunb 0:8918a71cdbe9 830 //Syntax error?
Sergunb 0:8918a71cdbe9 831 if(*end != '\0')
Sergunb 0:8918a71cdbe9 832 break;
Sergunb 0:8918a71cdbe9 833
Sergunb 0:8918a71cdbe9 834 //Get the IP address to be used
Sergunb 0:8918a71cdbe9 835 token = strtok_r(NULL, delimiter, &p);
Sergunb 0:8918a71cdbe9 836 //Syntax error?
Sergunb 0:8918a71cdbe9 837 if(token == NULL)
Sergunb 0:8918a71cdbe9 838 break;
Sergunb 0:8918a71cdbe9 839
Sergunb 0:8918a71cdbe9 840 #if (IPV4_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 841 //IPv4 address family?
Sergunb 0:8918a71cdbe9 842 if(protocol == 1)
Sergunb 0:8918a71cdbe9 843 {
Sergunb 0:8918a71cdbe9 844 //IPv4 addresses are 4-byte long
Sergunb 0:8918a71cdbe9 845 connection->remoteIpAddr.length = sizeof(Ipv4Addr);
Sergunb 0:8918a71cdbe9 846 //Convert the string to IPv4 address
Sergunb 0:8918a71cdbe9 847 error = ipv4StringToAddr(token, &connection->remoteIpAddr.ipv4Addr);
Sergunb 0:8918a71cdbe9 848 //Invalid IP address?
Sergunb 0:8918a71cdbe9 849 if(error)
Sergunb 0:8918a71cdbe9 850 break;
Sergunb 0:8918a71cdbe9 851 }
Sergunb 0:8918a71cdbe9 852 else
Sergunb 0:8918a71cdbe9 853 #endif
Sergunb 0:8918a71cdbe9 854 #if (IPV6_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 855 //IPv6 address family?
Sergunb 0:8918a71cdbe9 856 if(protocol == 2)
Sergunb 0:8918a71cdbe9 857 {
Sergunb 0:8918a71cdbe9 858 //IPv6 addresses are 16-byte long
Sergunb 0:8918a71cdbe9 859 connection->remoteIpAddr.length = sizeof(Ipv6Addr);
Sergunb 0:8918a71cdbe9 860 //Convert the string to IPv6 address
Sergunb 0:8918a71cdbe9 861 error = ipv6StringToAddr(token, &connection->remoteIpAddr.ipv6Addr);
Sergunb 0:8918a71cdbe9 862 //Invalid IP address?
Sergunb 0:8918a71cdbe9 863 if(error)
Sergunb 0:8918a71cdbe9 864 break;
Sergunb 0:8918a71cdbe9 865 }
Sergunb 0:8918a71cdbe9 866 else
Sergunb 0:8918a71cdbe9 867 #endif
Sergunb 0:8918a71cdbe9 868 //Unknown address family?
Sergunb 0:8918a71cdbe9 869 {
Sergunb 0:8918a71cdbe9 870 //Report an error
Sergunb 0:8918a71cdbe9 871 error = ERROR_INVALID_ADDRESS;
Sergunb 0:8918a71cdbe9 872 //Exit immediately
Sergunb 0:8918a71cdbe9 873 break;
Sergunb 0:8918a71cdbe9 874 }
Sergunb 0:8918a71cdbe9 875
Sergunb 0:8918a71cdbe9 876 //Assume an error condition...
Sergunb 0:8918a71cdbe9 877 error = ERROR_INVALID_SYNTAX;
Sergunb 0:8918a71cdbe9 878
Sergunb 0:8918a71cdbe9 879 //Get the port number to be used
Sergunb 0:8918a71cdbe9 880 token = strtok_r(NULL, delimiter, &p);
Sergunb 0:8918a71cdbe9 881 //Syntax error?
Sergunb 0:8918a71cdbe9 882 if(token == NULL)
Sergunb 0:8918a71cdbe9 883 break;
Sergunb 0:8918a71cdbe9 884
Sergunb 0:8918a71cdbe9 885 //Convert the string representation to integer
Sergunb 0:8918a71cdbe9 886 connection->remotePort = strtoul(token, &end, 10);
Sergunb 0:8918a71cdbe9 887 //Syntax error?
Sergunb 0:8918a71cdbe9 888 if(*end != '\0')
Sergunb 0:8918a71cdbe9 889 break;
Sergunb 0:8918a71cdbe9 890
Sergunb 0:8918a71cdbe9 891 //Successful processing
Sergunb 0:8918a71cdbe9 892 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 893
Sergunb 0:8918a71cdbe9 894 //End of exception handling block
Sergunb 0:8918a71cdbe9 895 } while(0);
Sergunb 0:8918a71cdbe9 896
Sergunb 0:8918a71cdbe9 897 //Any error to report?
Sergunb 0:8918a71cdbe9 898 if(error)
Sergunb 0:8918a71cdbe9 899 {
Sergunb 0:8918a71cdbe9 900 //Re initialize data connection
Sergunb 0:8918a71cdbe9 901 connection->passiveMode = FALSE;
Sergunb 0:8918a71cdbe9 902 connection->remotePort = 0;
Sergunb 0:8918a71cdbe9 903
Sergunb 0:8918a71cdbe9 904 //Format response message
Sergunb 0:8918a71cdbe9 905 strcpy(connection->response, "501 Syntax error in parameters or arguments\r\n");
Sergunb 0:8918a71cdbe9 906 //Exit immediately
Sergunb 0:8918a71cdbe9 907 return;
Sergunb 0:8918a71cdbe9 908 }
Sergunb 0:8918a71cdbe9 909
Sergunb 0:8918a71cdbe9 910 //Successful processing
Sergunb 0:8918a71cdbe9 911 strcpy(connection->response, "200 Command okay\r\n");
Sergunb 0:8918a71cdbe9 912 }
Sergunb 0:8918a71cdbe9 913
Sergunb 0:8918a71cdbe9 914
Sergunb 0:8918a71cdbe9 915 /**
Sergunb 0:8918a71cdbe9 916 * @brief PASV command processing
Sergunb 0:8918a71cdbe9 917 *
Sergunb 0:8918a71cdbe9 918 * The PASV command requests the server to listen on a data port and
Sergunb 0:8918a71cdbe9 919 * to wait for a connection rather than initiate one upon receipt of
Sergunb 0:8918a71cdbe9 920 * a transfer command
Sergunb 0:8918a71cdbe9 921 *
Sergunb 0:8918a71cdbe9 922 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 923 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 924 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 925 **/
Sergunb 0:8918a71cdbe9 926
Sergunb 0:8918a71cdbe9 927 void ftpServerProcessPasv(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 928 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 929 {
Sergunb 0:8918a71cdbe9 930 error_t error;
Sergunb 0:8918a71cdbe9 931 size_t n;
Sergunb 0:8918a71cdbe9 932 IpAddr ipAddr;
Sergunb 0:8918a71cdbe9 933 uint16_t port;
Sergunb 0:8918a71cdbe9 934
Sergunb 0:8918a71cdbe9 935 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 936 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 937 {
Sergunb 0:8918a71cdbe9 938 //Format response message
Sergunb 0:8918a71cdbe9 939 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 940 //Exit immediately
Sergunb 0:8918a71cdbe9 941 return;
Sergunb 0:8918a71cdbe9 942 }
Sergunb 0:8918a71cdbe9 943
Sergunb 0:8918a71cdbe9 944 //Close the data connection, if any
Sergunb 0:8918a71cdbe9 945 ftpServerCloseDataConnection(connection);
Sergunb 0:8918a71cdbe9 946
Sergunb 0:8918a71cdbe9 947 //Get the next passive port number to be used
Sergunb 0:8918a71cdbe9 948 port = ftpServerGetPassivePort(context);
Sergunb 0:8918a71cdbe9 949
Sergunb 0:8918a71cdbe9 950 //Start of exception handling block
Sergunb 0:8918a71cdbe9 951 do
Sergunb 0:8918a71cdbe9 952 {
Sergunb 0:8918a71cdbe9 953 //Open data socket
Sergunb 0:8918a71cdbe9 954 connection->dataSocket = socketOpen(SOCKET_TYPE_STREAM, SOCKET_IP_PROTO_TCP);
Sergunb 0:8918a71cdbe9 955 //Failed to open socket?
Sergunb 0:8918a71cdbe9 956 if(!connection->dataSocket)
Sergunb 0:8918a71cdbe9 957 {
Sergunb 0:8918a71cdbe9 958 //Report an error
Sergunb 0:8918a71cdbe9 959 error = ERROR_OPEN_FAILED;
Sergunb 0:8918a71cdbe9 960 //Exit immediately
Sergunb 0:8918a71cdbe9 961 break;
Sergunb 0:8918a71cdbe9 962 }
Sergunb 0:8918a71cdbe9 963
Sergunb 0:8918a71cdbe9 964 //Force the socket to operate in non-blocking mode
Sergunb 0:8918a71cdbe9 965 error = socketSetTimeout(connection->dataSocket, 0);
Sergunb 0:8918a71cdbe9 966 //Any error to report?
Sergunb 0:8918a71cdbe9 967 if(error)
Sergunb 0:8918a71cdbe9 968 break;
Sergunb 0:8918a71cdbe9 969
Sergunb 0:8918a71cdbe9 970 //Change the size of the TX buffer
Sergunb 0:8918a71cdbe9 971 error = socketSetTxBufferSize(connection->dataSocket,
Sergunb 0:8918a71cdbe9 972 FTP_SERVER_DATA_SOCKET_BUFFER_SIZE);
Sergunb 0:8918a71cdbe9 973 //Any error to report?
Sergunb 0:8918a71cdbe9 974 if(error)
Sergunb 0:8918a71cdbe9 975 break;
Sergunb 0:8918a71cdbe9 976
Sergunb 0:8918a71cdbe9 977 //Change the size of the RX buffer
Sergunb 0:8918a71cdbe9 978 error = socketSetRxBufferSize(connection->dataSocket,
Sergunb 0:8918a71cdbe9 979 FTP_SERVER_DATA_SOCKET_BUFFER_SIZE);
Sergunb 0:8918a71cdbe9 980 //Any error to report?
Sergunb 0:8918a71cdbe9 981 if(error)
Sergunb 0:8918a71cdbe9 982 break;
Sergunb 0:8918a71cdbe9 983
Sergunb 0:8918a71cdbe9 984 //Associate the socket with the relevant interface
Sergunb 0:8918a71cdbe9 985 error = socketBindToInterface(connection->dataSocket, connection->interface);
Sergunb 0:8918a71cdbe9 986 //Unable to bind the socket to the desired interface?
Sergunb 0:8918a71cdbe9 987 if(error)
Sergunb 0:8918a71cdbe9 988 break;
Sergunb 0:8918a71cdbe9 989
Sergunb 0:8918a71cdbe9 990 //Bind the socket to the passive port number
Sergunb 0:8918a71cdbe9 991 error = socketBind(connection->dataSocket, &IP_ADDR_ANY, port);
Sergunb 0:8918a71cdbe9 992 //Failed to bind the socket to the desired port?
Sergunb 0:8918a71cdbe9 993 if(error)
Sergunb 0:8918a71cdbe9 994 break;
Sergunb 0:8918a71cdbe9 995
Sergunb 0:8918a71cdbe9 996 //Place the data socket in the listening state
Sergunb 0:8918a71cdbe9 997 error = socketListen(connection->dataSocket, 1);
Sergunb 0:8918a71cdbe9 998 //Any error to report?
Sergunb 0:8918a71cdbe9 999 if(error)
Sergunb 0:8918a71cdbe9 1000 break;
Sergunb 0:8918a71cdbe9 1001
Sergunb 0:8918a71cdbe9 1002 //Retrieve local IP address
Sergunb 0:8918a71cdbe9 1003 error = socketGetLocalAddr(connection->controlSocket, &ipAddr, NULL);
Sergunb 0:8918a71cdbe9 1004 //Any error to report?
Sergunb 0:8918a71cdbe9 1005 if(error)
Sergunb 0:8918a71cdbe9 1006 break;
Sergunb 0:8918a71cdbe9 1007
Sergunb 0:8918a71cdbe9 1008 //The local IP address must be a valid IPv4 address
Sergunb 0:8918a71cdbe9 1009 if(ipAddr.length != sizeof(Ipv4Addr))
Sergunb 0:8918a71cdbe9 1010 {
Sergunb 0:8918a71cdbe9 1011 //PASV command cannot be used on IPv6 connections
Sergunb 0:8918a71cdbe9 1012 error = ERROR_INVALID_ADDRESS;
Sergunb 0:8918a71cdbe9 1013 //Exit immediately
Sergunb 0:8918a71cdbe9 1014 break;
Sergunb 0:8918a71cdbe9 1015 }
Sergunb 0:8918a71cdbe9 1016
Sergunb 0:8918a71cdbe9 1017 //End of exception handling block
Sergunb 0:8918a71cdbe9 1018 } while(0);
Sergunb 0:8918a71cdbe9 1019
Sergunb 0:8918a71cdbe9 1020 //Any error to report?
Sergunb 0:8918a71cdbe9 1021 if(error)
Sergunb 0:8918a71cdbe9 1022 {
Sergunb 0:8918a71cdbe9 1023 //Clean up side effects
Sergunb 0:8918a71cdbe9 1024 ftpServerCloseDataConnection(connection);
Sergunb 0:8918a71cdbe9 1025 //Format response message
Sergunb 0:8918a71cdbe9 1026 strcpy(connection->response, "425 Can't enter passive mode\r\n");
Sergunb 0:8918a71cdbe9 1027 //Exit immediately
Sergunb 0:8918a71cdbe9 1028 return;
Sergunb 0:8918a71cdbe9 1029 }
Sergunb 0:8918a71cdbe9 1030
Sergunb 0:8918a71cdbe9 1031 //Use passive data transfer
Sergunb 0:8918a71cdbe9 1032 connection->passiveMode = TRUE;
Sergunb 0:8918a71cdbe9 1033 //Update data connection state
Sergunb 0:8918a71cdbe9 1034 connection->dataState = FTP_DATA_STATE_LISTEN;
Sergunb 0:8918a71cdbe9 1035
Sergunb 0:8918a71cdbe9 1036 #if defined(FTP_SERVER_PASV_HOOK)
Sergunb 0:8918a71cdbe9 1037 FTP_SERVER_PASV_HOOK(connection, ipAddr);
Sergunb 0:8918a71cdbe9 1038 #endif
Sergunb 0:8918a71cdbe9 1039
Sergunb 0:8918a71cdbe9 1040 //Format response message
Sergunb 0:8918a71cdbe9 1041 n = sprintf(connection->response, "227 Entering passive mode (");
Sergunb 0:8918a71cdbe9 1042 //Append host address
Sergunb 0:8918a71cdbe9 1043 ipAddrToString(&ipAddr, connection->response + n);
Sergunb 0:8918a71cdbe9 1044
Sergunb 0:8918a71cdbe9 1045 //Parse the resulting string
Sergunb 0:8918a71cdbe9 1046 for(n = 0; connection->response[n] != '\0'; n++)
Sergunb 0:8918a71cdbe9 1047 {
Sergunb 0:8918a71cdbe9 1048 //Change dots to commas
Sergunb 0:8918a71cdbe9 1049 if(connection->response[n] == '.')
Sergunb 0:8918a71cdbe9 1050 connection->response[n] = ',';
Sergunb 0:8918a71cdbe9 1051 }
Sergunb 0:8918a71cdbe9 1052
Sergunb 0:8918a71cdbe9 1053 //Append port number
Sergunb 0:8918a71cdbe9 1054 sprintf(connection->response + n, ",%" PRIu8 ",%" PRIu8 ")\r\n", MSB(port), LSB(port));
Sergunb 0:8918a71cdbe9 1055 }
Sergunb 0:8918a71cdbe9 1056
Sergunb 0:8918a71cdbe9 1057
Sergunb 0:8918a71cdbe9 1058 /**
Sergunb 0:8918a71cdbe9 1059 * @brief EPSV command processing
Sergunb 0:8918a71cdbe9 1060 *
Sergunb 0:8918a71cdbe9 1061 * The EPSV command requests that a server listen on a data port and
Sergunb 0:8918a71cdbe9 1062 * wait for a connection
Sergunb 0:8918a71cdbe9 1063 *
Sergunb 0:8918a71cdbe9 1064 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 1065 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 1066 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 1067 **/
Sergunb 0:8918a71cdbe9 1068
Sergunb 0:8918a71cdbe9 1069 void ftpServerProcessEpsv(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 1070 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 1071 {
Sergunb 0:8918a71cdbe9 1072 error_t error;
Sergunb 0:8918a71cdbe9 1073 uint16_t port;
Sergunb 0:8918a71cdbe9 1074
Sergunb 0:8918a71cdbe9 1075 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 1076 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 1077 {
Sergunb 0:8918a71cdbe9 1078 //Format response message
Sergunb 0:8918a71cdbe9 1079 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 1080 //Exit immediately
Sergunb 0:8918a71cdbe9 1081 return;
Sergunb 0:8918a71cdbe9 1082 }
Sergunb 0:8918a71cdbe9 1083
Sergunb 0:8918a71cdbe9 1084 //Close the data connection, if any
Sergunb 0:8918a71cdbe9 1085 ftpServerCloseDataConnection(connection);
Sergunb 0:8918a71cdbe9 1086
Sergunb 0:8918a71cdbe9 1087 //Get the next passive port number to be used
Sergunb 0:8918a71cdbe9 1088 port = ftpServerGetPassivePort(context);
Sergunb 0:8918a71cdbe9 1089
Sergunb 0:8918a71cdbe9 1090 //Start of exception handling block
Sergunb 0:8918a71cdbe9 1091 do
Sergunb 0:8918a71cdbe9 1092 {
Sergunb 0:8918a71cdbe9 1093 //Open data socket
Sergunb 0:8918a71cdbe9 1094 connection->dataSocket = socketOpen(SOCKET_TYPE_STREAM, SOCKET_IP_PROTO_TCP);
Sergunb 0:8918a71cdbe9 1095 //Failed to open socket?
Sergunb 0:8918a71cdbe9 1096 if(!connection->dataSocket)
Sergunb 0:8918a71cdbe9 1097 {
Sergunb 0:8918a71cdbe9 1098 //Report an error
Sergunb 0:8918a71cdbe9 1099 error = ERROR_OPEN_FAILED;
Sergunb 0:8918a71cdbe9 1100 //Exit immediately
Sergunb 0:8918a71cdbe9 1101 break;
Sergunb 0:8918a71cdbe9 1102 }
Sergunb 0:8918a71cdbe9 1103
Sergunb 0:8918a71cdbe9 1104 //Force the socket to operate in non-blocking mode
Sergunb 0:8918a71cdbe9 1105 error = socketSetTimeout(connection->dataSocket, 0);
Sergunb 0:8918a71cdbe9 1106 //Any error to report?
Sergunb 0:8918a71cdbe9 1107 if(error)
Sergunb 0:8918a71cdbe9 1108 break;
Sergunb 0:8918a71cdbe9 1109
Sergunb 0:8918a71cdbe9 1110 //Change the size of the TX buffer
Sergunb 0:8918a71cdbe9 1111 error = socketSetTxBufferSize(connection->dataSocket,
Sergunb 0:8918a71cdbe9 1112 FTP_SERVER_DATA_SOCKET_BUFFER_SIZE);
Sergunb 0:8918a71cdbe9 1113 //Any error to report?
Sergunb 0:8918a71cdbe9 1114 if(error)
Sergunb 0:8918a71cdbe9 1115 break;
Sergunb 0:8918a71cdbe9 1116
Sergunb 0:8918a71cdbe9 1117 //Change the size of the RX buffer
Sergunb 0:8918a71cdbe9 1118 error = socketSetRxBufferSize(connection->dataSocket,
Sergunb 0:8918a71cdbe9 1119 FTP_SERVER_DATA_SOCKET_BUFFER_SIZE);
Sergunb 0:8918a71cdbe9 1120 //Any error to report?
Sergunb 0:8918a71cdbe9 1121 if(error)
Sergunb 0:8918a71cdbe9 1122 break;
Sergunb 0:8918a71cdbe9 1123
Sergunb 0:8918a71cdbe9 1124 //Associate the socket with the relevant interface
Sergunb 0:8918a71cdbe9 1125 error = socketBindToInterface(connection->dataSocket, connection->interface);
Sergunb 0:8918a71cdbe9 1126 //Unable to bind the socket to the desired interface?
Sergunb 0:8918a71cdbe9 1127 if(error)
Sergunb 0:8918a71cdbe9 1128 break;
Sergunb 0:8918a71cdbe9 1129
Sergunb 0:8918a71cdbe9 1130 //Bind the socket to the passive port number
Sergunb 0:8918a71cdbe9 1131 error = socketBind(connection->dataSocket, &IP_ADDR_ANY, port);
Sergunb 0:8918a71cdbe9 1132 //Failed to bind the socket to the desired port?
Sergunb 0:8918a71cdbe9 1133 if(error)
Sergunb 0:8918a71cdbe9 1134 break;
Sergunb 0:8918a71cdbe9 1135
Sergunb 0:8918a71cdbe9 1136 //Place the data socket in the listening state
Sergunb 0:8918a71cdbe9 1137 error = socketListen(connection->dataSocket, 1);
Sergunb 0:8918a71cdbe9 1138 //Any error to report?
Sergunb 0:8918a71cdbe9 1139 if(error)
Sergunb 0:8918a71cdbe9 1140 break;
Sergunb 0:8918a71cdbe9 1141
Sergunb 0:8918a71cdbe9 1142 //End of exception handling block
Sergunb 0:8918a71cdbe9 1143 } while(0);
Sergunb 0:8918a71cdbe9 1144
Sergunb 0:8918a71cdbe9 1145 //Any error to report?
Sergunb 0:8918a71cdbe9 1146 if(error)
Sergunb 0:8918a71cdbe9 1147 {
Sergunb 0:8918a71cdbe9 1148 //Clean up side effects
Sergunb 0:8918a71cdbe9 1149 ftpServerCloseDataConnection(connection);
Sergunb 0:8918a71cdbe9 1150 //Format response message
Sergunb 0:8918a71cdbe9 1151 strcpy(connection->response, "425 Can't enter passive mode\r\n");
Sergunb 0:8918a71cdbe9 1152 //Exit immediately
Sergunb 0:8918a71cdbe9 1153 return;
Sergunb 0:8918a71cdbe9 1154 }
Sergunb 0:8918a71cdbe9 1155
Sergunb 0:8918a71cdbe9 1156 //Use passive data transfer
Sergunb 0:8918a71cdbe9 1157 connection->passiveMode = TRUE;
Sergunb 0:8918a71cdbe9 1158 //Update data connection state
Sergunb 0:8918a71cdbe9 1159 connection->dataState = FTP_DATA_STATE_LISTEN;
Sergunb 0:8918a71cdbe9 1160
Sergunb 0:8918a71cdbe9 1161 //The response code for entering passive mode using an extended address must be 229
Sergunb 0:8918a71cdbe9 1162 sprintf(connection->response, "229 Entering extended passive mode (|||%" PRIu16 "|)\r\n",
Sergunb 0:8918a71cdbe9 1163 port);
Sergunb 0:8918a71cdbe9 1164 }
Sergunb 0:8918a71cdbe9 1165
Sergunb 0:8918a71cdbe9 1166
Sergunb 0:8918a71cdbe9 1167 /**
Sergunb 0:8918a71cdbe9 1168 * @brief ABOR command processing
Sergunb 0:8918a71cdbe9 1169 *
Sergunb 0:8918a71cdbe9 1170 * The ABOR command tells the server to abort the previous FTP
Sergunb 0:8918a71cdbe9 1171 * service command and any associated transfer of data
Sergunb 0:8918a71cdbe9 1172 *
Sergunb 0:8918a71cdbe9 1173 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 1174 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 1175 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 1176 **/
Sergunb 0:8918a71cdbe9 1177
Sergunb 0:8918a71cdbe9 1178 void ftpServerProcessAbor(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 1179 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 1180 {
Sergunb 0:8918a71cdbe9 1181 //There are two cases to consider upon receipt of this command
Sergunb 0:8918a71cdbe9 1182 if(connection->dataState == FTP_DATA_STATE_CLOSED)
Sergunb 0:8918a71cdbe9 1183 {
Sergunb 0:8918a71cdbe9 1184 //If the FTP service command was already completed, the server closes
Sergunb 0:8918a71cdbe9 1185 //the data connection (if it is open)...
Sergunb 0:8918a71cdbe9 1186 ftpServerCloseDataConnection(connection);
Sergunb 0:8918a71cdbe9 1187
Sergunb 0:8918a71cdbe9 1188 //...and responds with a 226 reply, indicating that the abort command
Sergunb 0:8918a71cdbe9 1189 //was successfully processed
Sergunb 0:8918a71cdbe9 1190 strcpy(connection->response, "226 Abort command successful\r\n");
Sergunb 0:8918a71cdbe9 1191 }
Sergunb 0:8918a71cdbe9 1192 else
Sergunb 0:8918a71cdbe9 1193 {
Sergunb 0:8918a71cdbe9 1194 //If the FTP service command is still in progress, the server aborts
Sergunb 0:8918a71cdbe9 1195 //the FTP service in progress and closes the data connection...
Sergunb 0:8918a71cdbe9 1196 ftpServerCloseDataConnection(connection);
Sergunb 0:8918a71cdbe9 1197
Sergunb 0:8918a71cdbe9 1198 //...returning a 426 reply to indicate that the service request
Sergunb 0:8918a71cdbe9 1199 //terminated abnormally
Sergunb 0:8918a71cdbe9 1200 strcpy(connection->response, "426 Connection closed; transfer aborted\r\n");
Sergunb 0:8918a71cdbe9 1201
Sergunb 0:8918a71cdbe9 1202 //The server then sends a 226 reply, indicating that the abort command
Sergunb 0:8918a71cdbe9 1203 //was successfully processed
Sergunb 0:8918a71cdbe9 1204 strcat(connection->response, "226 Abort command successful\r\n");
Sergunb 0:8918a71cdbe9 1205 }
Sergunb 0:8918a71cdbe9 1206
Sergunb 0:8918a71cdbe9 1207 //Release previously allocated resources
Sergunb 0:8918a71cdbe9 1208 if(connection->file != NULL)
Sergunb 0:8918a71cdbe9 1209 {
Sergunb 0:8918a71cdbe9 1210 fsCloseFile(connection->file);
Sergunb 0:8918a71cdbe9 1211 connection->file = NULL;
Sergunb 0:8918a71cdbe9 1212 }
Sergunb 0:8918a71cdbe9 1213 if(connection->dir != NULL)
Sergunb 0:8918a71cdbe9 1214 {
Sergunb 0:8918a71cdbe9 1215 fsCloseDir(connection->dir);
Sergunb 0:8918a71cdbe9 1216 connection->dir = NULL;
Sergunb 0:8918a71cdbe9 1217 }
Sergunb 0:8918a71cdbe9 1218 }
Sergunb 0:8918a71cdbe9 1219
Sergunb 0:8918a71cdbe9 1220
Sergunb 0:8918a71cdbe9 1221 /**
Sergunb 0:8918a71cdbe9 1222 * @brief PWD command processing
Sergunb 0:8918a71cdbe9 1223 *
Sergunb 0:8918a71cdbe9 1224 * The PWD command causes the name of the current working
Sergunb 0:8918a71cdbe9 1225 * directory to be returned in the reply
Sergunb 0:8918a71cdbe9 1226 *
Sergunb 0:8918a71cdbe9 1227 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 1228 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 1229 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 1230 **/
Sergunb 0:8918a71cdbe9 1231
Sergunb 0:8918a71cdbe9 1232 void ftpServerProcessPwd(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 1233 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 1234 {
Sergunb 0:8918a71cdbe9 1235 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 1236 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 1237 {
Sergunb 0:8918a71cdbe9 1238 //Format response message
Sergunb 0:8918a71cdbe9 1239 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 1240 //Exit immediately
Sergunb 0:8918a71cdbe9 1241 return;
Sergunb 0:8918a71cdbe9 1242 }
Sergunb 0:8918a71cdbe9 1243
Sergunb 0:8918a71cdbe9 1244 //A successful PWD command uses the 257 reply code
Sergunb 0:8918a71cdbe9 1245 sprintf(connection->response, "257 \"%s\" is current directory\r\n",
Sergunb 0:8918a71cdbe9 1246 ftpServerStripHomeDir(connection, connection->currentDir));
Sergunb 0:8918a71cdbe9 1247 }
Sergunb 0:8918a71cdbe9 1248
Sergunb 0:8918a71cdbe9 1249
Sergunb 0:8918a71cdbe9 1250 /**
Sergunb 0:8918a71cdbe9 1251 * @brief CWD command processing
Sergunb 0:8918a71cdbe9 1252 *
Sergunb 0:8918a71cdbe9 1253 * The CWD command allows the user to work with a different
Sergunb 0:8918a71cdbe9 1254 * directory
Sergunb 0:8918a71cdbe9 1255 *
Sergunb 0:8918a71cdbe9 1256 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 1257 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 1258 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 1259 **/
Sergunb 0:8918a71cdbe9 1260
Sergunb 0:8918a71cdbe9 1261 void ftpServerProcessCwd(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 1262 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 1263 {
Sergunb 0:8918a71cdbe9 1264 error_t error;
Sergunb 0:8918a71cdbe9 1265 uint_t perm;
Sergunb 0:8918a71cdbe9 1266
Sergunb 0:8918a71cdbe9 1267 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 1268 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 1269 {
Sergunb 0:8918a71cdbe9 1270 //Format response message
Sergunb 0:8918a71cdbe9 1271 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 1272 //Exit immediately
Sergunb 0:8918a71cdbe9 1273 return;
Sergunb 0:8918a71cdbe9 1274 }
Sergunb 0:8918a71cdbe9 1275
Sergunb 0:8918a71cdbe9 1276 //The argument specifies the pathname
Sergunb 0:8918a71cdbe9 1277 if(*param == '\0')
Sergunb 0:8918a71cdbe9 1278 {
Sergunb 0:8918a71cdbe9 1279 //The argument is missing...
Sergunb 0:8918a71cdbe9 1280 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 1281 //Exit immediately
Sergunb 0:8918a71cdbe9 1282 return;
Sergunb 0:8918a71cdbe9 1283 }
Sergunb 0:8918a71cdbe9 1284
Sergunb 0:8918a71cdbe9 1285 //Retrieve the full pathname
Sergunb 0:8918a71cdbe9 1286 error = ftpServerGetPath(connection, param,
Sergunb 0:8918a71cdbe9 1287 connection->path, FTP_SERVER_MAX_PATH_LEN);
Sergunb 0:8918a71cdbe9 1288
Sergunb 0:8918a71cdbe9 1289 //Make sure the pathname is valid
Sergunb 0:8918a71cdbe9 1290 if(error)
Sergunb 0:8918a71cdbe9 1291 {
Sergunb 0:8918a71cdbe9 1292 //Report an error
Sergunb 0:8918a71cdbe9 1293 strcpy(connection->response, "501 Invalid parameter\r\n");
Sergunb 0:8918a71cdbe9 1294 //Exit immediately
Sergunb 0:8918a71cdbe9 1295 return;
Sergunb 0:8918a71cdbe9 1296 }
Sergunb 0:8918a71cdbe9 1297
Sergunb 0:8918a71cdbe9 1298 //Retrieve permissions for the specified directory
Sergunb 0:8918a71cdbe9 1299 perm = ftpServerGetFilePermissions(context, connection, connection->path);
Sergunb 0:8918a71cdbe9 1300
Sergunb 0:8918a71cdbe9 1301 //Insufficient access rights?
Sergunb 0:8918a71cdbe9 1302 if(!(perm & FTP_FILE_PERM_READ))
Sergunb 0:8918a71cdbe9 1303 {
Sergunb 0:8918a71cdbe9 1304 //Report an error
Sergunb 0:8918a71cdbe9 1305 strcpy(connection->response, "550 Access denied\r\n");
Sergunb 0:8918a71cdbe9 1306 //Exit immediately
Sergunb 0:8918a71cdbe9 1307 return;
Sergunb 0:8918a71cdbe9 1308 }
Sergunb 0:8918a71cdbe9 1309
Sergunb 0:8918a71cdbe9 1310 //Make sure the specified directory exists
Sergunb 0:8918a71cdbe9 1311 if(!fsDirExists(connection->path))
Sergunb 0:8918a71cdbe9 1312 {
Sergunb 0:8918a71cdbe9 1313 //Report an error
Sergunb 0:8918a71cdbe9 1314 strcpy(connection->response, "550 Directory not found\r\n");
Sergunb 0:8918a71cdbe9 1315 //Exit immediately
Sergunb 0:8918a71cdbe9 1316 return;
Sergunb 0:8918a71cdbe9 1317 }
Sergunb 0:8918a71cdbe9 1318
Sergunb 0:8918a71cdbe9 1319 //Change current working directory
Sergunb 0:8918a71cdbe9 1320 strcpy(connection->currentDir, connection->path);
Sergunb 0:8918a71cdbe9 1321
Sergunb 0:8918a71cdbe9 1322 //A successful PWD command uses the 250 reply code
Sergunb 0:8918a71cdbe9 1323 sprintf(connection->response, "250 Directory changed to %s\r\n",
Sergunb 0:8918a71cdbe9 1324 ftpServerStripHomeDir(connection, connection->currentDir));
Sergunb 0:8918a71cdbe9 1325 }
Sergunb 0:8918a71cdbe9 1326
Sergunb 0:8918a71cdbe9 1327
Sergunb 0:8918a71cdbe9 1328 /**
Sergunb 0:8918a71cdbe9 1329 * @brief CDUP command processing
Sergunb 0:8918a71cdbe9 1330 *
Sergunb 0:8918a71cdbe9 1331 * The CDUP command allows the user to change to the parent directory
Sergunb 0:8918a71cdbe9 1332 *
Sergunb 0:8918a71cdbe9 1333 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 1334 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 1335 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 1336 **/
Sergunb 0:8918a71cdbe9 1337
Sergunb 0:8918a71cdbe9 1338 void ftpServerProcessCdup(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 1339 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 1340 {
Sergunb 0:8918a71cdbe9 1341 uint_t perm;
Sergunb 0:8918a71cdbe9 1342
Sergunb 0:8918a71cdbe9 1343 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 1344 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 1345 {
Sergunb 0:8918a71cdbe9 1346 //Format response message
Sergunb 0:8918a71cdbe9 1347 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 1348 //Exit immediately
Sergunb 0:8918a71cdbe9 1349 return;
Sergunb 0:8918a71cdbe9 1350 }
Sergunb 0:8918a71cdbe9 1351
Sergunb 0:8918a71cdbe9 1352 //Get current directory
Sergunb 0:8918a71cdbe9 1353 strcpy(connection->path, connection->currentDir);
Sergunb 0:8918a71cdbe9 1354
Sergunb 0:8918a71cdbe9 1355 //Change to the parent directory
Sergunb 0:8918a71cdbe9 1356 pathCombine(connection->path, "..", FTP_SERVER_MAX_PATH_LEN);
Sergunb 0:8918a71cdbe9 1357 pathCanonicalize(connection->path);
Sergunb 0:8918a71cdbe9 1358
Sergunb 0:8918a71cdbe9 1359 //Retrieve permissions for the directory
Sergunb 0:8918a71cdbe9 1360 perm = ftpServerGetFilePermissions(context, connection, connection->path);
Sergunb 0:8918a71cdbe9 1361
Sergunb 0:8918a71cdbe9 1362 //Check access rights
Sergunb 0:8918a71cdbe9 1363 if(perm & FTP_FILE_PERM_READ)
Sergunb 0:8918a71cdbe9 1364 {
Sergunb 0:8918a71cdbe9 1365 //Update current directory
Sergunb 0:8918a71cdbe9 1366 strcpy(connection->currentDir, connection->path);
Sergunb 0:8918a71cdbe9 1367 }
Sergunb 0:8918a71cdbe9 1368
Sergunb 0:8918a71cdbe9 1369 //A successful PWD command uses the 250 reply code
Sergunb 0:8918a71cdbe9 1370 sprintf(connection->response, "250 Directory changed to %s\r\n",
Sergunb 0:8918a71cdbe9 1371 ftpServerStripHomeDir(connection, connection->currentDir));
Sergunb 0:8918a71cdbe9 1372 }
Sergunb 0:8918a71cdbe9 1373
Sergunb 0:8918a71cdbe9 1374
Sergunb 0:8918a71cdbe9 1375 /**
Sergunb 0:8918a71cdbe9 1376 * @brief LIST command processing
Sergunb 0:8918a71cdbe9 1377 *
Sergunb 0:8918a71cdbe9 1378 * The LIST command is used to list the content of a directory
Sergunb 0:8918a71cdbe9 1379 *
Sergunb 0:8918a71cdbe9 1380 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 1381 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 1382 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 1383 **/
Sergunb 0:8918a71cdbe9 1384
Sergunb 0:8918a71cdbe9 1385 void ftpServerProcessList(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 1386 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 1387 {
Sergunb 0:8918a71cdbe9 1388 error_t error;
Sergunb 0:8918a71cdbe9 1389 uint_t perm;
Sergunb 0:8918a71cdbe9 1390
Sergunb 0:8918a71cdbe9 1391 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 1392 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 1393 {
Sergunb 0:8918a71cdbe9 1394 //Format response message
Sergunb 0:8918a71cdbe9 1395 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 1396 //Exit immediately
Sergunb 0:8918a71cdbe9 1397 return;
Sergunb 0:8918a71cdbe9 1398 }
Sergunb 0:8918a71cdbe9 1399
Sergunb 0:8918a71cdbe9 1400 //Any option flags
Sergunb 0:8918a71cdbe9 1401 while(*param == '-')
Sergunb 0:8918a71cdbe9 1402 {
Sergunb 0:8918a71cdbe9 1403 //Skip option flags
Sergunb 0:8918a71cdbe9 1404 while(*param != ' ' && *param != '\0')
Sergunb 0:8918a71cdbe9 1405 param++;
Sergunb 0:8918a71cdbe9 1406 //Skip whitespace characters
Sergunb 0:8918a71cdbe9 1407 while(*param == ' ')
Sergunb 0:8918a71cdbe9 1408 param++;
Sergunb 0:8918a71cdbe9 1409 }
Sergunb 0:8918a71cdbe9 1410
Sergunb 0:8918a71cdbe9 1411 //The pathname is optional
Sergunb 0:8918a71cdbe9 1412 if(*param == '\0')
Sergunb 0:8918a71cdbe9 1413 {
Sergunb 0:8918a71cdbe9 1414 //Use current directory if no pathname is specified
Sergunb 0:8918a71cdbe9 1415 strcpy(connection->path, connection->currentDir);
Sergunb 0:8918a71cdbe9 1416 }
Sergunb 0:8918a71cdbe9 1417 else
Sergunb 0:8918a71cdbe9 1418 {
Sergunb 0:8918a71cdbe9 1419 //Retrieve the full pathname
Sergunb 0:8918a71cdbe9 1420 error = ftpServerGetPath(connection, param,
Sergunb 0:8918a71cdbe9 1421 connection->path, FTP_SERVER_MAX_PATH_LEN);
Sergunb 0:8918a71cdbe9 1422
Sergunb 0:8918a71cdbe9 1423 //Any error to report?
Sergunb 0:8918a71cdbe9 1424 if(error)
Sergunb 0:8918a71cdbe9 1425 {
Sergunb 0:8918a71cdbe9 1426 //The specified pathname is not valid...
Sergunb 0:8918a71cdbe9 1427 strcpy(connection->response, "501 Invalid parameter\r\n");
Sergunb 0:8918a71cdbe9 1428 //Exit immediately
Sergunb 0:8918a71cdbe9 1429 return;
Sergunb 0:8918a71cdbe9 1430 }
Sergunb 0:8918a71cdbe9 1431 }
Sergunb 0:8918a71cdbe9 1432
Sergunb 0:8918a71cdbe9 1433 //Retrieve permissions for the specified directory
Sergunb 0:8918a71cdbe9 1434 perm = ftpServerGetFilePermissions(context, connection, connection->path);
Sergunb 0:8918a71cdbe9 1435
Sergunb 0:8918a71cdbe9 1436 //Insufficient access rights?
Sergunb 0:8918a71cdbe9 1437 if(!(perm & FTP_FILE_PERM_READ))
Sergunb 0:8918a71cdbe9 1438 {
Sergunb 0:8918a71cdbe9 1439 //Report an error
Sergunb 0:8918a71cdbe9 1440 strcpy(connection->response, "550 Access denied\r\n");
Sergunb 0:8918a71cdbe9 1441 //Exit immediately
Sergunb 0:8918a71cdbe9 1442 return;
Sergunb 0:8918a71cdbe9 1443 }
Sergunb 0:8918a71cdbe9 1444
Sergunb 0:8918a71cdbe9 1445 //Open specified directory for reading
Sergunb 0:8918a71cdbe9 1446 connection->dir = fsOpenDir(connection->path);
Sergunb 0:8918a71cdbe9 1447
Sergunb 0:8918a71cdbe9 1448 //Failed to open the directory?
Sergunb 0:8918a71cdbe9 1449 if(!connection->dir)
Sergunb 0:8918a71cdbe9 1450 {
Sergunb 0:8918a71cdbe9 1451 //Report an error
Sergunb 0:8918a71cdbe9 1452 strcpy(connection->response, "550 Directory not found\r\n");
Sergunb 0:8918a71cdbe9 1453 //Exit immediately
Sergunb 0:8918a71cdbe9 1454 return;
Sergunb 0:8918a71cdbe9 1455 }
Sergunb 0:8918a71cdbe9 1456
Sergunb 0:8918a71cdbe9 1457 //Check current data transfer mode
Sergunb 0:8918a71cdbe9 1458 if(connection->passiveMode)
Sergunb 0:8918a71cdbe9 1459 {
Sergunb 0:8918a71cdbe9 1460 //Check whether the data connection is already opened
Sergunb 0:8918a71cdbe9 1461 if(connection->dataState == FTP_DATA_STATE_IDLE)
Sergunb 0:8918a71cdbe9 1462 connection->dataState = FTP_DATA_STATE_SEND;
Sergunb 0:8918a71cdbe9 1463 }
Sergunb 0:8918a71cdbe9 1464 else
Sergunb 0:8918a71cdbe9 1465 {
Sergunb 0:8918a71cdbe9 1466 //Open the data connection
Sergunb 0:8918a71cdbe9 1467 error = ftpServerOpenDataConnection(context, connection);
Sergunb 0:8918a71cdbe9 1468
Sergunb 0:8918a71cdbe9 1469 //Any error to report?
Sergunb 0:8918a71cdbe9 1470 if(error)
Sergunb 0:8918a71cdbe9 1471 {
Sergunb 0:8918a71cdbe9 1472 //Clean up side effects
Sergunb 0:8918a71cdbe9 1473 fsCloseDir(connection->dir);
Sergunb 0:8918a71cdbe9 1474 //Format response
Sergunb 0:8918a71cdbe9 1475 strcpy(connection->response, "450 Can't open data connection\r\n");
Sergunb 0:8918a71cdbe9 1476 //Exit immediately
Sergunb 0:8918a71cdbe9 1477 return;
Sergunb 0:8918a71cdbe9 1478 }
Sergunb 0:8918a71cdbe9 1479
Sergunb 0:8918a71cdbe9 1480 //The data connection is ready to send data
Sergunb 0:8918a71cdbe9 1481 connection->dataState = FTP_DATA_STATE_SEND;
Sergunb 0:8918a71cdbe9 1482 }
Sergunb 0:8918a71cdbe9 1483
Sergunb 0:8918a71cdbe9 1484 //Flush transmission buffer
Sergunb 0:8918a71cdbe9 1485 connection->bufferLength = 0;
Sergunb 0:8918a71cdbe9 1486 connection->bufferPos = 0;
Sergunb 0:8918a71cdbe9 1487
Sergunb 0:8918a71cdbe9 1488 //LIST command is being processed
Sergunb 0:8918a71cdbe9 1489 connection->controlState = FTP_CONTROL_STATE_LIST;
Sergunb 0:8918a71cdbe9 1490
Sergunb 0:8918a71cdbe9 1491 //Format response message
Sergunb 0:8918a71cdbe9 1492 strcpy(connection->response, "150 Opening data connection\r\n");
Sergunb 0:8918a71cdbe9 1493 }
Sergunb 0:8918a71cdbe9 1494
Sergunb 0:8918a71cdbe9 1495
Sergunb 0:8918a71cdbe9 1496 /**
Sergunb 0:8918a71cdbe9 1497 * @brief MKD command processing
Sergunb 0:8918a71cdbe9 1498 *
Sergunb 0:8918a71cdbe9 1499 * The MKD command causes the directory specified in the pathname
Sergunb 0:8918a71cdbe9 1500 * to be created as a directory
Sergunb 0:8918a71cdbe9 1501 *
Sergunb 0:8918a71cdbe9 1502 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 1503 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 1504 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 1505 **/
Sergunb 0:8918a71cdbe9 1506
Sergunb 0:8918a71cdbe9 1507 void ftpServerProcessMkd(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 1508 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 1509 {
Sergunb 0:8918a71cdbe9 1510 error_t error;
Sergunb 0:8918a71cdbe9 1511 uint_t perm;
Sergunb 0:8918a71cdbe9 1512
Sergunb 0:8918a71cdbe9 1513 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 1514 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 1515 {
Sergunb 0:8918a71cdbe9 1516 //Format response message
Sergunb 0:8918a71cdbe9 1517 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 1518 //Exit immediately
Sergunb 0:8918a71cdbe9 1519 return;
Sergunb 0:8918a71cdbe9 1520 }
Sergunb 0:8918a71cdbe9 1521
Sergunb 0:8918a71cdbe9 1522 //The argument specifies the pathname
Sergunb 0:8918a71cdbe9 1523 if(*param == '\0')
Sergunb 0:8918a71cdbe9 1524 {
Sergunb 0:8918a71cdbe9 1525 //The argument is missing...
Sergunb 0:8918a71cdbe9 1526 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 1527 //Exit immediately
Sergunb 0:8918a71cdbe9 1528 return;
Sergunb 0:8918a71cdbe9 1529 }
Sergunb 0:8918a71cdbe9 1530
Sergunb 0:8918a71cdbe9 1531 //Retrieve the full pathname
Sergunb 0:8918a71cdbe9 1532 error = ftpServerGetPath(connection, param,
Sergunb 0:8918a71cdbe9 1533 connection->path, FTP_SERVER_MAX_PATH_LEN);
Sergunb 0:8918a71cdbe9 1534
Sergunb 0:8918a71cdbe9 1535 //Any error to report?
Sergunb 0:8918a71cdbe9 1536 if(error)
Sergunb 0:8918a71cdbe9 1537 {
Sergunb 0:8918a71cdbe9 1538 //The specified pathname is not valid...
Sergunb 0:8918a71cdbe9 1539 strcpy(connection->response, "501 Invalid parameter\r\n");
Sergunb 0:8918a71cdbe9 1540 //Exit immediately
Sergunb 0:8918a71cdbe9 1541 return;
Sergunb 0:8918a71cdbe9 1542 }
Sergunb 0:8918a71cdbe9 1543
Sergunb 0:8918a71cdbe9 1544 //Retrieve permissions for the specified directory
Sergunb 0:8918a71cdbe9 1545 perm = ftpServerGetFilePermissions(context, connection, connection->path);
Sergunb 0:8918a71cdbe9 1546
Sergunb 0:8918a71cdbe9 1547 //Insufficient access rights?
Sergunb 0:8918a71cdbe9 1548 if(!(perm & FTP_FILE_PERM_WRITE))
Sergunb 0:8918a71cdbe9 1549 {
Sergunb 0:8918a71cdbe9 1550 //Report an error
Sergunb 0:8918a71cdbe9 1551 strcpy(connection->response, "550 Access denied\r\n");
Sergunb 0:8918a71cdbe9 1552 //Exit immediately
Sergunb 0:8918a71cdbe9 1553 return;
Sergunb 0:8918a71cdbe9 1554 }
Sergunb 0:8918a71cdbe9 1555
Sergunb 0:8918a71cdbe9 1556 //Create the specified directory
Sergunb 0:8918a71cdbe9 1557 error = fsCreateDir(connection->path);
Sergunb 0:8918a71cdbe9 1558
Sergunb 0:8918a71cdbe9 1559 //Any error to report?
Sergunb 0:8918a71cdbe9 1560 if(error)
Sergunb 0:8918a71cdbe9 1561 {
Sergunb 0:8918a71cdbe9 1562 //The specified pathname is not valid...
Sergunb 0:8918a71cdbe9 1563 strcpy(connection->response, "550 Can't create directory\r\n");
Sergunb 0:8918a71cdbe9 1564 //Exit immediately
Sergunb 0:8918a71cdbe9 1565 return;
Sergunb 0:8918a71cdbe9 1566 }
Sergunb 0:8918a71cdbe9 1567
Sergunb 0:8918a71cdbe9 1568 //The specified directory was successfully created
Sergunb 0:8918a71cdbe9 1569 sprintf(connection->response, "257 \"%s\" created\r\n",
Sergunb 0:8918a71cdbe9 1570 ftpServerStripHomeDir(connection, connection->path));
Sergunb 0:8918a71cdbe9 1571 }
Sergunb 0:8918a71cdbe9 1572
Sergunb 0:8918a71cdbe9 1573
Sergunb 0:8918a71cdbe9 1574 /**
Sergunb 0:8918a71cdbe9 1575 * @brief RMD command processing
Sergunb 0:8918a71cdbe9 1576 *
Sergunb 0:8918a71cdbe9 1577 * The RMD command causes the directory specified in the pathname
Sergunb 0:8918a71cdbe9 1578 * to be removed
Sergunb 0:8918a71cdbe9 1579 *
Sergunb 0:8918a71cdbe9 1580 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 1581 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 1582 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 1583 **/
Sergunb 0:8918a71cdbe9 1584
Sergunb 0:8918a71cdbe9 1585 void ftpServerProcessRmd(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 1586 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 1587 {
Sergunb 0:8918a71cdbe9 1588 error_t error;
Sergunb 0:8918a71cdbe9 1589 uint_t perm;
Sergunb 0:8918a71cdbe9 1590
Sergunb 0:8918a71cdbe9 1591 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 1592 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 1593 {
Sergunb 0:8918a71cdbe9 1594 //Format response message
Sergunb 0:8918a71cdbe9 1595 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 1596 //Exit immediately
Sergunb 0:8918a71cdbe9 1597 return;
Sergunb 0:8918a71cdbe9 1598 }
Sergunb 0:8918a71cdbe9 1599
Sergunb 0:8918a71cdbe9 1600 //The argument specifies the directory to be removed
Sergunb 0:8918a71cdbe9 1601 if(*param == '\0')
Sergunb 0:8918a71cdbe9 1602 {
Sergunb 0:8918a71cdbe9 1603 //The argument is missing...
Sergunb 0:8918a71cdbe9 1604 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 1605 //Exit immediately
Sergunb 0:8918a71cdbe9 1606 return;
Sergunb 0:8918a71cdbe9 1607 }
Sergunb 0:8918a71cdbe9 1608
Sergunb 0:8918a71cdbe9 1609 //Retrieve the full pathname of the directory
Sergunb 0:8918a71cdbe9 1610 error = ftpServerGetPath(connection, param,
Sergunb 0:8918a71cdbe9 1611 connection->path, FTP_SERVER_MAX_PATH_LEN);
Sergunb 0:8918a71cdbe9 1612
Sergunb 0:8918a71cdbe9 1613 //Any error to report?
Sergunb 0:8918a71cdbe9 1614 if(error)
Sergunb 0:8918a71cdbe9 1615 {
Sergunb 0:8918a71cdbe9 1616 //The specified pathname is not valid...
Sergunb 0:8918a71cdbe9 1617 strcpy(connection->response, "501 Invalid parameter\r\n");
Sergunb 0:8918a71cdbe9 1618 //Exit immediately
Sergunb 0:8918a71cdbe9 1619 return;
Sergunb 0:8918a71cdbe9 1620 }
Sergunb 0:8918a71cdbe9 1621
Sergunb 0:8918a71cdbe9 1622 //Retrieve permissions for the specified directory
Sergunb 0:8918a71cdbe9 1623 perm = ftpServerGetFilePermissions(context, connection, connection->path);
Sergunb 0:8918a71cdbe9 1624
Sergunb 0:8918a71cdbe9 1625 //Insufficient access rights?
Sergunb 0:8918a71cdbe9 1626 if(!(perm & FTP_FILE_PERM_WRITE))
Sergunb 0:8918a71cdbe9 1627 {
Sergunb 0:8918a71cdbe9 1628 //Report an error
Sergunb 0:8918a71cdbe9 1629 strcpy(connection->response, "550 Access denied\r\n");
Sergunb 0:8918a71cdbe9 1630 //Exit immediately
Sergunb 0:8918a71cdbe9 1631 return;
Sergunb 0:8918a71cdbe9 1632 }
Sergunb 0:8918a71cdbe9 1633
Sergunb 0:8918a71cdbe9 1634 //Remove the specified directory
Sergunb 0:8918a71cdbe9 1635 error = fsRemoveDir(connection->path);
Sergunb 0:8918a71cdbe9 1636
Sergunb 0:8918a71cdbe9 1637 //Any error to report?
Sergunb 0:8918a71cdbe9 1638 if(error)
Sergunb 0:8918a71cdbe9 1639 {
Sergunb 0:8918a71cdbe9 1640 //The specified directory cannot be deleted...
Sergunb 0:8918a71cdbe9 1641 strcpy(connection->response, "550 Can't remove directory\r\n");
Sergunb 0:8918a71cdbe9 1642 //Exit immediately
Sergunb 0:8918a71cdbe9 1643 return;
Sergunb 0:8918a71cdbe9 1644 }
Sergunb 0:8918a71cdbe9 1645
Sergunb 0:8918a71cdbe9 1646 //The specified directory was successfully removed
Sergunb 0:8918a71cdbe9 1647 strcpy(connection->response, "250 Directory removed\r\n");
Sergunb 0:8918a71cdbe9 1648 }
Sergunb 0:8918a71cdbe9 1649
Sergunb 0:8918a71cdbe9 1650
Sergunb 0:8918a71cdbe9 1651 /**
Sergunb 0:8918a71cdbe9 1652 * @brief SIZE command processing
Sergunb 0:8918a71cdbe9 1653 *
Sergunb 0:8918a71cdbe9 1654 * The SIZE command is used to obtain the transfer size of the specified file
Sergunb 0:8918a71cdbe9 1655 *
Sergunb 0:8918a71cdbe9 1656 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 1657 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 1658 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 1659 **/
Sergunb 0:8918a71cdbe9 1660
Sergunb 0:8918a71cdbe9 1661 void ftpServerProcessSize(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 1662 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 1663 {
Sergunb 0:8918a71cdbe9 1664 error_t error;
Sergunb 0:8918a71cdbe9 1665 uint_t perm;
Sergunb 0:8918a71cdbe9 1666 uint32_t size;
Sergunb 0:8918a71cdbe9 1667
Sergunb 0:8918a71cdbe9 1668 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 1669 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 1670 {
Sergunb 0:8918a71cdbe9 1671 //Format response message
Sergunb 0:8918a71cdbe9 1672 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 1673 //Exit immediately
Sergunb 0:8918a71cdbe9 1674 return;
Sergunb 0:8918a71cdbe9 1675 }
Sergunb 0:8918a71cdbe9 1676
Sergunb 0:8918a71cdbe9 1677 //The argument specifies the pathname of the file
Sergunb 0:8918a71cdbe9 1678 if(*param == '\0')
Sergunb 0:8918a71cdbe9 1679 {
Sergunb 0:8918a71cdbe9 1680 //The argument is missing...
Sergunb 0:8918a71cdbe9 1681 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 1682 //Exit immediately
Sergunb 0:8918a71cdbe9 1683 return;
Sergunb 0:8918a71cdbe9 1684 }
Sergunb 0:8918a71cdbe9 1685
Sergunb 0:8918a71cdbe9 1686 //Retrieve the full pathname
Sergunb 0:8918a71cdbe9 1687 error = ftpServerGetPath(connection, param,
Sergunb 0:8918a71cdbe9 1688 connection->path, FTP_SERVER_MAX_PATH_LEN);
Sergunb 0:8918a71cdbe9 1689
Sergunb 0:8918a71cdbe9 1690 //Any error to report?
Sergunb 0:8918a71cdbe9 1691 if(error)
Sergunb 0:8918a71cdbe9 1692 {
Sergunb 0:8918a71cdbe9 1693 //The specified pathname is not valid...
Sergunb 0:8918a71cdbe9 1694 strcpy(connection->response, "501 Invalid parameter\r\n");
Sergunb 0:8918a71cdbe9 1695 //Exit immediately
Sergunb 0:8918a71cdbe9 1696 return;
Sergunb 0:8918a71cdbe9 1697 }
Sergunb 0:8918a71cdbe9 1698
Sergunb 0:8918a71cdbe9 1699 //Retrieve permissions for the specified directory
Sergunb 0:8918a71cdbe9 1700 perm = ftpServerGetFilePermissions(context, connection, connection->path);
Sergunb 0:8918a71cdbe9 1701
Sergunb 0:8918a71cdbe9 1702 //Insufficient access rights?
Sergunb 0:8918a71cdbe9 1703 if(!(perm & FTP_FILE_PERM_LIST) && !(perm & FTP_FILE_PERM_READ))
Sergunb 0:8918a71cdbe9 1704 {
Sergunb 0:8918a71cdbe9 1705 //Report an error
Sergunb 0:8918a71cdbe9 1706 strcpy(connection->response, "550 Access denied\r\n");
Sergunb 0:8918a71cdbe9 1707 //Exit immediately
Sergunb 0:8918a71cdbe9 1708 return;
Sergunb 0:8918a71cdbe9 1709 }
Sergunb 0:8918a71cdbe9 1710
Sergunb 0:8918a71cdbe9 1711 //Retrieve the size of the specified file
Sergunb 0:8918a71cdbe9 1712 error = fsGetFileSize(connection->path, &size);
Sergunb 0:8918a71cdbe9 1713
Sergunb 0:8918a71cdbe9 1714 //Any error to report?
Sergunb 0:8918a71cdbe9 1715 if(error)
Sergunb 0:8918a71cdbe9 1716 {
Sergunb 0:8918a71cdbe9 1717 //Report an error
Sergunb 0:8918a71cdbe9 1718 strcpy(connection->response, "550 File not found\r\n");
Sergunb 0:8918a71cdbe9 1719 //Exit immediately
Sergunb 0:8918a71cdbe9 1720 return;
Sergunb 0:8918a71cdbe9 1721 }
Sergunb 0:8918a71cdbe9 1722
Sergunb 0:8918a71cdbe9 1723 //Format response message
Sergunb 0:8918a71cdbe9 1724 sprintf(connection->response, "213 %" PRIu32 "\r\n", size);
Sergunb 0:8918a71cdbe9 1725 }
Sergunb 0:8918a71cdbe9 1726
Sergunb 0:8918a71cdbe9 1727
Sergunb 0:8918a71cdbe9 1728 /**
Sergunb 0:8918a71cdbe9 1729 * @brief RETR command processing
Sergunb 0:8918a71cdbe9 1730 *
Sergunb 0:8918a71cdbe9 1731 * The RETR command is used to retrieve the content of the specified file
Sergunb 0:8918a71cdbe9 1732 *
Sergunb 0:8918a71cdbe9 1733 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 1734 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 1735 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 1736 **/
Sergunb 0:8918a71cdbe9 1737
Sergunb 0:8918a71cdbe9 1738 void ftpServerProcessRetr(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 1739 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 1740 {
Sergunb 0:8918a71cdbe9 1741 error_t error;
Sergunb 0:8918a71cdbe9 1742 uint_t perm;
Sergunb 0:8918a71cdbe9 1743
Sergunb 0:8918a71cdbe9 1744 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 1745 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 1746 {
Sergunb 0:8918a71cdbe9 1747 //Format response message
Sergunb 0:8918a71cdbe9 1748 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 1749 //Exit immediately
Sergunb 0:8918a71cdbe9 1750 return;
Sergunb 0:8918a71cdbe9 1751 }
Sergunb 0:8918a71cdbe9 1752
Sergunb 0:8918a71cdbe9 1753 //The argument specifies the pathname of the file to read
Sergunb 0:8918a71cdbe9 1754 if(*param == '\0')
Sergunb 0:8918a71cdbe9 1755 {
Sergunb 0:8918a71cdbe9 1756 //The argument is missing...
Sergunb 0:8918a71cdbe9 1757 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 1758 //Exit immediately
Sergunb 0:8918a71cdbe9 1759 return;
Sergunb 0:8918a71cdbe9 1760 }
Sergunb 0:8918a71cdbe9 1761
Sergunb 0:8918a71cdbe9 1762 //Retrieve the full pathname
Sergunb 0:8918a71cdbe9 1763 error = ftpServerGetPath(connection, param,
Sergunb 0:8918a71cdbe9 1764 connection->path, FTP_SERVER_MAX_PATH_LEN);
Sergunb 0:8918a71cdbe9 1765
Sergunb 0:8918a71cdbe9 1766 //Any error to report?
Sergunb 0:8918a71cdbe9 1767 if(error)
Sergunb 0:8918a71cdbe9 1768 {
Sergunb 0:8918a71cdbe9 1769 //The specified pathname is not valid...
Sergunb 0:8918a71cdbe9 1770 strcpy(connection->response, "501 Invalid parameter\r\n");
Sergunb 0:8918a71cdbe9 1771 //Exit immediately
Sergunb 0:8918a71cdbe9 1772 return;
Sergunb 0:8918a71cdbe9 1773 }
Sergunb 0:8918a71cdbe9 1774
Sergunb 0:8918a71cdbe9 1775 //Retrieve permissions for the specified directory
Sergunb 0:8918a71cdbe9 1776 perm = ftpServerGetFilePermissions(context, connection, connection->path);
Sergunb 0:8918a71cdbe9 1777
Sergunb 0:8918a71cdbe9 1778 //Insufficient access rights?
Sergunb 0:8918a71cdbe9 1779 if(!(perm & FTP_FILE_PERM_READ))
Sergunb 0:8918a71cdbe9 1780 {
Sergunb 0:8918a71cdbe9 1781 //Report an error
Sergunb 0:8918a71cdbe9 1782 strcpy(connection->response, "550 Access denied\r\n");
Sergunb 0:8918a71cdbe9 1783 //Exit immediately
Sergunb 0:8918a71cdbe9 1784 return;
Sergunb 0:8918a71cdbe9 1785 }
Sergunb 0:8918a71cdbe9 1786
Sergunb 0:8918a71cdbe9 1787 //Open specified file for reading
Sergunb 0:8918a71cdbe9 1788 connection->file = fsOpenFile(connection->path, FS_FILE_MODE_READ);
Sergunb 0:8918a71cdbe9 1789
Sergunb 0:8918a71cdbe9 1790 //Failed to open the file?
Sergunb 0:8918a71cdbe9 1791 if(!connection->file)
Sergunb 0:8918a71cdbe9 1792 {
Sergunb 0:8918a71cdbe9 1793 //Report an error
Sergunb 0:8918a71cdbe9 1794 strcpy(connection->response, "550 File not found\r\n");
Sergunb 0:8918a71cdbe9 1795 //Exit immediately
Sergunb 0:8918a71cdbe9 1796 return;
Sergunb 0:8918a71cdbe9 1797 }
Sergunb 0:8918a71cdbe9 1798
Sergunb 0:8918a71cdbe9 1799 //Check current data transfer mode
Sergunb 0:8918a71cdbe9 1800 if(connection->passiveMode)
Sergunb 0:8918a71cdbe9 1801 {
Sergunb 0:8918a71cdbe9 1802 //Check whether the data connection is already opened
Sergunb 0:8918a71cdbe9 1803 if(connection->dataState == FTP_DATA_STATE_IDLE)
Sergunb 0:8918a71cdbe9 1804 connection->dataState = FTP_DATA_STATE_SEND;
Sergunb 0:8918a71cdbe9 1805 }
Sergunb 0:8918a71cdbe9 1806 else
Sergunb 0:8918a71cdbe9 1807 {
Sergunb 0:8918a71cdbe9 1808 //Open the data connection
Sergunb 0:8918a71cdbe9 1809 error = ftpServerOpenDataConnection(context, connection);
Sergunb 0:8918a71cdbe9 1810
Sergunb 0:8918a71cdbe9 1811 //Any error to report?
Sergunb 0:8918a71cdbe9 1812 if(error)
Sergunb 0:8918a71cdbe9 1813 {
Sergunb 0:8918a71cdbe9 1814 //Clean up side effects
Sergunb 0:8918a71cdbe9 1815 fsCloseFile(connection->file);
Sergunb 0:8918a71cdbe9 1816 //Format response
Sergunb 0:8918a71cdbe9 1817 strcpy(connection->response, "450 Can't open data connection\r\n");
Sergunb 0:8918a71cdbe9 1818 //Exit immediately
Sergunb 0:8918a71cdbe9 1819 return;
Sergunb 0:8918a71cdbe9 1820 }
Sergunb 0:8918a71cdbe9 1821
Sergunb 0:8918a71cdbe9 1822 //The data connection is ready to send data
Sergunb 0:8918a71cdbe9 1823 connection->dataState = FTP_DATA_STATE_SEND;
Sergunb 0:8918a71cdbe9 1824 }
Sergunb 0:8918a71cdbe9 1825
Sergunb 0:8918a71cdbe9 1826 //Flush transmission buffer
Sergunb 0:8918a71cdbe9 1827 connection->bufferLength = 0;
Sergunb 0:8918a71cdbe9 1828 connection->bufferPos = 0;
Sergunb 0:8918a71cdbe9 1829
Sergunb 0:8918a71cdbe9 1830 //RETR command is being processed
Sergunb 0:8918a71cdbe9 1831 connection->controlState = FTP_CONTROL_STATE_RETR;
Sergunb 0:8918a71cdbe9 1832
Sergunb 0:8918a71cdbe9 1833 //Format response message
Sergunb 0:8918a71cdbe9 1834 strcpy(connection->response, "150 Opening data connection\r\n");
Sergunb 0:8918a71cdbe9 1835 }
Sergunb 0:8918a71cdbe9 1836
Sergunb 0:8918a71cdbe9 1837
Sergunb 0:8918a71cdbe9 1838 /**
Sergunb 0:8918a71cdbe9 1839 * @brief STOR command processing
Sergunb 0:8918a71cdbe9 1840 *
Sergunb 0:8918a71cdbe9 1841 * The STOR command is used to store data to the specified file
Sergunb 0:8918a71cdbe9 1842 *
Sergunb 0:8918a71cdbe9 1843 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 1844 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 1845 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 1846 **/
Sergunb 0:8918a71cdbe9 1847
Sergunb 0:8918a71cdbe9 1848 void ftpServerProcessStor(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 1849 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 1850 {
Sergunb 0:8918a71cdbe9 1851 error_t error;
Sergunb 0:8918a71cdbe9 1852 uint_t perm;
Sergunb 0:8918a71cdbe9 1853
Sergunb 0:8918a71cdbe9 1854 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 1855 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 1856 {
Sergunb 0:8918a71cdbe9 1857 //Format response message
Sergunb 0:8918a71cdbe9 1858 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 1859 //Exit immediately
Sergunb 0:8918a71cdbe9 1860 return;
Sergunb 0:8918a71cdbe9 1861 }
Sergunb 0:8918a71cdbe9 1862
Sergunb 0:8918a71cdbe9 1863 //The argument specifies the pathname of the file to written
Sergunb 0:8918a71cdbe9 1864 if(*param == '\0')
Sergunb 0:8918a71cdbe9 1865 {
Sergunb 0:8918a71cdbe9 1866 //The argument is missing...
Sergunb 0:8918a71cdbe9 1867 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 1868 //Exit immediately
Sergunb 0:8918a71cdbe9 1869 return;
Sergunb 0:8918a71cdbe9 1870 }
Sergunb 0:8918a71cdbe9 1871
Sergunb 0:8918a71cdbe9 1872 //Retrieve the full pathname
Sergunb 0:8918a71cdbe9 1873 error = ftpServerGetPath(connection, param,
Sergunb 0:8918a71cdbe9 1874 connection->path, FTP_SERVER_MAX_PATH_LEN);
Sergunb 0:8918a71cdbe9 1875
Sergunb 0:8918a71cdbe9 1876 //Any error to report?
Sergunb 0:8918a71cdbe9 1877 if(error)
Sergunb 0:8918a71cdbe9 1878 {
Sergunb 0:8918a71cdbe9 1879 //The specified pathname is not valid...
Sergunb 0:8918a71cdbe9 1880 strcpy(connection->response, "501 Invalid parameter\r\n");
Sergunb 0:8918a71cdbe9 1881 //Exit immediately
Sergunb 0:8918a71cdbe9 1882 return;
Sergunb 0:8918a71cdbe9 1883 }
Sergunb 0:8918a71cdbe9 1884
Sergunb 0:8918a71cdbe9 1885 //Retrieve permissions for the specified directory
Sergunb 0:8918a71cdbe9 1886 perm = ftpServerGetFilePermissions(context, connection, connection->path);
Sergunb 0:8918a71cdbe9 1887
Sergunb 0:8918a71cdbe9 1888 //Insufficient access rights?
Sergunb 0:8918a71cdbe9 1889 if(!(perm & FTP_FILE_PERM_WRITE))
Sergunb 0:8918a71cdbe9 1890 {
Sergunb 0:8918a71cdbe9 1891 //Report an error
Sergunb 0:8918a71cdbe9 1892 strcpy(connection->response, "550 Access denied\r\n");
Sergunb 0:8918a71cdbe9 1893 //Exit immediately
Sergunb 0:8918a71cdbe9 1894 return;
Sergunb 0:8918a71cdbe9 1895 }
Sergunb 0:8918a71cdbe9 1896
Sergunb 0:8918a71cdbe9 1897 //Open specified file for writing
Sergunb 0:8918a71cdbe9 1898 connection->file = fsOpenFile(connection->path,
Sergunb 0:8918a71cdbe9 1899 FS_FILE_MODE_WRITE | FS_FILE_MODE_CREATE | FS_FILE_MODE_TRUNC);
Sergunb 0:8918a71cdbe9 1900
Sergunb 0:8918a71cdbe9 1901 //Failed to open the file?
Sergunb 0:8918a71cdbe9 1902 if(!connection->file)
Sergunb 0:8918a71cdbe9 1903 {
Sergunb 0:8918a71cdbe9 1904 //Report an error
Sergunb 0:8918a71cdbe9 1905 strcpy(connection->response, "550 File not found\r\n");
Sergunb 0:8918a71cdbe9 1906 //Exit immediately
Sergunb 0:8918a71cdbe9 1907 return;
Sergunb 0:8918a71cdbe9 1908 }
Sergunb 0:8918a71cdbe9 1909
Sergunb 0:8918a71cdbe9 1910 //Check current data transfer mode
Sergunb 0:8918a71cdbe9 1911 if(connection->passiveMode)
Sergunb 0:8918a71cdbe9 1912 {
Sergunb 0:8918a71cdbe9 1913 //Check whether the data connection is already opened
Sergunb 0:8918a71cdbe9 1914 if(connection->dataState == FTP_DATA_STATE_IDLE)
Sergunb 0:8918a71cdbe9 1915 connection->dataState = FTP_DATA_STATE_RECEIVE;
Sergunb 0:8918a71cdbe9 1916 }
Sergunb 0:8918a71cdbe9 1917 else
Sergunb 0:8918a71cdbe9 1918 {
Sergunb 0:8918a71cdbe9 1919 //Open the data connection
Sergunb 0:8918a71cdbe9 1920 error = ftpServerOpenDataConnection(context, connection);
Sergunb 0:8918a71cdbe9 1921
Sergunb 0:8918a71cdbe9 1922 //Any error to report?
Sergunb 0:8918a71cdbe9 1923 if(error)
Sergunb 0:8918a71cdbe9 1924 {
Sergunb 0:8918a71cdbe9 1925 //Clean up side effects
Sergunb 0:8918a71cdbe9 1926 fsCloseFile(connection->file);
Sergunb 0:8918a71cdbe9 1927 //Format response
Sergunb 0:8918a71cdbe9 1928 strcpy(connection->response, "450 Can't open data connection\r\n");
Sergunb 0:8918a71cdbe9 1929 //Exit immediately
Sergunb 0:8918a71cdbe9 1930 return;
Sergunb 0:8918a71cdbe9 1931 }
Sergunb 0:8918a71cdbe9 1932
Sergunb 0:8918a71cdbe9 1933 //The data connection is ready to receive data
Sergunb 0:8918a71cdbe9 1934 connection->dataState = FTP_DATA_STATE_RECEIVE;
Sergunb 0:8918a71cdbe9 1935 }
Sergunb 0:8918a71cdbe9 1936
Sergunb 0:8918a71cdbe9 1937 //Flush reception buffer
Sergunb 0:8918a71cdbe9 1938 connection->bufferLength = 0;
Sergunb 0:8918a71cdbe9 1939 connection->bufferPos = 0;
Sergunb 0:8918a71cdbe9 1940
Sergunb 0:8918a71cdbe9 1941 //STOR command is being processed
Sergunb 0:8918a71cdbe9 1942 connection->controlState = FTP_CONTROL_STATE_STOR;
Sergunb 0:8918a71cdbe9 1943
Sergunb 0:8918a71cdbe9 1944 //Format response message
Sergunb 0:8918a71cdbe9 1945 strcpy(connection->response, "150 Opening data connection\r\n");
Sergunb 0:8918a71cdbe9 1946 }
Sergunb 0:8918a71cdbe9 1947
Sergunb 0:8918a71cdbe9 1948
Sergunb 0:8918a71cdbe9 1949 /**
Sergunb 0:8918a71cdbe9 1950 * @brief APPE command processing
Sergunb 0:8918a71cdbe9 1951 *
Sergunb 0:8918a71cdbe9 1952 * The APPE command is used to append data to the specified file
Sergunb 0:8918a71cdbe9 1953 *
Sergunb 0:8918a71cdbe9 1954 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 1955 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 1956 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 1957 **/
Sergunb 0:8918a71cdbe9 1958
Sergunb 0:8918a71cdbe9 1959 void ftpServerProcessAppe(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 1960 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 1961 {
Sergunb 0:8918a71cdbe9 1962 error_t error;
Sergunb 0:8918a71cdbe9 1963 uint_t perm;
Sergunb 0:8918a71cdbe9 1964
Sergunb 0:8918a71cdbe9 1965 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 1966 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 1967 {
Sergunb 0:8918a71cdbe9 1968 //Format response message
Sergunb 0:8918a71cdbe9 1969 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 1970 //Exit immediately
Sergunb 0:8918a71cdbe9 1971 return;
Sergunb 0:8918a71cdbe9 1972 }
Sergunb 0:8918a71cdbe9 1973
Sergunb 0:8918a71cdbe9 1974 //The argument specifies the pathname of the file to written
Sergunb 0:8918a71cdbe9 1975 if(*param == '\0')
Sergunb 0:8918a71cdbe9 1976 {
Sergunb 0:8918a71cdbe9 1977 //The argument is missing...
Sergunb 0:8918a71cdbe9 1978 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 1979 //Exit immediately
Sergunb 0:8918a71cdbe9 1980 return;
Sergunb 0:8918a71cdbe9 1981 }
Sergunb 0:8918a71cdbe9 1982
Sergunb 0:8918a71cdbe9 1983 //Retrieve the full pathname
Sergunb 0:8918a71cdbe9 1984 error = ftpServerGetPath(connection, param,
Sergunb 0:8918a71cdbe9 1985 connection->path, FTP_SERVER_MAX_PATH_LEN);
Sergunb 0:8918a71cdbe9 1986
Sergunb 0:8918a71cdbe9 1987 //Any error to report?
Sergunb 0:8918a71cdbe9 1988 if(error)
Sergunb 0:8918a71cdbe9 1989 {
Sergunb 0:8918a71cdbe9 1990 //The specified pathname is not valid...
Sergunb 0:8918a71cdbe9 1991 strcpy(connection->response, "501 Invalid parameter\r\n");
Sergunb 0:8918a71cdbe9 1992 //Exit immediately
Sergunb 0:8918a71cdbe9 1993 return;
Sergunb 0:8918a71cdbe9 1994 }
Sergunb 0:8918a71cdbe9 1995
Sergunb 0:8918a71cdbe9 1996 //Retrieve permissions for the specified directory
Sergunb 0:8918a71cdbe9 1997 perm = ftpServerGetFilePermissions(context, connection, connection->path);
Sergunb 0:8918a71cdbe9 1998
Sergunb 0:8918a71cdbe9 1999 //Insufficient access rights?
Sergunb 0:8918a71cdbe9 2000 if(!(perm & FTP_FILE_PERM_WRITE))
Sergunb 0:8918a71cdbe9 2001 {
Sergunb 0:8918a71cdbe9 2002 //Report an error
Sergunb 0:8918a71cdbe9 2003 strcpy(connection->response, "550 Access denied\r\n");
Sergunb 0:8918a71cdbe9 2004 //Exit immediately
Sergunb 0:8918a71cdbe9 2005 return;
Sergunb 0:8918a71cdbe9 2006 }
Sergunb 0:8918a71cdbe9 2007
Sergunb 0:8918a71cdbe9 2008 //Open specified file for writing
Sergunb 0:8918a71cdbe9 2009 connection->file = fsOpenFile(connection->path,
Sergunb 0:8918a71cdbe9 2010 FS_FILE_MODE_WRITE | FS_FILE_MODE_CREATE);
Sergunb 0:8918a71cdbe9 2011
Sergunb 0:8918a71cdbe9 2012 //Failed to open the file?
Sergunb 0:8918a71cdbe9 2013 if(!connection->file)
Sergunb 0:8918a71cdbe9 2014 {
Sergunb 0:8918a71cdbe9 2015 //Report an error
Sergunb 0:8918a71cdbe9 2016 strcpy(connection->response, "550 File not found\r\n");
Sergunb 0:8918a71cdbe9 2017 //Exit immediately
Sergunb 0:8918a71cdbe9 2018 return;
Sergunb 0:8918a71cdbe9 2019 }
Sergunb 0:8918a71cdbe9 2020
Sergunb 0:8918a71cdbe9 2021 //Move to the end of the file
Sergunb 0:8918a71cdbe9 2022 error = fsSeekFile(connection->file, 0, FS_SEEK_END);
Sergunb 0:8918a71cdbe9 2023
Sergunb 0:8918a71cdbe9 2024 //Any error to report?
Sergunb 0:8918a71cdbe9 2025 if(error)
Sergunb 0:8918a71cdbe9 2026 {
Sergunb 0:8918a71cdbe9 2027 //Clean up side effects
Sergunb 0:8918a71cdbe9 2028 fsCloseFile(connection->file);
Sergunb 0:8918a71cdbe9 2029 //Format response
Sergunb 0:8918a71cdbe9 2030 strcpy(connection->response, "550 File unavailable\r\n");
Sergunb 0:8918a71cdbe9 2031 }
Sergunb 0:8918a71cdbe9 2032
Sergunb 0:8918a71cdbe9 2033 //Check current data transfer mode
Sergunb 0:8918a71cdbe9 2034 if(connection->passiveMode)
Sergunb 0:8918a71cdbe9 2035 {
Sergunb 0:8918a71cdbe9 2036 //Check whether the data connection is already opened
Sergunb 0:8918a71cdbe9 2037 if(connection->dataState == FTP_DATA_STATE_IDLE)
Sergunb 0:8918a71cdbe9 2038 connection->dataState = FTP_DATA_STATE_RECEIVE;
Sergunb 0:8918a71cdbe9 2039 }
Sergunb 0:8918a71cdbe9 2040 else
Sergunb 0:8918a71cdbe9 2041 {
Sergunb 0:8918a71cdbe9 2042 //Open the data connection
Sergunb 0:8918a71cdbe9 2043 error = ftpServerOpenDataConnection(context, connection);
Sergunb 0:8918a71cdbe9 2044
Sergunb 0:8918a71cdbe9 2045 //Any error to report?
Sergunb 0:8918a71cdbe9 2046 if(error)
Sergunb 0:8918a71cdbe9 2047 {
Sergunb 0:8918a71cdbe9 2048 //Clean up side effects
Sergunb 0:8918a71cdbe9 2049 fsCloseFile(connection->file);
Sergunb 0:8918a71cdbe9 2050 //Format response
Sergunb 0:8918a71cdbe9 2051 strcpy(connection->response, "450 Can't open data connection\r\n");
Sergunb 0:8918a71cdbe9 2052 //Exit immediately
Sergunb 0:8918a71cdbe9 2053 return;
Sergunb 0:8918a71cdbe9 2054 }
Sergunb 0:8918a71cdbe9 2055
Sergunb 0:8918a71cdbe9 2056 //The data connection is ready to receive data
Sergunb 0:8918a71cdbe9 2057 connection->dataState = FTP_DATA_STATE_RECEIVE;
Sergunb 0:8918a71cdbe9 2058 }
Sergunb 0:8918a71cdbe9 2059
Sergunb 0:8918a71cdbe9 2060 //Flush reception buffer
Sergunb 0:8918a71cdbe9 2061 connection->bufferLength = 0;
Sergunb 0:8918a71cdbe9 2062 connection->bufferPos = 0;
Sergunb 0:8918a71cdbe9 2063
Sergunb 0:8918a71cdbe9 2064 //APPE command is being processed
Sergunb 0:8918a71cdbe9 2065 connection->controlState = FTP_CONTROL_STATE_APPE;
Sergunb 0:8918a71cdbe9 2066
Sergunb 0:8918a71cdbe9 2067 //Format response message
Sergunb 0:8918a71cdbe9 2068 strcpy(connection->response, "150 Opening data connection\r\n");
Sergunb 0:8918a71cdbe9 2069 }
Sergunb 0:8918a71cdbe9 2070
Sergunb 0:8918a71cdbe9 2071
Sergunb 0:8918a71cdbe9 2072 /**
Sergunb 0:8918a71cdbe9 2073 * @brief RNFR command processing
Sergunb 0:8918a71cdbe9 2074 *
Sergunb 0:8918a71cdbe9 2075 * The RNFR command specifies the old pathname of the file which is
Sergunb 0:8918a71cdbe9 2076 * to be renamed
Sergunb 0:8918a71cdbe9 2077 *
Sergunb 0:8918a71cdbe9 2078 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 2079 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 2080 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 2081 **/
Sergunb 0:8918a71cdbe9 2082
Sergunb 0:8918a71cdbe9 2083 void ftpServerProcessRnfr(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 2084 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 2085 {
Sergunb 0:8918a71cdbe9 2086 error_t error;
Sergunb 0:8918a71cdbe9 2087 uint_t perm;
Sergunb 0:8918a71cdbe9 2088
Sergunb 0:8918a71cdbe9 2089 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 2090 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 2091 {
Sergunb 0:8918a71cdbe9 2092 //Format response message
Sergunb 0:8918a71cdbe9 2093 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 2094 //Exit immediately
Sergunb 0:8918a71cdbe9 2095 return;
Sergunb 0:8918a71cdbe9 2096 }
Sergunb 0:8918a71cdbe9 2097
Sergunb 0:8918a71cdbe9 2098 //The argument specifies the file to be renamed
Sergunb 0:8918a71cdbe9 2099 if(*param == '\0')
Sergunb 0:8918a71cdbe9 2100 {
Sergunb 0:8918a71cdbe9 2101 //The argument is missing...
Sergunb 0:8918a71cdbe9 2102 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 2103 //Exit immediately
Sergunb 0:8918a71cdbe9 2104 return;
Sergunb 0:8918a71cdbe9 2105 }
Sergunb 0:8918a71cdbe9 2106
Sergunb 0:8918a71cdbe9 2107 //Retrieve the full pathname
Sergunb 0:8918a71cdbe9 2108 error = ftpServerGetPath(connection, param,
Sergunb 0:8918a71cdbe9 2109 connection->path, FTP_SERVER_MAX_PATH_LEN);
Sergunb 0:8918a71cdbe9 2110
Sergunb 0:8918a71cdbe9 2111 //Any error to report?
Sergunb 0:8918a71cdbe9 2112 if(error)
Sergunb 0:8918a71cdbe9 2113 {
Sergunb 0:8918a71cdbe9 2114 //The specified pathname is not valid...
Sergunb 0:8918a71cdbe9 2115 strcpy(connection->response, "501 Invalid parameter\r\n");
Sergunb 0:8918a71cdbe9 2116 //Exit immediately
Sergunb 0:8918a71cdbe9 2117 return;
Sergunb 0:8918a71cdbe9 2118 }
Sergunb 0:8918a71cdbe9 2119
Sergunb 0:8918a71cdbe9 2120 //Retrieve permissions for the specified directory
Sergunb 0:8918a71cdbe9 2121 perm = ftpServerGetFilePermissions(context, connection, connection->path);
Sergunb 0:8918a71cdbe9 2122
Sergunb 0:8918a71cdbe9 2123 //Insufficient access rights?
Sergunb 0:8918a71cdbe9 2124 if(!(perm & FTP_FILE_PERM_WRITE))
Sergunb 0:8918a71cdbe9 2125 {
Sergunb 0:8918a71cdbe9 2126 //Report an error
Sergunb 0:8918a71cdbe9 2127 strcpy(connection->response, "550 Access denied\r\n");
Sergunb 0:8918a71cdbe9 2128 //Exit immediately
Sergunb 0:8918a71cdbe9 2129 return;
Sergunb 0:8918a71cdbe9 2130 }
Sergunb 0:8918a71cdbe9 2131
Sergunb 0:8918a71cdbe9 2132 //Make sure the file exists
Sergunb 0:8918a71cdbe9 2133 if(!fsFileExists(connection->path) && !fsDirExists(connection->path))
Sergunb 0:8918a71cdbe9 2134 {
Sergunb 0:8918a71cdbe9 2135 //No such file or directory...
Sergunb 0:8918a71cdbe9 2136 strcpy(connection->response, "550 File not found\r\n");
Sergunb 0:8918a71cdbe9 2137 //Exit immediately
Sergunb 0:8918a71cdbe9 2138 return;
Sergunb 0:8918a71cdbe9 2139 }
Sergunb 0:8918a71cdbe9 2140
Sergunb 0:8918a71cdbe9 2141 //This command must be immediately followed by a RNTO command
Sergunb 0:8918a71cdbe9 2142 connection->controlState = FTP_CONTROL_STATE_RNFR;
Sergunb 0:8918a71cdbe9 2143 //Format the response message
Sergunb 0:8918a71cdbe9 2144 strcpy(connection->response, "350 File exists, ready for destination name\r\n");
Sergunb 0:8918a71cdbe9 2145 }
Sergunb 0:8918a71cdbe9 2146
Sergunb 0:8918a71cdbe9 2147
Sergunb 0:8918a71cdbe9 2148 /**
Sergunb 0:8918a71cdbe9 2149 * @brief RNTO command processing
Sergunb 0:8918a71cdbe9 2150 *
Sergunb 0:8918a71cdbe9 2151 * The RNTO command specifies the new pathname of the file specified
Sergunb 0:8918a71cdbe9 2152 * in the immediately preceding RNFR command
Sergunb 0:8918a71cdbe9 2153 *
Sergunb 0:8918a71cdbe9 2154 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 2155 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 2156 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 2157 **/
Sergunb 0:8918a71cdbe9 2158
Sergunb 0:8918a71cdbe9 2159 void ftpServerProcessRnto(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 2160 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 2161 {
Sergunb 0:8918a71cdbe9 2162 error_t error;
Sergunb 0:8918a71cdbe9 2163 uint_t perm;
Sergunb 0:8918a71cdbe9 2164 char_t newPath[FTP_SERVER_MAX_PATH_LEN];
Sergunb 0:8918a71cdbe9 2165
Sergunb 0:8918a71cdbe9 2166 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 2167 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 2168 {
Sergunb 0:8918a71cdbe9 2169 //Format response message
Sergunb 0:8918a71cdbe9 2170 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 2171 //Exit immediately
Sergunb 0:8918a71cdbe9 2172 return;
Sergunb 0:8918a71cdbe9 2173 }
Sergunb 0:8918a71cdbe9 2174
Sergunb 0:8918a71cdbe9 2175 //This command must immediately follow a RNFR command
Sergunb 0:8918a71cdbe9 2176 if(connection->controlState != FTP_CONTROL_STATE_RNFR)
Sergunb 0:8918a71cdbe9 2177 {
Sergunb 0:8918a71cdbe9 2178 //Switch to idle state
Sergunb 0:8918a71cdbe9 2179 connection->controlState = FTP_CONTROL_STATE_IDLE;
Sergunb 0:8918a71cdbe9 2180 //Report an error
Sergunb 0:8918a71cdbe9 2181 strcpy(connection->response, "503 Bad sequence of commands\r\n");
Sergunb 0:8918a71cdbe9 2182 //Exit immediately
Sergunb 0:8918a71cdbe9 2183 return;
Sergunb 0:8918a71cdbe9 2184 }
Sergunb 0:8918a71cdbe9 2185
Sergunb 0:8918a71cdbe9 2186 //Switch to idle state
Sergunb 0:8918a71cdbe9 2187 connection->controlState = FTP_CONTROL_STATE_IDLE;
Sergunb 0:8918a71cdbe9 2188
Sergunb 0:8918a71cdbe9 2189 //The argument specifies the new pathname
Sergunb 0:8918a71cdbe9 2190 if(*param == '\0')
Sergunb 0:8918a71cdbe9 2191 {
Sergunb 0:8918a71cdbe9 2192 //The argument is missing...
Sergunb 0:8918a71cdbe9 2193 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 2194 //Exit immediately
Sergunb 0:8918a71cdbe9 2195 return;
Sergunb 0:8918a71cdbe9 2196 }
Sergunb 0:8918a71cdbe9 2197
Sergunb 0:8918a71cdbe9 2198 //Retrieve the full pathname
Sergunb 0:8918a71cdbe9 2199 error = ftpServerGetPath(connection, param,
Sergunb 0:8918a71cdbe9 2200 newPath, FTP_SERVER_MAX_PATH_LEN);
Sergunb 0:8918a71cdbe9 2201
Sergunb 0:8918a71cdbe9 2202 //Any error to report?
Sergunb 0:8918a71cdbe9 2203 if(error)
Sergunb 0:8918a71cdbe9 2204 {
Sergunb 0:8918a71cdbe9 2205 //The specified pathname is not valid...
Sergunb 0:8918a71cdbe9 2206 strcpy(connection->response, "501 Invalid parameter\r\n");
Sergunb 0:8918a71cdbe9 2207 //Exit immediately
Sergunb 0:8918a71cdbe9 2208 return;
Sergunb 0:8918a71cdbe9 2209 }
Sergunb 0:8918a71cdbe9 2210
Sergunb 0:8918a71cdbe9 2211 //Retrieve permissions for the specified directory
Sergunb 0:8918a71cdbe9 2212 perm = ftpServerGetFilePermissions(context, connection, newPath);
Sergunb 0:8918a71cdbe9 2213
Sergunb 0:8918a71cdbe9 2214 //Insufficient access rights?
Sergunb 0:8918a71cdbe9 2215 if(!(perm & FTP_FILE_PERM_WRITE))
Sergunb 0:8918a71cdbe9 2216 {
Sergunb 0:8918a71cdbe9 2217 //Report an error
Sergunb 0:8918a71cdbe9 2218 strcpy(connection->response, "550 Access denied\r\n");
Sergunb 0:8918a71cdbe9 2219 //Exit immediately
Sergunb 0:8918a71cdbe9 2220 return;
Sergunb 0:8918a71cdbe9 2221 }
Sergunb 0:8918a71cdbe9 2222
Sergunb 0:8918a71cdbe9 2223 //Check whether the file name already exists
Sergunb 0:8918a71cdbe9 2224 if(fsFileExists(newPath) || fsDirExists(newPath))
Sergunb 0:8918a71cdbe9 2225 {
Sergunb 0:8918a71cdbe9 2226 //Report an error
Sergunb 0:8918a71cdbe9 2227 strcpy(connection->response, "550 File already exists\r\n");
Sergunb 0:8918a71cdbe9 2228 //Exit immediately
Sergunb 0:8918a71cdbe9 2229 return;
Sergunb 0:8918a71cdbe9 2230 }
Sergunb 0:8918a71cdbe9 2231
Sergunb 0:8918a71cdbe9 2232 //Rename the specified file
Sergunb 0:8918a71cdbe9 2233 error = fsRenameFile(connection->path, newPath);
Sergunb 0:8918a71cdbe9 2234
Sergunb 0:8918a71cdbe9 2235 //Any error to report?
Sergunb 0:8918a71cdbe9 2236 if(error)
Sergunb 0:8918a71cdbe9 2237 {
Sergunb 0:8918a71cdbe9 2238 //The specified file cannot be renamed
Sergunb 0:8918a71cdbe9 2239 strcpy(connection->response, "550 Can't rename file\r\n");
Sergunb 0:8918a71cdbe9 2240 //Exit immediately
Sergunb 0:8918a71cdbe9 2241 return;
Sergunb 0:8918a71cdbe9 2242 }
Sergunb 0:8918a71cdbe9 2243
Sergunb 0:8918a71cdbe9 2244 //The specified file was successfully deleted
Sergunb 0:8918a71cdbe9 2245 strcpy(connection->response, "250 File renamed\r\n");
Sergunb 0:8918a71cdbe9 2246 }
Sergunb 0:8918a71cdbe9 2247
Sergunb 0:8918a71cdbe9 2248
Sergunb 0:8918a71cdbe9 2249 /**
Sergunb 0:8918a71cdbe9 2250 * @brief DELE command processing
Sergunb 0:8918a71cdbe9 2251 *
Sergunb 0:8918a71cdbe9 2252 * The DELE command causes the file specified in the pathname to be
Sergunb 0:8918a71cdbe9 2253 * deleted at the server site
Sergunb 0:8918a71cdbe9 2254 *
Sergunb 0:8918a71cdbe9 2255 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 2256 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 2257 * @param[in] param Command line parameters
Sergunb 0:8918a71cdbe9 2258 **/
Sergunb 0:8918a71cdbe9 2259
Sergunb 0:8918a71cdbe9 2260 void ftpServerProcessDele(FtpServerContext *context,
Sergunb 0:8918a71cdbe9 2261 FtpClientConnection *connection, char_t *param)
Sergunb 0:8918a71cdbe9 2262 {
Sergunb 0:8918a71cdbe9 2263 error_t error;
Sergunb 0:8918a71cdbe9 2264 uint_t perm;
Sergunb 0:8918a71cdbe9 2265
Sergunb 0:8918a71cdbe9 2266 //Ensure the user is logged in
Sergunb 0:8918a71cdbe9 2267 if(!connection->userLoggedIn)
Sergunb 0:8918a71cdbe9 2268 {
Sergunb 0:8918a71cdbe9 2269 //Format response message
Sergunb 0:8918a71cdbe9 2270 strcpy(connection->response, "530 Not logged in\r\n");
Sergunb 0:8918a71cdbe9 2271 //Exit immediately
Sergunb 0:8918a71cdbe9 2272 return;
Sergunb 0:8918a71cdbe9 2273 }
Sergunb 0:8918a71cdbe9 2274
Sergunb 0:8918a71cdbe9 2275 //The argument specifies the file to be deleted
Sergunb 0:8918a71cdbe9 2276 if(*param == '\0')
Sergunb 0:8918a71cdbe9 2277 {
Sergunb 0:8918a71cdbe9 2278 //The argument is missing...
Sergunb 0:8918a71cdbe9 2279 strcpy(connection->response, "501 Missing parameter\r\n");
Sergunb 0:8918a71cdbe9 2280 //Exit immediately
Sergunb 0:8918a71cdbe9 2281 return;
Sergunb 0:8918a71cdbe9 2282 }
Sergunb 0:8918a71cdbe9 2283
Sergunb 0:8918a71cdbe9 2284 //Retrieve the full pathname of the file
Sergunb 0:8918a71cdbe9 2285 error = ftpServerGetPath(connection, param,
Sergunb 0:8918a71cdbe9 2286 connection->path, FTP_SERVER_MAX_PATH_LEN);
Sergunb 0:8918a71cdbe9 2287
Sergunb 0:8918a71cdbe9 2288 //Any error to report?
Sergunb 0:8918a71cdbe9 2289 if(error)
Sergunb 0:8918a71cdbe9 2290 {
Sergunb 0:8918a71cdbe9 2291 //The specified pathname is not valid...
Sergunb 0:8918a71cdbe9 2292 strcpy(connection->response, "501 Invalid parameter\r\n");
Sergunb 0:8918a71cdbe9 2293 //Exit immediately
Sergunb 0:8918a71cdbe9 2294 return;
Sergunb 0:8918a71cdbe9 2295 }
Sergunb 0:8918a71cdbe9 2296
Sergunb 0:8918a71cdbe9 2297 //Retrieve permissions for the specified directory
Sergunb 0:8918a71cdbe9 2298 perm = ftpServerGetFilePermissions(context, connection, connection->path);
Sergunb 0:8918a71cdbe9 2299
Sergunb 0:8918a71cdbe9 2300 //Insufficient access rights?
Sergunb 0:8918a71cdbe9 2301 if(!(perm & FTP_FILE_PERM_WRITE))
Sergunb 0:8918a71cdbe9 2302 {
Sergunb 0:8918a71cdbe9 2303 //Report an error
Sergunb 0:8918a71cdbe9 2304 strcpy(connection->response, "550 Access denied\r\n");
Sergunb 0:8918a71cdbe9 2305 //Exit immediately
Sergunb 0:8918a71cdbe9 2306 return;
Sergunb 0:8918a71cdbe9 2307 }
Sergunb 0:8918a71cdbe9 2308
Sergunb 0:8918a71cdbe9 2309 //Delete the specified file
Sergunb 0:8918a71cdbe9 2310 error = fsDeleteFile(connection->path);
Sergunb 0:8918a71cdbe9 2311
Sergunb 0:8918a71cdbe9 2312 //Any error to report?
Sergunb 0:8918a71cdbe9 2313 if(error)
Sergunb 0:8918a71cdbe9 2314 {
Sergunb 0:8918a71cdbe9 2315 //The specified file cannot be deleted...
Sergunb 0:8918a71cdbe9 2316 strcpy(connection->response, "550 Can't delete file\r\n");
Sergunb 0:8918a71cdbe9 2317 //Exit immediately
Sergunb 0:8918a71cdbe9 2318 return;
Sergunb 0:8918a71cdbe9 2319 }
Sergunb 0:8918a71cdbe9 2320
Sergunb 0:8918a71cdbe9 2321 //The specified file was successfully deleted
Sergunb 0:8918a71cdbe9 2322 strcpy(connection->response, "250 File deleted\r\n");
Sergunb 0:8918a71cdbe9 2323 }
Sergunb 0:8918a71cdbe9 2324
Sergunb 0:8918a71cdbe9 2325 #endif
Sergunb 0:8918a71cdbe9 2326