Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build
.vscode
52 changes: 52 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
cmake_minimum_required(VERSION 3.5)
project(ftp)

if(DEFINED CROSS_COMPILE_PATH)
# the name of the target operating system
message(STATUS "SETTING CROSS COMPILER")
set(CMAKE_SYSTEM_NAME Linux)

#SET(CROSS_COMPILE_PATH "/opt/arm/arm-ca9-linux-gnueabihf-6.5")
if(NOT ${ROOTFS})
set(ROOTFS "${CROSS_COMPILE_PATH}")
endif()
#SET(ROOTFS "/na51055_linux_sdk/BSP/linux-kernel/")

add_compile_options(-nostdinc)

# which compilers to use for C and C++
set(CMAKE_C_COMPILER ${CROSS_COMPILE_PATH}/bin/arm-ca9-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${CROSS_COMPILE_PATH}/bin/arm-ca9-linux-gnueabihf-g++)

set(CMAKE_FIND_ROOT_PATH ${ROOTFS})
link_directories(${CROSS_COMPILE_PATH}/lib ${CROSS_COMPILE_PATH}/local/lib ${CROSS_COMPILE_PATH}/arch/powerpc/boot)




# adjust the default behavior of the FIND_XXX() commands:
# search programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

# search headers and libraries in the target environment
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

endif()

add_executable(${PROJECT_NAME} server.h server.c handles.c)


if(DEFINED CROSS_COMPILE_PATH)

# target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE
# /opt/arm/arm-ca9-linux-gnueabihf-6.5/arm-ca9-linux-gnueabihf/sysroot/usr/include/
# )
target_include_directories(${PROJECT_NAME} BEFORE PRIVATE
${CROSS_COMPILE_PATH}/arm-ca9-linux-gnueabihf/sysroot/usr/include/
${ROOTFS}/arch/powerpc/boot/
${ROOTFS}/arch/arm/include/generated/
${CROSS_COMPILE_PATH}/arm-ca9-linux-gnueabihf/include/c++/6.5.0/
${CROSS_COMPILE_PATH}/lib/gcc/arm-ca9-linux-gnueabihf/6.5.0/include/
)
endif()
6 changes: 5 additions & 1 deletion common.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#ifndef COMMON_INCLUDE_
#define COMMON_INCLUDE_
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
Expand Down Expand Up @@ -33,7 +35,7 @@ typedef struct State

/* Is this username allowed? */
int username_ok;
char *username;
char username[32];

/* Response message to client e.g. 220 Welcome */
char *message;
Expand Down Expand Up @@ -117,3 +119,5 @@ void ftp_abor(State *);

void str_perm(int, char *);
void my_wait(int);

