homepage
The M-ftp project consists of a concurent TCP based FTP server for Unix like systems.The implementation meets the standard requirements for File Transfer Protocol defined in RFC 959 plus some of the extensions required to cover a wide area of FTP clients.M-ftp is intended to be a very light,easy to set-up,easy to use and reliable FTP server.The target Operating System is LINUX although the source might compile and work just fine on other UNIX like systems.The source is distributed under the Open Source GPLv2 Licence.The current version 1.0 has been tested with a variety of clients including standard console ftp program on both Linux and Windows, Gnome FTP, Konqueror, Total-Commander, Internet Explorer, Mozilla Firefox and many more.Worth mentioning here is that the server works best with the console ftp client from both Linux and Windows.That is because those clients follow strictly by implementation the exact specifications of File Transfer Protocol(RFC959) plus some extensions that have been well arround for some time to be defined as extra standards.The grafical ftp clients use alot of non-standard conventions and assumings that make the development of a standard ftp server a hard job.
Technical description
Well as i said M-ftp is a concurent TCP based standard FTP server for UNIX like Operating Systems.It makes use of the standard BSD Sockets available under any *NIX version.And to be more specific while developing the server i was runing OpenSuse 10.3 with kernel 2.6.22 and gcc 4.2.The basic architecture of the program goes like this:a master process called the server opens a socket on port 21 or any other port specified in the configuration file or at the command line and listens for possible client connections.Once a connection has been made the server imidiatly forks a child which will handle the clients request commands.This process in RFC 959 is called the Control Process.Now this control process may in it's turn create another process called a Data Process if the client issues a data transfer request like RETR,STOR,LIST,NLST.Now in my code i named the entire Control sequence a Control Session while the Data sequence is called a Data Session.I think it's pretty clear why i named them like that :D.Now the Data Session may be activated in one of two ways specified by the client.One is the Active mode and the other is the Passive mode.In Active mode the client sends a PORT command followed by the IP and a random Port number of a client side process listening on that port number for a data connection to be issued by the server.So in this case the client listens() and the server connects().Now in the RFC it is clearly specified that the client port number must be greater than 1023 and the server port from which the connnect() is made must be 20.Well this is kind of a problem because in Linux as far as i have experienced there is a problem while trying to bind() to the same socket right after another socket binded to that port has been closed because the port goes in a TIME_WAIT() state and it is not closed until the kernel makes sure that all the data sent from the client is recieved by the socket...ring a bell??This is what the TCP protocol is guaranteeing:Everything sent from A is recieved by B and viceversa.Well you might be saying why must i close() the socket and then reopen it when i can just leave it open.Well the ietf rfc standard clearly states that a data transfer end must be signalled by the sender by closing the socket so that End-Of-File may be reached on the other side by the reader so that he knows that the transfer is done(or not).So as i was saying if i try to bind() a socket to port 20 right after i closed another one binded on 20 i get EADDRINUSE.And the time needed to pass until i can get the port binded again varies from 1 to 4 minutes.This is a real problem which i surfed alot and googled the heck out of the web about this problem but i couldn't find a working solution to it because the problem seems to be in the kernel(that's where the TCP protocol is implemented in Linux).I recommend not using the ACTIVE mode on clients for the Mftp server until i get this problem fixed or activating the random data port for active mode option in the configuration file.This is because the client will feel that TIME_WAIT() too between successive active data requests(eg.trying to transfer a file right after another transfer has finished or successive LIST commands).Eventually the request is completed but it takes time until the Data Process succeeds in binding the port 20 to the socket.The passive mode works like this:the client issues the PASV command and the server replies with the IP address and the random port of a socket(>1024) which will be listening for connections from the client.Then after the Data request command has been recieved the client program must connect() to the address sent in the reply.In this case the FTP client binds the source port of the connection to a random port greater than 1023.So you see in passive mode ports are random and this TCP Time_Wait() problem can be avoided.That's why i recommend like many others to use PASSIVE mode for data transfers in FTP clients.This is how the data connections are made.Now while a data connection is active the CONTROL process is still listening for commands.This is the basics of how Mftp works...it's nothing new if you know the FTP protocol.Now the code is small,i intend not to pass 2000 lines in the future.Right now the code is 1000+ lines.This is because Mftp is not intended to be a UNIVERSAL ftp server which works on all platforms.The goal is to follow the standards and provide a powerfull and easy to deploy standalone FTP server for *NIX like systems in as few lines of code as necessary.More technical details will be provided in Full Tech description as soon as my time will allow me to.:)
Deploying the server
The M-ftp.tar.gz archive contains five files:m-ftp.c , m-ftp_config , m-ftp_accts , README and COPYING."m-ftp.c" is the source code which can be compiled with "gcc -o mftp m-ftp.c"."m-ftp_config" is the configuration file which contains all the server options like the ports to be used or the root directory.Every option inside has a comment starting with // which explaines they're semnification.Every option has a default value so that you can start the server as soon as you compiled it."m-ftp_accts" contains all the accounts registered for M-ftp.The default account is anonymous with any password specified by the $any value.Every account must be on a single line with the username first followed by a blank and the password.If value for passowrd is $any then any password will generate a successfull login.Every option in the config file can be defined at the command line too.Specifying a value for an option at the command line will make the server ignore the value for that option in the config file.For a listing of the recognized command line arguments and they're meaning run "./mftp --help".README file i think it's explainatory by itself...if you're having problems starting just cat it.And finally COPYING is a text version of the GNU GPL v2,the licence under which this program is distributed.
Community
For now I am the only one coding at this project but if some of you feel interested in this solution and also have the basic knowledge required(Linux OS,C,Linux/Unix programming and IPC,client-server basics,sockets,etc.)all you have to do is contact me and you're part of it.I am also very open at suggestions about optimizing, standardization, bugs and any other way of improving the code,so if you think you found some bug or have an ideea about something in the code don't hesitate to mail me.
Special Thanks To...
- Me for coding M-ftp. :)
- eugenski for helping me with hard testing of M-ftp.