dhcpcd-discuss

Re: daemon.log being flooded

Roy Marples

Tue Jun 11 18:40:12 2019

Hi Rob

On 11/06/2019 14:54, rob stone wrote:
The daemon.log on my laptop is being flooded with these messages.

Jun 11 17:28:43 roblaptop dhcpcd[609]: eth0: Router Advertisement from
fe80::7e8b:caff:fecf:10fc
Jun 11 17:28:43 roblaptop dhcpcd[609]: eth0: soliciting a DHCPv6 lease
Jun 11 17:28:43 roblaptop dhcpcd[609]: eth0: dropping DHCPv6 due to no
valid routers
Jun 11 17:28:49 roblaptop dhcpcd[609]: eth0: Router Advertisement from
fe80::7e8b:caff:fecf:10fc
Jun 11 17:28:49 roblaptop dhcpcd[609]: eth0: soliciting a DHCPv6 lease
Jun 11 17:28:49 roblaptop dhcpcd[609]: eth0: dropping DHCPv6 due to no
valid routers
Jun 11 17:28:57 roblaptop dhcpcd[609]: eth0: Router Advertisement from
fe80::7e8b:caff:fecf:10fc
Jun 11 17:28:57 roblaptop dhcpcd[609]: eth0: soliciting a DHCPv6 lease
Jun 11 17:28:57 roblaptop dhcpcd[609]: eth0: dropping DHCPv6 due to no
valid routers
Jun 11 17:29:06 roblaptop dhcpcd[609]: eth0: Router Advertisement from
fe80::7e8b:caff:fecf:10fc
Jun 11 17:29:06 roblaptop dhcpcd[609]: eth0: soliciting a DHCPv6 lease
Jun 11 17:29:06 roblaptop dhcpcd[609]: eth0: dropping DHCPv6 due to no
valid routers

As you can see it happens every few seconds. I'm able to ping the IP
address.

I no little about dhcpcd.
I've read the man pages about dhcpcd.conf.

Do I have to set the option noipv6rs in dhcpcd.conf in order to stop
all these messages?

Yes, I would advise setting noipv6rs.
Basically you are receiving what looks like a pointless IPv6 Router Advertisement. dhcpcd normally discards these, but you're receiving them awfully quickly. Modern IPv6 routers send these messages a lot less frequently so it's not much of a problem.

You could also try this patch to dhcpcd-7.2 which will at least silence the solicit and drop DHCP messages without having to add noipv6rs. I'm currently unsure how to silence the Router Advertisement message by default.

Roy
diff --git a/src/ipv6nd.c b/src/ipv6nd.c
index b5e503cc..64d62a5d 100644
--- a/src/ipv6nd.c
+++ b/src/ipv6nd.c
@@ -122,6 +122,7 @@ __CTASSERT(sizeof(struct nd_opt_rdnss) == 8);
 //#define DEBUG_NS
 //
 
