fixed bug #37068 (netif up/down handling is unclear): correclty separated administrative status of a netif (up/down) from 'valid address' status ATTENTION: netif_set_up() now always has to be called, even when dhcp/autoip is used!

This commit is contained in:
sg 2015-03-05 20:57:43 +01:00
parent 72dcdb7655
commit 4e520cdd30
5 changed files with 86 additions and 89 deletions

View File

@ -6,6 +6,13 @@ HISTORY
++ New features:
2015-03-05: Simon Goldschmidt
* netif.c, ip4.c, dhcp.c, autoip.c: fixed bug #37068 (netif up/down handling
is unclear): correclty separated administrative status of a netif (up/down)
from 'valid address' status
ATTENTION: netif_set_up() now always has to be called, even when dhcp/autoip
is used!
2015-02-26: patch by TabascoEye
* netif.c, udp.h/.c: fixed bug #40753 (re-bind UDP pcbs on change of IP address)

View File

@ -221,12 +221,8 @@ dhcp_handle_nak(struct netif *netif)
struct dhcp *dhcp = netif->dhcp;
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
/* Set the interface down since the address must no longer be used, as per RFC2131 */
netif_set_down(netif);
/* remove IP address from interface */
netif_set_ipaddr(netif, IP_ADDR_ANY);
netif_set_gw(netif, IP_ADDR_ANY);
netif_set_netmask(netif, IP_ADDR_ANY);
/* remove IP address from interface (must no longer be used, as per RFC2131) */
netif_set_addr(netif, IP_ADDR_ANY, IP_ADDR_ANY, IP_ADDR_ANY);
/* Change to a defined state */
dhcp_set_state(dhcp, DHCP_BACKING_OFF);
/* We can immediately restart discovery */
@ -663,6 +659,7 @@ dhcp_start(struct netif *netif)
err_t result;
LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;);
dhcp = netif->dhcp;
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
@ -808,7 +805,6 @@ dhcp_network_changed(struct netif *netif)
case DHCP_RENEWING:
case DHCP_BOUND:
case DHCP_REBOOTING:
netif_set_down(netif);
dhcp->tries = 0;
dhcp_reboot(netif);
break;
@ -1034,17 +1030,11 @@ dhcp_bind(struct netif *netif)
}
#endif /* LWIP_DHCP_AUTOIP_COOP */
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n",
ip4_addr_get_u32(&dhcp->offered_ip_addr)));
netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n",
ip4_addr_get_u32(&sn_mask)));
netif_set_netmask(netif, &sn_mask);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n",
ip4_addr_get_u32(&gw_addr)));
netif_set_gw(netif, &gw_addr);
/* bring the interface up */
netif_set_up(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F" SN: 0x%08"X32_F" GW: 0x%08"X32_F"\n",
ip4_addr_get_u32(&dhcp->offered_ip_addr), ip4_addr_get_u32(&sn_mask), ip4_addr_get_u32(&gw_addr)));
netif_set_addr(netif, &dhcp->offered_ip_addr, &sn_mask, &gw_addr);
/* interface is used by routing now that an address is set */
/* netif is now bound to DHCP leased address */
dhcp_set_state(dhcp, DHCP_BOUND);
}
@ -1240,13 +1230,9 @@ dhcp_release(struct netif *netif)
msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs));
/* bring the interface down */
netif_set_down(netif);
/* remove IP address from interface */
netif_set_ipaddr(netif, IP_ADDR_ANY);
netif_set_gw(netif, IP_ADDR_ANY);
netif_set_netmask(netif, IP_ADDR_ANY);
/* remove IP address from interface (prevents routing from selecting this interface) */
netif_set_addr(netif, IP_ADDR_ANY, IP_ADDR_ANY, IP_ADDR_ANY);
return result;
}

View File

