changeset 5376:66bbeeebbe92 draft

dhcpcd: Add an option to poll the interface carrier state Only to be used if the interface does not report carrier state changes for whatever reason.
author Roy Marples <roy@marples.name>
date Thu, 18 Jun 2020 21:15:15 +0100
parents 0bbad3cb3f65
children 31ce574fac88
files src/common.h src/dhcpcd.c src/dhcpcd.conf.5.in src/dhcpcd.h src/if-bsd.c src/if-options.c src/if-options.h src/if.c src/if.h
diffstat 9 files changed, 64 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/common.h	Wed Jun 17 15:17:58 2020 +0100
+++ b/src/common.h	Thu Jun 18 21:15:15 2020 +0100
@@ -43,6 +43,7 @@
 #define	ELOOP_IPV6ND		6
 #define	ELOOP_IPV6RA_EXPIRE	7
 #define	ELOOP_DHCP6		8
+#define	ELOOP_IF		9
 
 #ifndef HOSTNAME_MAX_LEN
 #define HOSTNAME_MAX_LEN	250	/* 255 - 3 (FQDN) - 2 (DNS enc) */
--- a/src/dhcpcd.c	Wed Jun 17 15:17:58 2020 +0100
+++ b/src/dhcpcd.c	Thu Jun 18 21:15:15 2020 +0100
@@ -867,7 +867,6 @@
 {
 	struct interface *ifp = arg;
 	struct if_options *ifo = ifp->options;
-	int carrier;
 
 	if (ifo->options & DHCPCD_LINK) {
 		switch (ifp->carrier) {
@@ -879,19 +878,7 @@
 		case LINK_UNKNOWN:
 			/* No media state available.
 			 * Loop until both IFF_UP and IFF_RUNNING are set */
-			carrier = if_carrier(ifp);
-			if (carrier == LINK_UNKNOWN) {
-				if (IF_UPANDRUNNING(ifp))
-					carrier = LINK_UP;
-				else {
-					eloop_timeout_add_msec(ifp->ctx->eloop,
-					    IF_POLL_UP * MSEC_PER_SEC,
-					    dhcpcd_startinterface, ifp);
-					return;
-				}
-			}
-			dhcpcd_handlecarrier(ifp->ctx, carrier,
-			    ifp->flags, ifp->name);
+			if_pollinit(ifp);
 			return;
 		}
 	}
@@ -979,8 +966,12 @@
 dhcpcd_prestartinterface(void *arg)
 {
 	struct interface *ifp = arg;
+	struct dhcpcd_ctx *ctx = ifp->ctx;
 	bool anondown;
 
+	if (ifp->options->poll != 0)
+		if_pollinit(ifp);
+
 	if (ifp->carrier == LINK_DOWN &&
 	    ifp->options->options & DHCPCD_ANONYMOUS &&
 	    ifp->flags & IFF_UP)
@@ -990,7 +981,7 @@
 	} else
 		anondown = false;
 
-	if ((!(ifp->ctx->options & DHCPCD_MASTER) ||
+	if ((!(ctx->options & DHCPCD_MASTER) ||
 	    ifp->options->options & DHCPCD_IF_UP || anondown) &&
 	    !(ifp->flags & IFF_UP))
 	{
--- a/src/dhcpcd.conf.5.in	Wed Jun 17 15:17:58 2020 +0100
+++ b/src/dhcpcd.conf.5.in	Thu Jun 18 21:15:15 2020 +0100
@@ -24,7 +24,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd May 12, 2020
+.Dd June 18, 2020
 .Dt DHCPCD.CONF 5
 .Os
 .Sh NAME
@@ -595,6 +595,12 @@
 detects an address added to a point to point interface (PPP, TUN, etc) then
 it will set the listed DHCP options to the destination address of the
 interface.
+.It Ic poll Op Ar time
+Polls the interface every
+.Ar time
+milliseconds (default of 100) to check flags and carrier status.
+This option should only be used if the driver does not report link state
+changes but can report the link state.
 .It Ic profile Ar name
 Subsequent options are only parsed for this profile
 .Ar name .
--- a/src/dhcpcd.h	Wed Jun 17 15:17:58 2020 +0100
+++ b/src/dhcpcd.h	Thu Jun 18 21:15:15 2020 +0100
@@ -66,10 +66,6 @@
 #define IF_DATA_DHCP6	6
 #define IF_DATA_MAX	7
 
-/* 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 */
-
 #ifdef __QNX__
 /* QNX carries defines for, but does not actually support PF_LINK */
 #undef IFLR_ACTIVE
--- a/src/if-bsd.c	Wed Jun 17 15:17:58 2020 +0100
+++ b/src/if-bsd.c	Thu Jun 18 21:15:15 2020 +0100
@@ -358,6 +358,10 @@
 {
 	struct ifmediareq ifmr = { .ifm_status = 0 };
 
+	/* Not really needed, but the other OS update flags here also */
+	if (if_getflags(ifp) == -1)
+		return LINK_UNKNOWN;
+
 	strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name));
 	if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr) == -1 ||
 	    !(ifmr.ifm_status & IFM_AVALID))
--- a/src/if-options.c	Wed Jun 17 15:17:58 2020 +0100
+++ b/src/if-options.c	Thu Jun 18 21:15:15 2020 +0100
@@ -158,6 +158,7 @@
 	{"inactive",        no_argument,       NULL, O_INACTIVE},
 	{"mudurl",          required_argument, NULL, O_MUDURL},
 	{"link_rcvbuf",     required_argument, NULL, O_LINK_RCVBUF},
+	{"poll",            optional_argument, NULL, O_POLL},
 	{NULL,              0,                 NULL, '\0'}
 };
 
