mirror of
https://github.com/ipxe/ipxe
synced 2025-12-22 21:11:03 +03:00
[dhcp] Handle DHCPNAK by returning to discovery state
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>
This commit is contained in:
@@ -443,6 +443,26 @@ static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
|
|||||||
dhcp_set_state ( dhcp, &dhcp_state_request );
|
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
|
* Handle timer expiry during DHCP discovery
|
||||||
*
|
*
|
||||||
@@ -462,14 +482,8 @@ static void dhcp_discovery_expired ( struct dhcp_session *dhcp ) {
|
|||||||
dhcp_tx ( dhcp );
|
dhcp_tx ( dhcp );
|
||||||
|
|
||||||
/* If link is blocked, defer DHCP discovery timeout */
|
/* If link is blocked, defer DHCP discovery timeout */
|
||||||
if ( netdev_link_blocked ( dhcp->netdev ) &&
|
if ( netdev_link_blocked ( dhcp->netdev ) )
|
||||||
( dhcp->count <= DHCP_DISC_MAX_DEFERRALS ) ) {
|
dhcp_defer ( dhcp );
|
||||||
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 ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DHCP discovery state operations */
|
/** DHCP discovery state operations */
|
||||||
@@ -553,9 +567,17 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp,
|
|||||||
DBGC ( dhcp, " for %s", inet_ntoa ( ip ) );
|
DBGC ( dhcp, " for %s", inet_ntoa ( ip ) );
|
||||||
DBGC ( dhcp, "\n" );
|
DBGC ( dhcp, "\n" );
|
||||||
|
|
||||||
/* Filter out unacceptable responses */
|
/* Filter out invalid port */
|
||||||
if ( peer->sin_port != htons ( BOOTPS_PORT ) )
|
if ( peer->sin_port != htons ( BOOTPS_PORT ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Handle DHCPNAK */
|
||||||
|
if ( msgtype == DHCPNAK ) {
|
||||||
|
dhcp_defer ( dhcp );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Filter out unacceptable responses */
|
||||||
if ( msgtype /* BOOTP */ && ( msgtype != DHCPACK ) )
|
if ( msgtype /* BOOTP */ && ( msgtype != DHCPACK ) )
|
||||||
return;
|
return;
|
||||||
if ( server_id.s_addr != dhcp->server.s_addr )
|
if ( server_id.s_addr != dhcp->server.s_addr )
|
||||||
|
|||||||
Reference in New Issue
Block a user