]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
When dropping IPv4LL state, remove the address and rebuild routes before
authorRoy Marples <roy@marples.name>
Fri, 24 Jul 2015 20:47:08 +0000 (20:47 +0000)
committerRoy Marples <roy@marples.name>
Fri, 24 Jul 2015 20:47:08 +0000 (20:47 +0000)
calling dhcpcd-run-hooks.
Ensure that the IPv4LL random state is only used when picking addresses
and the original state is restored.

dhcpcd.h
ipv4ll.c

index 31b6959ec04da7b82453a4d7dd43a064962883ed..5c5fc18adff89e70acad2d8229ab46872eed8be9 100644 (file)
--- a/dhcpcd.h
+++ b/dhcpcd.h
@@ -123,6 +123,8 @@ struct dhcpcd_ctx {
        struct dhcp_opt *vivso;
        size_t vivso_len;
 
+       char *randomstate; /* original state */
+
 #ifdef INET
        struct dhcp_opt *dhcp_opts;
        size_t dhcp_opts_len;
index c119778fc9dff115428bead8cfb345f655a0c9c5..564f98f4d529151bdaf89ed0a889f27fdfa93dbb 100644 (file)
--- a/ipv4ll.c
+++ b/ipv4ll.c
@@ -52,6 +52,10 @@ static in_addr_t
 ipv4ll_pick_addr(const struct arp_state *astate)
 {
        struct in_addr addr;
+       struct ipv4ll_state *istate;
+
+       istate = IPV4LL_STATE(astate->iface);
+       setstate(istate->randomstate);
 
        do {
                /* RFC 3927 Section 2.1 states that the first 256 and
@@ -66,6 +70,9 @@ ipv4ll_pick_addr(const struct arp_state *astate)
                /* Ensure we don't have the address on another interface */
        } while (ipv4_findaddr(astate->iface->ctx, &addr) != NULL);
 
+       /* Restore the original random state */
+       setstate(astate->iface->ctx->randomstate);
+
        return addr.s_addr;
 }
 
@@ -315,6 +322,7 @@ ipv4ll_start(void *arg)
         * the same address without persistent storage. */
        if (state->conflicts == 0) {
                unsigned int seed;
+               char *orig;
 
                if (sizeof(seed) > ifp->hwlen) {
                        seed = 0;
@@ -322,7 +330,15 @@ ipv4ll_start(void *arg)
                } else
                        memcpy(&seed, ifp->hwaddr + ifp->hwlen - sizeof(seed),
                            sizeof(seed));
-               initstate(seed, state->randomstate, sizeof(state->randomstate));
+               orig = initstate(seed,
+                   state->randomstate, sizeof(state->randomstate));
+
+               /* Save the original state. */
+               if (ifp->ctx->randomstate == NULL)
+                       ifp->ctx->randomstate = orig;
+
+               /* Set back the original state until we need the seeded one. */
+               setstate(ifp->ctx->randomstate);
        }
 
        if ((astate = arp_new(ifp, NULL)) == NULL)
@@ -358,7 +374,6 @@ ipv4ll_start(void *arg)
                return;
        }
 
-       setstate(state->randomstate);
        logger(ifp->ctx, LOG_INFO, "%s: probing for an IPv4LL address",
            ifp->name);
        astate->addr.s_addr = ipv4ll_pick_addr(astate);
@@ -407,16 +422,15 @@ ipv4ll_freedrop(struct interface *ifp, int drop)
                                }
                        }
                }
-
-               if (dropped)
-                       script_runreason(ifp, "IPV4LL");
        }
 
        if (state) {
                free(state);
                ifp->if_data[IF_DATA_IPV4LL] = NULL;
 
-               if (dropped)
+               if (dropped) {
                        ipv4_buildroutes(ifp->ctx);
+                       script_runreason(ifp, "IPV4LL");
+               }
        }
 }