Blob Blame History Raw
From 515ba97595e60c762c448657f3c0e545c1e365f9 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 27 Jan 2020 23:30:10 +0000
Subject: [PATCH] Fix infinite-loop router advert problems.

The previous code here, which started fast-RA whenever that local
address associated with a DHCP context changed, is very vulnerable
to flapping  due to dynamically created addresses in the same net.

Simplify so that if a context which has never found an interface now
finds one, that gets advertised, but not for other changes. That satisfies
the original intention that prefixes not in place when dnsmasq starts
should be recognised.

Also totally ignore all interfaces where we are configured not to do DHCP,
to preclude flapping of they have prefixes in common with interfaces
where we do DHCP.
---
 src/dhcp6.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/src/dhcp6.c b/src/dhcp6.c
index 041ad07..51788ed 100644
--- a/src/dhcp6.c
+++ b/src/dhcp6.c
@@ -658,7 +658,8 @@ static int construct_worker(struct in6_addr *local, int prefix,
   char ifrn_name[IFNAMSIZ];
   struct in6_addr start6, end6;
   struct dhcp_context *template, *context;
-
+  struct iname *tmp;
+  
   (void)scope;
   (void)flags;
   (void)valid;
@@ -677,9 +678,15 @@ static int construct_worker(struct in6_addr *local, int prefix,
   if (flags & IFACE_DEPRECATED)
     return 1;
 
-  if (!indextoname(daemon->icmp6fd, if_index, ifrn_name))
-    return 0;
+  /* Ignore interfaces where we're not doing RA/DHCP6 */
+  if (!indextoname(daemon->icmp6fd, if_index, ifrn_name) ||
+      !iface_check(AF_LOCAL, NULL, ifrn_name, NULL))
+    return 1;
   
+  for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
+    if (tmp->name && wildcard_match(tmp->name, ifrn_name))
+      return 1;
+
   for (template = daemon->dhcp6; template; template = template->next)
     if (!(template->flags & (CONTEXT_TEMPLATE | CONTEXT_CONSTRUCTED)))
       {
@@ -689,7 +696,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
 	    is_same_net6(local, &template->end6, template->prefix))
 	  {
 	    /* First time found, do fast RA. */
-	    if (template->if_index != if_index || !IN6_ARE_ADDR_EQUAL(&template->local6, local))
+	    if (template->if_index == 0)
 	      {
 		ra_start_unsolicited(param->now, template);
 		param->newone = 1;
-- 
2.21.1