Esempio n. 1
0
static inline int tftp_parsedatapacket(const uint8_t *packet, uint16_t *opcode, uint16_t *blockno)
{
	*opcode = (uint16_t)packet[0] << 8 | (uint16_t)packet[1];
	if (*opcode == TFTP_DATA) {
		*blockno = (uint16_t)packet[2] << 8 | (uint16_t)packet[3];
		return OK;
	}
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET_ERROR)
	else if (*opcode == TFTP_ERR) {
		(void)tftp_parseerrpacket(packet);
	}
#endif
	return ERROR;
}
Esempio n. 2
0
static int tftp_rcvack(int sd, uint8_t *packet, struct sockaddr_in *server,
                       uint16_t *port, uint16_t *blockno)
{
  struct sockaddr_in from;     /* The address the last UDP message recv'd from */
  ssize_t nbytes;              /* The number of bytes received. */
  uint16_t opcode;             /* The received opcode */
  uint16_t rblockno;           /* The received block number */
  int packetlen;               /* Packet length */
  int retry;                   /* Retry counter */

  /* Try up to TFTP_RETRIES times */

  for (retry = 0; retry < TFTP_RETRIES; retry++)
    {
      /* Try for until a valid ACK is received or some error occurs */

      for (;;)
        {
          /* Receive the next UDP packet from the server */

          nbytes = tftp_recvfrom(sd, packet, TFTP_IOBUFSIZE, &from);
          if (nbytes < TFTP_ACKHEADERSIZE)
            {
              /* Failed to receive a good packet */

              if (nbytes == 0)
                {
                  ndbg("Connection lost: %d bytes\n", nbytes);
                }
              else if (nbytes > 0)
                {
                  ndbg("Short packet: %d bytes\n", nbytes);
                }
              else
                {
                  ndbg("Recveid failure\n");
                }

              /* Break out to bump up the retry count */

              break;
            }
          else
            {
               /* Get the port being used by the server if that has not yet been established */

               if (!*port)
                 {
                   *port            = from.sin_port;
                   server->sin_port = from.sin_port;
                 }

               /* Verify that the packet was received from the correct host and port */

               if (server->sin_addr.s_addr != from.sin_addr.s_addr)
                 {
                   nvdbg("Invalid address in DATA\n");
                   continue;
                 }

              if (*port != server->sin_port)
                {
                  nvdbg("Invalid port in DATA\n");
                  packetlen = tftp_mkerrpacket(packet, TFTP_ERR_UNKID, TFTP_ERRST_UNKID);
                  (void)tftp_sendto(sd, packet, packetlen, server);
                  continue;
                }

              /* Parse the error message */

               opcode   = (uint16_t)packet[0] << 8 | (uint16_t)packet[1];
               rblockno = (uint16_t)packet[2] << 8 | (uint16_t)packet[3];

              /* Verify that the message that we received is an ACK for the
               * expected block number.
               */

               if (opcode != TFTP_ACK)
                 {
                   nvdbg("Bad opcode\n");
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET)
                  if (opcode == TFTP_ERR)
                    {
                      (void)tftp_parseerrpacket(packet);
                    }
                  else
#endif
                  if (opcode > TFTP_MAXRFC1350)
                    {
                      packetlen = tftp_mkerrpacket(packet, TFTP_ERR_ILLEGALOP, TFTP_ERRST_ILLEGALOP);
                      (void)tftp_sendto(sd, packet, packetlen, server);
                    }

                  /* Break out an bump up the retry count */

                  break;
                }

              /* Success! */

              nvdbg("Received ACK for block %d\n", rblockno);
              *blockno = rblockno;
              return OK;
            }
        }
    }

  /* We have tried TFTP_RETRIES times */

  ndbg("Timeout, Waiting for ACK\n");
  return ERROR; /* Will never get here */
}