Example #1
0
/*! accept PASV connection for ftp session
 *
 *  @param[in] session ftp session
 *
 *  @returns -1 for failure
 */
static int
ftp_session_accept(ftp_session_t *session)
{
  int                rc, new_fd;
  struct sockaddr_in addr;
  socklen_t          addrlen = sizeof(addr);

  if(session->flags & SESSION_PASV)
  {
    /* clear PASV flag */
    session->flags &= ~SESSION_PASV;

    /* tell the peer that we're ready to accept the connection */
    ftp_send_response(session, 150, "Ready\r\n");

    /* accept connection from peer */
    new_fd = accept(session->pasv_fd, (struct sockaddr*)&addr, &addrlen);
    if(new_fd < 0)
    {
      console_print(RED "accept: %d %s\n" RESET, errno, strerror(errno));
      ftp_session_set_state(session, COMMAND_STATE);
      ftp_send_response(session, 425, "Failed to establish connection\r\n");
      return -1;
    }

    rc = ftp_set_socket_nonblocking(new_fd);
    if(rc != 0)
    {
      ftp_closesocket(new_fd, 1);
      ftp_session_set_state(session, COMMAND_STATE);
      ftp_send_response(session, 425, "Failed to establish connection\r\n");
      return -1;
    }

    console_print(CYAN "accepted connection from %s:%u\n" RESET,
                  inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));

    ftp_session_set_state(session, DATA_TRANSFER_STATE);
    session->data_fd = new_fd;

    return 0;
  }
  else
  {
    /* peer didn't send PASV command */
    ftp_send_response(session, 503, "Bad sequence of commands\r\n");
    return -1;
  }
}
Example #2
0
static int
store_transfer(ftp_session_t *session)
{
  ssize_t rc;

  if(session->bufferpos == session->buffersize)
  {
    rc = recv(session->data_fd, session->buffer, sizeof(session->buffer), 0);
    if(rc <= 0)
    {
      if(rc < 0)
      {
        if(errno == EWOULDBLOCK)
          return -1;
        console_print(RED "recv: %d %s\n" RESET, errno, strerror(errno));
      }

      ftp_session_close_file(session);
      ftp_session_set_state(session, COMMAND_STATE);

      if(rc == 0)
      {
        ftp_send_response(session, 226, "OK\r\n");
      }
      else
        ftp_send_response(session, 426, "Connection broken during transfer\r\n");
      return -1;
    }

    session->bufferpos  = 0;
    session->buffersize = rc;
  }

  rc = ftp_session_write_file(session);
  if(rc <= 0)
  {
    ftp_session_close_file(session);
    ftp_session_set_state(session, COMMAND_STATE);
    ftp_send_response(session, 451, "Failed to write file\r\n");
    return -1;
  }

  session->bufferpos += rc;
  return 0;
}
Example #3
0
static int
retrieve_transfer(ftp_session_t *session)
{
  ssize_t rc;

  if(session->bufferpos == session->buffersize)
  {
    rc = ftp_session_read_file(session);
    if(rc <= 0)
    {
      ftp_session_close_file(session);
      ftp_session_set_state(session, COMMAND_STATE);
      if(rc < 0)
        ftp_send_response(session, 451, "Failed to read file\r\n");
      else
        ftp_send_response(session, 226, "OK\r\n");
      return -1;
    }

    session->bufferpos  = 0;
    session->buffersize = rc;
  }

  rc = send(session->data_fd, session->buffer + session->bufferpos,
            session->buffersize - session->bufferpos, 0);
  if(rc <= 0)
  {
    if(rc < 0)
    {
      if(errno == EWOULDBLOCK)
        return -1;
      console_print(RED "send: %d %s\n" RESET, errno, strerror(errno));
    }
    else
      console_print(YELLOW "send: %d %s\n" RESET, ECONNRESET, strerror(ECONNRESET));

    ftp_session_close_file(session);
    ftp_session_set_state(session, COMMAND_STATE);
    ftp_send_response(session, 426, "Connection broken during transfer\r\n");
    return -1;
  }

  session->bufferpos += rc;
  return 0;
}
Example #4
0
int main(int argc, char **argv){
    WSADATA wsa_data;

    SOCKET	srv_soc = 0, acpt_soc;  /* socket 句柄 */
    struct sockaddr_in serv_addr;   /* 服务器地址  */
    struct sockaddr_in from_addr;   /* 客户端地址  */
    char recv_buf[FTP_BUF_SIZE];
    unsigned short port = FTP_DEF_PORT;
    int from_len = sizeof(from_addr);
    int	result = 0, recv_len;

    if (argc == 2) /* 端口号 */
        port = atoi(argv[1]);


    WSAStartup(MAKEWORD(2,0), &wsa_data); /* 初始化 WinSock 资源 */

    srv_soc = socket(AF_INET, SOCK_STREAM, 0); /* 创建 socket */
    if (srv_soc == INVALID_SOCKET)
    {
        printf("[FTP] socket() Fails, error = %d\n", WSAGetLastError());
        return -1;
    }

    /* 服务器地址 */
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    result = bind(srv_soc, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
    if (result == SOCKET_ERROR) /* 绑定失败 */
    {
        closesocket(srv_soc);
        printf("[FTP Server] Fail to bind, error = %d\n", WSAGetLastError());
        return -1;
    }

    result = listen(srv_soc, SOMAXCONN);
    printf("[FTP] The server is running ... ...\n");
	//printf("%d\n",SOMAXCONN);
	while (1)
    {
        acpt_soc = accept(srv_soc, (struct sockaddr *) &from_addr, &from_len);
        if (acpt_soc == INVALID_SOCKET) /* 接受失败 */
        {
            printf("[FTP] Fail to accept, error = %d\n", WSAGetLastError());
            break;
        }

        printf("[FTP] Accepted address:[%s], port:[%d]\n",
            inet_ntoa(from_addr.sin_addr), ntohs(from_addr.sin_port));

        recv_len = recv(acpt_soc, recv_buf, FTP_BUF_SIZE, 0);
        char temp[1] ={'a'};
        send(acpt_soc, temp, 1, 0);
        //getchar();
        if (recv_len == SOCKET_ERROR) /* 接收失败 */
        {
           // getchar();
            closesocket(acpt_soc);
            printf("[FTP] Fail to recv, error = %d\n", WSAGetLastError());
            break;
        }

        recv_buf[recv_len] = 0;
        /* 向客户端发送响应数据 */
        result = ftp_send_response(acpt_soc, recv_buf, recv_len);
        closesocket(acpt_soc);
    }

    closesocket(srv_soc);
    WSACleanup();
    printf("[FTP] The server is stopped.\n");
    return 0;
}
Example #5
0
int main(int argc, char **argv) {
    WSADATA wsa_data;
    WSAStartup(MAKEWORD(2,0), &wsa_data); /* 初始化 WinSock 资源 */
    //web
    SOCKET	web_srv_soc = 0;
    unsigned short web_port = HTTP_DEF_PORT;
    web_srv_soc = socket(AF_INET, SOCK_STREAM, 0); /* 创建 socket */
    if (web_srv_soc == INVALID_SOCKET)
    {
        printf("[Web] socket() Fails, error = %d\n", WSAGetLastError());
        return -1;
    }
    struct sockaddr_in web_serv_addr;   /* 服务器地址  */
    web_serv_addr.sin_family = AF_INET;
    web_serv_addr.sin_port = htons(web_port);
    web_serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    int result;
    result = bind(web_srv_soc, (struct sockaddr *) &web_serv_addr, sizeof(web_serv_addr));
    if (result == SOCKET_ERROR) /* 绑定失败 */
    {
        closesocket(web_srv_soc);
        printf("[Web Server] Fail to bind, error = %d\n", WSAGetLastError());
        return -1;
    }
    result = listen(web_srv_soc, SOMAXCONN);
    printf("[Web] The server is running ... ...\n");

    //FTP
    SOCKET	ftp_srv_soc = 0;
    unsigned short ftp_port = FTP_DEF_PORT;
    ftp_srv_soc = socket(AF_INET, SOCK_STREAM, 0); /* 创建 socket */
    if (ftp_srv_soc == INVALID_SOCKET)
    {
        printf("[FTP] socket() Fails, error = %d\n", WSAGetLastError());
        return -1;
    }
    struct sockaddr_in ftp_serv_addr;   /* 服务器地址  */
    ftp_serv_addr.sin_family = AF_INET;
    ftp_serv_addr.sin_port = htons(ftp_port);
    ftp_serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    result = bind(ftp_srv_soc, (struct sockaddr *) &ftp_serv_addr, sizeof(ftp_serv_addr));
    if (result == SOCKET_ERROR) /* 绑定失败 */
    {
        closesocket(ftp_srv_soc);
        printf("[FTP Server] Fail to bind, error = %d\n", WSAGetLastError());
        return -1;
    }
    result = listen(ftp_srv_soc, SOMAXCONN);
    printf("[FTP] The server is running ... ...\n");

    fd_set afds;
    FD_ZERO(&afds);
    FD_SET(web_srv_soc, &afds);
    FD_SET(ftp_srv_soc, &afds);

    fd_set rfds;
    SOCKET web_conn_soc;
    SOCKET ftp_conn_soc;
    while(1) {
        FD_ZERO(&rfds);
        memcpy(&rfds, &afds, sizeof(rfds));
        if(select(FD_SETSIZE, &rfds, (fd_set*)0, (fd_set*)0,
                  (struct timeval *)0)== SOCKET_ERROR)
            printf("select error\n");
        if(FD_ISSET(web_srv_soc, &rfds)) {
            struct sockaddr_in conn_addr;   /* 客户端地址  */
            int conn_addr_len = sizeof(conn_addr);
            web_conn_soc = accept(web_srv_soc, (struct sockaddr*)&conn_addr,&conn_addr_len);
            if(web_conn_soc == INVALID_SOCKET) {
                printf("[Web] Fail to accept, error = %d\n", WSAGetLastError());
                break;
            }
            printf("[Web] Accepted address:[%s], port:[%d]\n",
                   inet_ntoa(conn_addr.sin_addr), ntohs(conn_addr.sin_port));
            char recv_buf[BUF_SIZE];
            int recv_len;
            recv_len = recv(web_conn_soc, recv_buf, BUF_SIZE, 0);
            if (recv_len == SOCKET_ERROR) /* 接收失败 */
            {
                closesocket(web_conn_soc);
                printf("[Web] Fail to recv, error = %d\n", WSAGetLastError());
                break;
            }

            recv_buf[recv_len] = 0;

            /* 向客户端发送响应数据 */
            http_send_response(web_conn_soc, recv_buf, recv_len);
            closesocket(web_conn_soc);
        }
        if(FD_ISSET(ftp_srv_soc, &rfds)) {
            struct sockaddr_in conn_addr;   /* 客户端地址  */
            int conn_addr_len = sizeof(conn_addr);
            ftp_conn_soc = accept(ftp_srv_soc, (struct sockaddr*)&conn_addr,&conn_addr_len);
            if(ftp_conn_soc == INVALID_SOCKET) {
                printf("[FTP] Fail to accept, error = %d\n", WSAGetLastError());
                break;
            }
            printf("[FTP] Accepted address:[%s], port:[%d]\n",
                   inet_ntoa(conn_addr.sin_addr), ntohs(conn_addr.sin_port));
            char recv_buf[BUF_SIZE];
            int recv_len;
            recv_len = recv(ftp_conn_soc, recv_buf, BUF_SIZE, 0);
            if (recv_len == SOCKET_ERROR) /* 接收失败 */
            {
                closesocket(ftp_conn_soc);
                printf("[FTP] Fail to recv, error = %d\n", WSAGetLastError());
                break;
            }

            recv_buf[recv_len] = 0;

            /* 向客户端发送响应数据 */
            ftp_send_response(ftp_conn_soc, recv_buf, recv_len);
            closesocket(ftp_conn_soc);
        }

    }

    closesocket(web_srv_soc);
    closesocket(ftp_srv_soc);
    WSACleanup();
    printf("[web] The server is stopped.\n");
    printf("[FTP] The server is stopped.\n");
    return 0;
}
Example #6
0
/*! poll sockets for ftp session
 *
 *  @param[in] session ftp session
 *
 *  @returns next session
 */
static ftp_session_t*
ftp_session_poll(ftp_session_t *session)
{
  int           rc;
  struct pollfd pollinfo;

  switch(session->state)
  {
    case COMMAND_STATE:
      /* we are waiting to read a command */
      pollinfo.fd      = session->cmd_fd;
      pollinfo.events  = POLLIN;
      pollinfo.revents = 0;
      break;

    case DATA_CONNECT_STATE:
      /* we are waiting for a PASV connection */
      pollinfo.fd      = session->pasv_fd;
      pollinfo.events  = POLLIN;
      pollinfo.revents = 0;
      break;

    case DATA_TRANSFER_STATE:
      /* we need to transfer data */
      pollinfo.fd = session->data_fd;
      if(session->flags & SESSION_RECV)
        pollinfo.events = POLLIN;
      else
        pollinfo.events = POLLOUT;
      pollinfo.revents = 0;
      break;
  }

  /* poll the selected socket */
  rc = poll(&pollinfo, 1, 0);
  if(rc < 0)
    console_print(RED "poll: %d %s\n" RESET, errno, strerror(errno));
  else if(rc > 0)
  {
    if(pollinfo.revents != 0)
    {
      /* handle event */
      switch(session->state)
      {
        case COMMAND_STATE:
          if(pollinfo.revents & POLL_UNKNOWN)
            console_print(YELLOW "cmd_fd: revents=0x%08X\n" RESET, pollinfo.revents);

          /* we need to read a new command */
          if(pollinfo.revents & (POLLERR|POLLHUP))
            ftp_session_close_cmd(session);
          else if(pollinfo.revents & POLLIN)
            ftp_session_read_command(session);
          break;

        case DATA_CONNECT_STATE:
          if(pollinfo.revents & POLL_UNKNOWN)
            console_print(YELLOW "pasv_fd: revents=0x%08X\n" RESET, pollinfo.revents);

          /* we need to accept the PASV connection */
          if(pollinfo.revents & (POLLERR|POLLHUP))
          {
            ftp_session_set_state(session, COMMAND_STATE);
            ftp_send_response(session, 426, "Data connection failed\r\n");
          }
          else if(pollinfo.revents & POLLIN)
          {
            if(ftp_session_accept(session) != 0)
              ftp_session_set_state(session, COMMAND_STATE);
          }
          break;

        case DATA_TRANSFER_STATE:
          if(pollinfo.revents & POLL_UNKNOWN)
            console_print(YELLOW "data_fd: revents=0x%08X\n" RESET, pollinfo.revents);

          /* we need to transfer data */
          if(pollinfo.revents & (POLLERR|POLLHUP))
          {
            ftp_session_set_state(session, COMMAND_STATE);
            ftp_send_response(session, 426, "Data connection failed\r\n");
          }
          else if(pollinfo.revents & (POLLIN|POLLOUT))
            ftp_session_transfer(session);
          break;
      }
    }
  }

  /* still connected to peer; return next session */
  if(session->cmd_fd >= 0)
    return session->next;

  /* disconnected from peer; destroy it and return next session */
  return ftp_session_destroy(session);
}
Example #7
0
/*! read command for ftp session
 *
 *  @param[in] session ftp session
 */
static void
ftp_session_read_command(ftp_session_t *session)
{
  static char   buffer[CMD_BUFFERSIZE];
  ssize_t       rc;
  char          *args;
  ftp_command_t key, *command;

  memset(buffer, 0, sizeof(buffer));

  /* retrieve command */
  rc = recv(session->cmd_fd, buffer, sizeof(buffer), 0);
  if(rc < 0)
  {
    /* error retrieving command */
    console_print(RED "recv: %d %s\n" RESET, errno, strerror(errno));
    ftp_session_close_cmd(session);
    return;
  }
  if(rc == 0)
  {
    /* peer closed connection */
    ftp_session_close_cmd(session);
    return;
  }
  else
  {
    /* split into command and arguments */
    /* TODO: support partial transfers */
    buffer[sizeof(buffer)-1] = 0;

    args = buffer;
    while(*args && *args != '\r' && *args != '\n')
      ++args;
    *args = 0;
    
    args = buffer;
    while(*args && !isspace((int)*args))
      ++args;
    if(*args)
      *args++ = 0;

    /* look up the command */
    key.name = buffer;
    command = bsearch(&key, ftp_commands,
                      num_ftp_commands, sizeof(ftp_command_t),
                      ftp_command_cmp);

    /* execute the command */
    if(command == NULL)
    {
      ftp_send_response(session, 502, "invalid command -> %s %s\r\n",
                        key.name, args);
    }
    else
    {
      /* clear RENAME flag for all commands except RNTO */
      if(strcasecmp(command->name, "RNTO") != 0)
        session->flags &= ~SESSION_RENAME;
      command->handler(session, args);
    }
  }
}
Example #8
0
/*! allocate new ftp session
 *
 *  @param[in] listen_fd socket to accept connection from
 */
static void
ftp_session_new(int listen_fd)
{
  ssize_t            rc;
  int                new_fd;
  ftp_session_t      *session;
  struct sockaddr_in addr;
  socklen_t          addrlen = sizeof(addr);

  /* accept connection */
  new_fd = accept(listen_fd, (struct sockaddr*)&addr, &addrlen);
  if(new_fd < 0)
  {
    console_print(RED "accept: %d %s\n" RESET, errno, strerror(errno));
    return;
  }

  console_print(CYAN "accepted connection from %s:%u\n" RESET,
                inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));

  /* allocate a new session */
  session = (ftp_session_t*)malloc(sizeof(ftp_session_t));
  if(session == NULL)
  {
    console_print(RED "failed to allocate session\n" RESET);
    ftp_closesocket(new_fd, 1);
    return;
  }

  /* initialize session */
  memset(session->cwd, 0, sizeof(session->cwd));
  strcpy(session->cwd, "/");
  session->peer_addr.sin_addr.s_addr = INADDR_ANY;
  session->cmd_fd   = new_fd;
  session->pasv_fd  = -1;
  session->data_fd  = -1;
  session->flags    = 0;
  session->state    = COMMAND_STATE;
  session->next     = NULL;
  session->prev     = NULL;
  session->transfer = NULL;

  /* link to the sessions list */
  if(sessions == NULL)
  {
    sessions = session;
    session->prev = session;
  }
  else
  {
    sessions->prev->next = session;
    session->prev        = sessions->prev;
    sessions->prev       = session;
  }

  /* copy socket address to pasv address */
  addrlen = sizeof(session->pasv_addr);
  rc = getsockname(new_fd, (struct sockaddr*)&session->pasv_addr, &addrlen);
  if(rc != 0)
  {
    console_print(RED "getsockname: %d %s\n" RESET, errno, strerror(errno));
    ftp_send_response(session, 451, "Failed to get connection info\r\n");
    ftp_session_destroy(session);
    return;
  }

  session->cmd_fd = new_fd;

  /* send initiator response */
  rc = ftp_send_response(session, 200, "Hello!\r\n");
  if(rc <= 0)
    ftp_session_destroy(session);
}
Example #9
0
static int
list_transfer(ftp_session_t *session)
{
  ssize_t rc;

  if(session->bufferpos == session->buffersize)
  {
    struct stat   st;
    struct dirent *dent = readdir(session->dp);
    if(dent == NULL)
    {
      ftp_session_close_cwd(session);
      ftp_session_set_state(session, COMMAND_STATE);
      ftp_send_response(session, 226, "OK\r\n");
      return -1;
    }

    if(strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
      return 0;

    if(strcmp(session->cwd, "/") == 0)
      snprintf(session->buffer, sizeof(session->buffer),
               "/%s", dent->d_name);
    else
      snprintf(session->buffer, sizeof(session->buffer),
               "%s/%s", session->cwd, dent->d_name);
    rc = lstat(session->buffer, &st);
    if(rc != 0)
    {
      console_print(RED "stat '%s': %d %s\n" RESET, session->buffer, errno, strerror(errno));
      ftp_session_close_cwd(session);
      ftp_session_set_state(session, COMMAND_STATE);
      ftp_send_response(session, 550, "unavailable\r\n");
      return -1;
    }

    session->buffersize =
        sprintf(session->buffer,
                "%crwxrwxrwx 1 3DS 3DS %llu Jan 1 1970 %s\r\n",
                S_ISDIR(st.st_mode) ? 'd' :
                S_ISLNK(st.st_mode) ? 'l' : '-',
                (unsigned long long)st.st_size,
                dent->d_name);
    session->bufferpos = 0;
  }

  rc = send(session->data_fd, session->buffer + session->bufferpos,
            session->buffersize - session->bufferpos, 0);
  if(rc <= 0)
  {
    if(rc < 0)
    {
      if(errno == EWOULDBLOCK)
        return -1;
      console_print(RED "send: %d %s\n" RESET, errno, strerror(errno));
    }
    else
      console_print(YELLOW "send: %d %s\n" RESET, ECONNRESET, strerror(ECONNRESET));

    ftp_session_close_cwd(session);
    ftp_session_set_state(session, COMMAND_STATE);
    ftp_send_response(session, 426, "Connection broken during transfer\r\n");
    return -1;
  }

  session->bufferpos += rc;
  return 0;
}