Fix bug #50242: dhcp_release does not stop autoip (in coop mode)

Create new function dhcp_release_and_stop() that stops DHCP statemachine and sends release message if needed. Also stops AUTOIP if in coop mode.
Old dhcp_release() and dhcp_stop() function internally call dhcp_release_and_stop() now.
This commit is contained in:
Dirk Ziegelmeier 2017-03-01 13:18:37 +01:00
parent d8135f9ae2
commit ec4f00179d
2 changed files with 61 additions and 59 deletions

View File

@ -1271,31 +1271,30 @@ dhcp_reboot(struct netif *netif)
return result; return result;
} }
/** /**
* @ingroup dhcp4 * @ingroup dhcp4
* Release a DHCP lease (usually called before @ref dhcp_stop). * Release a DHCP lease and stop DHCP statemachine (and AUTOIP if LWIP_DHCP_AUTOIP_COOP).
* *
* @param netif network interface which must release its lease * @param netif network interface
*/ */
err_t void
dhcp_release(struct netif *netif) dhcp_release_and_stop(struct netif *netif)
{ {
struct dhcp *dhcp = netif_dhcp_data(netif); struct dhcp *dhcp = netif_dhcp_data(netif);
err_t result;
ip_addr_t server_ip_addr; ip_addr_t server_ip_addr;
u8_t is_dhcp_supplied_address;
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release_and_stop()\n"));
if (dhcp == NULL) { if (dhcp == NULL) {
return ERR_ARG; return;
} }
/* already off? -> nothing to do */
if (dhcp->state == DHCP_STATE_OFF) {
return;
}
ip_addr_copy(server_ip_addr, dhcp->server_ip_addr); ip_addr_copy(server_ip_addr, dhcp->server_ip_addr);
is_dhcp_supplied_address = dhcp_supplied_address(netif);
/* idle DHCP client */
dhcp_set_state(dhcp, DHCP_STATE_OFF);
/* clean old DHCP offer */ /* clean old DHCP offer */
ip_addr_set_zero_ip4(&dhcp->server_ip_addr); ip_addr_set_zero_ip4(&dhcp->server_ip_addr);
ip4_addr_set_zero(&dhcp->offered_ip_addr); ip4_addr_set_zero(&dhcp->offered_ip_addr);
@ -1307,65 +1306,67 @@ dhcp_release(struct netif *netif)
dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0; dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0;
dhcp->t1_renew_time = dhcp->t2_rebind_time = dhcp->lease_used = dhcp->t0_timeout = 0; dhcp->t1_renew_time = dhcp->t2_rebind_time = dhcp->lease_used = dhcp->t0_timeout = 0;
if (!is_dhcp_supplied_address) { /* send release message when current IP was assigned via DHCP */
/* don't issue release message when address is not dhcp-assigned */ if (dhcp_supplied_address(netif)) {
return ERR_OK; /* create and initialize the DHCP message header */
err_t result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE);
if (result == ERR_OK) {
dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&server_ip_addr))));
dhcp_option_trailer(dhcp);
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
udp_sendto_if(dhcp_pcb, dhcp->p_out, &server_ip_addr, DHCP_SERVER_PORT, netif);
dhcp_delete_msg(dhcp);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_STATE_OFF\n"));
} else {
/* sending release failed, but that's not a problem since the correct behaviour of dhcp does not rely on release */
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n"));
}
} }
/* create and initialize the DHCP message header */
result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE);
if (result == ERR_OK) {
dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&server_ip_addr))));
dhcp_option_trailer(dhcp);
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
udp_sendto_if(dhcp_pcb, dhcp->p_out, &server_ip_addr, DHCP_SERVER_PORT, netif);
dhcp_delete_msg(dhcp);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_STATE_OFF\n"));
} else {
/* sending release failed, but that's not a problem since the correct behaviour of dhcp does not rely on release */
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n"));
}
/* remove IP address from interface (prevents routing from selecting this interface) */ /* remove IP address from interface (prevents routing from selecting this interface) */
netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
return result; #if LWIP_DHCP_AUTOIP_COOP
if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
autoip_stop(netif);
dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
}
#endif /* LWIP_DHCP_AUTOIP_COOP */
LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL);
dhcp_set_state(dhcp, DHCP_STATE_OFF);
if (dhcp->pcb_allocated != 0) {
dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */
dhcp->pcb_allocated = 0;
}
} }
/** /**
* @ingroup dhcp4 * @ingroup dhcp4
* Remove the DHCP client from the interface. * @deprecated Use dhcp_release_and_stop() instead.
* * This function calls dhcp_release_and_stop() internally.
* @param netif The network interface to stop DHCP on */
err_t
dhcp_release(struct netif *netif)
{
dhcp_release_and_stop(netif);
return ERR_OK;
}
/**
* @ingroup dhcp4
* @deprecated Use dhcp_release_and_stop() instead.
* This function calls dhcp_release_and_stop() internally.
*/ */
void void
dhcp_stop(struct netif *netif) dhcp_stop(struct netif *netif)
{ {
struct dhcp *dhcp; dhcp_release_and_stop(netif);
LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;);
dhcp = netif_dhcp_data(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n"));
/* netif is DHCP configured? */
if (dhcp != NULL) {
#if LWIP_DHCP_AUTOIP_COOP
if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
autoip_stop(netif);
dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
}
#endif /* LWIP_DHCP_AUTOIP_COOP */
LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL);
dhcp_set_state(dhcp, DHCP_STATE_OFF);
if (dhcp->pcb_allocated != 0) {
dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */
dhcp->pcb_allocated = 0;
}
}
} }
/* /*

View File

@ -114,6 +114,7 @@ err_t dhcp_start(struct netif *netif);
err_t dhcp_renew(struct netif *netif); err_t dhcp_renew(struct netif *netif);
err_t dhcp_release(struct netif *netif); err_t dhcp_release(struct netif *netif);
void dhcp_stop(struct netif *netif); void dhcp_stop(struct netif *netif);
void dhcp_release_and_stop(struct netif *netif);
void dhcp_inform(struct netif *netif); void dhcp_inform(struct netif *netif);
void dhcp_network_changed(struct netif *netif); void dhcp_network_changed(struct netif *netif);
#if DHCP_DOES_ARP_CHECK #if DHCP_DOES_ARP_CHECK