www.pudn.com > src.rar > server.c
#include#include #include #include #include #include #include #include #define CRLF "\r\n" #define CALL_RETURN(a) if ( a == -1) return -1; #define SERVER_PORT 3441 int init_std_replies(); int ftp_startup(); int ftp_process(); int ftp_shutdown(); int ftp_user(char *username); int ftp_pass(char *password); int ftp_send(char *filename); int ftp_retr(char *filename); int ftp_list(); int ftp_cwd(char *path); int ftp_pwd(); int ftp_cdup(); int ftp_quit(); int ftp_port(); int ftp_pasv(); int ftp_type(); int _ftp_send_reply(char *command, int len); int ftp_send_reply(int reply_id); int ftp_recv_command(char *buffer, int len); int hallo(); enum { com_conn,com_user,com_pass,com_send,com_retr,com_list,com_cwd,com_pwd,com_quit,com_type,com_pasv,com_port }ftp_command; char *ftp_symbol[] = { "CONN","USER","PASS","STOR","RETR","LIST","CWD","PWD","QUIT","TYPE","PASV","PORT" }; const int ftp_command_count = 12; char command[1000], *command_param; #define REPLY_COUNT 1000 char *std_replies[REPLY_COUNT]; int std_replies_len[REPLY_COUNT]; int sock,ctl_sock,data_sock,pasv_sock; char peername[100]; char cwd[500]; typedef enum{ false,true }bool; bool running; bool loggedin; char port_addr[40]; int port_port; enum{ data_mode_pasv,data_mode_port } ftp_data_mode; int main(int argc,char *argv[]) { if( ftp_startup(argc,argv) == -1 ) exit(1); do { printf("[OPRATE]:Waiting for connection...\n"); ctl_sock = accept(sock,(struct sockaddr*)0,(int*)0); if (ctl_sock == -1) printf("[FAIL]:Accepting failed!!\n"); else { struct sockaddr_in addr; int length; length = sizeof(addr); if ( getpeername(ctl_sock,(struct sockaddr*)&addr,&length) == 0 ) { strcpy(peername,(char*)inet_ntoa(addr.sin_addr)); } printf("[SUCCEED]:Connection from %s accepted!!\n",peername); if( fork() == 0 ) { ftp_process(); exit(0); } } }while(true); ftp_shutdown(); exit(0); } int ftp_startup(int argc, char *argv[]) { int length,port; struct sockaddr_in server; char buf[1024]; init_std_replies(); getcwd(cwd,sizeof(cwd)); sock=socket(AF_INET,SOCK_STREAM,0); if (sock<0) { printf("[FAIL]:Opening stream socket failed!!\n"); return -1; } server.sin_family=AF_INET; if(argc>1) server.sin_addr.s_addr = inet_addr(argv[1]); else server.sin_addr.s_addr = INADDR_ANY; if(argc>2) sscanf(argv[2],"%d",&port); else port = SERVER_PORT; server.sin_port = htons(port); printf("[SUCCEED]:Startup ftp service on %s:%d!!\n",argv[1],port); if (bind(sock,(struct sockaddr *)&server,sizeof server)<0) { printf("[FAIL]:Binding stream socket failed!!\n"); return -1; } if ( listen(sock,5) < 0 ) { printf("[FAIL]:Listening to socket failed!!\n"); return -1; } return 0; } int ftp_shutdown() { close(sock); return 0; } int _ftp_send_reply(char *command,int len) { printf("%s <-- %s\n",peername,command); if (write(ctl_sock,command, len) == -1) { printf("[FAIL]:Sending ftp reply failed!!\n"); return -1; } if ( write(ctl_sock,CRLF,2) == -1 ) { printf("[FAIL]:sending ftp reply CRLF failed!!\n"); return -1; } return 0; } int ftp_send_reply(int reply_id) { char *command = std_replies[reply_id]; int len = std_replies_len[reply_id]; return _ftp_send_reply(command,len); } int ftp_recv_command(char *buffer, int len) { int i; for(i=0;i %s",peername,buffer); for(i=0;i h_addr, hp->h_length); printf("[OPERATE]:Establishing data connection to %s:%d...\n",port_addr,port_port); if (connect(data_sock,(struct sockaddr*)&server,sizeof server)<0) { printf("[FAIL]:Connecting data socket failed!!\n"); return -1; } printf("[SUCCEED]:Data connection established!!\n"); return 0; } case data_mode_pasv: { printf("[OPERATE]:Accepting data connection...\n"); data_sock = accept(pasv_sock,(struct sockaddr*)0,(int*)0); if(data_sock == -1) { printf("[FAIL]:Accepting data socket failed!!\n"); return -1; } return 0; } } } int ftp_close_data_transfer() { close(data_sock); data_sock = 0; } int ftp_retr(char *filename) { char buffer[512]; int len; FILE *file; file = fopen(filename,"r"); if( file == NULL ) { printf("open local file"); CALL_RETURN(ftp_send_reply(550)); return -1; } if( ftp_data_mode == data_mode_port ) { CALL_RETURN(ftp_send_reply(150)); } if( ftp_start_data_transfer() == 0 ) { if (ftp_data_mode == data_mode_pasv) { CALL_RETURN(ftp_send_reply(150)); } while( (len=fread(buffer,1,sizeof(buffer),file)) >0 ) { write(data_sock,buffer,len); } } else { printf("[FAIL]:Fail to start data transfer!!\n"); CALL_RETURN(ftp_send_reply(425)); return -1; } fclose(file); ftp_close_data_transfer(); CALL_RETURN(ftp_send_reply(226)); return 0; } int ftp_send(char *filename) { char buffer[512]; int len; FILE *file; file = fopen(filename,"w+"); if( file == NULL ) { printf("[FAIL]:Opening local file failed!!\n"); return -1; } if( ftp_data_mode == data_mode_port ) { CALL_RETURN(ftp_send_reply(150)); } if( ftp_start_data_transfer() == 0 ) { if (ftp_data_mode == data_mode_pasv) { CALL_RETURN(ftp_send_reply(150)); } while( (len=read(data_sock,buffer,sizeof(buffer))) >0 ) { fwrite(buffer,1,len,file); } } else { printf("[FAIL]:Fail to start data transfer!!\n"); CALL_RETURN(ftp_send_reply(425)); return -1; } fclose(file); ftp_close_data_transfer(); CALL_RETURN(ftp_send_reply(226)); return 0; } int ftp_list() { char cmd[200]; char buffer[512]; int len; if( ftp_data_mode == data_mode_port ) { CALL_RETURN(ftp_send_reply(150)); } if( ftp_start_data_transfer() == 0 ) { DIR *dp; struct dirent *ep; if (ftp_data_mode == data_mode_pasv) { CALL_RETURN(ftp_send_reply(150)); } dp = opendir (cwd); if (dp != NULL) { while (ep = readdir (dp)) { write(data_sock,ep->d_name,strlen(ep->d_name)); write(data_sock,CRLF,2); } closedir(dp); } else write(data_sock,"Couldn't open the directory.\r\n",30); } else { printf("[FAIL]:Fail to start data transfer!!\n"); CALL_RETURN(ftp_send_reply(425)); return -1; } CALL_RETURN(ftp_send_reply(226)); ftp_close_data_transfer(); return 0; } int ftp_cwd(char *path) { if ( chdir (path) == 0 ) { getcwd(cwd,sizeof(cwd)); CALL_RETURN(ftp_send_reply(250)); return 0; } else { CALL_RETURN(ftp_send_reply(550)); return -1; } } int ftp_pwd() { char cmd[500]; sprintf(cmd,"257 %s is current directory.",cwd); CALL_RETURN(_ftp_send_reply(cmd,strlen(cmd))); return 0; } int ftp_port() { int i,j,k,p1,p2; char cmd[200]; for(i=0,k=0;k<3&&command_param[i]!='\r';++i) if(command_param[i]==',') { ++k; command_param[i]='.'; } for(j=i+1;command_param[j]!='\r'&&command_param[j]!=',';++j); memcpy(port_addr,command_param+1,j-1); port_addr[j-1]='\0'; sscanf(command_param+j+1,"%d,%d",&p1,&p2); port_port=(long)p1*256+p2; printf("data connection at %s:%d\n",port_addr,port_port); CALL_RETURN(ftp_send_reply(200)); ftp_data_mode = data_mode_port; return 0; } int ftp_pasv() { int i,length,port; long ip; char cmd[200]; struct sockaddr_in server; pasv_sock=socket(AF_INET,SOCK_STREAM,0); if (pasv_sock<0) { printf("[FAIL]:Opening data socket failed!!\n"); return -1; } server.sin_family=AF_INET; server.sin_addr.s_addr=INADDR_ANY; server.sin_port=0; if (bind(pasv_sock,(struct sockaddr *)&server,sizeof(server))<0) { printf("[FAIL]:Binding stream socket failed!!\n"); return -1; } length=sizeof(server); if ( getsockname(pasv_sock,(struct sockaddr *)&server,&length)!=0 ) { printf("[FAIL]:Getting data socket port failed!!\n"); return -1; } port = ntohs(server.sin_port); if ( getsockname(ctl_sock,(struct sockaddr *)&server,&length)!=0 ) { printf("[FAIL]:Getting socket name failed!!\n"); return -1; } sprintf(cmd,"227 Entering Passive Mode (%s,%d,%d).",inet_ntoa(server.sin_addr),port/256,port%256); length = strlen(cmd); for(i=0;i