// something has timed out, handle this static void dhcp_timeout(struct dhcp_state *state) { DEBUGF(DHCP_DEBUG, ("dhcp_timeout()\n")); if ((state->state == DHCP_BACKING_OFF) || (state->state == DHCP_SELECTING)) { DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): restarting discovery\n")); dhcp_discover(state); } else if (state->state == DHCP_REQUESTING) { DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n")); if (state->tries <= 5) { dhcp_select(state); } else { DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REQUESTING, releasing, restarting\n")); dhcp_release(state); dhcp_discover(state); } } else if (state->state == DHCP_CHECKING) { DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): CHECKING, ARP request timed out\n")); if (state->tries <= 1) { dhcp_check(state); } // no ARP replies on the offered address, // looks like the IP address is indeed free else { dhcp_bind(state); } } else if (state->state == DHCP_RENEWING) { DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): RENEWING, DHCP request timed out\n")); dhcp_renew(state); } else if (state->state == DHCP_REBINDING) { DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REBINDING, DHCP request timed out\n")); if (state->tries <= 8) { dhcp_rebind(state); } else { DEBUGF(DHCP_DEBUG, ("dhcp_timeout(): REBINDING, release, restart\n")); dhcp_release(state); dhcp_discover(state); } } }
static void dhcp_handle_offer(struct dhcp_state *state) { u8_t *option_ptr = dhcp_get_option_ptr(state, DHCP_OPTION_SERVER_ID); if (option_ptr != NULL) { state->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2])); DEBUGF(DHCP_DEBUG, ("dhcp_handle_offer(): server 0x%08lx\n", state->server_ip_addr.addr)); /* remember offered address */ ip_addr_set(&state->offered_ip_addr, (struct ip_addr *)&state->msg_in->yiaddr); DEBUGF(DHCP_DEBUG, ("dhcp_handle_offer(): offer for 0x%08lx\n", state->offered_ip_addr.addr)); dhcp_select(state); } else { //dhcp_start(restart); } }
/* * Function: dhcp_init * Purpose: * Start in the DHCP INIT state sending DISCOVER's. When we get OFFER's, * try to select one of them by sending a REQUEST and waiting for an ACK. */ static int dhcp_init(struct dhcp_context * context) { struct timeval current_time; int error = 0; uint32_t lease_option = htonl(SUGGESTED_LEASE_LENGTH); dhcpoa_t * options_p; struct dhcp_packet * request; int request_size; int retry; int wait_ticks; /* remember the time we started */ microtime(&context->start_time); current_time = context->start_time; request = dhcp_context_request(context); options_p = &context->request_options; retry: /* format a DHCP DISCOVER packet */ make_dhcp_request(&request->dhcp, DHCP_PAYLOAD_MIN, dhcp_msgtype_discover_e, link_address(context->dl_p), ARPHRD_ETHER, link_address_length(context->dl_p), options_p); /* add the requested lease time */ dhcpoa_add(options_p, dhcptag_lease_time_e, sizeof(lease_option), &lease_option); dhcpoa_add(options_p, dhcptag_end_e, 0, 0); request_size = sizeof(*request) + RFC_MAGIC_SIZE + dhcpoa_used(options_p); if (request_size < (int)sizeof(struct bootp_packet)) { /* pad out to BOOTP-sized packet */ request_size = sizeof(struct bootp_packet); } init_dhcp_packet_header(request, request_size); wait_ticks = INITIAL_WAIT_SECS * hz; for (retry = 0; retry < context->max_try; retry++) { /* Send the request */ printf("dhcp: sending DISCOVER\n"); request->dhcp.dp_secs = htons((u_short)(current_time.tv_sec - context->start_time.tv_sec)); request->dhcp.dp_xid = htonl(context->xid); #ifdef RANDOM_IP_ID request->ip.ip_id = ip_randomid(); #else request->ip.ip_id = htons(ip_id++); #endif error = send_packet(context->ifp, request, request_size); if (error != 0) { printf("dhcp: send_packet failed with %d\n", error); goto failed; } wait_ticks += random_range(-RAND_TICKS, RAND_TICKS); dprintf(("dhcp: waiting %d ticks\n", wait_ticks)); error = dhcp_get_offer(context, wait_ticks); if (error == 0) { /* send a REQUEST */ error = dhcp_select(context); if (error == 0) { /* we're done !*/ goto done; } if (error != EPROTO && error != ETIMEDOUT) { /* fatal error */ dprintf(("dhcp: dhcp_select failed %d\n", error)); goto failed; } /* wait 10 seconds, and try again */ printf("dhcp: trying again in 10 seconds\n"); tsleep(&error, PRIBIO, "dhcp_init", 10 * hz); context->xid++; goto retry; } else if (error != EWOULDBLOCK) { dprintf(("dhcp: failed to receive packets: %d\n", error)); goto failed; } wait_ticks *= 2; if (wait_ticks > (MAX_WAIT_SECS * hz)) wait_ticks = MAX_WAIT_SECS * hz; microtime(¤t_time); } error = ETIMEDOUT; goto failed; done: error = 0; failed: return (error); }