📄 myftpserver.c~
字号:
#include "common.h"#define LOCAL_IP "192.168.0.74"char valid_user[]="fancy9";char valid_pass[]="fancy9";int current_data_port;int lsock;int asock;int dlsock;int dtsock;struct sockaddr_in serveraddr;struct sockaddr_in client;struct sockaddr_in serverdl;struct sockaddr_in serverdt;struct server_state{ short client_port; unsigned long client_ip; char current_dir[2048]; char path_prefix[2048]; char user[256]; char pass[256]; char type[2]; int isPassive; char mode[256];}ss;void init_server_state(){ // printf("[Fancy ftpd]Connected to %s:%d\n", inet_ntoa(client.sin_addr.s_addr),ntohs(client.sin_port)); reply(R220, NULL , asock); ss.client_port = client.sin_port; ss.client_ip = client.sin_addr.s_addr; strcpy(ss.current_dir, "/"); strcpy(ss.path_prefix, "."); ss.isPassive = 0; strcpy(ss.mode, "ASCII");}int begin_listen(){ int sock,length; sock=socket(AF_INET,SOCK_STREAM,0); check_error (sock,"opening stream socket"); serveraddr.sin_family=AF_INET; serveraddr.sin_addr.s_addr=htonl(INADDR_ANY); serveraddr.sin_port=htons(LISTEN_PORT); int opt = 1; check_error (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)), "setsockopt"); check_error (bind(sock,(struct sockaddr *)&serveraddr,sizeof( serveraddr)), "binding stream socket"); length=sizeof(serveraddr); check_error(getsockname(sock,(struct sockaddr *)&serveraddr,&length) ,"getting socket name"); printf("Socket port # %d\n",ntohs(serveraddr.sin_port)); listen(sock,5); return sock;}void get_port(char *arg){ int a[6]; sscanf(arg, "%d,%d,%d,%d,%d,%d", a, a+1, a+2, a+3, a+4, a+5); ss.isPassive = 0; ss.client_port = (short)((a[4])+(a[5]<<8)); ss.client_ip = (unsigned long)((a[0])+(a[1]<<8)+(a[2]<<16)+(a[3]<<24)); printf("[Fancy ftpd]Server data translation address is %s:%d\n", inet_ntoa(ss.client_ip), ntohs(ss.client_port));}void connect_to_client(char * arg){ // char buff1[TELNET_LENGTH]; char buff2[TELNET_LENGTH]; char *p1, *p2; // p1 = strchr(buff1,'('); //p2 = strrchr(buff1, ')'); //strncpy(buff2, p1+1, p2-p1+1); get_port(arg); int h; dtsock = socket(AF_INET, SOCK_STREAM, 0); check_error(dtsock, "socket of transfer"); serverdt.sin_family = AF_INET; serverdt.sin_port = ss.client_port; serverdt.sin_addr.s_addr = ss.client_ip; h = connect(dtsock, (struct sockaddr*)&serverdt, sizeof(serverdt)); check_error(h, "connect data address"); printf("[Fancy ftpd]Establish data connect to %s:%d\n", inet_ntoa(serverdt.sin_addr.s_addr), ntohs(serverdt.sin_port));}int parse_command(char *cmd){ int len = strlen(cmd); int end; end = 0; while (end<len && cmd[end]!=' ' && cmd[end]!='\r') { cmd[end] = toupper(cmd[end]); end++; } if(end == 0) return 0; else if (strncmp(cmd,"PASV",end)==0) return 1; else if (strncmp(cmd, "CWD", end)==0) return 2; else if (strncmp(cmd, "QUIT", end)==0) return 3; else if (strncmp(cmd, "TYPE", end)==0) return 4; else if (strncmp(cmd, "RETR", end)==0) return 5; else if (strncmp(cmd, "STOR", end)==0) return 6; else if (strncmp(cmd, "NOOP", end)==0) return 7; else if (strncmp(cmd, "HELP", end)==0) return 8; else if (strncmp(cmd, "PORT", end)==0) return 9; else if (strncmp(cmd, "PWD", end)==0) return 10; else if (strncmp(cmd, "LIST", end)==0 || strncmp(cmd, "NLST", end)==0) return 11; else if (strncmp(cmd, "USER", end)==0) return 12; else if (strncmp(cmd, "PASS", end)==0) return 13; else if (strncmp(cmd, "SYST", end)==0) return 14; else if (strncmp(cmd, "CDUP", end)==0) return 15; else return 0;}void * accept_data_connection(void * arg){ int addrlen = sizeof(serverdt); // struct sockaddr_in temp; dtsock = accept(dlsock, (struct sockaddr *) &serverdt, &addrlen); check_error(dtsock, "accept");}void handle_passive_mode(){ int h; dlsock = socket(AF_INET, SOCK_STREAM, 0); int opt = 1; h = setsockopt(dlsock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)); check_error(h, "setsockopt of data listen socket"); //serverdl.sin_family = AF_INET; //serverdl.sin_addr.s_addr = htonl(INADDR_ANY); //serverdl.sin_port = htons(current_data_port++); int addrlen = sizeof(serverdl); h = getsockname(dlsock, (struct sockaddr*)&serverdl, &addrlen); check_error(h ,"getsockname"); serverdl.sin_family = AF_INET; inet_aton(LOCAL_IP, &(serverdl.sin_addr)); // serverdl.sin_addr.s_addr = htonl(INADDR_ANY); do { serverdl.sin_port = htons(current_data_port++); } while (bind(dlsock, (struct sockaddr*)&serverdl, sizeof(serverdl))<0); h = listen(dlsock,10); check_error(h, "listen"); pthread_t accept_thread; pthread_create(&accept_thread, NULL, accept_data_connection, NULL); char rpl_buff[TELNET_LENGTH]; unsigned long dl_ip = serverdl.sin_addr.s_addr; unsigned short dl_port = serverdl.sin_port; sprintf(rpl_buff, "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)", (dl_ip&0xFF), (dl_ip&0x0000FF00)>>8, (dl_ip&0x00FF0000)>>16, dl_ip>>24, dl_port&0xFF,dl_port>>8); reply(R227, rpl_buff, asock); printf("[Fancy ftpd]%s\n", rpl_buff); ss.isPassive = 1; h = pthread_join(accept_thread, NULL); check_error(h, "pthread_join"); printf("[Fancy]Establish data transfer connection from %s:%d\n", inet_ntoa(serverdt.sin_addr.s_addr), ntohs(serverdt.sin_port));}void * list_dir(void *arg){ //if (!ss.isPassive) //establish_data_connection(); reply(R150, NULL, asock); char pathname[2048]; strcpy(pathname, ss.path_prefix); strcat(pathname, ss.current_dir); strcat(pathname, (char*)arg); if (pathname[strlen(pathname)-1]!='/') strcat(pathname, "/"); char line_buff[TELNET_LENGTH]; printf("[Fancy ftpd]Scan dir %s\n", pathname); struct dirent **eps; int n; n = scandir (pathname, &eps, one, alphasort); if (n >= 0) { int cnt; struct stat s; char pkg_buff[TELNET_LENGTH*10] = {'\0'}; for (cnt = 0; cnt < n; ++cnt) { strcpy(line_buff, pathname); strcat(line_buff, eps[cnt]->d_name); stat(line_buff, &s); char pbuff[32]; if (!S_ISREG(s.st_mode) && !S_ISDIR(s.st_mode)) continue; permission(s.st_mode, pbuff); struct passwd *uinfo; struct group *ginfo; uinfo = getpwuid(s.st_uid); ginfo = getgrgid(s.st_gid); char tbuff[256]; struct tm* t; t = localtime(&s.st_mtime); strftime(tbuff, 1024, "%b %d %k:%M", t); sprintf(line_buff, "%s%3d %s %s %12d %s %s\r\n", pbuff, s.st_nlink, uinfo->pw_name, ginfo->gr_name, s.st_size, tbuff, eps[cnt]->d_name); printf("%s", line_buff); strcat(pkg_buff, line_buff); } send_data(pkg_buff, strlen(pkg_buff), dtsock); } else perror ("Couldn't open the directory"); close(dtsock); ss.isPassive = 0; reply(226, "226 Transfer complete.", asock); free(arg); }void * retr_file(void *arg){ char rpl_buff[TELNET_LENGTH]; // if (!ss.isPassive) //establish_data_connection(); char pathname[2048]; strcpy(pathname, ss.path_prefix); if (((char*)arg)[0]=='/') strcat(pathname, (char*)arg); else { strcat(pathname, ss.current_dir); if (pathname[strlen(pathname)-1]!='/') strcat(pathname,"/"); strcat(pathname, (char*)arg); } printf("[Fancy ftpd]Retrive file %s\n", pathname); struct stat finfo; if (stat(pathname, &finfo)>=0) { sprintf(rpl_buff, "150 Opening BINARY mode data connection for %s(%d Bytes).", strchr(pathname,'/')+1, finfo.st_size); puts(rpl_buff); reply(R150, rpl_buff, asock); } else perror("File not fount.\n"); FILE *fl; fl = fopen(pathname, "r"); send_file(fl, dtsock); fclose(fl); free(arg); close(dtsock); reply(226, "226 Transfer complete.", asock);}void * stor_file(void *arg){ char rpl_buff[TELNET_LENGTH]; // if (!ss.isPassive) // establish_data_connection(); char pathname[2048]; strcpy(pathname, ss.path_prefix); if (((char*)arg)[0]=='/') strcat(pathname, (char*)arg); else { strcat(pathname, ss.current_dir); if (pathname[strlen(pathname)-1]!='/') strcat(pathname,"/"); strcat(pathname, (char*)arg); } printf("[Fancy ftpd]Store file %s\n", pathname); sprintf(rpl_buff, "150 Opening BINARY mode data connection for %s.",strchr(pathname,'/')+1); reply(R150, rpl_buff, asock); FILE *fl; fl = fopen(pathname, "w"); receive_file(fl, dtsock); fclose(fl); free(arg); close(dtsock); reply(226, "226 Transfer complete.", asock);}int check_account(){ printf("check account, user[%s], pass[%s]\n", ss.user, ss.pass); if (strcmp(ss.user,valid_user)==0 && strcmp(ss.pass, valid_pass)==0) return 1; else return 0;}void server_pi(){ init_server_state(); char cmd_buff[TELNET_LENGTH]; char rpl_buff[TELNET_LENGTH]; char param_buff[TELNET_LENGTH]; char * param; pthread_t trans_thread; while(1) { int len = receive_command(cmd_buff, TELNET_LENGTH, asock); cmd_buff[len - 2] = '\0'; int cmd_id = parse_command(cmd_buff); printf("[Fancy ftpd]Receive command <%s>(%d)\n", cmd_buff, cmd_id); switch(cmd_id) { case 0: reply(R500,NULL,asock); break;//Syntax error case 1: handle_passive_mode(); break;//PASV case 2: parse_parameters(cmd_buff, 1 ,param_buff); if(param_buff[0] == '/') strcpy(ss.current_dir, param_buff); else if((strcmp(param_buff,".")!=0)) strcat(ss.current_dir,param_buff); sprintf(rpl_buff,"250 Directory changed to %s", ss.current_dir); reply(R250, rpl_buff,asock); break;//CWD case 3: reply(R221, NULL, asock); break;//QUIT case 4: parse_parameters(cmd_buff, 1 ,ss.type); sprintf(rpl_buff, "200 Type set to %c.", ss.type[0]); reply(R200, rpl_buff, asock); break;//TYPE case 5: param = (char *)malloc(TELNET_LENGTH); parse_parameters(cmd_buff, 1 ,param); pthread_create(& trans_thread, NULL, retr_file, (void *)param); break;//RETR case 6: param = (char *)malloc(TELNET_LENGTH); parse_parameters(cmd_buff, 1 ,param); pthread_create(& trans_thread, NULL, stor_file, (void *)param); break;//STOR case 7: reply(R200, NULL, asock); break;//NOOP case 8: sprintf(rpl_buff, "214-The following commands are recognized\r\n USER PASS RETR STOR PORT PASV\r\n CWD CDUP PWD LIST TYPE STAT\r\n NOOP QUIT\r\n214 fancy@net9.org" //"214\r\n-blabla\r\nblablabla\r\n214 blabla\r\n"); reply(R214, rpl_buff, asock); break;//HELP case 9: parse_parameters(cmd_buff, 1 ,param_buff); connect_to_client(param_buff); reply(R200,"200 PORT Command Successful.",asock); //reply(R502, NULL, asock); break;//PORT case 10: sprintf(rpl_buff,"250 \"%s\" is current directory.", ss.current_dir); reply(R250, rpl_buff, asock); break;//PWD case 11: param = (char *)malloc(TELNET_LENGTH); parse_parameters(cmd_buff, 1 ,param); pthread_create(& trans_thread, NULL, list_dir, (void *)param); break;//LIST case 12: parse_parameters(cmd_buff, 1 , ss.user); reply(R331,NULL, asock); break;//USER case 13: parse_parameters(cmd_buff, 1 , ss.pass); if(check_account()) reply(R230,NULL,asock); else reply(R530,NULL,asock); break;//PASS case 14: reply(R215,NULL,asock); break;//SYST case 15: param = strrchr(ss.current_dir,'/'); *(param+1) = '\0'; sprintf(rpl_buff, "250 Directory changed to %s", ss.current_dir); reply(R250, rpl_buff,asock); break;//CDUP } if(cmd_id == 3) break; } close(asock);}int main(){ lsock = begin_listen(); current_data_port = LISTEN_PORT + 1; while(1) { current_data_port += 2; int client_len ; // struct sockaddr_in client; asock = accept(lsock,(struct sockaddr*) &client,&client_len); printf("[Fancy ftpd]Connected to %s:%d\n", inet_ntoa(client.sin_addr.s_addr),ntohs(client.sin_port)); if( fork() == 0 ) { close(lsock); server_pi(); return 0; } else close( asock ); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -