]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Include IPv6RA and DHCPv6 in the sorting of interfaces.
authorRoy Marples <roy@marples.name>
Sat, 7 Mar 2015 12:08:32 +0000 (12:08 +0000)
committerRoy Marples <roy@marples.name>
Sat, 7 Mar 2015 12:08:32 +0000 (12:08 +0000)
dhcp.c
dhcpcd.c
if.c
if.h
ipv4.c
ipv4.h
ipv6.c

diff --git a/dhcp.c b/dhcp.c
index 3f2b0c09d9b4602e33fbc37db57dad681469f014..ca33343e6016d265dc54b200dab03c020251b01e 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -3150,7 +3150,6 @@ dhcp_start1(void *arg)
                                state->addr = state->lease.addr;
                                state->net = state->lease.net;
                                state->added |= STATE_ADDED | STATE_FAKE;
-                               ipv4_sortinterfaces(ifp->ctx);
                                ipv4_buildroutes(ifp->ctx);
                        } else
                                syslog(LOG_ERR, "%s: %m", __func__);
index 15abc5bab3c540f0ef5c8be14f3b7f6daa9a9fb5..26b64361cd109727430c4117fef8b2bd7b07b146 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -1037,8 +1037,6 @@ reconf_reboot(struct dhcpcd_ctx *ctx, int action, int argc, char **argv, int oi)
                }
        }
        free(ifs);
-
-       ipv4_sortinterfaces(ctx);
 }
 
 static void
@@ -1790,7 +1788,7 @@ main(int argc, char **argv)
        free_options(ifo);
        ifo = NULL;
 
-       ipv4_sortinterfaces(&ctx);
+       if_sortinterfaces(&ctx);
        TAILQ_FOREACH(ifp, ctx.ifaces, next) {
                eloop_timeout_add_sec(ctx.eloop, 0,
                    dhcpcd_prestartinterface, ifp);
diff --git a/if.c b/if.c
index 7526b77a895df500f00fe8a33fe8f8dc75edb384..de3693e7248b3a77d5937a59ea7cc2711dbde434 100644 (file)
--- a/if.c
+++ b/if.c
@@ -588,3 +588,72 @@ if_domtu(const char *ifname, short int mtu)
                return -1;
        return ifr.ifr_mtu;
 }
+
+/* Interface comparer for working out ordering. */
+static int
+if_cmp(const struct interface *si, const struct interface *ti)
+{
+#ifdef INET
+       int r;
+#endif
+
+       if (D_STATE_RUNNING(si) && !D_STATE_RUNNING(ti))
+               return -1;
+       if (!D_STATE_RUNNING(si) && D_STATE_RUNNING(ti))
+               return 1;
+       if (RS_STATE_RUNNING(si) && !RS_STATE_RUNNING(ti))
+               return -1;
+       if (!RS_STATE_RUNNING(si) && RS_STATE_RUNNING(ti))
+               return 1;
+       if (D6_STATE_RUNNING(si) && !D6_STATE_RUNNING(ti))
+               return -1;
+       if (!D6_STATE_RUNNING(si) && D6_STATE_RUNNING(ti))
+               return 1;
+
+#ifdef INET
+       /* Special attention needed hereto due take states and IPv4LL. */
+       if ((r = ipv4_ifcmp(si, ti)) != 0)
+               return r;
+#endif
+
+       /* Then carrier status. */
+       if (si->carrier > ti->carrier)
+               return -1;
+       if (si->carrier < ti->carrier)
+               return 1;
+       /* Finally, metric */
+       if (si->metric < ti->metric)
+               return -1;
+       if (si->metric > ti->metric)
+               return 1;
+       return 0;
+}
+
+/* Sort the interfaces into a preferred order - best first, worst last. */
+void
+if_sortinterfaces(struct dhcpcd_ctx *ctx)
+{
+       struct if_head sorted;
+       struct interface *ifp, *ift;
+
+       if (ctx->ifaces == NULL ||
+           (ifp = TAILQ_FIRST(ctx->ifaces)) == NULL ||
+           TAILQ_NEXT(ifp, next) == NULL)
+               return;
+
+       TAILQ_INIT(&sorted);
+       TAILQ_REMOVE(ctx->ifaces, ifp, next);
+       TAILQ_INSERT_HEAD(&sorted, ifp, next);
+       while ((ifp = TAILQ_FIRST(ctx->ifaces))) {
+               TAILQ_REMOVE(ctx->ifaces, ifp, next);
+               TAILQ_FOREACH(ift, &sorted, next) {
+                       if (if_cmp(ifp, ift) == -1) {
+                               TAILQ_INSERT_BEFORE(ift, ifp, next);
+                               break;
+                       }
+               }
+               if (ift == NULL)
+                       TAILQ_INSERT_TAIL(&sorted, ifp, next);
+       }
+       TAILQ_CONCAT(ctx->ifaces, &sorted, next);
+}
diff --git a/if.h b/if.h
index fb2aa19cb25987debd40defc872ae0a5a012b980..b35bc340d14a893e98eb7cceb97fc9fc288e7b60 100644 (file)
--- a/if.h
+++ b/if.h
@@ -85,6 +85,7 @@ int if_setflag(struct interface *ifp, short flag);
 struct if_head *if_discover(struct dhcpcd_ctx *, int, char * const *);
 struct interface *if_find(struct dhcpcd_ctx *, const char *);
 struct interface *if_findindex(struct dhcpcd_ctx *, unsigned int);
