PREV NEXT INDEX



6. FTP Server

This chapter documents the FTP server. The following information is included:

The library FTP_SERVER.LIB implements the File Transfer Protocol for the server side of a connection. FTP uses two TCP connections to transfer a file. The FTP server does a passive open on well-known port 21 and then listens for a client. This is the command connection. The server receives commands through this port and sends reply codes. The second TCP connection is for the actual data transfer.

Anonymous FTP is supported. Most FTP servers on the Internet use the identifier "anonymous," so since FTP clients expect it, this is the identifier that is recommended, but any string (with a maximum length of SAUTH_MAXNAME) may be used.

6.1 Configuration Macros

The configuration macros control various conditions of the server's operation. Read through them to understand the default conditions. Any changes to these macros may be made in the server application with #define statements before inclusion of FTPSERVER.LIB.

FTP_EXTENSIONS

The macro is not defined by default. Define it to allow the server to recognize the DELE, SIZE and MDTM commands.

FTP_MAXSERVERS

The default is 1: the number of simultaneous connections the FTP server can support. Each server requires a significant amount of RAM (2500 bytes by default, though this can change through SOCK_BUF_SIZE or tcp_MaxBufSize (deprecated)).

FTP_MAXLINE

The default is 256: the number of bytes of the working buffer in each server. This is also the maximum size of each network read/write. The default value of 256 is the minimum value that allows the server to function properly.

FTP_NODEFAULTHANDLERS

This macro is undefined. Define it to eliminate the code for the default file handlers. You must then provide your own file handlers.

FTP_TIMEOUT

The default is 16: the number of seconds to wait for data from the remote host before terminating the connection. In a high-latency network this value may need to be increased to avoid premature closures. No one likes premature closures.

6.2 File Handlers

Default file handlers are provided. The defaults access the server spec list, which is set up using sspec_addxmemfile(), sauth_adduser() etc. (See Section 3.1.1 on page 123 for more information on the server spec list.) The default file handlers are used when NULL is passed to the initialization function ftp_init().

6.2.1 Replacing the Default Handlers

The FTPhandlers structure contains function pointers to the file handlers. This structure may be passed to ftp_init() to replace the default file handlers. You must provide at least a dummy function for all handlers.


typedef struct {
   int (*open)();
   int (*read)();
   int (*write)();
   int (*close)();
   long (*getfilesize)();
   int (*dirlist)();
   int (*cd)();
   int (*pwd)();
#ifdef FTP_EXTENSIONS
   long (*mdtm)();
   int (*delete)();
#endif
} FTPhandlers;

6.2.2 File Handlers Specification

Detailed function descriptions for the default handlers are found here. Additional information is provided in these descriptions when the default handler does not cover the entire function specification.

The default file handlers are found in FTPSERVER.LIB.


ftp_dflt_open



int ftp_dflt_open(char *name, int options, int uid, int cwd);

Description

Opens a file. If a file is successfully opened, the returned value is passed to subsequent handler routines to identify the particular file or resource, as the 'fd' parameter. If necessary, you can use this number to index an array of any other state information needed to communicate with the other handlers. The number returned should be unique with respect to all other open resource instances, so that your handler does not get confused if multiple FTP data transfers are active simultaneously.

Note that the specified file to open may be an absolute or relative path: if the handler supports the concept of directories, then it should handle the path name appropriately and not just assume that the file is in the current directory. If the filename is relative, then the cwd parameter indicates the current directory.

Parameters

name

The file to open.

options

File access options:

