예제 #1
0
uint32_t TFTPSRV_service_timer
   (
      TFTPSRV_STATE_STRUCT_PTR   tftpsrv_ptr
         /* [IN/OUT] The TFTP Server state */
   )
{ /* Body */
   TFTP_TRANS_STRUCT_PTR   trans_ptr;
   uint32_t                 time;
   bool                 expired;

   while (tftpsrv_ptr->EVENT_HEAD) {

      trans_ptr = tftpsrv_ptr->EVENT_HEAD;
      time = TFTP_timeout_left(&trans_ptr->XMIT_TIMER, &expired);
      if (!expired) {
         trans_ptr->TIME = time;
         return time;
      } /* Endif */

      RTCS_DLIST_DEL(tftpsrv_ptr->EVENT_HEAD, trans_ptr);

      if (trans_ptr->EXIT) {
         TFTPSRV_close_transaction(tftpsrv_ptr, trans_ptr);
         continue;
      } /* Endif */

#if TFTPSRV_TIMEOUT_RETRIES != TFTPSRV_INFINITE_RETRIES
      if (++trans_ptr->NUM_RETRIES > TFTPSRV_TIMEOUT_RETRIES) {
         TFTP_SEND(trans_ptr->SOCK, _tftp_error_to, trans_ptr->ADDR);
         TFTPSRV_close_transaction(tftpsrv_ptr, trans_ptr);
         continue;
      } /* Endif */
#endif

      TFTPSRV_send(trans_ptr);
      TFTPSRV_timer_start(tftpsrv_ptr, trans_ptr, time);

   } /* Endwhile */

   /* Nothing in the event queue */
   return 0;

} /* Endbody */
예제 #2
0
파일: tftp.c 프로젝트: mihaSoro/MQX-3.7.0
uchar_ptr TFTP_read
   (
      uint_32_ptr    size
         /* [OUT] number of bytes read, or error code */
   )
{ /* Body */
   uint_32        sock;
   sockaddr_in    remote_addr;
   uint_16        remote_size;
   uint_16        ack_block;
   uint_16        pkt_op, pkt_block;
   uint_32        pkt_size;
   uint_32        time_left;
   boolean        expired;
#if TFTP_TIMEOUT_RETRIES
   uint_32        retries = 0;
#endif

   ack_block = ntohs(TFTP_config.ACK.BLOCK);
   TFTP_timeout_restart(&TFTP_config.TIMEOUT);

   for (;;) {

      /* Check for timeout */
      time_left = TFTP_timeout_left(&TFTP_config.TIMEOUT, &expired);
      if (expired) {
#if TFTP_TIMEOUT_RETRIES
         retries++;
         if (retries > TFTP_TIMEOUT_RETRIES) {
            *size = RTCSERR_TFTP_TIMEOUT;
            TFTP_close();
            return NULL;
         } /* Endif */
#endif
         /* Retransmit the last packet */
         TFTP_RESEND();
      } /* Endif */

      /* Wait for a packet */
      sock = TFTP_WAIT(time_left);

      /* Timeout -- retransmit last packet */
      if (sock != TFTP_config.SOCK) {
         continue;
      } /* Endif */

      remote_size = sizeof(remote_addr);
      pkt_size = TFTP_RECV(TFTP_config.PACKET);

      pkt_op    = ntohs(TFTP_config.PACKET.HEAD.OP);
      pkt_block = ntohs(TFTP_config.PACKET.HEAD.BLOCK);

      /* Check source address of received packet */
      if (remote_addr.sin_addr.s_addr != TFTP_config.SADDR.sin_addr.s_addr) {
         continue;
      } /* Endif */

      /* Validate source port */
      if (ack_block && remote_addr.sin_port != TFTP_config.SADDR.sin_port) {
         TFTP_SEND(TFTP_config.SOCK, _tftp_error_tid, remote_addr);
         continue;
      } /* Endif */

      /* Check size of received packet */
      if (pkt_size < sizeof(TFTP_HEADER)) {
         TFTP_SEND(TFTP_config.SOCK, _tftp_error_op, remote_addr);
         *size = RTCSERR_TFTP_ERROR + TFTPERR_ILLEGAL_OP;
         TFTP_close();
         return NULL;
      } /* Endif */

      /* Check for error packet */
      if (pkt_op == TFTPOP_ERROR) {
         *size = RTCSERR_TFTP_ERROR + pkt_block;
         TFTP_close();
         return NULL;
      } /* Endif */

      /* Check for data packet */
      if ((pkt_op != TFTPOP_DATA)
       || (pkt_size > sizeof(TFTP_PACKET))
       || (pkt_block < ack_block)
       || (pkt_block > ack_block+1)) {
         TFTP_SEND(TFTP_config.SOCK, _tftp_error_op, remote_addr);
         *size = RTCSERR_TFTP_ERROR + TFTPERR_ILLEGAL_OP;
         TFTP_close();
         return NULL;
      } /* Endif */

      /* Check for retransmitted packet */
      if (pkt_block == ack_block) {
         TFTP_timeout_restart(&TFTP_config.TIMEOUT);
         TFTP_SEND(TFTP_config.SOCK, TFTP_config.ACK, TFTP_config.SADDR);
         continue;
      } /* Endif */

      /* We have the next packet */
      break;
   } /* Endfor */

   /* Update the adaptive timeout */
   TFTP_timeout_update(&TFTP_config.TIMEOUT);

   /* Free the original RRQ */
   if (!ack_block) {
      TFTP_config.SADDR.sin_port = remote_addr.sin_port;
      _mem_free(TFTP_config.RRQ_PTR);
      TFTP_config.RRQ_PTR = NULL;
   } /* Endif */

   /* ACK it */
   ack_block++;
   htons(TFTP_config.ACK.BLOCK, ack_block);
   TFTP_SEND(TFTP_config.SOCK, TFTP_config.ACK, TFTP_config.SADDR);
   TFTP_config.LAST = (pkt_size < sizeof(TFTP_PACKET));

   /* Return the data */
   *size = pkt_size - sizeof(TFTP_HEADER);
   return TFTP_config.PACKET.DATA;

} /* Endbody */
예제 #3
0
void TFTPSRV_service_request
   (
      TFTPSRV_STATE_STRUCT_PTR   tftpsrv_ptr
         /* [IN/OUT] The TFTP Server state */
   )
{ /* Body */
   TFTP_TRANS_STRUCT_PTR   trans_ptr;
   sockaddr_in             sockaddr_t;
   int32_t                  pkt_len, i;
   uint32_t                 error;
   char                *filename, *filemode;
   uint16_t                 sockaddrlen, pkt_op;

   /* receive the datagram */
   sockaddrlen = sizeof(sockaddr_t);
   pkt_len = recvfrom(tftpsrv_ptr->SRV_SOCK, tftpsrv_ptr->BUFFER,
                      TFTP_MAX_MESSAGE_SIZE, 0, (sockaddr *)&sockaddr_t, &sockaddrlen);
   if (pkt_len == RTCS_ERROR) {
      return;
   } /* Endif */

   /* limit the number of concurrent transactions */
   if (tftpsrv_ptr->NUM_TRANSACTIONS >= TFTPSRV_MAX_TRANSACTIONS) {
      TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_busy, sockaddr_t);
      return;
   } /* Endif */

   /* parse the request; extract op, filename and filemode */
   i = 2;
   filename = (char *)tftpsrv_ptr->BUFFER + i;
   for (; i<pkt_len; i++) {
      if (tftpsrv_ptr->BUFFER[i] == '\0') break;
   } /* Endfor */
   i++;
   filemode = (char *)tftpsrv_ptr->BUFFER + i;
   for (; i<pkt_len; i++) {
      if (tftpsrv_ptr->BUFFER[i] == '\0') break;
   } /* Endfor */
   if (i >= pkt_len) {
      TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_op, sockaddr_t);
      return;
   } /* Endif */
   pkt_op = mqx_ntohs(tftpsrv_ptr->BUFFER);

   /* allocate state for the new transaction */
   trans_ptr = RTCS_mem_alloc_zero(sizeof(TFTP_TRANS_STRUCT));
   if (trans_ptr == NULL) {
      TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_srv, sockaddr_t);
      return;
   } /* Endif */
   _mem_set_type(trans_ptr, MEM_TYPE_TFTP_TRANS_STRUCT);
   
   /* validate the requested operation */
   switch (pkt_op) {
   case TFTPOP_RRQ:
      trans_ptr->RECV_OP = TFTPOP_ACK;
      trans_ptr->SEND_OP = TFTPOP_DATA;
      break;
   case TFTPOP_WRQ:
      trans_ptr->RECV_OP = TFTPOP_DATA;
      trans_ptr->SEND_OP = TFTPOP_ACK;
      break;
   default:
      TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_op, sockaddr_t);
      _mem_free(trans_ptr);
      return;
   } /* Endswitch */

   /* open the requested file */
   error = TFTPSRV_open_device(pkt_op, filename, filemode, &trans_ptr->TRANS_FILE_PTR);
   if (error) {
      switch (error) {
      case RTCS_EACCES:
         TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_accvio, sockaddr_t);
         break;
      case RTCS_ENOENT:
         TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_nofile, sockaddr_t);
         break;
      case RTCS_EEXIST:
         TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_exists, sockaddr_t);
         break;
      default:
         TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_srv, sockaddr_t);
         break;
      } /* Endswitch */
      _mem_free(trans_ptr);
      return;
   } /* Endif */

   /* create a socket for the new transaction */
   trans_ptr->SOCK = socket(PF_INET, SOCK_DGRAM, 0);
   if (trans_ptr->SOCK == RTCS_SOCKET_ERROR) {
      TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_srv, sockaddr_t);
      RTCS_io_close(trans_ptr->TRANS_FILE_PTR);
      _mem_free(trans_ptr);
      return;
   } /* Endif */

   trans_ptr->ADDR.sin_family      = sockaddr_t.sin_family;
   trans_ptr->ADDR.sin_port        = sockaddr_t.sin_port;
   trans_ptr->ADDR.sin_addr.s_addr = sockaddr_t.sin_addr.s_addr;

   sockaddr_t.sin_family      = AF_INET;
   sockaddr_t.sin_port        = 0;
   sockaddr_t.sin_addr.s_addr = INADDR_ANY;

   error = bind(trans_ptr->SOCK, (const sockaddr *)&sockaddr_t, sizeof(sockaddr_t));
   if (error != RTCS_OK) {
      TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_srv, sockaddr_t);
      shutdown(trans_ptr->SOCK, 0);
      RTCS_io_close(trans_ptr->TRANS_FILE_PTR);
      _mem_free(trans_ptr);
      return;
   } /* Endif */

   /* build the first packet */
   trans_ptr->BLOCK = 0;
   switch (trans_ptr->SEND_OP) {
   case TFTPOP_DATA:
      TFTPSRV_build_DATA(trans_ptr);
      break;
   case TFTPOP_ACK:
      TFTPSRV_build_ACK(trans_ptr);
      trans_ptr->EXIT = FALSE;
      break;
   } /* Endswitch */
   if (trans_ptr->SEND_SIZE < sizeof(TFTP_HEADER)) {
      TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_srv, sockaddr_t);
      shutdown(trans_ptr->SOCK, 0);
      RTCS_io_close(trans_ptr->TRANS_FILE_PTR);
      _mem_free(trans_ptr);
      return;
   } /* Endif */

   /* send the first packet */
   TFTPSRV_timer_start(tftpsrv_ptr, trans_ptr, TFTP_timeout_init(&trans_ptr->XMIT_TIMER));
   TFTPSRV_send(trans_ptr);

   tftpsrv_ptr->SOCKETS[tftpsrv_ptr->NUM_TRANSACTIONS] = trans_ptr->SOCK;
   tftpsrv_ptr->TRANS_PTRS[tftpsrv_ptr->NUM_TRANSACTIONS] = trans_ptr;
   tftpsrv_ptr->NUM_TRANSACTIONS++;

} /* Endbody */
예제 #4
0
void TFTPSRV_service_transaction
   (
      TFTPSRV_STATE_STRUCT_PTR   tftpsrv_ptr,
         /* [IN/OUT] The TFTP Server state */
      TFTP_TRANS_STRUCT_PTR      trans_ptr
         /* [IN/OUT] The transaction state */
   )

