changeset 2518:28182250f3a0 draft

Add an IPv6 link-local address before upping the interface if needed. Bring an interface up when we start it and not during discovery. As such, stop waiting on carrier for a second if we did.
author Roy Marples <roy@marples.name>
date Wed, 04 Jun 2014 23:54:15 +0000
parents 1d4beca0771f
children 80278d0c53c3
files dhcpcd.c if-options.h if.c if.h ipv6.c
diffstat 5 files changed, 34 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/dhcpcd.c	Wed Jun 04 23:34:39 2014 +0000
+++ b/dhcpcd.c	Wed Jun 04 23:54:15 2014 +0000
@@ -569,6 +569,19 @@
 	size_t i;
 	char buf[DUID_LEN * 3];
 
+	/* Add our link-local address before upping the interface
+	 * so our RFC7217 address beats the hwaddr based one */
+	if (ifo->options & DHCPCD_IPV6 && ipv6_start(ifp) == -1) {
+		syslog(LOG_ERR, "%s: ipv6_start: %m", ifp->name);
+		ifo->options &= DHCPCD_IPV6;
+	}
+
+	if (!(ifp->flags & IFF_UP) && if_carrier(ifp) != LINK_UNKNOWN) {
+		if (if_up(ifp) == -1)
+			syslog(LOG_ERR, "%s: if_up: %m",
+			    ifp->name);
+	}
+
 	if (ifp->carrier == LINK_UNKNOWN)
 		dhcpcd_handlecarrier(ifp->ctx, LINK_UNKNOWN, 0, ifp->name);
 	if (ifp->carrier == LINK_DOWN) {
@@ -604,10 +617,6 @@
 		}
 	}
 
-	if (ifo->options & DHCPCD_IPV6 && ipv6_start(ifp) == -1) {
-		syslog(LOG_ERR, "%s: ipv6_start: %m", ifp->name);
-		ifo->options &= DHCPCD_IPV6;
-	}
 	if (ifo->options & DHCPCD_IPV6) {
 		if (ifo->options & DHCPCD_IPV6RS &&
 		    !(ifo->options & DHCPCD_INFORM))
@@ -1536,25 +1545,6 @@
 	}
 
 	if (!(ctx.options & DHCPCD_BACKGROUND)) {
-		/* If we don't have a carrier, we may have to wait for a second
-		 * before one becomes available if we brought an interface up */
-		if (opt == 0 &&
-		    ctx.options & DHCPCD_LINK &&
-		    ctx.options & DHCPCD_WAITUP &&
-		    !(ctx.options & DHCPCD_WAITIP))
-		{
-			ts.tv_sec = 1;
-			ts.tv_nsec = 0;
-			nanosleep(&ts, NULL);
-			TAILQ_FOREACH(ifp, ctx.ifaces, next) {
-				dhcpcd_handlecarrier(&ctx, LINK_UNKNOWN, 0,
-				    ifp->name);
-				if (ifp->carrier != LINK_DOWN) {
-					opt = 1;
-					break;
-				}
-			}
-		}
 		if (ctx.options & DHCPCD_MASTER)
 			t = ifo->timeout;
 		else if ((ifp = TAILQ_FIRST(ctx.ifaces)))
--- a/if-options.h	Wed Jun 04 23:34:39 2014 +0000
+++ b/if-options.h	Wed Jun 04 23:54:15 2014 +0000
@@ -77,7 +77,7 @@
 #define DHCPCD_VENDORRAW		(1ULL << 23)
 #define DHCPCD_TIMEOUT_IPV4LL		(1ULL << 24)
 #define DHCPCD_WAITIP			(1ULL << 25)
-#define DHCPCD_WAITUP			(1ULL << 26)
+#define DHCPCD_SLAACPRIVATE		(1ULL << 26)
 #define DHCPCD_CSR_WARNED		(1ULL << 27)
 #define DHCPCD_XID_HWADDR		(1ULL << 28)
 #define DHCPCD_BROADCAST		(1ULL << 29)
@@ -102,7 +102,6 @@
 #define DHCPCD_IAID			(1ULL << 48)
 #define DHCPCD_DHCP			(1ULL << 49)
 #define DHCPCD_DHCP6			(1ULL << 50)
-#define DHCPCD_SLAACPRIVATE		(1ULL << 51)
 
 extern const struct option cf_options[];
 
--- a/if.c	Wed Jun 04 23:34:39 2014 +0000
+++ b/if.c	Wed Jun 04 23:54:15 2014 +0000
@@ -132,8 +132,8 @@
 	return r;
 }
 
