From d83fc6893b75a773a4fd75366d704a25c43ef7b4 Mon Sep 17 00:00:00 2001 From: stoklund Date: Mon, 24 Aug 2009 13:11:35 +0000 Subject: [PATCH] Don't use an AutoIP-configured address on a new network until the address has been configured. When connecting to a new network with an AutoIP address, take the interface down until the old address has passed the AUTOIP_STATE_PROBING state. --- src/core/ipv4/autoip.c | 70 +++++++++++++++++++++++++++------- src/core/netif.c | 21 +++++++--- src/include/ipv4/lwip/autoip.h | 3 ++ 3 files changed, 76 insertions(+), 18 deletions(-) diff --git a/src/core/ipv4/autoip.c b/src/core/ipv4/autoip.c index 367adb06..225db4b6 100644 --- a/src/core/ipv4/autoip.c +++ b/src/core/ipv4/autoip.c @@ -110,12 +110,18 @@ static void autoip_handle_arp_conflict(struct netif *netif); /* creates a pseudo random LL IP-Address for a network interface */ static void autoip_create_addr(struct netif *netif, struct ip_addr *IPAddr); +/* sends an ARP probe */ +static err_t autoip_arp_probe(struct netif *netif); + /* sends an ARP announce */ static err_t autoip_arp_announce(struct netif *netif); /* configure interface for use with current LL IP-Address */ static err_t autoip_bind(struct netif *netif); +/* start sending probes for llipaddr */ +static void autoip_start_probing(struct netif *netif); + /** * Initialize this module */ @@ -191,6 +197,19 @@ autoip_create_addr(struct netif *netif, struct ip_addr *IPAddr) (u16_t)(netif->autoip->tried_llipaddr), (u32_t)(IPAddr->addr))); } +/** + * Sends an ARP probe from a network interface + * + * @param netif network interface used to send the probe + */ +static err_t +autoip_arp_probe(struct netif *netif) +{ + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, IP_ADDR_ANY, ðzero, + &netif->autoip->llipaddr, ARP_REQUEST); +} + /** * Sends an ARP announce from a network interface * @@ -281,6 +300,16 @@ autoip_start(struct netif *netif) autoip_create_addr(netif, &(autoip->llipaddr)); autoip->tried_llipaddr++; + autoip_start_probing(netif); + + return result; +} + +static void +autoip_start_probing(struct netif *netif) +{ + struct autoip *autoip = netif->autoip; + autoip->state = AUTOIP_STATE_PROBING; autoip->sent_num = 0; @@ -295,12 +324,24 @@ autoip_start(struct netif *netif) * accquiring and probing address * compliant to RFC 3927 Section 2.2.1 */ - if(autoip->tried_llipaddr > MAX_CONFLICTS) { autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND; } +} - return result; +/** + * Handle a possible change in the network configuration. + * + * If there is an AutoIP address configured, take the interface down + * and begin probing with the same address. + */ +void +autoip_network_changed(struct netif *netif) +{ + if (netif->autoip && netif->autoip->state != AUTOIP_STATE_OFF) { + netif_set_down(netif); + autoip_start_probing(netif); + } } /** @@ -340,12 +381,12 @@ autoip_tmr() if(netif->autoip->ttw > 0) { netif->autoip->ttw--; } else { - if(netif->autoip->sent_num == PROBE_NUM) { + if(netif->autoip->sent_num >= PROBE_NUM) { netif->autoip->state = AUTOIP_STATE_ANNOUNCING; netif->autoip->sent_num = 0; netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; } else { - etharp_request(netif, &(netif->autoip->llipaddr)); + autoip_arp_probe(netif); LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3, ("autoip_tmr() PROBING Sent Probe\n")); netif->autoip->sent_num++; @@ -363,21 +404,24 @@ autoip_tmr() } else { if(netif->autoip->sent_num == 0) { /* We are here the first time, so we waited ANNOUNCE_WAIT seconds - * Now we can bind to an IP address and use it + * Now we can bind to an IP address and use it. + * + * autoip_bind calls netif_set_up. This triggers a gratuitous ARP + * which counts as an announcement. */ autoip_bind(netif); - } - - if(netif->autoip->sent_num == ANNOUNCE_NUM) { - netif->autoip->state = AUTOIP_STATE_BOUND; - netif->autoip->sent_num = 0; - netif->autoip->ttw = 0; } else { autoip_arp_announce(netif); LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | 3, ("autoip_tmr() ANNOUNCING Sent Announce\n")); - netif->autoip->sent_num++; - netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; + } + netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; + netif->autoip->sent_num++; + + if(netif->autoip->sent_num >= ANNOUNCE_NUM) { + netif->autoip->state = AUTOIP_STATE_BOUND; + netif->autoip->sent_num = 0; + netif->autoip->ttw = 0; } } break; diff --git a/src/core/netif.c b/src/core/netif.c index c9b6b9b5..d8be7970 100644 --- a/src/core/netif.c +++ b/src/core/netif.c @@ -52,6 +52,10 @@ #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ #endif /* ENABLE_LOOPBACK */ +#if LWIP_AUTOIP +#include "lwip/autoip.h" +#endif /* LWIP_AUTOIP */ + #if LWIP_NETIF_STATUS_CALLBACK #define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); } #else @@ -459,6 +463,13 @@ void netif_set_link_up(struct netif *netif ) { netif->flags |= NETIF_FLAG_LINK_UP; +#if LWIP_AUTOIP + if (netif->autoip) { + autoip_network_changed(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) { @@ -467,12 +478,12 @@ void netif_set_link_up(struct netif *netif ) #endif /* LWIP_ARP */ #if LWIP_IGMP - /* resend IGMP memberships */ - if (netif->flags & NETIF_FLAG_IGMP) { - igmp_report_groups( netif); - } + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups( netif); + } #endif /* LWIP_IGMP */ - + } NETIF_LINK_CALLBACK(netif); } diff --git a/src/include/ipv4/lwip/autoip.h b/src/include/ipv4/lwip/autoip.h index 076a2ed2..fe0d6280 100644 --- a/src/include/ipv4/lwip/autoip.h +++ b/src/include/ipv4/lwip/autoip.h @@ -100,6 +100,9 @@ void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr); /** Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds */ void autoip_tmr(void); +/** Handle a possible change in the network configuration */ +void autoip_network_changed(struct netif *netif); + #endif /* LWIP_AUTOIP */ #endif /* __LWIP_AUTOIP_H__ */