]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Add a delay to initial Rebind IA_PD message.
authorRoy Marples <roy@marples.name>
Tue, 18 Jun 2013 09:17:28 +0000 (09:17 +0000)
committerRoy Marples <roy@marples.name>
Tue, 18 Jun 2013 09:17:28 +0000 (09:17 +0000)
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.

dhcp6.c
dhcpcd.c
eloop.c
if-options.h

diff --git a/dhcp6.c b/dhcp6.c
index 08a51a873b438cf9a20cb5b8b03e58938077045d..ecb6a1c0b7e9c9f24aa0cf98eeea283643750b7a 100644 (file)
--- 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";
index f57818697ec4bad79f071631b1c31e88f2284337..0ded685caf06d5b4368cfa20968371ad41b81043 100644 (file)
--- 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 7f7364cd23d39dab56ea78f5146519e491b37efb..0a7f69a63e3e9e92ff71fb25920d7f8a6ac4b2ba 100644 (file)
--- 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;
 }
index 579a0ffa043d7c14259db1b1c958a9e9a0eb9dce..06cccdf0c16828b0279972a64bcad5c3e2f91212 100644 (file)
@@ -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[];