{ /* Body */
   sockaddr_in sockaddr_tftp;
   uint32_t     block_num;
   int32_t      pkt_len, write_len;
   uint16_t     sockaddrlen, pkt_op;

   /* receive the datagram */
   sockaddrlen = sizeof(sockaddr_tftp);
   pkt_len = recvfrom(trans_ptr->SOCK, tftpsrv_ptr->BUFFER,
                      TFTP_MAX_MESSAGE_SIZE, 0,(sockaddr *)&sockaddr_tftp, &sockaddrlen);
   if (pkt_len == RTCS_ERROR) {
      return;
   } /* Endif */

   /* verify the sender's address and port */
   if ((trans_ptr->ADDR.sin_port        != sockaddr_tftp.sin_port) ||
       (trans_ptr->ADDR.sin_addr.s_addr != sockaddr_tftp.sin_addr.s_addr)) {
      TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_tid, sockaddr_tftp);
      return;
   } /* Endif */

   /* get op and block number */
   if (pkt_len < sizeof(TFTP_HEADER)) {
      TFTP_SEND(trans_ptr->SOCK, _tftp_error_tid, sockaddr_tftp);
      return;
   } /* Endif */
   pkt_op    = mqx_ntohs(tftpsrv_ptr->BUFFER);
   block_num = mqx_ntohs(tftpsrv_ptr->BUFFER + 2);

   /* verify the requested operation */
   if (pkt_op != trans_ptr->RECV_OP) {
      if (pkt_op != TFTPOP_ERROR) {
         TFTP_SEND(trans_ptr->SOCK, _tftp_error_op, sockaddr_tftp);
      } /* Endif */
      TFTPSRV_close_transaction(tftpsrv_ptr, trans_ptr);
      return;
   } /* Endif */

   switch (pkt_op) {
   case TFTPOP_DATA:
      /* We are servicing a write request from a TFTP Client here */
      if (block_num == trans_ptr->BLOCK) {

         pkt_len -= sizeof(TFTP_HEADER);
         write_len = RTCS_io_write(trans_ptr->TRANS_FILE_PTR,
                                   tftpsrv_ptr->BUFFER + sizeof(TFTP_HEADER),
                                   pkt_len);
         fflush(trans_ptr->TRANS_FILE_PTR);
         if (write_len != pkt_len) {
            TFTP_SEND(trans_ptr->SOCK, _tftp_error_srv, trans_ptr->ADDR);
            TFTPSRV_close_transaction(tftpsrv_ptr, trans_ptr);
            return;
         } /* Endif */

         TFTPSRV_build_ACK(trans_ptr);
         trans_ptr->EXIT = (write_len < sizeof(TFTP_PACKET) - sizeof(TFTP_HEADER));
         TFTPSRV_timer_cancel(tftpsrv_ptr, trans_ptr);
         TFTPSRV_timer_start(tftpsrv_ptr, trans_ptr, TFTP_timeout_update(&trans_ptr->XMIT_TIMER));
         TFTPSRV_send(trans_ptr);

      } else if (block_num == trans_ptr->BLOCK - 1) {
         TFTPSRV_timer_cancel(tftpsrv_ptr, trans_ptr);
         TFTPSRV_timer_start(tftpsrv_ptr, trans_ptr, TFTP_timeout_restart(&trans_ptr->XMIT_TIMER));
         TFTPSRV_send(trans_ptr);
      } /* Endif */
      break;

   case TFTPOP_ACK:
      /* We are servicing a read request */
      if (block_num == trans_ptr->BLOCK) {
         if (trans_ptr->EXIT) {
            /* We've received the last ACK, exit */
            TFTPSRV_close_transaction(tftpsrv_ptr, trans_ptr);
            return;
         } /* Endif */
         TFTPSRV_build_DATA(trans_ptr);
         if (trans_ptr->SEND_SIZE < sizeof(TFTP_HEADER)) {
            TFTP_SEND(trans_ptr->SOCK, _tftp_error_srv, sockaddr_tftp);
            TFTPSRV_close_transaction(tftpsrv_ptr, trans_ptr);
            return;
         } /* Endif */
         TFTPSRV_timer_cancel(tftpsrv_ptr, trans_ptr);
         TFTPSRV_timer_start(tftpsrv_ptr, trans_ptr, TFTP_timeout_update(&trans_ptr->XMIT_TIMER));
         TFTPSRV_send(trans_ptr);
      } /* Endif */
      break;

   } /* Endswitch */
} /* Endbody */
예제 #5
0
unsigned char *TFTP_read
   (
      uint32_t    *size
         /* [OUT] number of bytes read, or error code */
   )
{ /* Body */
   uint32_t        sock;
   sockaddr_in    remote_addr;
   uint16_t        remote_size;
   uint16_t        ack_block;
   uint16_t        pkt_op, pkt_block;
   uint32_t        pkt_size;
   uint32_t        time_left;
   bool        expired;
#if TFTP_TIMEOUT_RETRIES
   uint32_t        retries = 0;
#endif

   ack_block = mqx_ntohs(TFTP_config.ACK.BLOCK);
   TFTP_timeout_restart(&TFTP_config.TIMEOUT);

   for (;;) {

      /* Check for timeout */
      time_left = TFTP_timeout_left(&TFTP_config.TIMEOUT, &expired);
      if (expired) {
#if TFTP_TIMEOUT_RETRIES
         retries++;
         if (retries > TFTP_TIMEOUT_RETRIES) {
            *size = RTCSERR_TFTP_TIMEOUT;
            TFTP_close();
            return NULL;
         } /* Endif */
#endif
         /* Retransmit the last packet */
         TFTP_RESEND();
      } /* Endif */

      /* Wait for a packet */
      sock = TFTP_WAIT(time_left);

      /* Timeout -- retransmit last packet */
      if (sock != TFTP_config.SOCK) {
         continue;
      } /* Endif */

      remote_size = sizeof(remote_addr);
      pkt_size = TFTP_RECV(TFTP_config.PACKET);

      pkt_op    = mqx_ntohs(TFTP_config.PACKET.HEAD.OP);
      pkt_block = mqx_ntohs(TFTP_config.PACKET.HEAD.BLOCK);

      /* Check source address of received packet */
      if (remote_addr.sin_addr.s_addr != TFTP_config.SADDR.sin_addr.s_addr) {
         continue;
      } /* Endif */

      /* Validate source port */
      if (ack_block && remote_addr.sin_port != TFTP_config.SADDR.sin_port) {
         TFTP_SEND(TFTP_config.SOCK, _tftp_error_tid, remote_addr);
         continue;
      } /* Endif */

      /* Check size of received packet */
      if (pkt_size < sizeof(TFTP_HEADER)) {
         TFTP_SEND(TFTP_config.SOCK, _tftp_error_op, remote_addr);
         *size = RTCSERR_TFTP_ERROR + TFTPERR_ILLEGAL_OP;
         TFTP_close();
         return NULL;
      } /* Endif */

      /* Check for error packet */
      if (pkt_op == TFTPOP_ERROR) {
         *size = RTCSERR_TFTP_ERROR + pkt_block;
         TFTP_close();
         return NULL;
      } /* Endif */

      /* Check for data packet */
      if ((pkt_op != TFTPOP_DATA)
       || (pkt_size > sizeof(TFTP_PACKET))) {
         TFTP_SEND(TFTP_config.SOCK, _tftp_error_op, remote_addr);
         *size = RTCSERR_TFTP_ERROR + TFTPERR_ILLEGAL_OP;
         TFTP_close();
         return NULL;
      } /* Endif */

      /* Check for retransmitted packet */
      if (pkt_block == ack_block) {
         TFTP_timeout_restart(&TFTP_config.TIMEOUT);
         TFTP_SEND(TFTP_config.SOCK, TFTP_config.ACK, TFTP_config.SADDR);
         continue;
      } /* Endif */

      /* Aknowledge also packets with lower id, some servers do retransmit them until they get an ack */
      if (pkt_block < ack_block) {
         TFTP_timeout_restart(&TFTP_config.TIMEOUT);
         mqx_htons(TFTP_config.ACK.BLOCK, pkt_block);
         TFTP_SEND(TFTP_config.SOCK, TFTP_config.ACK, TFTP_config.SADDR);
         mqx_htons(TFTP_config.ACK.BLOCK, ack_block); /* Restore id of last acknowledged packet */
         continue;
      } /* Endif */

      /* Drop unexpected packets */
      if (pkt_block > ack_block+1) {
         /* Some server do send more than one packet at a time, these will eventually retransmitted */
         continue;
      }

      /* We have the next packet */
      break;
   } /* Endfor */

   /* Update the adaptive timeout */
   TFTP_timeout_update(&TFTP_config.TIMEOUT);

   /* Free the original RRQ */
   if (!ack_block) {
      TFTP_config.SADDR.sin_port = remote_addr.sin_port;
      _mem_free(TFTP_config.RRQ_PTR);
      TFTP_config.RRQ_PTR = NULL;
   } /* Endif */

   /* ACK it */
   ack_block++;
   mqx_htons(TFTP_config.ACK.BLOCK, ack_block);
   TFTP_SEND(TFTP_config.SOCK, TFTP_config.ACK, TFTP_config.SADDR);
   TFTP_config.LAST = (pkt_size < sizeof(TFTP_PACKET));

   /* Return the data */
   *size = pkt_size - sizeof(TFTP_HEADER);
   return TFTP_config.PACKET.DATA;

} /* Endbody */