diff options
author | Michael Brown <mcb30@ipxe.org> | 2021-03-11 15:54:26 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2021-03-11 16:04:19 +0000 |
commit | 1192edf394aaebde666c6aafda1c8b782b08a845 (patch) | |
tree | 01a7c2eafaed69bf97feca388262c3fb903aa6f6 | |
parent | 7c8fc2cae8769fff7d9fe8af3cef046995a3fd3e (diff) | |
download | ipxe-1192edf394aaebde666c6aafda1c8b782b08a845.tar.gz |
[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.c | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c index 4ebd38bbb..a335a778a 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 ) |