Fix logic for associating leases with interfaces.

This handles the case that more than one interface contains
the network the lease address is on, but the interfaces have different
prefix lengths. Use the longest prefix length.
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 30f176a..8e103d3 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -641,6 +641,8 @@
   unsigned char *extradata;
   unsigned int extradata_len, extradata_size;
   int last_interface;
+  int new_interface;     /* save possible originated interface */
+  int new_prefixlen;     /* and its prefix length */
 #ifdef HAVE_DHCP6
   struct in6_addr addr6;
   int iaid;
@@ -1132,6 +1134,7 @@
 int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
 int hostname_isequal(const char *a, const char *b);
 time_t dnsmasq_time(void);
+int netmask_length(struct in_addr mask);
 int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask);
 #ifdef HAVE_IPV6
 int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen);
@@ -1244,6 +1247,7 @@
 #ifdef HAVE_DHCP
 void lease_update_file(time_t now);
 void lease_update_dns(int force);
+void lease_update_interface(time_t now);
 void lease_init(time_t now);
 struct dhcp_lease *lease4_allocate(struct in_addr addr);
 #ifdef HAVE_DHCP6
diff --git a/src/lease.c b/src/lease.c
index 5d1eefc..9479afc 100644
--- a/src/lease.c
+++ b/src/lease.c
@@ -352,16 +352,21 @@
 			     struct in_addr netmask, struct in_addr broadcast, void *vparam)
 {
   struct dhcp_lease *lease;
-  
+  int prefix;
+
   (void) label;
   (void) broadcast;
   (void) vparam;
 
   for (lease = leases; lease; lease = lease->next)
-    if (!(lease->flags & (LEASE_TA | LEASE_NA)))
-      if (is_same_net(local, lease->addr, netmask))
-	lease_set_interface(lease, if_index, *((time_t *)vparam));
-  
+    if (!(lease->flags & (LEASE_TA | LEASE_NA))) {
+      prefix = netmask_length(netmask);
+      if (is_same_net(local, lease->addr, netmask) && prefix > lease->new_prefixlen) {
+        lease->new_interface = if_index;
+        lease->new_prefixlen = prefix;
+      }
+    }
+
   return 1;
 }
 
@@ -371,17 +376,23 @@
 			     int preferred, int valid, void *vparam)
 {
   struct dhcp_lease *lease;
-  
+
   (void)scope;
   (void)flags;
   (void)preferred;
   (void)valid;
+  (void)vparam;
 
   for (lease = leases; lease; lease = lease->next)
     if ((lease->flags & (LEASE_TA | LEASE_NA)))
-      if (is_same_net6(local, &lease->addr6, prefix))
-	lease_set_interface(lease, if_index, *((time_t *)vparam));
-  
+      if (is_same_net6(local, &lease->addr6, prefix) && prefix > lease->new_prefixlen) {
+        /* save prefix length for comparison, as we might get shorter matching
+         * prefix in upcoming netlink GETADDR responses
+         * */
+        lease->new_interface = if_index;
+        lease->new_prefixlen = prefix;
+      }
+
   return 1;
 }
 
@@ -418,6 +429,7 @@
 #ifdef HAVE_DHCP6
   iface_enumerate(AF_INET6, &now, find_interface_v6);
 #endif
+  lease_update_interface(now);
 }
 
 #ifdef HAVE_DHCP6
@@ -492,6 +504,16 @@
     }
 }
 
+void lease_update_interface(time_t now)
+{
+  struct dhcp_lease *lease;
+
+  for (lease = leases; lease; lease = lease->next)
+    if (lease->new_interface > 0) {
+      lease_set_interface(lease, lease->new_interface, now);
+    }
+}
+
 void lease_prune(struct dhcp_lease *target, time_t now)
 {
   struct dhcp_lease *lease, *tmp, **up;
diff --git a/src/util.c b/src/util.c
index a503082..c1b0c50 100644
--- a/src/util.c
+++ b/src/util.c
@@ -319,6 +319,18 @@
 #endif
 }
 
+int netmask_length(struct in_addr mask)
+{
+  int zero_count = 0;
+
+  while (0x0 == (mask.s_addr & 0x1)) {
+    mask.s_addr >>= 1;
+    ++zero_count;
+  }
+
+  return 32 - zero_count;
+}
+
 int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
 {
   return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);