diff --git a/CHANGELOG b/CHANGELOG index ddc65357..9f87ed05 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -216,6 +216,9 @@ HISTORY ++ Bugfixes: + 2015-03-21: Simon Goldschmidt (patch by Christoffer Lind) + * dhcp.h/.c: fixed bug #38204 (DHCP lease time not handled correctly) + 2015-03-20: Simon Goldschmidt * dhcp.c: fixed bug #38714 (Missing option and client address in DHCPRELEASE message) diff --git a/src/core/dhcp.c b/src/core/dhcp.c index 94d6a56a..92f268da 100644 --- a/src/core/dhcp.c +++ b/src/core/dhcp.c @@ -360,13 +360,19 @@ dhcp_coarse_tmr() while (netif != NULL) { /* only act on DHCP configured interfaces */ if (netif->dhcp != NULL) { + /* compare lease time to expire timeout */ + if (++netif->dhcp->lease_used == netif->dhcp->t0_timeout) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t0 timeout\n")); + /* this clients' lease time has expired */ + dhcp_release(netif); + dhcp_discover(netif); /* timer is active (non zero), and triggers (zeroes) now? */ - if (netif->dhcp->t2_timeout-- == 1) { + } else if (netif->dhcp->t2_rebind_time-- == 1) { LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n")); /* this clients' rebind timeout triggered */ dhcp_t2_timeout(netif); /* timer is active (non zero), and triggers (zeroes) now */ - } else if (netif->dhcp->t1_timeout-- == 1) { + } else if (netif->dhcp->t1_renew_time-- == 1) { LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n")); /* this clients' renewal timeout triggered */ dhcp_t1_timeout(netif); @@ -448,23 +454,6 @@ dhcp_timeout(struct netif *netif) dhcp_bind(netif); } #endif /* DHCP_DOES_ARP_CHECK */ - } - /* did not get response to renew request? */ - else if (dhcp->state == DHCP_RENEWING) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RENEWING, DHCP request timed out\n")); - /* just retry renewal */ - /* note that the rebind timer will eventually time-out if renew does not work */ - dhcp_renew(netif); - /* did not get response to rebind request? */ - } else if (dhcp->state == DHCP_REBINDING) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REBINDING, DHCP request timed out\n")); - if (dhcp->tries <= 8) { - dhcp_rebind(netif); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RELEASING, DISCOVERING\n")); - dhcp_release(netif); - dhcp_discover(netif); - } } else if (dhcp->state == DHCP_REBOOTING) { if (dhcp->tries < REBOOT_TRIES) { dhcp_reboot(netif); @@ -493,6 +482,11 @@ dhcp_t1_timeout(struct netif *netif) /* This slightly different to RFC2131: DHCPREQUEST will be sent from state DHCP_RENEWING, not DHCP_BOUND */ dhcp_renew(netif); + /* Calculate next timeout */ + if (((netif->dhcp->t2_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) + { + netif->dhcp->t1_renew_time = ((netif->dhcp->t2_timeout - dhcp->lease_used) / 2); + } } } @@ -507,13 +501,18 @@ dhcp_t2_timeout(struct netif *netif) struct dhcp *dhcp = netif->dhcp; LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n")); if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || - (dhcp->state == DHCP_RENEWING)) { + (dhcp->state == DHCP_RENEWING) || (dhcp->state == DHCP_REBINDING)) { /* just retry to rebind */ LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout(): must rebind\n")); /* This slightly different to RFC2131: DHCPREQUEST will be sent from state DHCP_REBINDING, not DHCP_BOUND */ dhcp_rebind(netif); + /* Calculate next timeout */ + if (((netif->dhcp->t0_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) + { + netif->dhcp->t2_rebind_time = ((netif->dhcp->t0_timeout - dhcp->lease_used) / 2); + } } } @@ -559,8 +558,8 @@ dhcp_handle_ack(struct netif *netif) /* remember given rebind period */ dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2); } else { - /* calculate safe periods for rebinding */ - dhcp->offered_t2_rebind = dhcp->offered_t0_lease; + /* calculate safe periods for rebinding (offered_t0_lease * 0.875 -> 87.5%)*/ + dhcp->offered_t2_rebind = (dhcp->offered_t0_lease * 7U) / 8U; } /* (y)our internet address */ @@ -966,6 +965,23 @@ dhcp_bind(struct netif *netif) LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* reset time used of lease */ + dhcp->lease_used = 0; + + if (dhcp->offered_t0_lease != 0xffffffffUL) { + /* set renewal period timer */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t0 renewal timer %"U32_F" secs\n", dhcp->offered_t0_lease)); + timeout = (dhcp->offered_t0_lease + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if(timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t0_timeout = (u16_t)timeout; + if (dhcp->t0_timeout == 0) { + dhcp->t0_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t0_lease*1000)); + } + /* temporary DHCP lease? */ if (dhcp->offered_t1_renew != 0xffffffffUL) { /* set renewal period timer */ @@ -979,6 +995,7 @@ dhcp_bind(struct netif *netif) dhcp->t1_timeout = 1; } LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000)); + dhcp->t1_renew_time = dhcp->t1_timeout; } /* set renewal period timer */ if (dhcp->offered_t2_rebind != 0xffffffffUL) { @@ -992,6 +1009,7 @@ dhcp_bind(struct netif *netif) dhcp->t2_timeout = 1; } LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000)); + dhcp->t2_rebind_time = dhcp->t2_timeout; } /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */ diff --git a/src/include/lwip/dhcp.h b/src/include/lwip/dhcp.h index 3526f036..04f9f30e 100644 --- a/src/include/lwip/dhcp.h +++ b/src/include/lwip/dhcp.h @@ -49,6 +49,10 @@ struct dhcp u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ + u16_t t1_renew_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew try */ + u16_t t2_rebind_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next rebind try */ + u16_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */ + u16_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */ ip_addr_t server_ip_addr; /* dhcp server address that offered this lease */ ip_addr_t offered_ip_addr; ip_addr_t offered_sn_mask; @@ -56,7 +60,7 @@ struct dhcp u32_t offered_t0_lease; /* lease period (in seconds) */ u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ - u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period) */ + u32_t offered_t2_rebind; /* recommended rebind time (usually 87.5 of lease period) */ #if LWIP_DHCP_BOOTP_FILE ip_addr_t offered_si_addr; char boot_file_name[DHCP_FILE_LEN]; @@ -161,9 +165,9 @@ void dhcp_fine_tmr(void); #define DHCP_REBINDING 4 #define DHCP_RENEWING 5 #define DHCP_SELECTING 6 -/* not yet implemented #define DHCP_INFORMING 7*/ +#define DHCP_INFORMING 7 #define DHCP_CHECKING 8 -/* not yet implemented #define DHCP_PERMANENT 9*/ +#define DHCP_PERMANENT 9 #define DHCP_BOUND 10 /** not yet implemented #define DHCP_RELEASING 11 */ #define DHCP_BACKING_OFF 12