]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Re-introduce our loop to poll interface flags when the interface does
authorRoy Marples <roy@marples.name>
Wed, 8 Oct 2014 12:30:27 +0000 (12:30 +0000)
committerRoy Marples <roy@marples.name>
Wed, 8 Oct 2014 12:30:27 +0000 (12:30 +0000)
not support link states, but this time ensure we don't call IFF_UP inside
the loop. This now works nicely with PPP interfaces on NetBSD at least.

dhcpcd.c
dhcpcd.h

index 3740ce1e9a2210a3d868b8bf31f571bb83583c16..67ed5538ae6ddb020782885e4b54100102d80fab 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -640,10 +640,8 @@ dhcpcd_startinterface(void *arg)
        struct if_options *ifo = ifp->options;
        size_t i;
        char buf[DUID_LEN * 3];
-
-       pre_start(ifp);
-       if (if_up(ifp) == -1)
-               syslog(LOG_ERR, "%s: if_up: %m", ifp->name);
+       int carrier;
+       struct timeval tv;
 
        if (ifo->options & DHCPCD_LINK) {
                switch (ifp->carrier) {
@@ -654,18 +652,15 @@ dhcpcd_startinterface(void *arg)
                        return;
                case LINK_UNKNOWN:
                        /* No media state available.
-                        * Any change on state such as IFF_UP and IFF_RUNNING
-                        * should be reported to us via the route socket
-                        * as we've done the best we can to bring the interface
-                        * up at this point. */
-                       ifp->carrier = if_carrier(ifp);
-                       if (ifp->carrier == LINK_UNKNOWN) {
-                               syslog(LOG_INFO, "%s: unknown carrier",
-                                   ifp->name);
-                               return;
-                       }
-                       dhcpcd_handlecarrier(ifp->ctx, ifp->carrier,
-                           ifp->flags, ifp->name);
+                        * Loop until both IFF_UP and IFF_RUNNING are set */
+                       if ((carrier = if_carrier(ifp)) == LINK_UNKNOWN) {
+                               tv.tv_sec = 0;
+                               tv.tv_usec = IF_POLL_UP * 1000;
+                               eloop_timeout_add_tv(ifp->ctx->eloop,
+                                   &tv, dhcpcd_startinterface, ifp);
+                       } else
+                               dhcpcd_handlecarrier(ifp->ctx, carrier,
+                                   ifp->flags, ifp->name);
                        return;
                }
        }
@@ -745,6 +740,33 @@ dhcpcd_startinterface(void *arg)
                dhcp_start(ifp);
 }
 
+static void
+dhcpcd_prestartinterface(void *arg)
+{
+       struct interface *ifp = arg;
+
+       pre_start(ifp);
+       if (if_up(ifp) == -1)
+               syslog(LOG_ERR, "%s: if_up: %m", ifp->name);
+
+       if (ifp->options->options & DHCPCD_LINK &&
+           ifp->carrier == LINK_UNKNOWN)
+       {
+               int carrier;
+
+               if ((carrier = if_carrier(ifp)) != LINK_UNKNOWN) {
+                       dhcpcd_handlecarrier(ifp->ctx, carrier,
+                           ifp->flags, ifp->name);
+                       return;
+               }
+               syslog(LOG_INFO,
+                   "%s: unknown carrier, waiting for interface flags",
+                   ifp->name);
+       }
+
+       dhcpcd_startinterface(ifp);
+}
+
 static void
 handle_link(void *arg)
 {
@@ -803,8 +825,7 @@ run_preinit(struct interface *ifp)
 
        script_runreason(ifp, "PREINIT");
 
-       if (ifp->carrier != LINK_UNKNOWN &&
-           ifp->options->options & DHCPCD_LINK)
+       if (ifp->options->options & DHCPCD_LINK && ifp->carrier != LINK_UNKNOWN)
                script_runreason(ifp,
                    ifp->carrier == LINK_UP ? "CARRIER" : "NOCARRIER");
 }
@@ -864,7 +885,7 @@ dhcpcd_handleinterface(void *arg, int action, const char *ifname)
                        iff = ifp;
                }
                if (action > 0)
-                       dhcpcd_startinterface(iff);
+                       dhcpcd_prestartinterface(iff);
        }
 
        /* Free our discovered list */
@@ -915,7 +936,7 @@ if_reboot(struct interface *ifp, int argc, char **argv)
        configure_interface(ifp, argc, argv);
        dhcp_reboot_newopts(ifp, oldopts);
        dhcp6_reboot(ifp);
-       dhcpcd_startinterface(ifp);
+       dhcpcd_prestartinterface(ifp);
 }
 
 static void
@@ -941,7 +962,7 @@ reconf_reboot(struct dhcpcd_ctx *ctx, int action, int argc, char **argv, int oi)
                        TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next);
                        dhcpcd_initstate1(ifp, argc, argv);
                        run_preinit(ifp);
-                       dhcpcd_startinterface(ifp);
+                       dhcpcd_prestartinterface(ifp);
                }
        }
        free(ifs);
@@ -1691,7 +1712,8 @@ main(int argc, char **argv)
 
        ipv4_sortinterfaces(&ctx);
        TAILQ_FOREACH(ifp, ctx.ifaces, next) {
-               eloop_timeout_add_sec(ctx.eloop, 0, dhcpcd_startinterface, ifp);
+               eloop_timeout_add_sec(ctx.eloop, 0,
+                   dhcpcd_prestartinterface, ifp);
        }
 
        i = eloop_start(&ctx);
index df4af79a6e64259854a6ffae1bd9aea324cb4e7f..34c727215e50dfddc094979bf6db8eea4845bdd9 100644 (file)
--- a/dhcpcd.h
+++ b/dhcpcd.h
 #define IF_DATA_DHCP6  4
 #define IF_DATA_MAX    5
 
+/* If the interface does not support carrier status (ie PPP),
+ * dhcpcd can poll it for the relevant flags periodically */
+#define IF_POLL_UP     100     /* milliseconds */
+
 struct interface {
        struct dhcpcd_ctx *ctx;
        TAILQ_ENTRY(interface) next;