changeset 2997:76a226c99061 draft

Include IPv6RA and DHCPv6 in the sorting of interfaces.
author Roy Marples <roy@marples.name>
date Sat, 07 Mar 2015 12:08:32 +0000
parents 20c2c44431c9
children 371e20a2dbba
files dhcp.c dhcpcd.c if.c if.h ipv4.c ipv4.h ipv6.c
diffstat 7 files changed, 85 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/dhcp.c	Fri Mar 06 10:03:25 2015 +0000
+++ b/dhcp.c	Sat Mar 07 12:08:32 2015 +0000
@@ -3150,7 +3150,6 @@
 				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__);
--- a/dhcpcd.c	Fri Mar 06 10:03:25 2015 +0000
+++ b/dhcpcd.c	Sat Mar 07 12:08:32 2015 +0000
@@ -1037,8 +1037,6 @@
 		}
 	}
 	free(ifs);
-
-	ipv4_sortinterfaces(ctx);
 }
 
 static void
@@ -1790,7 +1788,7 @@
 	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);
--- a/if.c	Fri Mar 06 10:03:25 2015 +0000
+++ b/if.c	Sat Mar 07 12:08:32 2015 +0000
@@ -588,3 +588,72 @@
 		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);
+}
--- a/if.h	Fri Mar 06 10:03:25 2015 +0000
+++ b/if.h	Sat Mar 07 12:08:32 2015 +0000
@@ -85,6 +85,7 @@
 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)
--- a/ipv4.c	Fri Mar 06 10:03:25 2015 +0000
+++ b/ipv4.c	Sat Mar 07 12:08:32 2015 +0000
@@ -207,10 +207,9 @@
 }
 
 /* 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 @@
 	/* 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 @@
 	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 @@
 	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;
--- a/ipv4.h	Fri Mar 06 10:03:25 2015 +0000
+++ b/ipv4.h	Sat Mar 07 12:08:32 2015 +0000
@@ -65,7 +65,7 @@
 
 #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);
--- a/ipv6.c	Fri Mar 06 10:03:25 2015 +0000
+++ b/ipv6.c	Sat Mar 07 12:08:32 2015 +0000
@@ -1989,6 +1989,10 @@
 	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 */