@ -266,12 +266,8 @@ autoip_bind(struct netif *netif)
IP4_ADDR(&sn_mask, 255, 255, 0, 0);
IP4_ADDR(&gw_addr, 0, 0, 0, 0);
netif_set_ipaddr(netif, &autoip->llipaddr);
netif_set_netmask(netif, &sn_mask);
netif_set_gw(netif, &gw_addr);
/* bring the interface up */
netif_set_up(netif);
netif_set_addr(netif, &autoip->llipaddr, &sn_mask, &gw_addr);
/* interface is used by routing now that an address is set */
return ERR_OK;
}
@ -287,16 +283,12 @@ autoip_start(struct netif *netif)
struct autoip *autoip = netif->autoip;
err_t result = ERR_OK;
if (netif_is_up(netif)) {
netif_set_down(netif);
}
LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;);
/* Set IP-Address, Netmask and Gateway to 0 to make sure that
* ARP Packets are formed correctly
*/
ip_addr_set_zero(&netif->ip_addr);
ip_addr_set_zero(&netif->netmask);
ip_addr_set_zero(&netif->gw);
netif_set_addr(netif, IP_ADDR_ANY, IP_ADDR_ANY, IP_ADDR_ANY);
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0],
@ -367,7 +359,6 @@ void
autoip_network_changed(struct netif *netif)
{
if (netif->autoip && netif->autoip->state != AUTOIP_STATE_OFF) {
netif_set_down(netif);
autoip_start_probing(netif);
}
}
@ -380,8 +371,12 @@ autoip_network_changed(struct netif *netif)
err_t
autoip_stop(struct netif *netif)
{
netif->autoip->state = AUTOIP_STATE_OFF;
netif_set_down(netif);
if (netif->autoip) {
netif->autoip->state = AUTOIP_STATE_OFF;
if (ip_addr_islinklocal(&netif->ip_addr)) {
netif_set_addr(netif, IP_ADDR_ANY, IP_ADDR_ANY, IP_ADDR_ANY);
}
}
return ERR_OK;
}
@ -438,7 +433,7 @@ autoip_tmr()
/* We are here the first time, so we waited ANNOUNCE_WAIT seconds
* Now we can bind to an IP address and use it.
*
* autoip_bind calls netif_set_up. This triggers a gratuitous ARP
* autoip_bind calls netif_set_addr. This triggers a gratuitous ARP
* which counts as an announcement.
*/
autoip_bind(netif);

View File

