-
FTP Client
I am a C Newbie. I have been working on this simple FTP client for my school, and I have been coming a particular issue with the FTP protocol. I cant seem to get a handle on the NVT-ASCII format. I try to send commands over the control connection based on my interpretation of the commands in the FTP protocol, and I am not getting anywhere. Any advice? But to show an example, I dont see any examples for sending an NLST command. The specs say 'NLST [<sp> <path-name>] <crlf>', and I interpret it as 'NLST \r\n', as if you want to specify the current directory, you need a null argument. am I on the right track? or are other things involved that I seem to be missing?
Thanks again for your help.
Ayo.
-
I've moved this to the networking forum.
First off is read the sticky threads to get up to speed on lots of networking issues.
Second is study what a real FTP client does, by watching the message traffic using ethereal.
Then study what your FTP client does, by watching the message traffic using ethereal.
The difference between them is usually the problem.
> am I on the right track?
That seems to be about right, from just reading the words.
> or are other things involved that I seem to be missing?
Well since we can't see your code, I can't comment.
-
Thx for the prompt response, I will post my code shortly.
Thx again.
-
Here is my code
Its a little lengthy.
Code:
/* function: implementation of 'ls' 1=> success, -1=> fail*/
int nlst()
{
struct sockaddr_in client;
struct hostent *clientAddr;
short portNum;
char cmd[STDSIZE];
int dataSockFD;
socklen_t sin_size;
if((dataSockFD = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket call failed!");
exit(0);
}
/* gethostname call */
if(gethostname(hPtr,STDSIZE) == -1)
printf("%s\n", strerror(errno));
/* WORKS SO FAR */
/* finding out my IP address */
if( (clientAddr = gethostbyname(hPtr)) == NULL)
{
printf("Gethostbyname error!");
exit(1);
}
// short port;
client.sin_family = AF_INET;
client.sin_port = htons(0);
client.sin_addr = *((struct in_addr *)clientAddr->h_addr);
memset(&(client.sin_zero), '\0', 8); // zero the rest
/* set sock option for port reuse */
if(setsockopt(dataSockFD, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) {
printf("setsockopt failed!");
exit(1);
}
/* attempt to bind while it fails */
if((bind(dataSockFD, (struct sockaddr *)&client, sizeof(struct sockaddr)) == -1))
{
printf("bind failed.");
exit(1);
}
/* start listening for a connection from server-DTP */
if(listen(dataSockFD, QUEUE) == -1)
{
printf("%s\nE:",strerror(errno));
exit(1);
}
sin_size = sizeof(client);
if(getsockname(dataSockFD,(struct sockaddr *)&client, &sin_size) == -1)
{
printf("getsockname failed.");
exit(1);
}
// put it in
int IP = *( (int *)(clientAddr->h_addr_list[0]));
IP = htonl(IP);
sprintf(cmd,"PORT %d,%d,%d,%d,%d,%d\r\n",
(IP & 0xFF000000) >> 24 ,
(IP & 0x00FF0000) >> 16 ,
(IP & 0x0000FF00) >> 8 ,
(IP & 0x000000FF) ,
(client.sin_port & 0xFF00) >> 8 ,
(client.sin_port & 0x00FF));
char *c;
char cmd1[STDSIZE];
// send PORT command
c = cmd;
write(sockFD,c, strlen(c)); // sending PORT command
if(receive() == 0) { }
// if NLST
strcpy(cmd1, "NLST \r\n"); <--- issues at this point!!!!
c = cmd1;
write(sockFD,c,strlen(c));
if(receive() == 0) {
int dataFD;
if((dataFD = accept(dataSockFD, NULL, NULL)) == -1)
{
printf("%s\n",strerror(errno));
}
else
printf("Accepted from server!");
char l;
if(read(dataFD, l, 1) > 0) // test if anything has been written to socket by server
printf("%c\n",l);
}
else
printf("something wrong with 'NLST' command");
// receive again... after reading directory...
if(receive() == -1) {
printf("receive error 2\n");
exit(0);
}
return 1;
}
-
> if(read(dataFD, l, 1) > 0)
Well this should have got a warning from the compiler. The 2nd parameter is a pointer to where you want the answer stored.
-
I replaced that part with the ampersand. But I am going to try what you said using tcpdump to see the behavior with regular ftp clients, to compare with mine.
Thanks again.
I will tell you how it went soon.