+void if_sortinterfaces(struct dhcpcd_ctx *);
 void if_free(struct interface *);
 int if_domtu(const char *, short int);
 #define if_getmtu(iface) if_domtu(iface, 0)
diff --git a/ipv4.c b/ipv4.c
index 62cc60f5f60d8d47ec1776ae594c187c8e39c635..544d6febca1dac4f6766466f5187d5a137c3cb67 100644 (file)
--- a/ipv4.c
+++ b/ipv4.c
@@ -207,10 +207,9 @@ ipv4_init(struct dhcpcd_ctx *ctx)
 }
 
 /* Interface comparer for working out ordering. */
-static int
+int
 ipv4_ifcmp(const struct interface *si, const struct interface *ti)
 {
-       int sill, till;
        const struct dhcp_state *sis, *tis;
 
        sis = D_CSTATE(si);
@@ -234,55 +233,16 @@ ipv4_ifcmp(const struct interface *si, const struct interface *ti)
        /* If we are either, they neither have a lease, or they both have.
         * We need to check for IPv4LL and make it non-preferred. */
        if (sis->new && tis->new) {
-               sill = (sis->new->cookie == htonl(MAGIC_COOKIE));
-               till = (tis->new->cookie == htonl(MAGIC_COOKIE));
-               if (!sill && till)
-                       return 1;
+               int sill = (sis->new->cookie == htonl(MAGIC_COOKIE));
+               int till = (tis->new->cookie == htonl(MAGIC_COOKIE));
                if (sill && !till)
                        return -1;
+               if (!sill && till)
+                       return 1;
        }
-       /* Then carrier status. */
-       if (si->carrier > ti->carrier)
-               return -1;
-       if (si->carrier < ti->carrier)
-               return 1;
-       /* Finally, metric */
-       if (si->metric < ti->metric)
-               return -1;
-       if (si->metric > ti->metric)
-               return 1;
        return 0;
 }
 
-/* Sort the interfaces into a preferred order - best first, worst last. */
-void
-ipv4_sortinterfaces(struct dhcpcd_ctx *ctx)
-{
-       struct if_head sorted;
-       struct interface *ifp, *ift;
-
-       if (ctx->ifaces == NULL ||
-           (ifp = TAILQ_FIRST(ctx->ifaces)) == NULL ||
-           TAILQ_NEXT(ifp, next) == NULL)
-               return;
-
-       TAILQ_INIT(&sorted);
-       TAILQ_REMOVE(ctx->ifaces, ifp, next);
-       TAILQ_INSERT_HEAD(&sorted, ifp, next);
-       while ((ifp = TAILQ_FIRST(ctx->ifaces))) {
-               TAILQ_REMOVE(ctx->ifaces, ifp, next);
-               TAILQ_FOREACH(ift, &sorted, next) {
-                       if (ipv4_ifcmp(ifp, ift) == -1) {
-                               TAILQ_INSERT_BEFORE(ift, ifp, next);
-                               break;
-                       }
-               }
-               if (ift == NULL)
-                       TAILQ_INSERT_TAIL(&sorted, ifp, next);
-       }
-       TAILQ_CONCAT(ctx->ifaces, &sorted, next);
-}
-
 static struct rt *
 find_route(struct rt_head *rts, const struct rt *r, const struct rt *srt)
 {
@@ -678,6 +638,10 @@ ipv4_buildroutes(struct dhcpcd_ctx *ctx)
        struct interface *ifp;
        const struct dhcp_state *state;
 
+       /* We need to have the interfaces in the correct order to ensure
+        * our routes are managed correctly. */
+       if_sortinterfaces(ctx);
+
        nrs = malloc(sizeof(*nrs));
        if (nrs == NULL) {
                syslog(LOG_ERR, "%s: %m", __func__);
@@ -859,10 +823,6 @@ ipv4_applyaddr(void *arg)
        struct ipv4_state *istate = NULL;
        int r;
 
-       /* As we are now adjusting an interface, we need to ensure
-        * we have them in the right order for routing and configuration. */
-       ipv4_sortinterfaces(ifp->ctx);
-
        if (state == NULL)
                return;
        dhcp = state->new;
diff --git a/ipv4.h b/ipv4.h
index 14b4e41e71b242c8eef86d9b59e2158b159a1458..a9fca8fee2624ec197c63a651879bef8ee1bcc55 100644 (file)
--- a/ipv4.h
+++ b/ipv4.h
@@ -65,7 +65,7 @@ struct ipv4_state {
 
 #ifdef INET
 int ipv4_init(struct dhcpcd_ctx *);
-void ipv4_sortinterfaces(struct dhcpcd_ctx *);
+int ipv4_ifcmp(const struct interface *, const struct interface *);
 uint8_t inet_ntocidr(struct in_addr);
 int inet_cidrtoaddr(int, struct in_addr *);
 uint32_t ipv4_getnetmask(uint32_t);
diff --git a/ipv6.c b/ipv6.c
index 8bf8ec35e6afee7df1ada8edddab897309222489..b5f836a1349db84ce2e7902653305db270795d73 100644 (file)
--- a/ipv6.c
+++ b/ipv6.c
@@ -1989,6 +1989,10 @@ ipv6_buildroutes(struct dhcpcd_ctx *ctx)
        uint8_t have_default;
        unsigned long long o;
 
+       /* We need to have the interfaces in the correct order to ensure
+        * our routes are managed correctly. */
+       if_sortinterfaces(ctx);
+
        TAILQ_INIT(&dnr);
 
        /* First add reachable routers and their prefixes */