+static void ipv6nd_expireiface(void *);
 static void ipv6nd_handledata(void *);
 
 /*
@@ -563,7 +564,7 @@ ipv6nd_expire(struct interface *ifp, uint32_t seconds)
 		}
 	}
 	if (seconds)
-		ipv6nd_expirera(ifp);
+		ipv6nd_expireiface(ifp);
 	else
 		rt_build(ifp->ctx, AF_INET6);
 }
@@ -801,6 +802,122 @@ ipv6nd_scriptrun(struct ra *rap)
 	return pid;
 }
 
+static struct ra *
+ipv6nd_expirera(struct interface *ifp, struct ra *ra)
+{
+	struct ra *rap, *ran;
+	struct timespec now, lt, expire, next;
+	bool expired, valid, validone;
+	struct ipv6_addr *ia;
+#ifdef DHCP6
+	bool anyvalid = false;
+#endif
+
+	clock_gettime(CLOCK_MONOTONIC, &now);
+	expired = false;
+	timespecclear(&next);
+
+	TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
+		if (rap->iface != ifp)
+			continue;
+		valid = validone = false;
+		if (rap->lifetime) {
+			lt.tv_sec = (time_t)rap->lifetime;
+			lt.tv_nsec = 0;
+			timespecadd(&rap->acquired, &lt, &expire);
+			if (rap->lifetime == 0 || timespeccmp(&now, &expire, >))
+			{
+				if (!rap->expired) {
+					logwarnx("%s: %s: router expired",
+					    ifp->name, rap->sfrom);
+					rap->expired = expired = 1;
+					rap->lifetime = 0;
+				}
+			} else {
+				valid = true;
+				timespecsub(&expire, &now, &lt);
+				if (!timespecisset(&next) ||
+				    timespeccmp(&next, &lt, >))
+					next = lt;
+			}
+		}
+
+		/* Not every prefix is tied to an address which
+		 * the kernel can expire, so we need to handle it ourself.
+		 * Also, some OS don't support address lifetimes (Solaris). */
+		TAILQ_FOREACH(ia, &rap->addrs, next) {
+			if (ia->prefix_vltime == 0)
+				continue;
+			if (ia->prefix_vltime == ND6_INFINITE_LIFETIME) {
+				validone = true;
+				continue;
+			}
+			lt.tv_sec = (time_t)ia->prefix_vltime;
+			lt.tv_nsec = 0;
+			timespecadd(&ia->acquired, &lt, &expire);
+			if (timespeccmp(&now, &expire, >)) {
+				if (ia->flags & IPV6_AF_ADDED) {
+					logwarnx("%s: expired address %s",
+					    ia->iface->name, ia->saddr);
+					if (if_address6(RTM_DELADDR, ia)== -1 &&
+					    errno != EADDRNOTAVAIL &&
+					    errno != ENXIO)
+						logerr(__func__);
+				}
+				ia->prefix_vltime = ia->prefix_pltime = 0;
+				ia->flags &=
+				    ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
+				expired = true;
+			} else {
+				timespecsub(&expire, &now, &lt);
+				if (!timespecisset(&next) ||
+				    timespeccmp(&next, &lt, >))
+					next = lt;
+				validone = true;
+			}
+		}
+
+		/* XXX FixMe!
+		 * We need to extract the lifetime from each option and check
+		 * if that has expired or not.
+		 * If it has, zero the option out in the returned data. */
+
+		/* No valid lifetimes are left on the RA, so we might
+		 * as well punt it. */
+		if (!valid && !validone) {
+			ipv6nd_free_ra(rap);
+			if (rap == ra)
+				ra = NULL;
+		}
+#ifdef DHCP6
+		else
+			anyvalid = true;
+#endif
+	}
+
+	if (timespecisset(&next))
+		eloop_timeout_add_tv(ifp->ctx->eloop,
+		    &next, ipv6nd_expireiface, ifp);
+	if (expired) {
+		rt_build(ifp->ctx, AF_INET6);
+		script_runreason(ifp, "ROUTERADVERT");
+	}
+
+#ifdef DHCP6
+	/* No valid routers? Kill any DHCPv6. */
+	if (!anyvalid)
+		dhcp6_dropnondelegates(ifp);
+#endif
+	return ra;
+}
+
+static void
+ipv6nd_expireiface(void *arg)
+{
+
+	ipv6nd_expirera(arg, NULL);
+}
+
 static void
 ipv6nd_addaddr(void *arg)
 {
@@ -1294,8 +1411,14 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 	eloop_timeout_delete(ifp->ctx->eloop, NULL, rap); /* reachable timer */
 
 handle_flag:
+	/* If the advertisement has fully expired, do nothing.
+	 * It's pointless running DHCP in this case. */
+	if (ipv6nd_expirera(ifp, rap) != rap)
+		return;
+
 	if (!(ifp->options->options & DHCPCD_DHCP6))
 		goto nodhcp6;
+
 /* Only log a DHCPv6 start error if compiled in or debugging is enabled. */
 #ifdef DHCP6
 #define LOG_DHCP6	logerr
@@ -1319,9 +1442,6 @@ nodhcp6:
 			return;
 		}
 	}
-
-	/* Expire should be called last as the rap object could be destroyed */
-	ipv6nd_expirera(ifp);
 }
 
 int
@@ -1517,113 +1637,6 @@ ipv6nd_handleifa(int cmd, struct ipv6_addr *addr, pid_t pid)
 	}
 }
 
