From: Roy Marples Date: Tue, 18 Jun 2013 09:17:28 +0000 (+0000) Subject: Add a delay to initial Rebind IA_PD message. X-Git-Tag: v6.0.0~13 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a945c63ad93e801765afbd4c900740861118abbb;p=thirdparty%2Fdhcpcd.git Add a delay to initial Rebind IA_PD message. Delay initial DHCPv6 messages a futher 2 seconds for POINTOPOINT links to try and ensure dhcpcd receives a reply. Process link events last so that dhcpcd can process any rejection messages. When a delegating interface stops, the delegates addresses will be removed. --- diff --git a/dhcp6.c b/dhcp6.c index 08a51a87..ecb6a1c0 100644 --- a/dhcp6.c +++ b/dhcp6.c @@ -742,7 +742,14 @@ dhcp6_sendmessage(struct interface *ifp, void (*callback)(void *)) state->send->xid[2]); else { if (state->IMD) { - state->RT.tv_sec = 0; + /* Some buggy PPP servers close the link too early + * after sending an invalid status in their reply + * which means this host won't see it. + * 2 seconds grace seems to be the sweet spot. */ + if (ifp->flags & IFF_POINTOPOINT) + state->RT.tv_sec = 2; + else + state->RT.tv_sec = 0; state->RT.tv_usec = arc4random() % (state->IMD * 1000000); timernorm(&state->RT); @@ -1008,11 +1015,12 @@ dhcp6_startrebind(void *arg) /* RFC 3633 section 12.1 */ if (ifp->options->ia_type == D6_OPTION_IA_PD) { - state->IRT = CNF_TIMEOUT; - state->MRT = CNF_MAX_RT; + state->IMD = CNF_MAX_DELAY; + state->IRT = CNF_TIMEOUT; + state->MRT = CNF_MAX_RT; } else { - state->IRT = REB_TIMEOUT; - state->MRT = REB_MAX_RT; + state->IRT = REB_TIMEOUT; + state->MRT = REB_MAX_RT; } if (dhcp6_makemessage(ifp) == -1) @@ -2392,10 +2400,20 @@ dhcp6_freedrop(struct interface *ifp, int drop, const char *reason) if (ifp->options->options & DHCPCD_RELEASE) { if (ifp->carrier != LINK_DOWN) dhcp6_startrelease(ifp); - dhcp6_delete_delegates(ifp); unlink(state->leasefile); } dhcp6_freedrop_addrs(ifp, drop, NULL); + /* As the interface is going away from dhcpcd we need to + * remove the delegated addresses, otherwise we lose track + * of which interface is delegating as we remeber it by pointer. + * So if we need to change this behaviour, we need to change + * how we remember which interface delegated. + * To make it more interesting, on some OS's with PPP links + * there is no guarantee the delegating interface will have + * the same name or index so think very hard before changing + * this. */ + if (ifp->options->options & (DHCPCD_STOPPING | DHCPCD_RELEASE)) + dhcp6_delete_delegates(ifp); if (drop && state->new) { if (reason == NULL) reason = "STOP6"; diff --git a/dhcpcd.c b/dhcpcd.c index f5781869..0ded685c 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -274,6 +274,7 @@ stop_interface(struct interface *ifp) { syslog(LOG_INFO, "%s: removing interface", ifp->name); + ifp->options->options |= DHCPCD_STOPPING; // Remove the interface from our list TAILQ_REMOVE(ifaces, ifp, next); diff --git a/eloop.c b/eloop.c index 7f7364cd..0a7f69a6 100644 --- a/eloop.c +++ b/eloop.c @@ -132,7 +132,13 @@ eloop_event_add(int fd, void (*callback)(void *), void *arg) e->fd = fd; e->callback = callback; e->arg = arg; - TAILQ_INSERT_TAIL(&events, e, next); + /* The order of events should not matter. + * However, some PPP servers love to close the link right after + * sending their final message. So to ensure dhcpcd processes this + * message (which is likely to be that the DHCP addresses are wrong) + * we insert new events at the queue head as the link fd will be + * the first event added. */ + TAILQ_INSERT_HEAD(&events, e, next); eloop_event_setup_fds(); return 0; } diff --git a/if-options.h b/if-options.h index 579a0ffa..06cccdf0 100644 --- a/if-options.h +++ b/if-options.h @@ -92,7 +92,8 @@ #define DHCPCD_STARTED (1ULL << 38) #define DHCPCD_NOALIAS (1ULL << 39) #define DHCPCD_IA_FORCED (1ULL << 40) -#define DHCPCD_DEPARTED (1ULL << 41) +#define DHCPCD_STOPPING (1ULL << 41) +#define DHCPCD_DEPARTED (1ULL << 42) extern const struct option cf_options[];