Advertisement
Guest User

Untitled

a guest
Aug 19th, 2017
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.96 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <arpa/inet.h>
  4. #include <unistd.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <sys/stat.h>
  8. #include <fcntl.h>
  9. #include <netdb.h>
  10. #include <syslog.h>
  11. #include <netinet/in.h>
  12. #include <signal.h>
  13. #include <strings.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <pthread.h>
  17. #include <regex.h>
  18.  
  19. #define MAX_BUFF 516
  20. #define DATA_SIZE 512
  21. #define CTRL 64
  22.  
  23. int is_daemon=0;
  24.  
  25. struct arguments {
  26.     unsigned short opcode;
  27.     char filename[CTRL];
  28.     char mode[CTRL];
  29.     struct sockaddr_in sender;
  30. };
  31.  
  32. struct ackpacket {
  33.     unsigned short opcode;
  34.     unsigned short blockno;
  35. };
  36.  
  37. struct datapacket {
  38.     unsigned short opcode;
  39.     unsigned short blockno;
  40.     char data[DATA_SIZE];
  41. };
  42.  
  43. struct errorpacket {
  44.     unsigned short opcode;
  45.     unsigned short errcode;
  46.     char errtext[CTRL];
  47. };
  48.  
  49. void *con_accept(void *senderargs);
  50. uint16_t getopcode(const char *addr);
  51. void usage(void);
  52.  
  53. int main(int argc, char *argv[]) {
  54.     int socketfd, connectfd, port_no, c_arg, cli_len, c_msg, i;
  55.     char buffer[MAX_BUFF];
  56.     struct sockaddr_in server_ad;
  57.     struct sockaddr_in client_ad;
  58.     struct arguments *senderargs;
  59.     struct servent *myserv;
  60.     FILE *infile;
  61.     pthread_t tid;
  62.     regex_t portre;
  63.        
  64.     regcomp(&portre, "^[0-9]+$", REG_EXTENDED);
  65.    
  66.     opterr=0;
  67.  
  68.     fflush (stderr);
  69.     while ((c_arg= getopt(argc, argv, "d")) != -1) {
  70.         switch (c_arg)
  71.         {
  72.             case 'd':
  73.                 is_daemon=1;
  74.                 break;
  75.             case '?':
  76.                 if (isprint(optopt)) {
  77.                     fprintf(stderr, "Nepoznata opcija -%c\n", optopt);
  78.                     usage();
  79.                     return -1;
  80.                 }
  81.                 else {
  82.                     fprintf(stderr, "Nepoznata opcija\n");
  83.                     usage();
  84.                     return -1;
  85.                 }
  86.             return -1;
  87.         }
  88.     }
  89.     if(!argv[optind]) {
  90.         usage();
  91.         return -1;
  92.     }
  93.    
  94.     if(!regexec (&portre, argv[optind], 0, NULL, 0)) {
  95.         port_no = strtol(argv[optind], NULL, 10);
  96.     }
  97.     else {
  98.         myserv = getservbyname(argv[optind], NULL);
  99.         port_no = ntohs(myserv->s_port);
  100.     }
  101.        
  102.    
  103.     if(is_daemon)
  104.         daemon(0,0);
  105.  
  106.     chdir("/tftpboot/");
  107.     signal(SIGCHLD, SIG_IGN);
  108.     if((socketfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
  109.         perror("Error creating socket");
  110.         return 2;
  111.     }
  112.     cli_len = sizeof(struct sockaddr_in);
  113.     memset(&server_ad, 0, cli_len);
  114.     server_ad.sin_family=AF_INET;
  115.     server_ad.sin_addr.s_addr=INADDR_ANY;
  116.     server_ad.sin_port=htons(port_no);
  117.     if (bind(socketfd, (struct sockaddr *) &server_ad, cli_len) < 0)
  118.             perror("Error binding to socket");
  119.  
  120.     while (1) {
  121.         memset(buffer,0,MAX_BUFF);
  122.        
  123.         senderargs = malloc(sizeof(struct arguments));
  124.        
  125.         if((c_msg=recvfrom(socketfd, buffer, MAX_BUFF, 0, (struct sockaddr *) &server_ad, &cli_len)) < 0) {
  126.             perror("Error recieving message");
  127.             return -2;
  128.         }
  129.     senderargs->opcode = getopcode(buffer);
  130.    
  131.     //senderargs->sender = malloc(sizeof (struct sockaddr_in));
  132.     memcpy (&senderargs->sender, &server_ad, sizeof(struct sockaddr_in));
  133.     strncpy ( senderargs->filename, (buffer+2), CTRL);
  134.     strncpy( senderargs->mode, buffer+strlen(buffer+2)+3, CTRL);
  135.        
  136.     pthread_create(&tid, NULL, con_accept, (void *) senderargs);
  137.     }
  138.     return 0;
  139. }
  140.    
  141.  
  142. uint16_t getopcode(const char *addr) {
  143.     return ntohs(*((uint16_t *) addr));
  144. }
  145.  
  146. void usage(void) {
  147.     fprintf(stderr, "Usage: tftpserver [-d] port_name_or_number");
  148. }
  149.  
  150.  
  151. void *con_accept(void *senderargs) {
  152.     int i=0, socksend, sent, overflow=0, check=0;
  153.     int c_msg, s_rez, c_len=sizeof(struct sockaddr_in);
  154.     unsigned int blkcnt=1;
  155.     char buffer[MAX_BUFF]={0};
  156.     struct arguments argssender = *((struct arguments *) senderargs);
  157.     struct ackpacket myack;
  158.     struct datapacket mydata;
  159.     struct errorpacket myerror;
  160.     struct sockaddr_in client_ad;
  161.     struct timeval mytime;
  162.     fd_set myset;
  163.     FILE *input;
  164.     regex_t re1, re2;
  165.    
  166.     openlog("MrePro tftpserver", LOG_PID, LOG_FTP);
  167.      
  168.     regcomp(&re1, "^/tftpboot/[^/]+$", REG_EXTENDED);
  169.     regcomp(&re2, "^[^/]+$", REG_EXTENDED);
  170.  
  171.    
  172.     mytime.tv_sec = 3;
  173.     mytime.tv_usec = 0;
  174.    
  175.     if(is_daemon)
  176.             syslog(LOG_INFO, "%s->%s", inet_ntoa(argssender.sender.sin_addr), argssender.filename);
  177.         else
  178.             fprintf(stderr, "%s->%s", inet_ntoa(argssender.sender.sin_addr), argssender.filename);
  179.    
  180.     if((socksend = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
  181.         perror("Error creating socket");
  182.         free(senderargs);
  183.         return;
  184.     }
  185.    
  186.     if(regexec (&re1, argssender.filename, 0, NULL, 0) && regexec (&re2, argssender.filename, 0, NULL, 0)) {
  187.         if(is_daemon)
  188.             syslog(LOG_INFO, "TFTP ERROR 2 nm44814");
  189.         else
  190.             fprintf(stderr, "TFTP ERROR 2 nm44814\n");
  191.         myerror.opcode = htons((uint16_t) 5);
  192.         myerror.errcode = htons((uint16_t) 2);
  193.         strncpy(myerror.errtext, "TFTP ERROR 2 nm44814", CTRL);
  194.         c_msg=sendto(socksend, &myerror, sizeof(myerror), 0, (const struct sockaddr *) &(argssender.sender), c_len);
  195.         free(senderargs);
  196.         close(socksend);
  197.         return;
  198.     }
  199.    
  200.    
  201.     if((input=fopen(argssender.filename, "rb"))==NULL) {
  202.         if(is_daemon)
  203.             syslog(LOG_INFO, "TFTP ERROR 1 nm44814");
  204.         else
  205.             fprintf(stderr, "TFTP ERROR 1 nm44814\n");
  206.         myerror.opcode = htons((uint16_t) 5);
  207.         myerror.errcode = htons((uint16_t) 1);
  208.         strncpy(myerror.errtext, "TFTP ERROR 1 nm44814", CTRL);
  209.         c_msg=sendto(socksend, &myerror, sizeof(myerror), 0, (const struct sockaddr *) &(argssender.sender), c_len);
  210.         free(senderargs);
  211.         close(socksend);
  212.         return;
  213.     }
  214.  
  215.     while(!feof(input)) {
  216.         memset(mydata.data, 0, DATA_SIZE);
  217.         mydata.opcode = htons((uint16_t) 3);
  218.         mydata.blockno = htons ((uint16_t) blkcnt);
  219.         printf ("%s %s %d\n", argssender.filename, argssender.mode, blkcnt);
  220.         fflush(stdout);
  221.         if(!strcasecmp("octet", argssender.mode)) {
  222.             sent = fread(mydata.data, 1, DATA_SIZE, input);
  223.         }
  224.         else if (!strcasecmp("netascii", argssender.mode)) {
  225.             for(sent=0; sent<DATA_SIZE; sent++) {
  226.                 if(overflow) {
  227.                     mydata.data[sent++]='\n';
  228.                     overflow=0;
  229.                 }
  230.                 if(fread(&mydata.data[sent],1,1,input)!=1) {
  231.                         break;
  232.                 }
  233.                 if(mydata.data[sent]=='\n') {
  234.                     mydata.data[sent++]='\r';
  235.                     if(sent < DATA_SIZE) {
  236.                         mydata.data[sent]='\n';
  237.                     }
  238.                     else {
  239.                         overflow=1;
  240.                     }
  241.                 }
  242.             }
  243.         }
  244.        
  245.         check=0;
  246.         for(i=0; i<4; i++) {
  247.             FD_ZERO(&myset);
  248.             FD_SET(socksend, &myset);
  249.             c_msg=sendto(socksend, &mydata, sent+2*sizeof(unsigned short), 0, (const struct sockaddr *) &(argssender.sender), c_len);
  250.             s_rez=select(socksend+1, &myset, NULL, NULL, &mytime);
  251.             if(!s_rez) {
  252.                 //printf("Propustio %d\n", i+1);
  253.                 //fflush(stdout);
  254.                 continue;
  255.             }
  256.             else if(s_rez > 0) {
  257.                 if(FD_ISSET(socksend, &myset)) {
  258.                     c_msg = recvfrom(socksend, &myack, sizeof(myack), 0, ( struct sockaddr *) &client_ad, &c_len);
  259.                     if(ntohs(myack.opcode) == 4 && ntohs(myack.blockno) == blkcnt) {
  260.                         printf("Got ACK with block count = %d\n", ntohs(myack.blockno));
  261.                         fflush(stdout);
  262.                         break;
  263.                     }
  264.                     else if(ntohs(myack.opcode) == 4 && (ntohs(myack.blockno) == blkcnt-1) && check==0) {
  265.                         i--;
  266.                         check=1;
  267.                         continue;
  268.                     }
  269.                 }
  270.             }
  271.             else if (s_rez < 0){
  272.                 return;    
  273.             }
  274.             }
  275.             if(i==4) {
  276.                 close(socksend);
  277.                 free(senderargs);
  278.                 return;
  279.             }
  280.             blkcnt++;
  281.     }
  282. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement