aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2021-03-11 15:54:26 +0000
committerMichael Brown <mcb30@ipxe.org>2021-03-11 16:04:19 +0000
commit1192edf394aaebde666c6aafda1c8b782b08a845 (patch)
tree01a7c2eafaed69bf97feca388262c3fb903aa6f6
parent7c8fc2cae8769fff7d9fe8af3cef046995a3fd3e (diff)
downloadipxe-1192edf394aaebde666c6aafda1c8b782b08a845.zip
ipxe-1192edf394aaebde666c6aafda1c8b782b08a845.tar.gz
ipxe-1192edf394aaebde666c6aafda1c8b782b08a845.tar.bz2
[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>
-rw-r--r--src/net/udp/dhcp.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c
index 4ebd38b..a335a77 100644
--- a/src/net/udp/dhcp.c
+++ b/src/net/udp/dhcp.c
@@ -444,6 +444,26 @@ static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
}
/**
+ * 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
*
* @v dhcp DHCP session
@@ -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 */
@@ -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 )