-static int
-up_interface(struct interface *iface)
+int
+if_up(struct interface *ifp)
 {
 	struct ifreq ifr;
 	int s, r;
@@ -144,7 +144,7 @@
 	if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
 		return -1;
 	memset(&ifr, 0, sizeof(ifr));
-	strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
+	strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
 #ifdef __linux__
 	/* We can only bring the real interface up */
 	if ((p = strchr(ifr.ifr_name, ':')))
@@ -159,7 +159,7 @@
 			if (ioctl(s, SIOCSIFFLAGS, &ifr) == 0)
 				r = 0;
 		}
-		iface->flags = (unsigned int)ifr.ifr_flags;
+		ifp->flags = (unsigned int)ifr.ifr_flags;
 	}
 	close(s);
 	return r;
@@ -296,20 +296,6 @@
 		strlcpy(ifp->name, p, sizeof(ifp->name));
 		ifp->flags = ifa->ifa_flags;
 
-		/* Bring the interface up if not already */
-		if (!(ifp->flags & IFF_UP)
-#ifdef SIOCGIFMEDIA
-		    && if_carrier(ifp) != LINK_UNKNOWN
-#endif
-		   )
-		{
-			if (up_interface(ifp) == 0)
-				ctx->options |= DHCPCD_WAITUP;
-			else
-				syslog(LOG_ERR, "%s: up_interface: %m",
-				    ifp->name);
-		}
-
 		sdl_type = 0;
 		/* Don't allow loopback unless explicit */
 		if (ifp->flags & IFF_LOOPBACK) {
--- a/if.h	Wed Jun 04 23:34:39 2014 +0000
+++ b/if.h	Wed Jun 04 23:54:15 2014 +0000
@@ -90,6 +90,7 @@
 #define RAW_EOF			1 << 0
 #define RAW_PARTIALCSUM		2 << 0
 
+int if_up(struct interface *ifp);
 struct if_head *if_discover(struct dhcpcd_ctx *, int, char * const *);
 struct interface *if_find(struct dhcpcd_ctx *, const char *);
 void if_free(struct interface *);
--- a/ipv6.c	Wed Jun 04 23:34:39 2014 +0000
+++ b/ipv6.c	Wed Jun 04 23:54:15 2014 +0000
@@ -31,6 +31,7 @@
 #include <sys/stat.h>
 
 #include <net/route.h>
+#include <netinet/if_ether.h>
 #include <netinet/in.h>
 
 #ifdef __linux__
@@ -917,7 +918,7 @@
 		switch (ifp->family) {
 		case ARPHRD_ETHER:
 			/* Check for a valid hardware address */
-			if (ifp->hwlen != 6 & ifp->hwlen != 8) {
+			if (ifp->hwlen != 6 && ifp->hwlen != 8) {
 				errno = ENOTSUP;
 				return -1;
 			}
@@ -988,8 +989,20 @@
 int
 ipv6_start(struct interface *ifp)
 {
+	const struct ipv6_state *state;
+	const struct ipv6_addr *ap;
 
-	if (ipv6_linklocal(ifp) == NULL && ipv6_addlinklocal(ifp) == -1)
+	state = IPV6_CSTATE(ifp);
+	if (state) {
+		TAILQ_FOREACH(ap, &state->addrs, next) {
+			if (IN6_IS_ADDR_LINKLOCAL(&ap->addr) &&
+			    !(ap->addr_flags & IN6_IFF_DUPLICATED))
+				break;
+		}
+	} else
+		ap = NULL;
+
+	if (ap == NULL && ipv6_addlinklocal(ifp) == -1)
 		return -1;
 	return 0;
 }