![]() |
|
| << Previous | Index | Next >> | |
| | |
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
HTTP_NO_FLASHSPEC SSPEC_NO_STATIC) may be used.Dynamic C 8 includes some enhancements that basically let the FTP server act as a full FTP server, where you can create, read and delete files at will. To use these enhancements, the configuration macro
FTP_USE_FS2_HANDLERSmust be defined to enable FS2 support in the default file handler functions. The structure that holds the association of filenames and FS2 file locations is the server spec list--the global array defined inzserver.lib. It is stored in the User block and the API functionsftp_save_filenames()andftp_load_filenames()are used for support of this.
NOTE For a demonstration of the enhanced FTP server, see the sample program, /SAMPLES/TCPIP/FTP/FTP_SERVER_FULL.C.7.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_CMDPORT
This macro defaults to 21 which is the well-known FTP server port number. You can override this to cause the server to listen on a non-standard port number.
FTP_CREATE_MASK
This macro specifies the mask that is passed into the servermask parameter in
sspec_addfsfile()calls when a new file is created. In particular, this defines which servers will be allowed to access this file. By default, it is defined toSERVER_FTP|SERVER_WRITABLE.FTP_DTPTIMEOUT
The default is 16, the same as
FTP_TIMEOUT. This applies to the data transfer port instead of the command port. The data transfer port is involved with get/store commands, as well as directory listings.FTP_EXTENSIONS
The macro is not defined by default. Define it to allow the server to recognize the
DELE,SIZEandMDTMcommands. If this macro is defined, then the FTP handler structure (FTPhandlers) is augmented with pointers to mdtm and delete handlers.FTP_INTERFACE
This macro defaults to
IF_DEFAULT, i.e., the (single) default interface. Define toIF_ANYif FTP sessions can be accepted on any active interface, or a specific interface number (e.g.,IF_ETH0) to allow sessions on that interface only. Note that you are currently limited to a single interface, or all interfaces. This macro is only relevant starting with Dynamic C version 7.30.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_MAXSERVERS
The default is 1: the number of simultaneous connections the FTP server can support. Each server requires a significant amount of RAM (4096 bytes by default, though this can change through
SOCK_BUF_SIZEortcp_MaxBufSize(deprecated)).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. This macro is no longer needed starting with Dynamic C version 7.20.
FTP_TIMEOUT
The default is 16: the number of seconds to wait for FTP commands from the remote host before terminating the connection. In a high-latency network this value may need to be increased to avoid premature closures.
FTP_USE_FS2_HANDLERS
Define this to enable the full use of FS2 in the default FTP handler functions. Defining this macro will automatically define
FTP_WRITABLE_FILESto 1, as well.FTP_USERBLOCK_OFFSET
This macro should be defined to a number that specifies the offset into the User block at which the list of filenames will be saved. This list correlates the filenames with the locations of the files in the filesystem (FS2). This macro defaults to 0. If the user is putting other information in the User block, this offset may need to be adjusted to prevent clobbering the other data.
FTP_WRITABLE_FILES
The defaults is 0. Define to 1 to provide support in
ftp_dflt_open()for authenticating a user for write access before a file is opened. This also provides support in the file listing function,ftp_dflt_list(), to show the write permission for writable files.
NOTE The user will need to override both the write and close default file handlers to provide full support for writing a file. SSPEC_NO_STATIC
This macro must be defined in any FTP server application compiled with Dynamic C 8.50 or later.
7.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. The default file handlers are used whenNULLis passed to the initialization functionftp_init().7.2.1 Replacing the Default Handlers
The
FTPhandlersstructure contains function pointers to the file handlers. This structure may be passed toftp_init()to selectively replace the default file handlers. You may provide aNULLpointer for handlers that you do not wish to override. If you have definedFTP_EXTENSIONSthen there are an additional two function pointers that should be initialized.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;Starting with Dynamic C 7.30, all FTP server instances share the same set of data handlers. Before this release, there was a separate copy of the handler pointers for each instance of the server. This change does not affect your existing application except to slightly reduce memory usage. This change does add flexibility because it gives any file handler the ability to call any other file handler. In particular,
ftp_dflt_list()may now callftp_dflt_getfilesize()to get the file's size7.2.2 File Handlers Specification
Function descriptions for the default handlers are detailed in this section. Additional information is provided in these descriptions when the default handler does not cover the entire function specification.
The default file handlers are in
FTPSERVER.LIB.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
- 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.In the first case, 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 given file name may be an absolute or relative path: if the handler supports the concept of directories, then it should handle the path name as appropriate and not just assume that the file is in the current directory. If the filename is "relative," then the
cwdparameter indicates the current directory.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.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 that find it inconvenient to retrieve data from arbitrary offsets, for example a log reader that 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
- The number of bytes to read.
Return value
0: EOF.
>0: The number of bytes read intobuf.-1: Error, transfer aborted.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
- The number of bytes to write.
Return value
≥
0: The number of bytes written. If this is less thanlen, an error occurred.-1: Error.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
0int 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.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
- The currently logged-in user.
Return Value
0: No such directory exists.-1: Root directory.>0: Anything that is meaningful to the handler.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
- The current directory.
buf
- Pointer to buffer to put the string.
Return Value
The return value is ignored.
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.
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
- 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.7.3 API Functions
The API functions described here, initialize and run the FTP server.
int ftp_dflt_is_auth( int spec, int options, int uid );Description
Determine amount of access to a file. If the FTP anonymous user has been set, then also checks that. "options" is how to access the file. Currently, this value is ignored. If the anonymous user ID has been set, then files it owns are globally accessible.
Returns whether the user can access it ("owner permission") or if access is because there is an anonymous user ("world permission").
NOTE: This routine only determines accessibility of a name, not whether the user can read and/or write the contents.
Parameters
spec
- Handle to SSPEC file (item).
options
- How to access
O_RDONLY,O_WRONLYorO_RDWR. Currently this value is ignored.uid
- The userID to access as.
Return Value
0: No access.1:uidonly access.2: anonymous access (user "anonymous" has been set).See Also
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
FTPhandlersstructure. All FTP server instances share the same list of handlers.The FTPhandlers structure is defined as:
typedef struct {
int (*open)(char *name, int options, int uid, int cwd);
int (*read)(int fd, char *buf, long offset, int len);
int (*write)(int fd, char *buf, long offset, int len);
int (*close)(int fd);
long (*getfilesize)(int fd);int (*dirlist)(int item, char *line, int listing, int uid, int cwd);int (*cd)(int cwd, char *dir, int uid);
int (*pwd)(int cwd, char *buf);
[long (*mdtm)(int fd);]
[int (*delete)(char *name, int uid, int cwd);]
} FTPhandlers;If you always provide all your own handlers, then you can define
FTP_NODEFAULTHANDLERto eliminate the code for the default handlers. The handlers must be written to the specification described in Section 7.2.2. To use a default handler, leave the fieldNULL. If you pass aNULLhandlers pointer, then the all default handlers will be used.The defaults access the server spec list which is set up using the zserver functions
sspec_addxmemfile(),sauth_adduser()etc.Parameters
handlers
NULLmeans use default internal file handlers. Otherwise, you must supply a struct of pointers to the various file handlers (open, read, write, close, getfilesize, list). To not override a particular handler, leave itNULLin the structure.Library
See Also
int ftp_load_filenames( void );Description
This function is used in conjunction with the
FTP_USE_FS2_HANDLERSmacro. It loads the data structure (i.e., the server spec list) that keeps track of the association of filenames to file locations in the file system. The information is loaded from the User block, from the offset given inFTP_USERBLOCK_OFFSET.The function removes any entries from the server spec list that are not FS2 files.
Return Value
0: Success-1: Failure (possibly due to the filenames having not yet been saved)See Also
int ftp_save_filenames( void );Description
This function is used in conjunction with the
FTP_USE_FS2_HANDLERSmacro. This function saves the data structure (i.e., the server spec list) that keeps track of the association of filenames to file locations in the file system. The information is saved to the User block, at the offset given inFTP_USERBLOCK_OFFSET.Return Value
0: Success.-1: Failure, the information could not be saved (due to a write error).See Also
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 that 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-1to set no anonymous user.Return Value
Same as the
uidparameter, except -1 ifuidis invalid.Library
See Also
void ftp_shutdown( int bGraceful );Description
Close and cancel all FTP connections. If the server is connected to a client, forces the QUIT state. If the application has called
tcp_reserveport(), then it must calltcp_clearreserve(). For a graceful shutdown, the application must calltcp_tick()a few more times.After the FTP sockets close, the application must call
ftp_init()to again start the server running.Parameter
bGraceful
- (boolean) zero to immediately abort all open connections, or non-zero to simulate the QUIT command.
Return Value
None
Library
See Also
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
See Also
7.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.
File 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.
Notice the definition for
TCP_CONFIG. When the value for this macro exceeds 100, a special configuration file is pulled in that will not be overridden by future updates of Dynamic C. In the fileCUSTOM_CONFIG.LIB, you may specify any network configuration that suits your purposes. Please see/LIB/TCPIP/TCP_CONFIG.LIBfor examples of setting up a library of configuration options.7.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.
7.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 7.7 on page 81. They are noted here to associate them with the commands that may cause them to be sent.
7.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.
| TCP/IP Manual Vol. 2 |
<< Previous | Index | Next>> | rabbit.com |