#endif
5 changes: 5 additions & 0 deletions compile.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
rm -r build
mkdir build
cd build
cmake ..
make
7 changes: 7 additions & 0 deletions cross_compile.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
rm -r build
mkdir build
cd build
cmake -DCROSS_COMPILE_PATH="/opt/arm/arm-ca9-linux-gnueabihf-6.5" \
-DROOTFS="/na51055_linux_sdk/BSP/linux-kernel/" \
..
make
33 changes: 21 additions & 12 deletions handles.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include "common.h"
#include "server.h"
#include <arpa/inet.h>
#ifndef sendfile
#define BUF_SIZE 8192
ssize_t sendfile(int out_fd, int in_fd, off_t * offset, size_t count )
Expand Down Expand Up @@ -98,7 +100,6 @@ void ftp_user(Command *cmd, State *state)
{
const int total_usernames = sizeof(usernames)/sizeof(char *);
if(lookup(cmd->arg,usernames,total_usernames)>=0){
state->username = malloc(32);
memset(state->username,0,32);
strcpy(state->username,cmd->arg);
state->username_ok = 1;
Expand Down Expand Up @@ -128,17 +129,17 @@ void ftp_pasv(Command *cmd, State *state)
int ip[4];
char buff[255];
char *response = "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\n";
Port *port = malloc(sizeof(Port));
gen_port(port);
Port port;
gen_port(&port);
getip(state->connection,ip);

/* Close previous passive socket? */
close(state->sock_pasv);

/* Start listening here, but don't accept the connection */
state->sock_pasv = create_socket((256*port->p1)+port->p2);
printf("port: %d\n",256*port->p1+port->p2);
sprintf(buff,response,ip[0],ip[1],ip[2],ip[3],port->p1,port->p2);
state->sock_pasv = create_socket((256*port.p1)+port.p2);
printf("port: %d\n",256*port.p1+port.p2);
sprintf(buff,response,ip[0],ip[1],ip[2],ip[3],port.p1,port.p2);
state->message = buff;
state->mode = SERVER;
puts(state->message);
Expand Down Expand Up @@ -190,16 +191,24 @@ void ftp_list(Command *cmd, State *state)
if(stat(entry->d_name,&statbuf)==-1){
fprintf(stderr, "FTP: Error reading file stats...\n");
}else{
char *perms = malloc(9);
memset(perms,0,9);
char perms[10];
memset(perms,0,10);

/* Convert time_t to tm struct */
rawtime = statbuf.st_mtime;
time = localtime(&rawtime);
strftime(timebuff,80,"%b %d %H:%M",time);
str_perm((statbuf.st_mode & ALLPERMS), perms);
printf("%c%s %5ld %4d %4d %8ld %s %s\r\n",
(entry->d_type==DT_DIR)?'d':'-',
perms,statbuf.st_nlink,
statbuf.st_uid,
statbuf.st_gid,
statbuf.st_size,
timebuff,
entry->d_name);
dprintf(connection,
"%c%s %5d %4d %4d %8d %s %s\r\n",
"%c%s %5ld %4d %4d %8ld %s %s\r\n",
(entry->d_type==DT_DIR)?'d':'-',
perms,statbuf.st_nlink,
statbuf.st_uid,
Expand Down Expand Up @@ -506,7 +515,7 @@ void ftp_size(Command *cmd, State *state)
memset(filesize,0,128);
/* Success */
if(stat(cmd->arg,&statbuf)==0){
sprintf(filesize, "213 %d\n", statbuf.st_size);
sprintf(filesize, "213 %ld\n", statbuf.st_size);
state->message = filesize;
}else{
state->message = "550 Could not get file size.\n";
Expand All @@ -531,7 +540,7 @@ void str_perm(int perm, char *str_perm)
int read, write, exec;

/* Flags buffer */
char fbuff[3];
char fbuff[4];

read = write = exec = 0;

Expand All @@ -540,7 +549,7 @@ void str_perm(int perm, char *str_perm)
/* Explode permissions of user, group, others; starting with users */
curperm = ((perm & ALLPERMS) >> i ) & 0x7;

memset(fbuff,0,3);
memset(fbuff,0,4);
/* Check rwx flags for each*/
read = (curperm >> 2) & 0x1;
write = (curperm >> 1) & 0x1;
Expand Down
25 changes: 16 additions & 9 deletions server.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#include "common.h"
#include "server.h"

#include <arpa/inet.h>
#include <sys/wait.h>
/**
* Sets up server and handles incoming connections
* @param port Server port
Expand All @@ -13,8 +16,8 @@ void server(int port)
while(1){
connection = accept(sock, (struct sockaddr*) &client_address,&len);
char buffer[BSIZE];
Command *cmd = malloc(sizeof(Command));
State *state = malloc(sizeof(State));
Command cmd;
State state;
pid = fork();

memset(buffer,0,BSIZE);
Expand Down Expand Up @@ -45,16 +48,20 @@ void server(int port)
if(!(bytes_read>BSIZE)){
/* TODO: output this to log */
buffer[BSIZE-1] = '\0';
printf("User %s sent command: %s\n",(state->username==0)?"unknown":state->username,buffer);
parse_command(buffer,cmd);
state->connection = connection;
printf("User %s sent command: %s\n",(state.username==0)?"unknown":state.username,buffer);
parse_command(buffer,&cmd);
state.connection = connection;

/* Ignore non-ascii char. Ignores telnet command */
if(buffer[0]<=127 || buffer[0]>=0){
response(cmd,state);
response(&cmd,&state);
}
else
{
printf("Ignoring command %s\n", cmd.command);
}
memset(buffer,0,BSIZE);
memset(cmd,0,sizeof(cmd));
memset(&cmd,0,sizeof(cmd));
}else{
/* Read error */
perror("server:read");
Expand Down Expand Up @@ -203,7 +210,7 @@ void my_wait(int signum)
wait(&status);
}

main()
int main()
{
server(8021);
return 0;
Expand Down
75 changes: 75 additions & 0 deletions server.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#ifndef SERVER_INCLUDE
#define SERVER_INCLUDE

#include "common.h"
/**
* Sets up server and handles incoming connections
* @param port Server port
*/
void server(int port);

/**
* Creates socket on specified port and starts listening to this socket
* @param port Listen on this port
* @return int File descriptor for new socket
*/
int create_socket(int port);

/**
* Accept connection from client
* @param socket Server listens this
* @return int File descriptor to accepted connection
*/
int accept_connection(int socket);

/**
* Get ip where client connected to
* @param sock Commander socket connection
* @param ip Result ip array (length must be 4 or greater)
* result IP array e.g. {127,0,0,1}
*/
void getip(int sock, int *ip);

/**
* Lookup enum value of string
* @param cmd Command string
* @return Enum index if command found otherwise -1
*/

int lookup_cmd(char *cmd);
/**
* General lookup for string arrays
* It is suitable for smaller arrays, for bigger ones trie is better
* data structure for instance.
* @param needle String to lookup
* @param haystack Strign array
* @param count Size of haystack
*/
int lookup(char *needle, const char **haystack, int count);


/**
* Writes current state to client
*/
void write_state(State *state);

/**
* Generate random port for passive mode
* @param state Client state
*/
void gen_port(Port *port);

/**
* Parses FTP command string into struct
* @param cmdstring Command string (from ftp client)
* @param cmd Command struct
*/
void parse_command(char *cmdstring, Command *cmd);

/**
* Handles zombies
* @param signum Signal number
*/
void my_wait(int signum);

#endif