-3

When I attempt to get to my ls command with ftp, I hit the 425 in my PORT section always, can anyone tell me why this is? My user section works, and if I can get port to work, I can focus on STOR and RETR.

/*FTP server*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h> 
/*for getting file size using stat()*/
#include<sys/stat.h>

/*for sendfile()*/
#include<sys/sendfile.h>

/*for O_RDONLY*/
#include<fcntl.h>
int active=0; 
int sock1, sock2;
char buf[100], command[5], filename[20];
struct sockaddr_in remoteaddr, remoteaddr_data;
int main(int argc,char *argv[])
{
  struct sockaddr_in server, client;
  struct stat obj;
  struct sockaddr_in local_data_addr_act;
  int s, s_data, s_data_act;
  s = socket(AF_INET, SOCK_STREAM, 0);
  s_data = socket(AF_INET, SOCK_STREAM, 0);
  s_data_act = socket(AF_INET, SOCK_STREAM, 0);
  int k, i, size, len, c;
  int filehandle;
  sock1 = socket(AF_INET, SOCK_STREAM, 0);
  if(sock1 == -1)
  {
    printf("Socket creation failed");
    exit(1);
  }
  server.sin_port = htons(atoi(argv[1]));
  server.sin_addr.s_addr = 0;
  k = bind(sock1,(struct sockaddr*)&server,sizeof(server));
  if(k == -1)
  {
    printf("Binding error");
    exit(1);
  }
  k = listen(sock1,1);
  if(k == -1)
  {
    printf("Listen failed");
    exit(1);
  }
  len = sizeof(client);
  sock2 = accept(sock1,(struct sockaddr*)&client, &len);
  write(sock2,"220\r\n", 6);
  i = 1;
  while(1)
  {
    recv(sock2, buf, 100, 0);
    printf("%s\n", buf);
    sscanf(buf, "%s", command);
    printf("%s\n", command);
    if(!strcmp(command, "LIST"))
    {
      system("ls >tmp.txt");
      FILE *fin=fopen("tmp.txt","r");
      sprintf(buf, "125\r\n");
      send(sock2, buf, strlen(buf), 0);
      char temp_buf[10];
      while (!feof(fin))
      {
        fgets(temp_buf, 98, fin);
        sprintf(buf, "%s", temp_buf);
        if (!active)send(sock1, buf, strlen(buf), 0);
        else send(s_data_act, buf, strlen(buf), 0); 
      }
      fclose(fin);
      sprintf(buf, "250\r\n");
      send(sock2, buf, strlen(buf), 0);
      if(!active) close(sock1);
      else close(s_data_act);
      sprintf(buf, "226\r\n");
      send(sock2, buf, strlen(buf), 0);
    }
    else if(!strcmp(command,"USER"))
    {
      sprintf(buf, "230\r\n");
      send(sock2, buf, strlen(buf), 0);
    }
    else if(!strcmp(command,"SYST"))
    {
      write(sock2, "502\r\n", 6);
    }
    else if(!strcmp(command,"PORT"))
    {
      unsigned char act_port[2];
      int act_ip[4], port_dec;
      char ip_decimal[40];
      active=1;
      sscanf(command, "PORT %d,%d,%d,%d,%d,%d",&act_ip[0],&act_ip[1],&act_ip[2],&act_ip[3], &act_port[0], &act_port[1]);
      local_data_addr_act.sin_family=AF_INET;
      sprintf(ip_decimal, "%d.%d.%d.%d", act_ip[0], act_ip[1], act_ip[2], act_ip[3]);
      local_data_addr_act.sin_addr.s_addr=inet_addr(ip_decimal);
      port_dec=act_port[0];
      port_dec=port_dec<<8;
      port_dec=port_dec+act_port[1];
      local_data_addr_act.sin_port=htons(port_dec);
      if (connect(s_data_act,(struct sockaddr*)&local_data_addr_act, (int)sizeof(struct sockaddr))!=0)
      {
        printf("%s%d\n",inet_ntoa(local_data_addr_act.sin_addr),ntohs(local_data_addr_act.sin_port)); 
        sprintf(buf, "425\r\n");
        send(sock2, buf, strlen(buf), 0);
        close(s_data_act);
      }
      else
      {
        sprintf(buf, "200\r\n");
        send(sock2, buf, strlen(buf), 0); 
      }
    }
    else if(!strcmp(command,"RETR"))
    {
      sscanf(buf, "%s%s", filename, filename);
      stat(filename, &obj);
      filehandle = open(filename, O_RDONLY);
      size = obj.st_size;
      if(filehandle == -1)
        size = 0;
      send(sock2, &size, sizeof(int), 0);
      if(size)
        sendfile(sock2, filehandle, NULL, size);
    }
    else if(!strcmp(command, "STOR"))
    {
      int c = 0, len;
      char *f;
      sscanf(buf+strlen(command), "%s", filename);
      recv(sock2, &size, sizeof(int), 0);
      i = 1;
      while(1)
      {
        filehandle = open(filename, O_CREAT | O_EXCL | O_WRONLY, 0666);
        if(filehandle == -1)
        {
          sprintf(filename + strlen(filename), "%d", i);
        }
        else
          break;
      }
      f = malloc(size);
      recv(sock2, f, size, 0);
      c = write(filehandle, f, size);
      close(filehandle);
      send(sock2, &c, sizeof(int), 0);
    }
    else if(!strcmp(command, "pwd"))
    {
      system("pwd>temp.txt");
      i = 0;
      FILE*f = fopen("temp.txt","r");
      while(!feof(f))
        buf[i++] = fgetc(f);
      buf[i-1] = '\0';
      fclose(f);
      send(sock2, buf, 100, 0);
    }
    else if(!strcmp(command, "cd"))
    {
      if(chdir(buf+3) == 0)
        c = 1;
      else
        c = 0;
      send(sock2, &c, sizeof(int), 0);
    }
    else if(!strcmp(command, "bye") || !strcmp(command, "QUIT"))
    {
      printf("FTP server quitting..\n");
      i = 1;
      send(sock2, &i, sizeof(int), 0);
      exit(0);
    }
  }
  return 0;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Jf2k
  • 139
  • 1
  • 15

1 Answers1

4

This code is FULL of errors and mistakes. Whatever you tried to implement with this code, it is not even remotely close to a conforming FTP server implementation.

You are creating too many sockets, and not even using all of them. And you are creating some of them at the wrong time under the wrong conditions.

A COMPLETE lack of error handling on most socket/file function calls.

NOT handling socket reads/writes correctly, in particular not accounting for the fact that TCP is a streaming transport that does not provide any guarantee of a 1-to-1 relationship between writes and reads. You MUST MUST MUST account for this!

Writing INCORRECT data to the client at times - sending null terminators that are not expected, sending data buffers as if they were null terminated when they really are not, sending file sizes as binary integers when they are not expected, etc.

Assuming received data is null terminated when it really is not.

Sending passive-mode data to the wrong socket (and not even implementing the PASV command to begin with).

NOT implementing the PORT, STOR, and RETR commands correctly (mismanaging the sockets).

NOT implementing the PWD, CD, and BYE/QUIT commands correctly (sending completely invalid replies).

And, although not technically an error, you really should not be using system(). There are better native ways to get the data needed. For LIST, you can use opendir() instead and then write the entries of the directory as needed. For PWD, you can use getcwd().

You need to scrap this code and start over. There are just too many things wrong with it to try to fix. Numerous examples are available online for how to implement socket I/O correctly, and especially how to do line-based I/O with sockets (since FTP is a line-based protocol). And please read RFC 959 for the proper rules of handling FTP command/responses and data transfer management.

Community
  • 1
  • 1
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770