Skip to content

Commit

Permalink
[dhcp] Handle DHCPNAK by returning to discovery state
Browse files Browse the repository at this point in the history
Handle a DHCPNAK by returning to the discovery state to allow iPXE to
attempt to obtain a replacement IPv4 address.

Reuse the existing logic for deferring discovery when the link is
blocked: this avoids hammering a misconfigured DHCP server with a
non-stop stream of requests and allows the DHCP process to eventually
time out and fail.

Originally-implemented-by: Blake Rouse <blake.rouse@canonical.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed Mar 11, 2021
1 parent 7c8fc2c commit 1192edf
Showing 1 changed file with 31 additions and 9 deletions.
40 changes: 31 additions & 9 deletions src/net/udp/dhcp.c
Expand Up @@ -443,6 +443,26 @@ static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
dhcp_set_state ( dhcp, &dhcp_state_request );
}

/**
* Defer DHCP discovery
*
* @v dhcp DHCP session
*/
static void dhcp_defer ( struct dhcp_session *dhcp ) {

/* Do nothing if we have reached the deferral limit */
if ( dhcp->count > DHCP_DISC_MAX_DEFERRALS )
return;

/* Return to discovery state */
DBGC ( dhcp, "DHCP %p deferring discovery\n", dhcp );
dhcp_set_state ( dhcp, &dhcp_state_discover );

/* Delay first DHCPDISCOVER */
start_timer_fixed ( &dhcp->timer,
( DHCP_DISC_START_TIMEOUT_SEC * TICKS_PER_SEC ) );
}

/**
* Handle timer expiry during DHCP discovery
*
Expand All @@ -462,14 +482,8 @@ static void dhcp_discovery_expired ( struct dhcp_session *dhcp ) {
dhcp_tx ( dhcp );

/* If link is blocked, defer DHCP discovery timeout */
if ( netdev_link_blocked ( dhcp->netdev ) &&
( dhcp->count <= DHCP_DISC_MAX_DEFERRALS ) ) {
DBGC ( dhcp, "DHCP %p deferring discovery timeout\n", dhcp );
dhcp->start = currticks();
start_timer_fixed ( &dhcp->timer,
( DHCP_DISC_START_TIMEOUT_SEC *
TICKS_PER_SEC ) );
}
if ( netdev_link_blocked ( dhcp->netdev ) )
dhcp_defer ( dhcp );
}

/** DHCP discovery state operations */
Expand Down Expand Up @@ -553,9 +567,17 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp,
DBGC ( dhcp, " for %s", inet_ntoa ( ip ) );
DBGC ( dhcp, "\n" );

/* Filter out unacceptable responses */
/* Filter out invalid port */
if ( peer->sin_port != htons ( BOOTPS_PORT ) )
return;

/* Handle DHCPNAK */
if ( msgtype == DHCPNAK ) {
dhcp_defer ( dhcp );
return;
}

/* Filter out unacceptable responses */
if ( msgtype /* BOOTP */ && ( msgtype != DHCPACK ) )
return;
if ( server_id.s_addr != dhcp->server.s_addr )
Expand Down

0 comments on commit 1192edf

Please sign in to comment.