diff options
| author | Roy Marples <roy@marples.name> | 2015-03-07 12:08:32 +0000 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2015-03-07 12:08:32 +0000 |
| commit | 3e3a5dcbbe0ebfd891f71da296d8ae7be394428c (patch) | |
| tree | 921acf96c2be6910f837cfcecf49a4d668696e0a /if.c | |
| parent | 648b5c64478baaab23926809e723ce5425cea42f (diff) | |
| download | dhcpcd-3e3a5dcbbe0ebfd891f71da296d8ae7be394428c.tar.xz | |
Include IPv6RA and DHCPv6 in the sorting of interfaces.
Diffstat (limited to 'if.c')
| -rw-r--r-- | if.c | 69 |
1 files changed, 69 insertions, 0 deletions
@@ -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); +} |
