summaryrefslogtreecommitdiffstats
path: root/dhcpcd.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2014-12-09 09:39:30 +0000
committerRoy Marples <roy@marples.name>2014-12-09 09:39:30 +0000
commit0ddc18a90d17f56377a0c7d3fcbedbd2252512b3 (patch)
tree6263011ec7c0ba8a606c0a0cb4491b47d347fc0d /dhcpcd.c
parente7afdb1d82974ccbb011e5dc3df5cccd74eba8eb (diff)
downloaddhcpcd-0ddc18a90d17f56377a0c7d3fcbedbd2252512b3.tar.xz
Instead if giving up if we receive a LINK_UP event before the kernel has set
IFF_UP, poll for it until it's set or carrier goes down.
Diffstat (limited to 'dhcpcd.c')
-rw-r--r--dhcpcd.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/dhcpcd.c b/dhcpcd.c
index 9e35738f..cb51141f 100644
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -538,6 +538,25 @@ configure_interface(struct interface *ifp, int argc, char **argv)
configure_interface1(ifp);
}
+static void
+dhcpcd_pollup(void *arg)
+{
+ struct interface *ifp = arg;
+ int carrier;
+
+ carrier = if_carrier(ifp); /* will set ifp->flags */
+ if (carrier == LINK_UP && !(ifp->flags & IFF_UP)) {
+ struct timeval tv;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = IF_POLL_UP * 1000;
+ eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcpcd_pollup, ifp);
+ return;
+ }
+
+ dhcpcd_handlecarrier(ifp->ctx, carrier, ifp->flags, ifp->name);
+}
+
void
dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
const char *ifname)
@@ -553,14 +572,15 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
carrier = if_carrier(ifp); /* will set ifp->flags */
break;
case LINK_UP:
- /* we have a carrier! however, we need to ignore the flags
- * set in the kernel message as sometimes this message is
- * reported before IFF_UP is set by the kernel even though
- * dhcpcd has already set it.
- *
- * So we check the flags now. If IFF_UP is still not set
- * then we should expect an accompanying link_down message */
- if_setflag(ifp, 0); /* will set ifp->flags */
+ /* we have a carrier! Still need to check for IFF_UP */
+ if (flags & IFF_UP)
+ ifp->flags = flags;
+ else {
+ /* So we need to poll for IFF_UP as there is no
+ * kernel notification when it's set. */
+ dhcpcd_pollup(ifp);
+ return;
+ }
break;
default:
ifp->flags = flags;