Fix DHCPv6 address allocation for some pathalogical cases.
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index b131c96..5cbe0e5 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -992,6 +992,7 @@
 struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type);
 struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len, 
 			       int lease_type, int iaid, struct in6_addr *addr);
+void lease6_filter(int lease_type, int iaid, struct dhcp_context *context);
 struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr);
 u64 lease_find_max_addr6(struct dhcp_context *context);
 void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface);
diff --git a/src/lease.c b/src/lease.c
index cff24a2..5f91bc8 100644
--- a/src/lease.c
+++ b/src/lease.c
@@ -562,18 +562,31 @@
 	   memcmp(clid, lease->clid, clid_len) != 0))
 	continue;
       
-      if (clid || addr)
-	{
-	  lease->flags |= LEASE_USED;
-	  return lease;
-	}
-      else 
-	lease->flags &= ~LEASE_USED;
+      lease->flags |= LEASE_USED;
+      return lease;
     }
   
   return NULL;
 }
 
+void lease6_filter(int lease_type, int iaid, struct dhcp_context *context)
+{
+  struct dhcp_lease *lease;
+  
+  for (lease = leases; lease; lease = lease->next)
+    {
+      /* reset "USED flag */
+      lease->flags &= ~LEASE_USED;
+      
+      if (!(lease->flags & lease_type) || lease->hwaddr_type != iaid)
+	continue;
+      
+      /* leases on the wrong interface get filtered out here */
+      if (!address6_available(context, (struct in6_addr *)&lease->hwaddr, NULL))
+	lease->flags |= LEASE_USED;
+    }
+}
+
 struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr)
 {
   struct dhcp_lease *lease;
diff --git a/src/rfc3315.c b/src/rfc3315.c
index a1c8326..14cbc66 100644
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -497,7 +497,7 @@
 	    ia_option =  opt6_find(opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4), ia_end, OPTION6_IAADDR, 24);
 	    
 	    /* reset "USED" flags on leases */
-	    lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
+	    lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
 	    
 	    o = new_opt6(ia_type);
 	    put_opt6_long(iaid);
@@ -570,7 +570,12 @@
 			  my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), 
 				    daemon->addrbuff);
 			else
-			  addrp = &config->addr6;			 
+			  {
+			    addrp = &config->addr6;
+			    /* may have existing lease for this address */
+			    lease = lease6_find(clid, clid_len, 
+						ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, addrp); 
+			  }
 		      }
 		    
 		    /* existing lease */
@@ -832,7 +837,7 @@
 	    iacntr = save_counter(-1); 
 	    
 	    /* reset "USED" flags on leases */
-	    lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
+	    lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
 	    
 	    ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
 	    ia_end = opt6_ptr(opt, opt6_len(opt));
@@ -1036,7 +1041,7 @@
 	    ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
 	    
 	    /* reset "USED" flags on leases */
-	    lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
+	    lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
 		
 	    for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
 		 ia_option;
@@ -1115,7 +1120,7 @@
 	    ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
 	    
 	    /* reset "USED" flags on leases */
-	    lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
+	    lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
 		
 	    for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
 		 ia_option;