Ejemplo n.º 1
0
/*!
 * \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;
}