From c488b68e75ee5304007eef37203c4fc10193d191 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sat, 2 Jun 2018 13:06:00 +0100
Subject: [PATCH 11/17] Handle standard and contructed dhcp-ranges on the same
 interface.

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
 CHANGELOG   |  6 ++++++
 src/dhcp6.c | 29 +++++++++++++++++------------
 2 files changed, 23 insertions(+), 12 deletions(-)

--- a/CHANGELOG
+++ b/CHANGELOG
@@ -23,6 +23,12 @@ version 2.80
 	which packets should be dumped is given by the --dumpmask
 	option.
 
+	Handle the case of both standard and constructed dhcp-ranges on the
+	same interface better. We don't now contruct a dhcp-range if there's
+	already one specified. This allows the specified interface to
+	have different parameters and avoids advertising the same
+	prefix twice. Thanks to Luis Marsano for spotting this case.
+
 
 version 2.79
 	Fix parsing of CNAME arguments, which are confused by extra spaces.
--- a/src/dhcp6.c
+++ b/src/dhcp6.c
@@ -667,23 +667,28 @@ static int construct_worker(struct in6_a
 	end6 = *local;
 	setaddr6part(&end6, addr6part(&template->end6));
 	
+	/* If there's an absolute address context covering this address
+	   then don't contruct one as well. */
 	for (context = daemon->dhcp6; context; context = context->next)
-	  if ((context->flags & CONTEXT_CONSTRUCTED) &&
+	  if (!(context->flags & CONTEXT_TEMPLATE) &&
 	      IN6_ARE_ADDR_EQUAL(&start6, &context->start6) &&
 	      IN6_ARE_ADDR_EQUAL(&end6, &context->end6))
 	    {
-	      int flags = context->flags;
-	      context->flags &= ~(CONTEXT_GC | CONTEXT_OLD);
-	      if (flags & CONTEXT_OLD)
+	      if (context->flags & CONTEXT_CONSTRUCTED)
 		{
-		  /* address went, now it's back */
-		  log_context(AF_INET6, context); 
-		  /* fast RAs for a while */
-		  ra_start_unsolicited(param->now, context);
-		  param->newone = 1; 
-		  /* Add address to name again */
-		  if (context->flags & CONTEXT_RA_NAME)
-		    param->newname = 1;
+		  int cflags = context->flags;
+		  context->flags &= ~(CONTEXT_GC | CONTEXT_OLD);
+		  if (cflags & CONTEXT_OLD)
+		    {
+		      /* address went, now it's back */
+		      log_context(AF_INET6, context); 
+		      /* fast RAs for a while */
+		      ra_start_unsolicited(param->now, context);
+		      param->newone = 1; 
+		      /* Add address to name again */
+		      if (context->flags & CONTEXT_RA_NAME)
+			param->newname = 1;
+		    }
 		}
 	      break;
 	    }