@@ -2192,6 +2193,18 @@
 		}
 #endif
 		break;
+	case O_POLL:
+		if (arg == NULL) {
+			ifo->poll = IF_POLL_UP;
+			break;
+		}
+		ifo->poll = (unsigned long)
+		    strtou(arg, NULL, 0, 0, ULONG_MAX, &e);
+		if (e) {
+			logerrx("failed to convert poll %s", arg);
+			return -1;
+		}
+		break;
 	default:
 		return 0;
 	}
--- a/src/if-options.h	Wed Jun 17 15:17:58 2020 +0100
+++ b/src/if-options.h	Thu Jun 18 21:15:15 2020 +0100
@@ -180,6 +180,7 @@
 #define O_INACTIVE		O_BASE + 47
 #define O_MUDURL		O_BASE + 48
 #define O_MSUSERCLASS		O_BASE + 49
+#define	O_POLL			O_BASE + 50
 
 extern const struct option cf_options[];
 
@@ -215,6 +216,7 @@
 	time_t mtime;
 	uint8_t iaid[4];
 	int metric;
+	unsigned long poll;
 	uint8_t requestmask[256 / NBBY];
 	uint8_t requiremask[256 / NBBY];
 	uint8_t nomask[256 / NBBY];
--- a/src/if.c	Wed Jun 17 15:17:58 2020 +0100
+++ b/src/if.c	Thu Jun 18 21:15:15 2020 +0100
@@ -64,7 +64,9 @@
 #include <syslog.h>
 #include <unistd.h>
 
+#define ELOOP_QUEUE	ELOOP_IF
 #include "common.h"
+#include "eloop.h"
 #include "dev.h"
 #include "dhcp.h"
 #include "dhcp6.h"
@@ -661,6 +663,30 @@
 	return ifs;
 }
 
+static void
+if_poll(void *arg)
+{
+	struct interface *ifp = arg;
+	unsigned int flags = ifp->flags;
+	int carrier;
+
+	carrier = if_carrier(ifp); /* if_carrier will update ifp->flags */
+	if (ifp->carrier != carrier || ifp->flags != flags)
+		dhcpcd_handlecarrier(ifp->ctx, carrier, ifp->flags, ifp->name);
+
+	if (ifp->options->poll != 0 || ifp->carrier != LINK_UP)
+		if_pollinit(ifp);
+}
+
+int
+if_pollinit(struct interface *ifp)
+{
+	unsigned long msec;
+
+	msec = ifp->options->poll != 0 ? ifp->options->poll : IF_POLL_UP;
+	return eloop_timeout_add_msec(ifp->ctx->eloop, msec, if_poll, ifp);
+}
+
 /*
  * eth0.100:2 OR eth0i100:2 (seems to be NetBSD xvif(4) only)
  *
--- a/src/if.h	Wed Jun 17 15:17:58 2020 +0100
+++ b/src/if.h	Thu Jun 18 21:15:15 2020 +0100
@@ -38,6 +38,10 @@
 
 #include <ifaddrs.h>
 
+/* 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 */
+
 /* Some systems have in-built IPv4 DAD.
  * However, we need them to do DAD at carrier up as well. */
 #ifdef IN_IFF_TENTATIVE
@@ -156,6 +160,7 @@
 #define if_getmtu(ifp) if_domtu((ifp), 0)
 #define if_setmtu(ifp, mtu) if_domtu((ifp), (mtu))
 int if_carrier(struct interface *);
+int if_pollinit(struct interface *ifp);
 
 #ifdef ALIAS_ADDR
 int if_makealias(char *, size_t, const char *, int);