]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
DHCPv6: confirm lease on carrier up
authorRoy Marples <roy@marples.name>
Tue, 14 Nov 2017 16:41:59 +0000 (16:41 +0000)
committerRoy Marples <roy@marples.name>
Tue, 14 Nov 2017 16:41:59 +0000 (16:41 +0000)
On some platforms which preserve state when carrier goes down,
such as NetBSD-8, the state does not enter the CONFIRM state.
Add more logic to dhcp6_start so that we can better control this
from the various call points.

src/dhcp6.c
src/dhcpcd.c
src/ipv6nd.c

index 2910274a49fe9687c806b0e4037c07e4a490f5e4..7e85a455c4f889209254e28e7bae12e637101e38 100644 (file)
@@ -3673,28 +3673,47 @@ dhcp6_start(struct interface *ifp, enum DH6S init_state)
        struct dhcp6_state *state;
 
        state = D6_STATE(ifp);
-       if (state) {
-               if (state->state == DH6S_INFORMED &&
-                   init_state == DH6S_INFORM)
-               {
-                       dhcp6_startinform(ifp);
-                       return 0;
-               }
-               if (init_state == DH6S_INIT &&
-                   ifp->options->options & DHCPCD_DHCP6 &&
-                   (state->state == DH6S_INFORM ||
-                   state->state == DH6S_INFORMED ||
-                   state->state == DH6S_DELEGATED))
-               {
-                       /* Change from stateless to stateful */
+       if (state != NULL) {
+               switch (init_state) {
+               case DH6S_INIT:
+                       /* This should only happen on OS's where we keep state
+                        * on carrier down, such as NetBSD-8. */
                        goto gogogo;
+               case DH6S_INFORM:
+                       if (state->state == DH6S_INFORMED)
+                               dhcp6_startinform(ifp);
+                       break;
+               case DH6S_REQUEST:
+                       if (ifp->options->options & DHCPCD_DHCP6 &&
+                           (state->state == DH6S_INFORM ||
+                            state->state == DH6S_INFORMED ||
+                            state->state == DH6S_DELEGATED))
+                       {
+                               /* Change from stateless to stateful */
+                               init_state = DH6S_INIT;
+                               goto gogogo;
+                       }
+                       break;
+               case DH6S_CONFIRM:
+                       /* This should only happen on OS's where we keep state
+                        * on carrier down, such as NetBSD-8. */
+                       init_state = DH6S_INIT;
+                       goto gogogo;
+               default:
+                       /* Not possible, but sushes some compiler warnings. */
+                       break;
                }
-               /* We're already running DHCP6 */
-               /* XXX: What if the managed flag vanishes from all RA? */
-#ifndef SMALL
-               dhcp6_activateinterfaces(ifp);
-#endif
                return 0;
+       } else {
+               switch (init_state) {
+               case DH6S_CONFIRM:
+                       /* No DHCPv6 config, no existing state
+                        * so nothing to do. */
+                       return 0;
+               default:
+                       init_state = DH6S_INIT;
+                       break;
+               }
        }
 
        if (!(ifp->options->options & DHCPCD_DHCP6))
index 8b3ac1b5baacc2605ca30da6c6ddd56248a97c80..e677e4c62a0a32a2ec3f644117b9a7277d56440c 100644 (file)
@@ -871,37 +871,22 @@ dhcpcd_startinterface(void *arg)
                                ipv6nd_startrs(ifp);
                }
 
-               if (ifo->options & DHCPCD_DHCP6)
+
+               if (ifo->options & DHCPCD_DHCP6) {
                        dhcp6_find_delegates(ifp);
 
-               if ((!(ifo->options & DHCPCD_IPV6RS) ||
-                   ifo->options & (DHCPCD_IA_FORCED | DHCPCD_INFORM6)) &&
-                   ifp->active == IF_ACTIVE_USER)
-               {
-                       ssize_t nolease;
-
-                       if (ifo->options & DHCPCD_IA_FORCED)
-                               nolease = dhcp6_start(ifp, DH6S_INIT);
-                       else if (ifo->options & DHCPCD_INFORM6)
-                               nolease = dhcp6_start(ifp, DH6S_INFORM);
-                       else {
-                               nolease = 0;
-                               /* Enabling the below doesn't really make
-                                * sense as there is currently no standard
-                                * to push routes via DHCPv6.
-                                * (There is an expired working draft,
-                                * maybe abandoned?)
-                                * You can also get it to work by forcing
-                                * an IA as shown above. */
-#if 0
-                               /* With no RS or delegates we might
-                                * as well try and solicit a DHCPv6 address */
-                               if (nolease == 0)
-                                       nolease = dhcp6_start(ifp, DH6S_INIT);
-#endif
+                       if (ifp->active == IF_ACTIVE_USER) {
+                               enum DH6S d6_state;
+
+                               if (ifo->options & DHCPCD_IA_FORCED)
+                                       d6_state = DH6S_INIT;
+                               else if (ifo->options & DHCPCD_INFORM6)
+                                       d6_state = DH6S_INFORM;
+                               else
+                                       d6_state = DH6S_CONFIRM;
+                               if (dhcp6_start(ifp, d6_state) == -1)
+                                       logerr("%s: dhcp6_start", ifp->name);
                        }
-                       if (nolease == -1)
-                               logerr("%s: dhcp6_start", ifp->name);
                }
        }
 
index a5b032ed347a07440e4aa452a63f3a46d1723f5b..a4bae15bbb50633acf9ac4435f4478d13dae184c 100644 (file)
@@ -1095,7 +1095,7 @@ handle_flag:
 #define LOG_DHCP6      logdebug
 #endif
        if (rap->flags & ND_RA_FLAG_MANAGED) {
-               if (new_data && dhcp6_start(ifp, DH6S_INIT) == -1)
+               if (new_data && dhcp6_start(ifp, DH6S_REQUEST) == -1)
                        LOG_DHCP6("dhcp6_start: %s", ifp->name);
        } else if (rap->flags & ND_RA_FLAG_OTHER) {
                if (new_data && dhcp6_start(ifp, DH6S_INFORM) == -1)