O_RDONLY (marks file as read-only).
O_WRONLY (not currently supported by the default handler).
O_RDWR (not used since it's not supported by the FTP protocol).

uid

The userid of the currently logged-in user.

cwd

Current directory (not currently supported by the default handler).

Return Value

0: File descriptor of the opened file.
FTP_ERR_NOTFOUND: File not found.
FTP_ERR_NOTAUTH: Unauthorized user.
FTP_ERR_BADMODE: Requested option (2nd parameter) is not supported.
FTP_ERR_UNAVAIL: Resource temporarily unavailable.


ftp_dflt_getfilesize



long ftp_dflt_getfilesize(int fd);

Description

Return the length of the specified file. This is called immediately after open for a read file. If the file is of a known constant length, the correct length should be returned. If the resource length is not known (perhaps it is generated on-the-fly) then return -1. For write operations, the maximum permissible length should be returned, or -1 if not known.

Parameters

fd

The file descriptor returned when the file was opened.

Return value

0: The size of the file in bytes.
-1: The length of the file is not known.


ftp_dflt_read



int ftp_dflt_read(int fd, char *buf, long offset, int len);

Description

Read file identified by fd. The file contents at the specified offset should be stored into buf, up to a maximum length of len. The return value should be the actual number of bytes transferred, which may be less than len. If the return value is zero, this indicates normal end-of-file. If the return value is negative, then the transfer is aborted. Each successive call to this handler will have an increasing offset. If the getfilesize handler returns a non-negative length, then the read handler will only be called for data up to that length -- there is no need for such read handlers to check for EOF since the server will assume that only the specified amount of data is available.

The return value can also be greater than len. This is interpreted as "I have not put anything in buf. Call me back when you (the server) can accept at least len bytes of data." This is useful for read handlers which find it inconvenient to retrieve data from arbitrary offsets, for example a log reader which can only access whole log records. If the returned value is greater than the server can ever offer, then the server aborts the data transfer. The handler should never ask for more than FTP_MAXLINE bytes.

Parameters

fd

The file descriptor returned when the file was opened.

buf

Pointer to the buffer to place the file contents.

offset

Offset in the file at which copying should begin.

len

The number of bytes to read.

Return value

 0: EOF.
>0: The number of bytes read into buf.
-1: Error, transfer aborted.


ftp_dflt_write



int ftp_dflt_write(int fd, char *buf, long offset, int len);

Description

The default write handler does nothing but return zero.

The specification states that the handler may write the file identified by fd. buf contains data of length len, which is to be written to the file at the given offset within the file. The return value must be equal to len, or a negative number if an error occurs (such as out of space).

The FTP server does not handle partial writes: the given data must be completely written or not at all. If the return code is less than len, an error is assumed to have occurred. Note that it is up to the handler to ensure that another FTP server is not accessing a file which is opened for write. The open call for the other server should return FTP_ERR_UNAVAIL if the current server is writing to a file.

Parameters

fd

The file descriptor returned when the file was opened.

buf

Pointer to the data to be written.

offset

Offset in the file at which to start.

len

The number of bytes to write.

Return value

0: The number of bytes written. If this is less than len, an error occurred.
-1: Error.


ftp_dflt_close



int ftp_dflt_close(int fd);

Description

The default close handler does nothing but return zero.

The handler may close the specified file and free up any temporary resources associated with the transfer.

Parameters

fd

The file descriptor returned when the file was opened.

Return value

0


ftp_dflt_list



int ftp_dflt_list (int item, char *line, int listing, int uid, int cwd);

Description

Returns the next file for the FTP server to list. The file name is formatted as a string.

Parameters

item

Index number starting at zero for the first function call. Subsequent calls should be one plus the return value from the previous call.

line

Pointer to location to put the formatted string.

listing

Boolean variable to control string form:

0: print file name, permissions, date, etc.
1: print file name only.

uid

The currently logged-in user.

cwd

The current working directory.

Return Value

0: File descriptor for last file listed.
-1: Error.


ftp_dflt_cd



int ftp_dflt_cd(int cwd, char * dir, int uid);

Description

Change to new "directory." This is called when the client issues a CWD command. The FTP server itself has no concept of what a directory is --this is meaningful only to the handler.

Parameters

cwd

Integer representing the current directory.

dir

String that indicates the new directory that will become the current directory. The interpretation of this string is entirely up to the handler. The dir string will be passed as ".." to move up one level.

uid

The currently logged-in user.

Return Value

 0: No such directory exists.
-1: Root directory.
>0: Anything that is meaningful to the handler.


ftp_dflt_pwd



int ftp_dflt_pwd(int cwd, char * buf);

Description

Print the current directory, passed as cwd, as a string. The result is placed in buf, whose length may be assumed to be at least (FTP_MAXLINE-6). The return value is ignored.

Parameters

cwd

The current directory.

buf

Pointer to buffer to put the string.

Return Value

The return value is ignored.


ftp_dflt_mdtm



unsigned long ftp_dflt_mdtm(int fd);

Description

This handler function is called when the server receives the FTP command MDTM. The return value of this handler function is the number of seconds that have passed since January 1, 1980. A return value of zero will cause the reply code 213 followed by a space and then the value 19800101000000 (yyyymmddhhmmss) to be sent by the server.

The FTP server assumes that this return value is in UTC (Coordinated Universal Time). If SEC_TIMER is running in local time, the handler should make the necessary time zone adjustment so that the return value is expressed in UTC.

The handler is only recognized if FTP_EXTENSIONS is defined.

Parameters

fd

File descriptor for the currently opened file.

Return Value

The number of seconds that have passed since January 1, 1980. The default handler always returns zero. The number of seconds will be converted to a date and time value of the form yyyymmddhhmmss.


ftp_dflt_delete



int ftp_dflt_delete(char * name, int uid, int cwd);

Description

The default handler does not support the delete command. It simply returns the error code for an unauthorized user.

The delete handler is only recognized by the server if FTP_EXTENSIONS is defined. It is called when the DELE command is received. The given file name (possibly relative to cwd) should be deleted.

Parameters

name

Pointer to the name of a file.

uid

The currently logged-in user.

cwd

The current directory.

Return Value

0: File was successfully deleted .
FTP_ERR_NOTFOUND: File not found.
FTP_ERR_NOTAUTH: Unauthorized user.
FTP_ERR_BADMODE: Requested option (2nd parameter) is not supported.
FTP_ERR_UNAVAIL: Resource temporarily unavailable.

6.3 Functions

The API functions described here, initialize and run the FTP server.


ftp_init



void ftp_init(FTPhandlers *handlers);

Description

Initializes the FTP server. You can optionally specify a set of handlers for controlling what the server presents to the client. This is done with function pointers in the FTPhandlers structure.

Parameters

handlers

NULL means use default internal file handlers;
!NULL means to supply a structure of pointers to the various custom file handlers (open, read, write, close, getfilesize).

Return value

None.

Library

FTP_SERVER.LIB

See Also

ftp_tick


ftp_set_anonymous



int ftp_set_anonymous(int uid);

Description

Set the "anonymous" user ID. Resources belonging to this userID may be accessed by any user. A typical use of this function would be


ftp_set_anonymous (sauth_adduser("anonymous", "", SERVER_FTP));

which defines an "anonymous" login for the FTP server. This only applies to the FTP server. The username "anonymous" is recommended, since most FTP clients use this for hosts which have no account for the user.

Parameter

uid

The user ID to use as the anonymous user. This should have been defined using sauth_adduser(). Pass -1 to set no anonymous user.

Return Value

Same as the uid parameter, except -1 if uid is invalid.

Library

FTP_SERVER.LIB

See Also

sauth_adduser


ftp_tick



void ftp_tick(void);

Description

Once ftp_init has been called, ftp_tick must be called periodically to run the server. This function is non-blocking.

Library

FTP_SERVER.LIB

See Also

ftp_init

6.4 Sample FTP Server

This code demonstrates a simple FTP server, using the ftp library. The user "anonymous" may download the file "rabbitA.gif," but not "rabbitF.gif." The user "foo" (with password "bar") may download "rabbitF.gif," but also "rabbitA.gif," since files owned by the anonymous user are world-readable.

Program Name: samples/tcpip/ftp_server.c

#define MY_IP_ADDRESS "10.10.6.105"   // All fields in this section must be 
#define MY_NETMASK "255.255.255.0"    //  changed to match local
#define MY_GATEWAY "10.10.6.19"       //  network settings.

#memmap xmem
#use "dcrtcp.lib"
#use "ftp_server.lib"

#ximport "samples/tcpip/http/pages/rabbit1.gif" rabbit1_gif

main(){
int file;
int user;

   /* Set up the first file and user */

   file = sspec_addxmemfile("rabbitA.gif", rabbit1_gif, SERVER_FTP);

   user = sauth_adduser("anonymous", "", SERVER_FTP);
ftp_set_anonymous(user);
sspec_setuser(file, user);

   sspec_setuser(sspec_addxmemfile("test1", rabbit1_gif, SERVER_FTP), user);

   sspec_setuser(sspec_addxmemfile("test2", rabbit1_gif, SERVER_FTP), user);

   /* Set up the second file and user */

   file = sspec_addxmemfile("rabbitF.gif", rabbit1_gif, SERVER_FTP);

   user = sauth_adduser("foo", "bar", SERVER_FTP);
sspec_setuser(file, user);

   sspec_setuser(sspec_addxmemfile("test3", rabbit1_gif, SERVER_FTP), user);

   sspec_setuser(sspec_addxmemfile("test4", rabbit1_gif, SERVER_FTP), user);

   sock_init();
ftp_init(NULL);                 // use default handlers
tcp_reserveport(FTP_CMDPORT);   // Port 21

   while(1) {
ftp_tick();
}
}

Each user may execute the "dir" or "ls" command to see a listing of the available files. The listing shows only the files that the logged-in user can access.

6.5 Getting Through a Firewall

If a client is behind a firewall, it is incumbent upon the client to request that the server do a passive open on its data port instead of the normal active open. This is so that the client can then do an active open using the passively opened data port of the server, thus getting through the firewall.

Typically the server would not be behind a firewall.

6.6 FTP Server Commands

The following commands are recognized by the FTP server. The reply codes sent in response to these commands are detailed in Section 6.7 on page 235. They are noted here to associate them with the commands that may cause them to be sent.
Table 2. Recognized FTP Server Commands

Command

Description

Possible Reply Codes

ABOR
The current data transfer completes before the abort command is read by the server. 226
CDUP
A special case of CWD (Change Working Directory); the parent of the working directory is changed to be the working directory. 250, 431
CWD
Changes working directory. 250, 431
DELE
Delete the specified file. 250, 450, 550
LIST
Displays list of files requested by its argument in ls -l format. This gives extra information about the file. 150, 226, 425
MDTM
Shows the last modification time of the specified file. 213, 250, 450, 550
MODE
Confirms the mode of data transmission. Only stream mode is supported. 200, 504
NLST
Displays list of files requested by its argument, with names only. This allows an application to further process the files. 150, 226, 425
NOOP
Specifies no action except that the server send an OK reply. It does not affect any parameters or previously entered commands. 200
PASV
Requests a passive open on a port that is not the default data port. The server responds with the host and port address on which it is listening. 227, 452
PORT

Changes the data port from the default port to the port specified in the command's argument. The argument is the concatenation of a 32-bit internet host address and a 16-bit TCP port address.

200
PWD
Prints the working directory name. 257
QUIT
Closes the control connection. If a data transfer is in progress, the connection will not be closed until it has completed. 221
RETR
Transfers a copy of the file specified in the pathname argument from the server to the client. 150, 226, 425, 550
SIZE
Returns the size of the specified file. 213, 250, 450, 550
STOR
Stores a file from the client onto the server. The file will be overwritten if it already exists at the specified pathname, or it will be created if it does not exist. 150, 226, 250 425, 450, 452, 550
STRU
Confirms the supported structure of a file. Only file-structure is supported: a continuous stream of data bytes. 200, 504
SYST
Sends the string "RABBIT2000." 215
TYPE
Confirms the transfer type. The types IMAGE (binary), ASCII and Local with 8-bit bytes are all supported and are treated the same. 200, 504

6.7 Reply Codes to FTP Commands

The FTP server replies to all of the commands that it receives. The reply consists of a 3-digit number followed by a space and then a text string explaining the reply. All reply codes sent from the FTP server are listed here.

Reply Code

Reply Text

150
File status okay; about to open data connection.
200
Command okay.
202
Command not implemented, superfluous at this site.
211
System status, or system help reply.
213
File status
214
Help message. On how to use the server or the meaning of a particular non-standard command. This reply is useful only to the human user.
215
System type.
220
Service ready for new user.
221
Service closing connection.
226
Closing data connection. Requested file action successful (for example, file transfer or file abort).
227
Entering Passive Mode (h1,h2,h3,h4,p1,p2).
230
User logged in, proceed
250
Requested file action okay, completed.
257
"PATHNAME" created.
331
User name okay, need password.
425
Can't open data connection.
450
Requested file action not taken. File unavailable (e.g., file busy).
452
Requested action not taken. Insufficient storage space in system.
502
Command not implemented.
504
Command not implemented for that parameter.
530
Not logged in.
550
Requested action not taken. File unavailable (e.g., file not found, no access).

The text used for the reply codes, may be slightly different than what is shown here. It will be context specific.


Z-World
http://www.zworld.com
Voice: 530.757.3737
Fax: 530.757.3792 or 530.753.5141
sales@zworld.com
PREV NEXT INDEX