HW 3: ftpread
CS 494/594 Homework Bart Massey
In this assignment, you will write
ftpread, an FTP reader
client in C in the style of the
tftpread program written
FTP is described in RFC 959. You should start by reading and thoroughly understanding the relevant portions of this RFC.
Your client will start by making a TCP "control" connection
to the FTP daemon on a host specified on the command line.
You will then establish a TCP "data" connection to retrieve
a file at a path specified on the command line, writing the
retrieved file to standard output as
Your client must authenticate itself with username "anonymous" (spelled correctly) and your email address as the "password", as per the specifications for anonymous FTP.
Your client must be able to retrieve a file in binary stream mode. There are two basic types of retrieve: "active" and "passive". In an active FTP retrieve, you listen for a data connection, then retrieve the file from that data connection when the server connects to you. In a passive FTP retrieve, you connect to a port specified by the server and retrieve the data from there.
For the purposes of this assignment, you are successful when
ftpread program can retrieve the file
from the host
svcs.cs.pdx.edu using FTP. CS 494 students
may choose to do only an active retrieve. The
CS 594 students must be able to do either an active or
passive retrieve, as specified on the command line.
This is a fairly challenging assignment. Here's some hints to make it easier.
You may want to start with
available on my Github
It contains a bunch of code that is similar to code you will
ftpread. If you cannot use git, note that there is
a "ZIP" button near the top left of the page that will create
a ZIP archive to download.
You will be sending a lot of commands, and parsing a lot of
responses. One good trick is to use
fdopen() to turn the
file descriptor of your socket into a
FILE * suitable for
use with standard IO functions such as
Note that you need to
fdopen() the input and output
of the socket separately, else you may get confusion with buffering.
FILE *s_in = fdopen(s, "r"); FILE *s_out = fdopen(s, "w");
expect / send
Parsing response codes gets pretty tedious too, so you will want some code to handle that. I recommend my "expect / send" library, also available on my GitHub. This (documented) C library provides simple functions for sending commands and dealing with expected responses.
You will probably want to just hardwire your client to not handle unexpected response codes gracefully: just exit. That's what my expect / send library does, and it's fine for this assignment. The easiest way to discover what response codes to expect is via experimentation.
The PORT command
Whether doing an active or passive transfer, you will need
to use the
PORT command to inform the server of the IP
address and port number of your end of the socket. The best
way to get this information is via the
Make sure you send the
PORT bytes in network order.
The order of operations for a passive transfer is pretty
specific: you must send
the data socket, then
RETR. Any other order is unlikely
You will want to get a real FTP client and try retrieving the specified file that way. Use wireshark / tshark to watch the flow of commands and responses during the transaction; this is basically what you are trying to duplicate.
Make sure you turn on the
cexpect_verbose variable in
my expect / send library if you are using that library; it
is really useful to see what your program is doing.
It is really easy to get host and network byte-order
problems. The routines
ntohs() do conversions between host and network byte order
for short (16-bit, like port numbers) and long (32-bit, like
IP addresses) integers.
inet_ntoa() will convert a 32-bit IPv4 address
into a string for printing purposes.
You must submit the following:
Your C source code, together with any other files needed to try it out.
A README.homework file containing a writeup in plain text of not more than 1000 words describing what you did, how it worked, and anything else you think we should know.