]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
When starting an interface and the carrier is UNKNOWN, wait 100ms before trying to...
authorRoy Marples <roy@marples.name>
Tue, 22 Jul 2014 18:03:34 +0000 (18:03 +0000)
committerRoy Marples <roy@marples.name>
Tue, 22 Jul 2014 18:03:34 +0000 (18:03 +0000)
UNKNOWN should only be reported for BSD systems where the carrier medium reports an error or is
not valid. In this case the carrier is only UP when IFF_RUNNING is set.

dhcpcd.c
if.c
if.h

index f9e12ca56fbe66966162995ee69a0a04a3398985..79e48ec871930bd109e25ba1bcf7c4065aec81ef 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -610,14 +610,27 @@ dhcpcd_startinterface(void *arg)
        struct if_options *ifo = ifp->options;
        size_t i;
        char buf[DUID_LEN * 3];
+       struct timeval tv;
 
        pre_start(ifp);
        if (if_up(ifp) == -1)
                syslog(LOG_ERR, "%s: if_up: %m", ifp->name);
 
-       if (ifp->carrier == LINK_DOWN && ifo->options & DHCPCD_LINK) {
-               syslog(LOG_INFO, "%s: waiting for carrier", ifp->name);
-               return;
+       if (ifo->options & DHCPCD_LINK) {
+               switch (ifp->carrier) {
+               case LINK_UP:
+                       break;
+               case LINK_DOWN:
+                       syslog(LOG_INFO, "%s: waiting for carrier", ifp->name);
+                       return;
+               case LINK_UNKNOWN:
+                       syslog(LOG_INFO, "%s: unknown carrier", ifp->name);
+                       tv.tv_sec = 0;
+                       tv.tv_usec = 100;
+                       eloop_timeout_add_tv(ifp->ctx->eloop, &tv,
+                           dhcpcd_startinterface, ifp);
+                       return;
+               }
        }
 
        if (ifo->options & (DHCPCD_DUID | DHCPCD_IPV6)) {
diff --git a/if.c b/if.c
index 67eadcf67edbec2e0ed66c094a983d59cca74d88..ba374452e416e5fd0b3ce1079de1d33c5d8323c2 100644 (file)
--- a/if.c
+++ b/if.c
@@ -118,16 +118,17 @@ if_carrier(struct interface *iface)
        }
        iface->flags = (unsigned int)ifr.ifr_flags;
 
-       r = LINK_UNKNOWN;
 #ifdef SIOCGIFMEDIA
        memset(&ifmr, 0, sizeof(ifmr));
        strlcpy(ifmr.ifm_name, iface->name, sizeof(ifmr.ifm_name));
        if (ioctl(s, SIOCGIFMEDIA, &ifmr) != -1 &&
            ifmr.ifm_status & IFM_AVALID)
                r = (ifmr.ifm_status & IFM_ACTIVE) ? LINK_UP : LINK_DOWN;
+       else
+               r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_UNKNOWN;
+#else
+       r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN;
 #endif
-       if (r == LINK_UNKNOWN)
-               r = (ifr.ifr_flags & IFF_RUNNING) ? LINK_UP : LINK_DOWN;
        close(s);
        return r;
 }
@@ -152,7 +153,7 @@ if_setflag(struct interface *ifp, short flag)
 #endif
        r = -1;
        if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) {
-               if (flag == 0 || ifr.ifr_flags & flag)
+               if (flag == 0 || (ifr.ifr_flags & flag) == flag)
                        r = 0;
                else {
                        ifr.ifr_flags |= flag;
diff --git a/if.h b/if.h
index 2f6e25b536eca2a5b5f1312558f160e7c3a98caa..c829b7eaaa8c5dc986cd7c57bd1c1c47ea303c3a 100644 (file)
--- a/if.h
+++ b/if.h
@@ -91,7 +91,7 @@
 #define RAW_PARTIALCSUM                2 << 0
 
 int if_setflag(struct interface *ifp, short flag);
-#define if_up(ifp) if_setflag((ifp), IFF_UP)
+#define if_up(ifp) if_setflag((ifp), (IFF_UP | IFF_RUNNING))
 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 *);