@ -153,7 +153,8 @@ ip_route(const ip_addr_t *dest)
}
}
}
if ((netif_default == NULL) || (!netif_is_up(netif_default))) {
if ((netif_default == NULL) || !netif_is_up(netif_default) ||
ip_addr_isany(&netif_default->ip_addr)) {
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
IP_STATS_INC(ip.rterr);

View File

@ -85,6 +85,10 @@ struct netif *netif_default;
static u8_t netif_num;
#define NETIF_REPORT_TYPE_IPV4 0x01
#define NETIF_REPORT_TYPE_IPV6 0x02
static void netif_issue_reports(struct netif* netif, u8_t report_type);
#if LWIP_IPV6
static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr);
#endif /* LWIP_IPV6 */
@ -281,9 +285,10 @@ void
netif_set_addr(struct netif *netif, const ip_addr_t *ipaddr, const ip_addr_t *netmask,
const ip_addr_t *gw)
{
netif_set_ipaddr(netif, ipaddr);
netif_set_netmask(netif, netmask);
netif_set_gw(netif, gw);
/* set ipaddr last to ensure netmask/gw have been set when status callback is called */
netif_set_ipaddr(netif, ipaddr);
}
/**
@ -394,8 +399,9 @@ netif_find(char *name)
void
netif_set_ipaddr(struct netif *netif, const ip_addr_t *ipaddr)
{
ip_addr_t new_addr = (ipaddr ? *ipaddr : *IP_ADDR_ANY);
/* address is actually being changed? */
if (ipaddr && (ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) {
if (ip_addr_cmp(&new_addr, &(netif->ip_addr)) == 0) {
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n"));
#if LWIP_TCP
tcp_netif_ipv4_addr_changed(&netif->ip_addr, ipaddr);
@ -403,14 +409,18 @@ netif_set_ipaddr(struct netif *netif, const ip_addr_t *ipaddr)
#if LWIP_UDP
udp_netif_ipv4_addr_changed(&netif->ip_addr, ipaddr);
#endif /* LWIP_UDP */
}
snmp_delete_ipaddridx_tree(netif);
snmp_delete_iprteidx_tree(0, netif);
/* set new IP address to netif */
ip_addr_set(&(netif->ip_addr), ipaddr);
snmp_insert_ipaddridx_tree(netif);
snmp_insert_iprteidx_tree(0, netif);
snmp_delete_ipaddridx_tree(netif);
snmp_delete_iprteidx_tree(0, netif);
/* set new IP address to netif */
ip_addr_set(&(netif->ip_addr), ipaddr);
snmp_insert_ipaddridx_tree(netif);
snmp_insert_iprteidx_tree(0, netif);
netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4);
NETIF_STATUS_CALLBACK(netif);
}
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
netif->name[0], netif->name[1],
@ -498,7 +508,7 @@ void netif_set_up(struct netif *netif)
{
if (!(netif->flags & NETIF_FLAG_UP)) {
netif->flags |= NETIF_FLAG_UP;
#if LWIP_SNMP
snmp_get_sysuptime(&netif->ts);
#endif /* LWIP_SNMP */
@ -506,31 +516,45 @@ void netif_set_up(struct netif *netif)
NETIF_STATUS_CALLBACK(netif);
if (netif->flags & NETIF_FLAG_LINK_UP) {
netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6);
}
}
}
/** Send ARP/IGMP/MLD/RS events, e.g. on link-up/netif-up or addr-change
*/
static void
netif_issue_reports(struct netif* netif, u8_t report_type)
{
if ((report_type & NETIF_REPORT_TYPE_IPV4) &&
!ip_addr_isany(&netif->ip_addr)) {
#if LWIP_ARP
/* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
if (netif->flags & (NETIF_FLAG_ETHARP)) {
etharp_gratuitous(netif);
}
/* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
if (netif->flags & (NETIF_FLAG_ETHARP)) {
etharp_gratuitous(netif);
}
#endif /* LWIP_ARP */
#if LWIP_IGMP
/* resend IGMP memberships */
if (netif->flags & NETIF_FLAG_IGMP) {
igmp_report_groups( netif);
}
#endif /* LWIP_IGMP */
#if LWIP_IPV6 && LWIP_IPV6_MLD
/* send mld memberships */
mld6_report_groups( netif);
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
#if LWIP_IPV6_SEND_ROUTER_SOLICIT
/* Send Router Solicitation messages. */
netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT;
#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
/* resend IGMP memberships */
if (netif->flags & NETIF_FLAG_IGMP) {
igmp_report_groups(netif);
}
#endif /* LWIP_IGMP */
}
#if LWIP_IPV6
if (report_type & NETIF_REPORT_TYPE_IPV6) {
#if LWIP_IPV6_MLD
/* send mld memberships */
mld6_report_groups(netif);
#endif /* LWIP_IPV6_MLD */
#if LWIP_IPV6_SEND_ROUTER_SOLICIT
/* Send Router Solicitation messages. */
netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT;
#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
}
#endif /* LWIP_IPV6 */
}
/**
@ -560,7 +584,7 @@ void netif_set_down(struct netif *netif)
#if LWIP_NETIF_STATUS_CALLBACK
/**
* Set callback to be called when interface is brought up/down
* Set callback to be called when interface is brought up/down or address is changed while up
*/
void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback)
{
@ -604,23 +628,7 @@ void netif_set_link_up(struct netif *netif )
#endif /* LWIP_AUTOIP */
if (netif->flags & NETIF_FLAG_UP) {
#if LWIP_ARP
/* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
if (netif->flags & NETIF_FLAG_ETHARP) {
etharp_gratuitous(netif);
}
#endif /* LWIP_ARP */
#if LWIP_IGMP
/* resend IGMP memberships */
if (netif->flags & NETIF_FLAG_IGMP) {
igmp_report_groups( netif);
}
#endif /* LWIP_IGMP */
#if LWIP_IPV6 && LWIP_IPV6_MLD
/* send mld memberships */
mld6_report_groups( netif);
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6);
}
NETIF_LINK_CALLBACK(netif);
}