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; }
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 */ }