Пример #1
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 */
Пример #2
0
uint_32 TFTP_open
   (
      pointer  ft_data
         /* [IN] the address and filename of the bootimage */
   )
{ /* Body */
   TFTP_DATA_STRUCT_PTR    tftp;
   sockaddr_in             local_addr;
   char_ptr                str_ptr;
   uchar_ptr               packet;
   uint_32                 sock;
   uint_32                 error;
   uint_32                 fn_len, fm_len;
   uint_32                 pkt_len;

   tftp = (TFTP_DATA_STRUCT_PTR) ft_data;

   /* Get a socket */
   sock = socket(AF_INET, SOCK_DGRAM, 0);
   if (sock == RTCS_SOCKET_ERROR) {
      return RTCSERR_TFTP_SOCKET;
   } /* Endif */

   /* Must be initialized in order for TFTP_close to be able to release socket and memory */
   TFTP_config.SOCK = sock;  
   TFTP_config.RRQ_PTR = NULL;  

   /* Bind it */
   local_addr.sin_family      = AF_INET;
   local_addr.sin_port        = 0;
   local_addr.sin_addr.s_addr = INADDR_ANY;
   error = bind(sock, &local_addr, sizeof(local_addr));
   if (error != RTCS_OK) {
      TFTP_close();
      return error;
   } /* Endif */

   if ( (tftp->FILENAME == NULL) || (tftp->FILEMODE == NULL) ){      
      TFTP_close();
      return TFTPERR_FILE_NOT_FOUND;
   } /* Endif */

   /* Prepare a read request (RRQ) */
   str_ptr = tftp->FILENAME;
   while (*str_ptr++) {};
   fn_len = str_ptr - tftp->FILENAME;
   str_ptr = tftp->FILEMODE;
   while (*str_ptr++) {};
   fm_len = str_ptr - tftp->FILEMODE;
   pkt_len = 2 + fn_len + fm_len;
   packet = RTCS_mem_alloc(pkt_len);
   if (packet == NULL) {
      TFTP_close();
      return RTCSERR_TFTP_RRQ_ALLOC;
   } /* Endif */
   _mem_set_type(packet, MEM_TYPE_TFTP_PACKET);
   TFTP_config.RRQ_PTR = packet;  
   htons(packet, TFTPOP_RRQ);
   _mem_copy(tftp->FILENAME, &packet[       2], fn_len);
   _mem_copy(tftp->FILEMODE, &packet[fn_len+2], fm_len);

   /* Send the RRQ */
   TFTP_config.SOCK = sock;
   TFTP_config.SADDR.sin_family      = AF_INET;
   TFTP_config.SADDR.sin_port        = IPPORT_TFTP;
   TFTP_config.SADDR.sin_addr.s_addr = tftp->SERVER;
   TFTP_timeout_init(&TFTP_config.TIMEOUT);
   error = sendto(sock, packet, pkt_len, 0,
                  &TFTP_config.SADDR, sizeof(TFTP_config.SADDR));
   if (error != pkt_len) {
      TFTP_close();
      return RTCSERR_TFTP_RRQ_SEND;
   } /* Endif */

   /* Initialize the TFTP client */
   TFTP_config.RRQ_PTR = packet;
   TFTP_config.RRQ_LEN = pkt_len;
   TFTP_config.LAST    = FALSE;
   htons(TFTP_config.ACK.OP,    TFTPOP_ACK);
   htons(TFTP_config.ACK.BLOCK, 0);
   return RTCS_OK;

} /* Endbody */
Пример #3
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 */