]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Add an IPv6 link-local address before upping the interface if needed.
authorRoy Marples <roy@marples.name>
Wed, 4 Jun 2014 23:54:15 +0000 (23:54 +0000)
committerRoy Marples <roy@marples.name>
Wed, 4 Jun 2014 23:54:15 +0000 (23:54 +0000)
Bring an interface up when we start it and not during discovery.
As such, stop waiting on carrier for a second if we did.

dhcpcd.c
if-options.h
if.c
if.h
ipv6.c

index c89922a36d8560dfeecb085d3adfc0db3763d149..516076577fb9587930dd8399f0459b65c5138c9f 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -569,6 +569,19 @@ dhcpcd_startinterface(void *arg)
        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 @@ dhcpcd_startinterface(void *arg)
                }
        }
 
-       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 @@ main(int argc, char **argv)
        }
 
        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)))
index b5cf156ab848704e88101af1dc915381def45f85..f90e428e9f6b6b07150c9b3c316a9c57659ae324 100644 (file)
@@ -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)
 #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[];
 
diff --git a/if.c b/if.c
index f4b8c7a96c6c94609f514526e445f25dab349968..7d5f3896d957367f44e307ec830469b9bd737c62 100644 (file)
--- a/if.c
+++ b/if.c
@@ -132,8 +132,8 @@ if_carrier(struct interface *iface)
        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 @@ up_interface(struct interface *iface)
        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 @@ up_interface(struct interface *iface)
                        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 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv)
                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) {
diff --git a/if.h b/if.h
index d8e8304b954204f8df157e70e38c83f0fa60982b..080ea07fa182fa94384392c8cf354dac1078ae32 100644 (file)
--- a/if.h
+++ b/if.h
@@ -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 *);
diff --git a/ipv6.c b/ipv6.c
index f9a79ae8a3377a49b34857c0abb1659a76c4c183..1b2300ec756e84d3cd32aa0e3367aafd8a0d9799 100644 (file)
--- a/ipv6.c
+++ b/ipv6.c
@@ -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 @@ ipv6_addlinklocal(struct interface *ifp)
                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 @@ ipv6_addlinklocal(struct interface *ifp)
 int
 ipv6_start(struct interface *ifp)
 {
+       const struct ipv6_state *state;
+       const struct ipv6_addr *ap;
+
+       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 (ipv6_linklocal(ifp) == NULL && ipv6_addlinklocal(ifp) == -1)
+       if (ap == NULL && ipv6_addlinklocal(ifp) == -1)
                return -1;
        return 0;
 }