From abacf8ad0d8844685e5cd76645a34ef2b8da3253 Mon Sep 17 00:00:00 2001
From: Thomas Markwalder <tmark@isc.org>
Date: Fri, 1 Dec 2017 09:13:26 -0500
Subject: [PATCH] [master] Use 0 instead of -1 to indicate empty heap index

    Merges in rt46719.
---
 RELNOTES                     |  5 +++++
 includes/dhcpd.h             |  5 +++--
 server/mdb6.c                | 42 ++++++++++++++++++++++--------------------
 server/tests/mdb6_unittest.c |  9 +++++++--
 4 files changed, 37 insertions(+), 24 deletions(-)

#diff --git a/RELNOTES b/RELNOTES
#index ececd89e..b93af612 100644
#--- a/RELNOTES
#+++ b/RELNOTES
#@@ -1176,6 +1176,11 @@ dhcp-users@lists.isc.org.
#   in the lease file causing issues with DDNS and so forth.
#   [ISC-bugs #43786]
# 
#+- Replaced iasubopt::heap_index with separate values for active and inactive
#+  heaps: iasubopt::active_index and iasubopt::inactive_index.  This was done
#+  to accomodate a change in behavior in BIND9 isc_heap_delete().
#+  [ISC-bugs #46719]
#+
# 			Changes since 4.2.0 (new features)
# 
# - If a client renews before 'dhcp-cache-threshold' percent of its lease
Index: isc-dhcp-4.3.5/includes/dhcpd.h
===================================================================
--- isc-dhcp-4.3.5.orig/includes/dhcpd.h	2019-05-06 08:57:34.738578132 -0400
+++ isc-dhcp-4.3.5/includes/dhcpd.h	2019-05-06 08:57:34.734578119 -0400
@@ -1624,8 +1624,9 @@ struct iasubopt {
  */
 #define EXPIRED_IPV6_CLEANUP_TIME (60*60)
 
-	int heap_index;				/* index into heap, or -1
-						   (internal use only) */
+	/* index into heaps, or -1 (internal use only) */
+	int active_index;
+	int inactive_index;
 
 	/*
 	 * A pointer to the state of the ddns update for this lease.
Index: isc-dhcp-4.3.5/server/mdb6.c
===================================================================
--- isc-dhcp-4.3.5.orig/server/mdb6.c	2019-05-06 08:57:34.738578132 -0400
+++ isc-dhcp-4.3.5/server/mdb6.c	2019-05-06 08:57:34.734578119 -0400
@@ -216,7 +216,8 @@ iasubopt_allocate(struct iasubopt **iasu
 
 	tmp->refcnt = 1;
 	tmp->state = FTS_FREE;
-	tmp->heap_index = -1;
+	tmp->active_index = 0;
+	tmp->inactive_index = 0;
 	tmp->plen = 255;
 
 	*iasubopt = tmp;
@@ -600,14 +601,18 @@ lease_older(void *a, void *b) {
 }
 
 /*
- * Helper function for lease address/prefix heaps.
+ * Helper functions for lease address/prefix heaps.
  * Callback when an address's position in the heap changes.
  */
 static void
-lease_index_changed(void *iasubopt, unsigned int new_heap_index) {
-	((struct iasubopt *)iasubopt)-> heap_index = new_heap_index;
+active_changed(void *iasubopt, unsigned int new_heap_index) {
+	((struct iasubopt *)iasubopt)->active_index = new_heap_index;
 }
 
+static void
+inactive_changed(void *iasubopt, unsigned int new_heap_index) {
+	((struct iasubopt *)iasubopt)->inactive_index = new_heap_index;
+}
 
 /*!
  *
@@ -660,13 +665,13 @@ ipv6_pool_allocate(struct ipv6_pool **po
 		dfree(tmp, file, line);
 		return ISC_R_NOMEMORY;
 	}
-	if (isc_heap_create(dhcp_gbl_ctx.mctx, lease_older, lease_index_changed,
+	if (isc_heap_create(dhcp_gbl_ctx.mctx, lease_older, active_changed,
 			    0, &(tmp->active_timeouts)) != ISC_R_SUCCESS) {
 		iasubopt_free_hash_table(&(tmp->leases), file, line);
 		dfree(tmp, file, line);
 		return ISC_R_NOMEMORY;
 	}
-	if (isc_heap_create(dhcp_gbl_ctx.mctx, lease_older, lease_index_changed,
+	if (isc_heap_create(dhcp_gbl_ctx.mctx, lease_older, inactive_changed,
 			    0, &(tmp->inactive_timeouts)) != ISC_R_SUCCESS) {
 		isc_heap_destroy(&(tmp->active_timeouts));
 		iasubopt_free_hash_table(&(tmp->leases), file, line);
@@ -1186,7 +1191,7 @@ cleanup_lease6(ia_hash_t *ia_table,
 	 * Remove the old lease from the active heap and from the hash table
 	 * then remove the lease from the IA and clean up the IA if necessary.
 	 */
-	isc_heap_delete(pool->active_timeouts, test_iasubopt->heap_index);
+	isc_heap_delete(pool->active_timeouts, test_iasubopt->active_index);
 	pool->num_active--;
 	if (pool->ipv6_pond)
 		pool->ipv6_pond->num_active--;
@@ -1259,7 +1264,7 @@ add_lease6(struct ipv6_pool *pool, struc
 		if ((test_iasubopt->state == FTS_ACTIVE) ||
 		    (test_iasubopt->state == FTS_ABANDONED)) {
 			isc_heap_delete(pool->active_timeouts,
-					test_iasubopt->heap_index);
+					test_iasubopt->active_index);
 			pool->num_active--;
 			if (pool->ipv6_pond)
 				pool->ipv6_pond->num_active--;
@@ -1271,7 +1276,7 @@ add_lease6(struct ipv6_pool *pool, struc
 			}
 		} else {
 			isc_heap_delete(pool->inactive_timeouts,
-					test_iasubopt->heap_index);
+					test_iasubopt->inactive_index);
 			pool->num_inactive--;
 		}
 
@@ -1392,14 +1397,13 @@ lease6_usable(struct iasubopt *lease) {
 static isc_result_t
 move_lease_to_active(struct ipv6_pool *pool, struct iasubopt *lease) {
 	isc_result_t insert_result;
-	int old_heap_index;
 
-	old_heap_index = lease->heap_index;
 	insert_result = isc_heap_insert(pool->active_timeouts, lease);
 	if (insert_result == ISC_R_SUCCESS) {
        		iasubopt_hash_add(pool->leases, &lease->addr, 
 				  sizeof(lease->addr), lease, MDL);
-		isc_heap_delete(pool->inactive_timeouts, old_heap_index);
+		isc_heap_delete(pool->inactive_timeouts,
+				lease->inactive_index);
 		pool->num_active++;
 		pool->num_inactive--;
 		lease->state = FTS_ACTIVE;
@@ -1449,16 +1453,16 @@ renew_lease6(struct ipv6_pool *pool, str
 	if (lease->state == FTS_ACTIVE) {
 		if (old_end_time <= lease->hard_lifetime_end_time) {
 			isc_heap_decreased(pool->active_timeouts,
-					   lease->heap_index);
+					   lease->active_index);
 		} else {
 			isc_heap_increased(pool->active_timeouts,
-					   lease->heap_index);
+					   lease->active_index);
 		}
 		return ISC_R_SUCCESS;
 	} else if (lease->state == FTS_ABANDONED) {
 		char tmp_addr[INET6_ADDRSTRLEN];
                 lease->state = FTS_ACTIVE;
-                isc_heap_increased(pool->active_timeouts, lease->heap_index);
+                isc_heap_increased(pool->active_timeouts, lease->active_index);
 		log_info("Reclaiming previously abandoned address %s",
 			 inet_ntop(AF_INET6, &(lease->addr), tmp_addr,
 				   sizeof(tmp_addr)));
@@ -1480,9 +1484,7 @@ static isc_result_t
 move_lease_to_inactive(struct ipv6_pool *pool, struct iasubopt *lease, 
 		       binding_state_t state) {
 	isc_result_t insert_result;
-	int old_heap_index;
 
-	old_heap_index = lease->heap_index;
 	insert_result = isc_heap_insert(pool->inactive_timeouts, lease);
 	if (insert_result == ISC_R_SUCCESS) {
 		/*
@@ -1533,7 +1535,7 @@ move_lease_to_inactive(struct ipv6_pool
 
 		iasubopt_hash_delete(pool->leases, 
 				     &lease->addr, sizeof(lease->addr), MDL);
-		isc_heap_delete(pool->active_timeouts, old_heap_index);
+		isc_heap_delete(pool->active_timeouts, lease->active_index);
 		lease->state = state;
 		pool->num_active--;
 		pool->num_inactive++;
@@ -1611,7 +1613,7 @@ decline_lease6(struct ipv6_pool *pool, s
 		pool->ipv6_pond->num_abandoned++;
 
 	lease->hard_lifetime_end_time = MAX_TIME;
-	isc_heap_decreased(pool->active_timeouts, lease->heap_index);
+	isc_heap_decreased(pool->active_timeouts, lease->active_index);
 	return ISC_R_SUCCESS;
 }
 
@@ -1884,7 +1886,7 @@ cleanup_old_expired(struct ipv6_pool *po
 			break;
 		}
 
-		isc_heap_delete(pool->inactive_timeouts, tmp->heap_index);
+		isc_heap_delete(pool->inactive_timeouts, tmp->inactive_index);
 		pool->num_inactive--;
 
 		if (tmp->ia != NULL) {
Index: isc-dhcp-4.3.5/server/tests/mdb6_unittest.c
===================================================================
--- isc-dhcp-4.3.5.orig/server/tests/mdb6_unittest.c	2019-05-06 08:57:34.738578132 -0400
+++ isc-dhcp-4.3.5/server/tests/mdb6_unittest.c	2019-05-06 08:57:34.734578119 -0400
@@ -65,8 +65,13 @@ ATF_TC_BODY(iaaddr_basic, tc)
     if (iaaddr->state != FTS_FREE) {
         atf_tc_fail("ERROR: bad state %s:%d", MDL);
     }
-    if (iaaddr->heap_index != -1) {
-        atf_tc_fail("ERROR: bad heap_index %s:%d", MDL);
+    if (iaaddr->active_index != 0) {
+        atf_tc_fail("ERROR: bad active_index :%d %s:%d",
+            iaaddr->active_index, MDL);
+    }
+    if (iaaddr->inactive_index != 0) {
+        atf_tc_fail("ERROR: bad inactive_index %d %s:%d",
+            iaaddr->inactive_index, MDL);
     }
     if (iasubopt_reference(&iaaddr_copy, iaaddr, MDL) != ISC_R_SUCCESS) {
         atf_tc_fail("ERROR: iasubopt_reference() %s:%d", MDL);
