⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myftpserver.c~

📁 简单ftp协议实现
💻 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 + -