/*! * \brief Send DHCP datagram and wait for a specified answer. * * \param slen Length of message to send. * \param xtype Expected response type. * * \return The number of data bytes received, 0 on timeout or -1 in * case of a failure. */ int DhcpTransact(u_short slen, u_char xtype) { u_char type; u_char retry; int rlen = 0; for (retry = 0; retry < 3; ) { /* * Send a message, if nothing has been received yet. */ if (rlen == 0) { if (UdpOutput(INADDR_BROADCAST, DHCP_SERVERPORT, DHCP_CLIENTPORT, slen) < 0) { /* Transmit failure, must be a NIC problem. Give up. */ return -1; } } /* * Do a retry on timouts or failures. A receive failures may be * caused by a hardware failure or a bad frame. */ if ((rlen = UdpInput(DHCP_CLIENTPORT, 5000)) <= 0) { retry++; continue; } /* * Check if the response contains the expected ID and * message type. */ if (rframe.u.bootp.bp_xid == sframe.u.bootp.bp_xid && DhcpGetOption(DHCPOPT_MSGTYPE, &type, 1) == 1 && type == xtype) { DEBUG("[DHCP]"); break; } } return rlen; }
/*! * \brief Download a file from a TFTP server and burn it into the flash ROM. * * \return 0 on success, -1 otherwise. */ int TftpRecv(void) { u_char retry; int rlen = 0; int slen; u_short tport = 69; u_short block = 0; u_char *cp; u_char *cp1; /* * Prepare the transmit buffer for a file request. */ sframe.u.tftp.th_opcode = htons(TFTP_RRQ); slen = 2; cp = (u_char *)sframe.u.tftp.th_u.tu_stuff; cp1 = bootfile; do { *cp = *cp1++; slen++; } while(*cp++); *cp++ = 'o'; *cp++ = 'c'; *cp++ = 't'; *cp++ = 'e'; *cp++ = 't'; *cp++ = 0; slen += 6; /* * Lopp until we receive a packet with less than 512 bytes of data. */ do { /* * Send file request or acknowledge and receive * a data block. */ for (retry = 0; retry < 3; retry++) { if (UdpOutput(server_ip, tport, SPORT, slen) >= 0) { if ((rlen = UdpInput(SPORT, 5000)) >= 4) break; } } /* * Can't reach the TFTP server or got a malformed * repsonse. */ if (rlen < 4) return -1; /* * Accept data blocks only. Anything else will stop * the transfer with an error. */ if (ntohs(rframe.u.tftp.th_opcode) != TFTP_DATA) return -1; /* * If this was the first block we received, prepare * the send buffer for sending ACKs. */ if (block == 0) { tport = ntohs(rframe.udp_hdr.uh_sport); sframe.u.tftp.th_opcode = htons(TFTP_ACK); slen = 4; } /* * If this block is out of sequence, we ignore it. * However, if we missed the first block, return * with an error. */ if (ntohs(rframe.u.tftp.th_u.tu_block) != block + 1) { if (block == 0) return -1; continue; } /* * Burn the received data into the flash ROM. */ if (rlen > 4) { FlashPage(block << 1, rframe.u.tftp.th_data, rlen - 4); if (rlen > 260) FlashPage((block << 1) + 1, &rframe.u.tftp.th_data[256], rlen - 260); } /* * Update our block counter. */ block++; sframe.u.tftp.th_u.tu_block = htons(block); } while (rlen >= 516); /* * Send the last ACK. */ UdpOutput(server_ip, tport, SPORT, slen); return 0; }