This chapter documents the FTP server. The following information is included:
- configuration macros.
- the default file handlers.
- how to assign replacement file handlers.
- what to do when there is a firewall.
- API functions.
- commands accepted by the server.
- reply codes generated by the server.
- sample code demonstrating a working FTP server.
The library
FTP_SERVER.LIBimplements 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
#definestatements before inclusion ofFTPSERVER.LIB.FTP_EXTENSIONS
The macro is not defined by default. Define it to allow the server to recognize the
DELE,SIZEandMDTMcommands.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_SIZEortcp_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 whenNULLis passed to the initialization functionftp_init().6.2.1 Replacing the Default Handlers
The
FTPhandlersstructure contains function pointers to the file handlers. This structure may be passed toftp_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
cwdparameter indicates the current directory.Parameters
name
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 intobuf, up to a maximum length oflen. The return value should be the actual number of bytes transferred, which may be less thanlen. 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 inbuf. Call me back when you (the server) can accept at leastlenbytes 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 thanFTP_MAXLINEbytes.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
Return value
0: EOF.
>0: The number of bytes read intobuf.-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.bufcontains data of lengthlen, which is to be written to the file at the given offset within the file. The return value must be equal tolen, 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 returnFTP_ERR_UNAVAILif 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
Return value
≥
0: The number of bytes written. If this is less thanlen, 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
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
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
dirstring will be passed as ".." to move up one level.uid
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 inbuf, whose length may be assumed to be at least (FTP_MAXLINE-6). The return value is ignored.Parameters
cwd
buf
Pointer to buffer to put the string.
Return Value
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_TIMERis 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_EXTENSIONSis 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_EXTENSIONSis defined. It is called when theDELEcommand is received. The given file name (possibly relative tocwd) should be deleted.Parameters
name
Pointer to the name of a file.
uid
cwd
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
NULLmeans use default internal file handlers;!NULLmeans to supply a structure of pointers to the various custom file handlers (open, read, write, close, getfilesize).Return value
Library
See Also
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
uidparameter, except -1 ifuidis invalid.Library
See Also
ftp_tick
void ftp_tick(void);Description
Once
ftp_inithas been called,ftp_tickmust be called periodically to run the server. This function is non-blocking.Library
See Also
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
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.
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.
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 |