示例#1
0
void DHClient::request(UDPSocket& sock)
{
    // form a response
    const size_t packetlen = sizeof(dhcp_packet_t);
    char packet[packetlen];

    dhcp_packet_t* resp = (dhcp_packet_t*) packet;
    resp->op    = BOOTREQUEST;
    resp->htype = HTYPE_ETHER;
    resp->hlen  = ETH_ALEN;
    resp->hops  = 0;
    resp->xid   = htonl(this->xid);
    resp->secs  = 0;
    resp->flags = htons(BOOTP_BROADCAST);

    resp->ciaddr = IP4::INADDR_ANY;
    resp->yiaddr = IP4::INADDR_ANY;
    resp->siaddr = IP4::INADDR_ANY;
    resp->giaddr = IP4::INADDR_ANY;

    Ethernet::addr link_addr = stack.link_addr();

    // copy our hardware address to chaddr field
    memset(resp->chaddr, 0, dhcp_packet_t::CHADDR_LEN);
    memcpy(resp->chaddr, &link_addr, ETH_ALEN);
    // zero server, file and options
    memset(resp->sname, 0, dhcp_packet_t::SNAME_LEN + dhcp_packet_t::FILE_LEN);
    // magic DHCP bootp values
    resp->magic[0] =  99;
    resp->magic[1] = 130;
    resp->magic[2] =  83;
    resp->magic[3] =  99;

    dhcp_option_t* opt = conv_option(resp->options + 0);
    // DHCP Request
    opt->code   = DHO_DHCP_MESSAGE_TYPE;
    opt->length = 1;
    opt->val[0] = DHCPREQUEST;
    // DHCP client identifier
    opt = conv_option(resp->options + 3);
    opt->code   = DHO_DHCP_CLIENT_IDENTIFIER;
    opt->length = 7;
    opt->val[0] = HTYPE_ETHER;
    memcpy(&opt->val[1], &link_addr, ETH_ALEN);
    // DHCP server identifier
    opt = conv_option(resp->options + 12);
    opt->code   = DHO_DHCP_SERVER_IDENTIFIER;
    opt->length = 4;
    memcpy(&opt->val[0], &this->router, sizeof(IP4::addr));
    // DHCP Requested Address
    opt = conv_option(resp->options + 18);
    opt->code   = DHO_DHCP_REQUESTED_ADDRESS;
    opt->length = 4;
    memcpy(&opt->val[0], &this->ipaddr, sizeof(IP4::addr));
    // DHCP Parameter Request Field
    opt = conv_option(resp->options + 24);
    opt->code   = DHO_DHCP_PARAMETER_REQUEST_LIST;
    opt->length = 3;
    opt->val[0] = DHO_ROUTERS;
    opt->val[1] = DHO_SUBNET_MASK;
    opt->val[2] = DHO_DOMAIN_NAME_SERVERS;
    // END
    opt = conv_option(resp->options + 29);
    opt->code   = DHO_END;
    opt->length = 0;

    // set our onRead function to point to a hopeful DHCP ACK!
    sock.on_read(
        [this] (IP4::addr, UDP::port_t port,
                const char* data, size_t len)
    {
        if (port == DHCP_DEST_PORT)
        {
            // we have hopefully got a DHCP Ack
            debug("\tReceived DHCP ACK from %s:%d\n",
                  addr.str().c_str(), DHCP_DEST_PORT);
            this->acknowledge(data, len);
        }
    });

    // send our DHCP Request
    sock.bcast(IP4::INADDR_ANY, DHCP_DEST_PORT, packet, packetlen);
}