aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/udp/dhcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/udp/dhcp.c')
-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 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 )