-void
-ipv6nd_expirera(void *arg)
-{
-	struct interface *ifp;
-	struct ra *rap, *ran;
-	struct timespec now, lt, expire, next;
-	bool expired, valid, validone;
-	struct ipv6_addr *ia;
-#ifdef DHCP6
-	bool anyvalid = false;
-#endif
-
-	ifp = arg;
-	clock_gettime(CLOCK_MONOTONIC, &now);
-	expired = false;
-	timespecclear(&next);
-
-	TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
-		if (rap->iface != ifp)
-			continue;
-		valid = validone = false;
-		if (rap->lifetime) {
-			lt.tv_sec = (time_t)rap->lifetime;
-			lt.tv_nsec = 0;
-			timespecadd(&rap->acquired, &lt, &expire);
-			if (rap->lifetime == 0 || timespeccmp(&now, &expire, >))
-			{
-				if (!rap->expired) {
-					logwarnx("%s: %s: router expired",
-					    ifp->name, rap->sfrom);
-					rap->expired = expired = 1;
-					rap->lifetime = 0;
-				}
-			} else {
-				valid = true;
-				timespecsub(&expire, &now, &lt);
-				if (!timespecisset(&next) ||
-				    timespeccmp(&next, &lt, >))
-					next = lt;
-			}
-		}
-
-		/* Not every prefix is tied to an address which
-		 * the kernel can expire, so we need to handle it ourself.
-		 * Also, some OS don't support address lifetimes (Solaris). */
-		TAILQ_FOREACH(ia, &rap->addrs, next) {
-			if (ia->prefix_vltime == 0)
-				continue;
-			if (ia->prefix_vltime == ND6_INFINITE_LIFETIME) {
-				validone = true;
-				continue;
-			}
-			lt.tv_sec = (time_t)ia->prefix_vltime;
-			lt.tv_nsec = 0;
-			timespecadd(&ia->acquired, &lt, &expire);
-			if (timespeccmp(&now, &expire, >)) {
-				if (ia->flags & IPV6_AF_ADDED) {
-					logwarnx("%s: expired address %s",
-					    ia->iface->name, ia->saddr);
-					if (if_address6(RTM_DELADDR, ia)== -1 &&
-					    errno != EADDRNOTAVAIL &&
-					    errno != ENXIO)
-						logerr(__func__);
-				}
-				ia->prefix_vltime = ia->prefix_pltime = 0;
-				ia->flags &=
-				    ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
-				expired = true;
-			} else {
-				timespecsub(&expire, &now, &lt);
-				if (!timespecisset(&next) ||
-				    timespeccmp(&next, &lt, >))
-					next = lt;
-				validone = true;
-			}
-		}
-
-		/* XXX FixMe!
-		 * We need to extract the lifetime from each option and check
-		 * if that has expired or not.
-		 * If it has, zero the option out in the returned data. */
-
-		/* No valid lifetimes are left on the RA, so we might
-		 * as well punt it. */
-		if (!valid && !validone)
-			ipv6nd_free_ra(rap);
-#ifdef DHCP6
-		else
-			anyvalid = true;
-#endif
-	}
-
-	if (timespecisset(&next))
-		eloop_timeout_add_tv(ifp->ctx->eloop,
-		    &next, ipv6nd_expirera, ifp);
-	if (expired) {
-		rt_build(ifp->ctx, AF_INET6);
-		script_runreason(ifp, "ROUTERADVERT");
-	}
-
-#ifdef DHCP6
-	/* No valid routers? Kill any DHCPv6. */
-	if (!anyvalid)
-		dhcp6_dropnondelegates(ifp);
-#endif
-}
-
 void
 ipv6nd_drop(struct interface *ifp)
 {
diff --git a/src/ipv6nd.h b/src/ipv6nd.h
index 7b959814..07a99438 100644
--- a/src/ipv6nd.h
+++ b/src/ipv6nd.h
@@ -101,7 +101,6 @@ const struct ipv6_addr *ipv6nd_iffindaddr(const struct interface *ifp,
 struct ipv6_addr *ipv6nd_findaddr(struct dhcpcd_ctx *,
     const struct in6_addr *, unsigned int);
 ssize_t ipv6nd_free(struct interface *);
-void ipv6nd_expirera(void *arg);
 int ipv6nd_hasra(const struct interface *);
 int ipv6nd_hasradhcp(const struct interface *);
 void ipv6nd_handleifa(int, struct ipv6_addr *, pid_t);

Follow-Ups:
Re: daemon.log being floodedRoy Marples
References:
daemon.log being floodedrob stone
Archive administrator: postmaster@marples.name