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__);
}
}
free(ifs);
-
- ipv4_sortinterfaces(ctx);
}
static void
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);
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);
+}
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)
}
/* 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);
/* 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)
{
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__);
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;
#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);
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 */