home *** CD-ROM | disk | FTP | other *** search
/ ftp.urbanrage.com / 2015-02-07.ftp.urbanrage.com.tar / ftp.urbanrage.com / pub / tftp.c < prev    next >
C/C++ Source or Header  |  2007-02-15  |  11KB  |  345 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4.  
  5. #include <sys/types.h>
  6. #include <sys/mman.h>
  7. #include <sys/un.h>
  8. #include <netinet/in.h>
  9. #include <netinet/udp.h>
  10. #include <fcntl.h>
  11. #include <string.h>
  12. #include <errno.h>
  13. #include <poll.h>
  14. #include <time.h>
  15.  
  16. #include "tftp.h"
  17.  
  18. #define MAX_ACTIVE 100
  19.  
  20. int setup_udp_listener(void) {
  21.    int                sfd;
  22.    int                option_on = 1;
  23.    int                error;
  24.    int                slen;
  25.    struct sockaddr_in saddr;
  26.  
  27.    sfd = socket(PF_INET, SOCK_DGRAM, 0);
  28.    if (sfd < 0) {
  29.       perror("Couldn't open a socket");
  30.       exit(0);
  31.    }
  32.    
  33.    setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char *)&option_on,
  34.               sizeof(option_on));
  35.  
  36.    /* set up sock_addr structure */
  37.    memset(&saddr, 0, sizeof(saddr));
  38.    saddr.sin_family = AF_INET;
  39.    saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
  40.    saddr.sin_port = htons(6943);
  41.  
  42.    error = bind(sfd, (struct sockaddr*)&saddr, sizeof(saddr));
  43.    if (error < 0) {
  44.       perror("couldn't bind socket to address");
  45.       close(sfd);
  46.       exit(0);
  47.    }
  48.    
  49.    return sfd;
  50. }
  51.  
  52. int find_free(active_t* active) {
  53.   int i;
  54.  
  55.   for (i=0; i < MAX_ACTIVE; i++) {
  56.     if (active[i].fd == 0) {
  57.       return i;
  58.     }
  59.   }
  60.   return -1;
  61. }
  62.  
  63. int find_active(active_t* active, struct sockaddr_in from) {
  64.   int i;
  65.  
  66.   for (i=0; i < MAX_ACTIVE; i++) {
  67.     if ((active[i].ip == from.sin_addr.s_addr) &&
  68.         (active[i].port == from.sin_port)) {
  69.       return i;
  70.     }
  71.   }
  72.   return -1;
  73. }
  74.  
  75. int write_block(int sfd, active_t* aptr, tftp_t* tptr, int size, 
  76.                 struct sockaddr_in from) {
  77.   int       n;
  78.   off_t     fpos;
  79.   socklen_t flen;
  80.  
  81.   size -= 4;
  82.   if (size < 1) {
  83.     return -1;
  84.   }
  85.   memset(&aptr->last.ack, 0, sizeof(tf_ack_t));
  86.   fpos = lseek(aptr->fd, tptr->data.block*512, SEEK_SET);
  87.   if (fpos == -1) {
  88.     return 1;
  89.   }
  90.   n = write(aptr->fd, tptr->data.data, size);
  91.   if (n <= 0) {
  92.     return -1;
  93.   }
  94.   aptr->last.ack.op = ACK;
  95.   aptr->last.ack.block = tptr->data.block;
  96.   
  97.   flen = sizeof(from);
  98.   sendto(sfd, &aptr->last.ack, sizeof(tf_ack_t), 0, (struct sockaddr*)&from, flen);
  99.   aptr->drop = time(0)+5;
  100.   aptr->retransmit = aptr->drop - 3;
  101.   aptr->last.size = sizeof(tf_ack_t);
  102.   return 0;
  103. }
  104.  
  105. int send_block(int sfd, active_t* aptr, struct sockaddr_in from) {
  106.   int       n;
  107.   off_t     fpos;
  108.   socklen_t flen;
  109.  
  110.   memset(&aptr->last.data, 0, sizeof(tf_data_t));
  111.   fpos = lseek(aptr->fd, aptr->block*512, SEEK_SET);
  112.   if (fpos == -1) {
  113.     return 1;
  114.   }
  115.   aptr->last.data.op = DATA;
  116.   aptr->last.data.block = (unsigned short)(aptr->block & 0xffff);
  117.   n = read(aptr->fd, aptr->last.data.data, 512);
  118.   if (n <= 0) {
  119.     return 1;
  120.   }
  121.   flen = sizeof(from);
  122.   sendto(sfd, &aptr->last.data, n+4, 0, (struct sockaddr*)&from, flen);
  123.   aptr->drop = time(0)+5;
  124.   aptr->retransmit = aptr->drop - 3;
  125.   aptr->last.size = n+4;
  126.   return 0;
  127. }
  128.  
  129. void send_error(int sfd, unsigned short error, char* errmsg, struct sockaddr_in from) {
  130.   tf_err_t  err;
  131.   socklen_t flen;
  132.  
  133.   memset(&err, 0, sizeof(err));
  134.   err.op = ERR;
  135.   err.error = error;
  136.   if (errmsg != NULL) {
  137.     snprintf(err.errmsg, sizeof(err.errmsg), "%s", errmsg);
  138.   }
  139.   flen = sizeof(from);
  140.   sendto(sfd, &err, 4+strlen(err.errmsg), 0, (struct sockaddr*)&from, flen);
  141. }
  142.  
  143. char* inet_ntoa_r(in_addr_t ip, char* buffer) {
  144.   char*         ptr = (char*)&ip;
  145.   unsigned char a = ptr[0];
  146.   unsigned char b = ptr[1];
  147.   unsigned char c = ptr[2];
  148.   unsigned char d = ptr[3];
  149.  
  150.   if (buffer != NULL) {
  151.     memset(buffer, 0, 16);
  152.     snprintf(buffer, 16, "%d.%d.%d.%d", a, b, c, d);
  153.   }
  154.   return buffer;
  155. }
  156.  
  157. void client_request(int sfd, active_t* active, int* active_count) {
  158.    int                tfd;
  159.    int                err;
  160.    int                n;
  161.    int                flags;
  162.    ssize_t            size;
  163.    char               buffer[8192];
  164.    char               filename[4096];
  165.    char               ip[16];
  166.    struct sockaddr_in from;
  167.    socklen_t          flen;
  168.    tftp_t*            tptr;
  169.    tf_ack_t           ack;
  170.  
  171.    memset(&from, 0, sizeof(from));
  172.    flen = sizeof(from);
  173.    size = recvfrom(sfd, buffer, sizeof(buffer)-1, 0, (struct sockaddr*)&from, &flen);
  174.    if (size > 0) {
  175.      buffer[size] = 0;
  176.      tptr = (tftp_t*)&buffer[0];
  177.      switch (tptr->op) {
  178.      case WRQ : flags = O_WRONLY | O_TRUNC; /* no CREAT so mode ignored */
  179.      case RRQ : {
  180.        if (*active_count < MAX_ACTIVE) { /* a new request can be serviced */
  181.          n = find_free(active);
  182.          if (n >= 0) { /* open slot */
  183.            snprintf(filename, sizeof(filename), "/tmp/%s",
  184.                     tptr->req.buffer);
  185.            if (tptr->op == RRQ) {
  186.              flags = O_RDONLY;
  187.            }
  188.            tfd = open(filename, flags);
  189.            if (tfd >= 0) {
  190.              active[n].ip = from.sin_addr.s_addr;
  191.              active[n].port = from.sin_port;
  192.              active[n].fd = tfd;
  193.              active[n].block = 0;
  194.              active[n].retransmit = 0;
  195.              active[n].drop = time(0) + 5; /* give the client some initial time */
  196.              /* here we'd return the OACK instead of the first block or ack
  197.                 if we handle tftp option extensions */
  198.              if (tptr->op == RRQ) {
  199.                err = send_block(sfd, &active[n], from);
  200.                if (err != 0) {
  201.                  close(tfd);
  202.                  memset(&active[n], 0, sizeof(active_t));
  203.                } else {
  204.                  fprintf(stderr, "started transfer of %s to [%s:%d]\n",
  205.                          filename, inet_ntoa_r(from.sin_addr.s_addr, ip), from.sin_port);
  206.                  *active_count++;
  207.                }
  208.              } else {
  209.                fprintf(stderr, "started transfer of %s from [%s:%d]\n",
  210.                        filename, inet_ntoa_r(from.sin_addr.s_addr, ip), from.sin_port);
  211.                *active_count++;
  212.                memset(&active[n].last.ack, 0, sizeof(ack));
  213.                active[n].last.ack.op = ACK;
  214.                active[n].last.ack.block = 0;
  215.                flen = sizeof(from);
  216.                sendto(sfd, &active[n].last.ack, sizeof(tf_ack_t), 0, 
  217.                       (struct sockaddr*)&from, flen);
  218.                active[n].retransmit = time(0) + 2;
  219.                active[n].last.size = sizeof(tf_ack_t);
  220.              }
  221.            } else {
  222.              err = errno; /* preserve err */
  223.              snprintf(buffer, sizeof(buffer), "Couldn't open file %s",
  224.                       filename);
  225.              perror(buffer);
  226.              if (err == ENOENT) {
  227.                send_error(sfd, 1, "file not found", from);
  228.              } else {
  229.                send_error(sfd, 2, "permission denied", from); break;
  230.              }
  231.            }
  232.          }
  233.        } else {
  234.          fprintf(stderr, "handling as many clients as I can\n");
  235.          send_error(sfd, 3, "too many clients", from);
  236.          /* send error #3 */
  237.        }
  238.      } break;
  239.      case DATA : {
  240.        n = find_active(active, from);
  241.        if (n >= 0) {
  242.          err = write_block(sfd, active, tptr, size, from);
  243.          if (err < 0) {
  244.            send_error(sfd, 0, "write error", from);
  245.          }
  246.          if (err < 512) { /* small packet or error, write finished */
  247.            *active_count--;
  248.            close(active[n].fd);
  249.            memset(&active[n], 0, sizeof(active_t));
  250.            fprintf(stderr, "finished transfer from client [%s:%d]\n",
  251.                    inet_ntoa_r(from.sin_addr.s_addr, ip), from.sin_port);
  252.          }
  253.        } else { /* got a retransmit on something we already closed */
  254.          send_error(sfd, 5, "unknown transfer id", from);
  255.        }
  256.      }; break;
  257.      case ACK : {
  258.        n = find_active(active, from);
  259.        if (n >= 0) {
  260.          active[n].block++;
  261.          if (active[n].block == 0) {
  262.            fprintf(stderr, "block wrap around, do what?\n");
  263.            /* send error */
  264.          } else {
  265.            err = send_block(sfd, &active[n], from);
  266.            if (err != 0) { /* done with client */
  267.              *active_count--;
  268.              close(active[n].fd);
  269.              memset(&active[n], 0, sizeof(active_t));
  270.              fprintf(stderr, "finished transfer to client [%s:%d]\n",
  271.                      inet_ntoa_r(from.sin_addr.s_addr, ip), from.sin_port);
  272.            }
  273.          }
  274.        } else {
  275.          fprintf(stderr, "Got an ack but no active connection [%s:%d]\n",
  276.                  inet_ntoa_r(from.sin_addr.s_addr, ip), from.sin_port);
  277.          send_error(sfd, 5, "unknown transfer id", from);
  278.        }
  279.      }; break;
  280.      
  281.      default : {
  282.        fprintf(stderr, "received error or unknown packet from [%s:%d]\n",
  283.                inet_ntoa_r(from.sin_addr.s_addr, ip), from.sin_port);
  284.        n = find_active(active, from);
  285.        if (n >= 0) {
  286.          *active_count--;
  287.          close(active[n].fd);
  288.          memset(&active[n], 0, sizeof (active_t));
  289.        }
  290.      }; break;
  291.      };
  292.    }
  293. }
  294.  
  295. int main (int argc, char* argv[]) {
  296.    int                sfd;
  297.    int                n;
  298.    int                active_count = 0;
  299.    active_t           active[MAX_ACTIVE];
  300.    struct pollfd      fds[1];
  301.    struct sockaddr_in from;
  302.    time_t             tdrop;
  303.    char               ip[16];
  304.  
  305.    sfd = setup_udp_listener();
  306.    
  307.    memset(active, 0, sizeof(active));
  308.    memset(fds, 0, sizeof(fds));
  309.    fds[0].fd = sfd;
  310.    fds[0].events = POLLIN;
  311.    while(1) {
  312.      n = poll(fds, 1, 1);
  313.      if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN)) {
  314.        client_request(sfd, active, &active_count);
  315.      }
  316.      tdrop = time(0);
  317.      for (n=0; n < MAX_ACTIVE; n++) {
  318.        if ((active[n].fd != 0) && (active[n].drop < tdrop)) {
  319.          memset(&from, 0, sizeof(from));
  320.          from.sin_family = AF_INET;
  321.          from.sin_addr.s_addr = active[n].ip;
  322.          from.sin_port = active[n].port;
  323.          send_error(sfd, 0, "transaction timed out", from);
  324.          fprintf(stderr, "transaction with client [%s:%d] timed out\n",
  325.                  inet_ntoa_r(active[n].ip, ip), active[n].port);
  326.          close(active[n].fd);
  327.          memset(&active[n], 0, sizeof (active_t));
  328.        }
  329.        if ((active[n].fd != 0) && (active[n].retransmit) &&
  330.            (active[n].retransmit < tdrop)) {
  331.          active[n].retransmit = 0;
  332.          memset(&from, 0, sizeof(from));
  333.          from.sin_family = AF_INET;
  334.          from.sin_addr.s_addr = active[n].ip;
  335.          from.sin_port = active[n].port;
  336.          fprintf(stderr, "retransmitting [%d] to client [%s:%d]\n",
  337.                  active[n].last.op, inet_ntoa_r(active[n].ip, ip), active[n].port);
  338.          sendto(sfd, &active[n].last, active[n].last.size, 0, 
  339.                 (struct sockaddr*)&from, sizeof(from));
  340.        }
  341.      }
  342.    }
  343. }
  344.  
  345.