/* Run command, check authentication first */ static void ftpsrv_process_cmd(FTPSRV_SESSION_STRUCT* session) { const FTPSRV_COMMAND_STRUCT* row = ftpsrv_commands; int result = 1; char* cp = session->command; uint32_t auth_valid; /* Convert command to upper case */ while (*cp) { *cp = toupper(*cp); cp++; } /* Find function corresponding to command */ while ((row->command != NULL) && strncmp(session->command, row->command, strlen(row->command))) { row++; } /* Process authentication sequence if required */ auth_valid = ftpsrv_process_auth(session, row->auth_req); /* Run command if authentication is valid */ if (auth_valid) { if (row->function != NULL) { row->function(session); } else { session->message = (char*) ftpsrvmsg_unimp; } } else { if (session->message == NULL) { session->message = (char*) ftpsrvmsg_not_logged; } if (session->auth_input.uid != NULL) { _mem_free(session->auth_input.uid); session->auth_input.uid = NULL; } } ftpsrv_send_msg(session, session->message); session->message = NULL; _mem_zero(session->buffer, FTPSRV_BUF_SIZE); }
int32_t ftpsrv_help(FTPSRV_SESSION_STRUCT* session) { const FTPSRV_COMMAND_STRUCT* cmd_ptr = ftpsrv_commands; uint32_t length = 0; uint32_t n = 1; uint32_t space = FTPSRV_BUF_SIZE; uint32_t max_cmd_length = ftpsrv_max_cmd_length(); char* separator; char* buffer = session->buffer; ftpsrv_send_msg(session, ftpsrvmsg_help_start); while(cmd_ptr->command != NULL) { /* After every fifth command print a new line. Commands are separated by spaces */ separator = (n % 4) ? " " : "\r\n"; n++; length += snprintf(buffer+length, space, "%s%s", cmd_ptr->command, separator); space = FTPSRV_BUF_SIZE-length; /* If there is not enough space in the buffer flush it to client and repeat printing */ if (space < (max_cmd_length + sizeof("\r\n"))) { send(session->control_sock, buffer, FTPSRV_BUF_SIZE-space, 0); _mem_zero(buffer, length); space = FTPSRV_BUF_SIZE; length = 0; } cmd_ptr++; } if (n) { space -= snprintf(buffer+length, space, "\r\n"); } /* Send command list from the buffer and set message to HELP end text */ send(session->control_sock, buffer, FTPSRV_BUF_SIZE-space, 0); session->message = (char*) ftpsrvmsg_help_end; return(FTPSRV_OK); }
/* Task for reading/writing file */ void ftpsrv_transfer_task(void* init_ptr, void* creator) { FTPSRV_TRANSFER_PARAM* param = (FTPSRV_TRANSFER_PARAM*) init_ptr; MQX_FILE_PTR file = param->file; uint32_t mode = param->mode; uint32_t sock = param->sock; FTPSRV_SESSION_STRUCT* session = param->session; void* data_buffer; char* msg_str; if (session->state == FTPSRV_STATE_TRANSFER) { RTCS_task_resume_creator(creator, (uint32_t) RTCS_ERROR); return; } data_buffer = RTCS_mem_alloc(FTPSRVCFG_DATA_BUFFER_SIZE); if (data_buffer == NULL) { RTCS_task_resume_creator(creator, (uint32_t) RTCS_ERROR); return; } session->transfer_tid = _task_get_id(); session->state = FTPSRV_STATE_TRANSFER; RTCS_task_resume_creator(creator, (uint32_t) RTCS_OK); while (1) { FTPSRV_TRANSFER_MSG message; _mqx_uint retval; /* Reading from file */ if (mode == FTPSRV_MODE_READ) { uint32_t length; int32_t error; length = fread((void*) data_buffer, 1, FTPSRVCFG_DATA_BUFFER_SIZE, file); if ((length != FTPSRVCFG_DATA_BUFFER_SIZE) && ferror(file) && !feof(file)) { msg_str = (char*) ftpsrvmsg_locerr; break; } error = send(sock, data_buffer, length, 0); if (error == RTCS_ERROR) { msg_str = (char*) ftpsrvmsg_locerr; break; } if (feof(file)) { msg_str = (char*) ftpsrvmsg_trans_complete; break; } } /* Writing to file */ else if ((mode == FTPSRV_MODE_WRITE) || (mode == FTPSRV_MODE_APPEND)) { uint32_t length; int32_t received; received = recv(sock, data_buffer, FTPSRVCFG_DATA_BUFFER_SIZE, 0); if (received == RTCS_ERROR) { msg_str = (char*) ftpsrvmsg_trans_complete; break; } length = fwrite((void*) data_buffer, 1, received, file); if (length != received) { if (length == IO_ERROR) { msg_str = (char*) ftpsrvmsg_no_space; } else { msg_str = (char*) ftpsrvmsg_writefail; } break; } } retval = _lwmsgq_receive((void*) session->msg_queue, (uint32_t *)&message, LWMSGQ_TIMEOUT_FOR, 1, NULL); if (retval != MQX_OK) { continue; } if (message.command == FTPSRV_CMD_ABORT) { msg_str = (char*) ftpsrvmsg_trans_abort; break; } else if (message.command == FTPSRV_CMD_STAT) { /* TODO: Add code to print out transfer statistics */ } } _mem_free(data_buffer); fclose(file); ftpsrv_send_msg(session, msg_str); shutdown(sock, FLAG_CLOSE_TX); session->state = FTPSRV_STATE_IDLE; }
static void ftpsrv_session_task(void* init_ptr, void* creator) { FTPSRV_SESSION_STRUCT* session; FTPSRV_STRUCT* server = ((FTPSRV_SESSION_PARAM*) init_ptr)->server; uint32_t sock = ((FTPSRV_SESSION_PARAM*) init_ptr)->sock; uint32_t i; _task_id tid = _task_get_id(); _mqx_uint retval = 0; /* Find empty session */ _lwsem_wait(&server->tid_sem); for (i = 0; i < server->params.max_ses; i++) { if (server->session[i] == NULL) { break; } } if (i == server->params.max_ses) { RTCS_task_resume_creator(creator, (uint32_t) RTCS_ERROR); _lwsem_post(&server->tid_sem); _lwsem_post(&server->ses_cnt); return; } /* Save task ID - used for indication of running task */ server->ses_tid[i] = tid; /* Access to array done. Unblock other tasks. */ _lwsem_post(&server->tid_sem); /* Allocate session */ session = ftpsrv_ses_alloc(server); if (session) { server->session[i] = session; RTCS_task_resume_creator(creator, RTCS_OK); ftpsrv_ses_init(server, session, sock); ftpsrv_send_msg(session, ftpsrvmsg_banner); /* Read and process commands */ while (session->connected) { if (ftpsrv_read_cmd(session) != FTPSRV_OK) { _mem_zero(session->buffer, FTPSRV_BUF_SIZE); continue; } ftpsrv_process_cmd(session); _sched_yield(); } /* cleanup session */ ftpsrv_ses_close(session); ftpsrv_ses_free(session); server->session[i] = NULL; } else { RTCS_task_resume_creator(creator, (uint32_t) RTCS_ERROR); } /* Cleanup and end task */ _lwsem_post(&server->ses_cnt); /* Null tid => task is no longer running */ _lwsem_wait(&server->tid_sem); server->ses_tid[i] = 0; _lwsem_post(&server->tid_sem); }
int32_t ftpsrv_list(FTPSRV_SESSION_STRUCT* session) { int32_t length; char* path; void* dir_ptr; uint32_t sock; char* dir_param; char* full_path; char* temp; uint32_t path_length; uint32_t wrong_path; if (session->cmd_arg == NULL) { path = ""; } else { rtcs_url_decode(session->cmd_arg); path = rtcs_path_strip_delimiters(session->cmd_arg); } /* Translate relative path to absolute. */ full_path = ftpsrv_get_full_path(session, path, &wrong_path); if (full_path == NULL) { if (wrong_path) { session->message = (char*) ftpsrvmsg_no_file; } else { session->message = (char*) ftpsrvmsg_no_memory; } return(FTPSRV_ERROR); } path_length = strlen(full_path); /* Allocate space for path + appendix, copy full path and add appendix to it. */ /* This is required because MFS cannot list directories, only files. */ temp = RTCS_mem_alloc_zero(path_length+sizeof(FTPSRV_PATH_APPENDIX)); _mem_copy(full_path, temp, path_length); _mem_copy(FTPSRV_PATH_APPENDIX, temp+path_length, sizeof(FTPSRV_PATH_APPENDIX)-1); _mem_free(full_path); full_path = temp; /* Open directory. Unix format for LIST command, simple file list for NLIST. */ if (!strcmp(session->command, "LIST")) { /* Unix */ dir_param = "u*"; } else { /* File list */ dir_param = "f*"; } /* Open directory, get list, cleanup and return. */ dir_ptr = _io_mfs_dir_open(session->fs_ptr, full_path, dir_param); if (dir_ptr == NULL) { session->message = (char*) ftpsrvmsg_no_file; return(FTPSRV_ERROR); } /* Send initialization message */ ftpsrv_send_msg(session, ftpsrvmsg_opening_datacon); /* Open data connection */ sock = ftpsrv_open_data_connection(session); if (sock == RTCS_SOCKET_ERROR) { session->message = (char*) ftpsrvmsg_locerr; _mem_free(full_path); _io_mfs_dir_close(dir_ptr); return(FTPSRV_ERROR); } /* Send data (directory listing). */ while ((length = _io_mfs_dir_read(dir_ptr, session->buffer, FTPSRV_BUF_SIZE)) > 0) { /* If we are in root do not list "one level up" nor "current dir" link */ if ((strstr(session->buffer, " .. ") || strstr(session->buffer, " . ")) && !strcmp(session->cur_dir, "\\")) { _mem_zero(session->buffer, length); } else { if (send(sock, session->buffer, length, 0) != length) { ftpsrv_send_msg(session, ftpsrvmsg_writefail); break; } } } /* Cleanup */ closesocket(sock); _io_mfs_dir_close(dir_ptr); _mem_free(full_path); session->message = (char*) ftpsrvmsg_trans_complete; return FTPSRV_OK; }