Home | History | Annotate | Line # | Download | only in isc
      1 /*	$NetBSD: radix.c,v 1.11 2025/07/17 19:01:46 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 /*
     17  * This source was adapted from MRT's RCS Ids:
     18  * Id: radix.c,v 1.10.2.1 1999/11/29 05:16:24 masaki Exp
     19  * Id: prefix.c,v 1.37.2.9 2000/03/10 02:53:19 labovit Exp
     20  */
     21 
     22 #include <inttypes.h>
     23 
     24 #include <isc/mem.h>
     25 #include <isc/radix.h>
     26 #include <isc/types.h>
     27 #include <isc/util.h>
     28 
     29 #define BIT_TEST(f, b) (((f) & (b)) != 0)
     30 
     31 static isc_result_t
     32 _new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family, void *dest,
     33 	    int bitlen);
     34 
     35 static void
     36 _deref_prefix(isc_prefix_t *prefix);
     37 
     38 static isc_result_t
     39 _ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix);
     40 
     41 static int
     42 _comp_with_mask(void *addr, void *dest, u_int mask);
     43 
     44 static void
     45 _clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func);
     46 
     47 static isc_result_t
     48 _new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family, void *dest,
     49 	    int bitlen) {
     50 	isc_prefix_t *prefix;
     51 
     52 	REQUIRE(target != NULL);
     53 
     54 	if (family != AF_INET6 && family != AF_INET && family != AF_UNSPEC) {
     55 		return ISC_R_NOTIMPLEMENTED;
     56 	}
     57 
     58 	prefix = isc_mem_get(mctx, sizeof(isc_prefix_t));
     59 
     60 	if (family == AF_INET6) {
     61 		prefix->bitlen = (bitlen >= 0) ? bitlen : 128;
     62 		memmove(&prefix->add.sin6, dest, 16);
     63 	} else {
     64 		/* AF_UNSPEC is "any" or "none"--treat it as AF_INET */
     65 		prefix->bitlen = (bitlen >= 0) ? bitlen : 32;
     66 		memmove(&prefix->add.sin, dest, 4);
     67 	}
     68 
     69 	prefix->family = family;
     70 	prefix->mctx = NULL;
     71 	isc_mem_attach(mctx, &prefix->mctx);
     72 
     73 	isc_refcount_init(&prefix->refcount, 1);
     74 
     75 	*target = prefix;
     76 	return ISC_R_SUCCESS;
     77 }
     78 
     79 static void
     80 _deref_prefix(isc_prefix_t *prefix) {
     81 	if (prefix != NULL) {
     82 		if (isc_refcount_decrement(&prefix->refcount) == 1) {
     83 			isc_refcount_destroy(&prefix->refcount);
     84 			isc_mem_putanddetach(&prefix->mctx, prefix,
     85 					     sizeof(isc_prefix_t));
     86 		}
     87 	}
     88 }
     89 
     90 static isc_result_t
     91 _ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix) {
     92 	INSIST(prefix != NULL);
     93 	INSIST((prefix->family == AF_INET && prefix->bitlen <= 32) ||
     94 	       (prefix->family == AF_INET6 && prefix->bitlen <= 128) ||
     95 	       (prefix->family == AF_UNSPEC && prefix->bitlen == 0));
     96 	REQUIRE(target != NULL && *target == NULL);
     97 
     98 	/*
     99 	 * If this prefix is a static allocation, copy it into new memory.
    100 	 * (Note, the refcount still has to be destroyed by the calling
    101 	 * routine.)
    102 	 */
    103 	if (isc_refcount_current(&prefix->refcount) == 0) {
    104 		isc_result_t ret;
    105 		ret = _new_prefix(mctx, target, prefix->family, &prefix->add,
    106 				  prefix->bitlen);
    107 		return ret;
    108 	}
    109 
    110 	isc_refcount_increment(&prefix->refcount);
    111 
    112 	*target = prefix;
    113 	return ISC_R_SUCCESS;
    114 }
    115 
    116 static int
    117 _comp_with_mask(void *addr, void *dest, u_int mask) {
    118 	/* Mask length of zero matches everything */
    119 	if (mask == 0) {
    120 		return 1;
    121 	}
    122 
    123 	if (memcmp(addr, dest, mask / 8) == 0) {
    124 		u_int n = mask / 8;
    125 		u_int m = ((~0U) << (8 - (mask % 8)));
    126 
    127 		if ((mask % 8) == 0 ||
    128 		    (((u_char *)addr)[n] & m) == (((u_char *)dest)[n] & m))
    129 		{
    130 			return 1;
    131 		}
    132 	}
    133 	return 0;
    134 }
    135 
    136 void
    137 isc_radix_create(isc_mem_t *mctx, isc_radix_tree_t **target, int maxbits) {
    138 	REQUIRE(target != NULL && *target == NULL);
    139 	RUNTIME_CHECK(maxbits <= RADIX_MAXBITS);
    140 
    141 	isc_radix_tree_t *radix = isc_mem_get(mctx, sizeof(isc_radix_tree_t));
    142 	*radix = (isc_radix_tree_t){
    143 		.maxbits = maxbits,
    144 		.magic = RADIX_TREE_MAGIC,
    145 	};
    146 	isc_mem_attach(mctx, &radix->mctx);
    147 	*target = radix;
    148 }
    149 
    150 /*
    151  * if func is supplied, it will be called as func(node->data)
    152  * before deleting the node
    153  */
    154 
    155 static void
    156 _clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) {
    157 	REQUIRE(radix != NULL);
    158 
    159 	if (radix->head != NULL) {
    160 		isc_radix_node_t *Xstack[RADIX_MAXBITS + 1];
    161 		isc_radix_node_t **Xsp = Xstack;
    162 		isc_radix_node_t *Xrn = radix->head;
    163 
    164 		while (Xrn != NULL) {
    165 			isc_radix_node_t *l = Xrn->l;
    166 			isc_radix_node_t *r = Xrn->r;
    167 
    168 			if (Xrn->prefix != NULL) {
    169 				_deref_prefix(Xrn->prefix);
    170 				if (func != NULL) {
    171 					func(Xrn->data);
    172 				}
    173 			} else {
    174 				INSIST(Xrn->data[RADIX_V4] == NULL &&
    175 				       Xrn->data[RADIX_V6] == NULL);
    176 			}
    177 
    178 			isc_mem_put(radix->mctx, Xrn, sizeof(*Xrn));
    179 			radix->num_active_node--;
    180 
    181 			if (l != NULL) {
    182 				if (r != NULL) {
    183 					*Xsp++ = r;
    184 				}
    185 				Xrn = l;
    186 			} else if (r != NULL) {
    187 				Xrn = r;
    188 			} else if (Xsp != Xstack) {
    189 				Xrn = *(--Xsp);
    190 			} else {
    191 				Xrn = NULL;
    192 			}
    193 		}
    194 	}
    195 	RUNTIME_CHECK(radix->num_active_node == 0);
    196 }
    197 
    198 void
    199 isc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) {
    200 	REQUIRE(radix != NULL);
    201 	_clear_radix(radix, func);
    202 	isc_mem_putanddetach(&radix->mctx, radix, sizeof(*radix));
    203 }
    204 
    205 /*
    206  * func will be called as func(node->prefix, node->data)
    207  */
    208 void
    209 isc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func) {
    210 	isc_radix_node_t *node;
    211 
    212 	REQUIRE(func != NULL);
    213 
    214 	RADIX_WALK(radix->head, node) { func(node->prefix, node->data); }
    215 	RADIX_WALK_END;
    216 }
    217 
    218 isc_result_t
    219 isc_radix_search(isc_radix_tree_t *radix, isc_radix_node_t **target,
    220 		 isc_prefix_t *prefix) {
    221 	isc_radix_node_t *node;
    222 	isc_radix_node_t *stack[RADIX_MAXBITS + 1];
    223 	u_char *addr;
    224 	uint32_t bitlen;
    225 	int tfam = -1, cnt = 0;
    226 
    227 	REQUIRE(radix != NULL);
    228 	REQUIRE(prefix != NULL);
    229 	REQUIRE(target != NULL && *target == NULL);
    230 	RUNTIME_CHECK(prefix->bitlen <= radix->maxbits);
    231 
    232 	*target = NULL;
    233 
    234 	node = radix->head;
    235 
    236 	if (node == NULL) {
    237 		return ISC_R_NOTFOUND;
    238 	}
    239 
    240 	addr = isc_prefix_touchar(prefix);
    241 	bitlen = prefix->bitlen;
    242 
    243 	while (node != NULL && node->bit < bitlen) {
    244 		if (node->prefix) {
    245 			stack[cnt++] = node;
    246 		}
    247 
    248 		if (BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
    249 		{
    250 			node = node->r;
    251 		} else {
    252 			node = node->l;
    253 		}
    254 	}
    255 
    256 	if (node != NULL && node->prefix) {
    257 		stack[cnt++] = node;
    258 	}
    259 
    260 	while (cnt-- > 0) {
    261 		node = stack[cnt];
    262 
    263 		if (prefix->bitlen < node->bit) {
    264 			continue;
    265 		}
    266 
    267 		if (_comp_with_mask(isc_prefix_tochar(node->prefix),
    268 				    isc_prefix_tochar(prefix),
    269 				    node->prefix->bitlen))
    270 		{
    271 			int fam = ISC_RADIX_FAMILY(prefix);
    272 			if (node->node_num[fam] != -1 &&
    273 			    ((*target == NULL) ||
    274 			     (*target)->node_num[tfam] > node->node_num[fam]))
    275 			{
    276 				*target = node;
    277 				tfam = fam;
    278 			}
    279 		}
    280 	}
    281 
    282 	if (*target == NULL) {
    283 		return ISC_R_NOTFOUND;
    284 	} else {
    285 		return ISC_R_SUCCESS;
    286 	}
    287 }
    288 
    289 isc_result_t
    290 isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
    291 		 isc_radix_node_t *source, isc_prefix_t *prefix) {
    292 	isc_radix_node_t *node, *new_node, *parent, *glue = NULL;
    293 	u_char *addr, *test_addr;
    294 	uint32_t bitlen, fam, check_bit, differ_bit;
    295 	uint32_t i, j, r;
    296 	isc_result_t result;
    297 
    298 	REQUIRE(radix != NULL);
    299 	REQUIRE(target != NULL && *target == NULL);
    300 	REQUIRE(prefix != NULL || (source != NULL && source->prefix != NULL));
    301 	RUNTIME_CHECK(prefix == NULL || prefix->bitlen <= radix->maxbits);
    302 
    303 	if (prefix == NULL) {
    304 		prefix = source->prefix;
    305 	}
    306 
    307 	INSIST(prefix != NULL);
    308 
    309 	bitlen = prefix->bitlen;
    310 	fam = prefix->family;
    311 
    312 	if (radix->head == NULL) {
    313 		node = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
    314 		node->bit = bitlen;
    315 		for (i = 0; i < RADIX_FAMILIES; i++) {
    316 			node->node_num[i] = -1;
    317 		}
    318 		node->prefix = NULL;
    319 		result = _ref_prefix(radix->mctx, &node->prefix, prefix);
    320 		if (result != ISC_R_SUCCESS) {
    321 			isc_mem_put(radix->mctx, node,
    322 				    sizeof(isc_radix_node_t));
    323 			return result;
    324 		}
    325 		node->parent = NULL;
    326 		node->l = node->r = NULL;
    327 		if (source != NULL) {
    328 			/*
    329 			 * If source is non-NULL, then we're merging in a
    330 			 * node from an existing radix tree.  To keep
    331 			 * the node_num values consistent, the calling
    332 			 * function will add the total number of nodes
    333 			 * added to num_added_node at the end of
    334 			 * the merge operation--we don't do it here.
    335 			 */
    336 			for (i = 0; i < RADIX_FAMILIES; i++) {
    337 				if (source->node_num[i] != -1) {
    338 					node->node_num[i] =
    339 						radix->num_added_node +
    340 						source->node_num[i];
    341 				}
    342 				node->data[i] = source->data[i];
    343 			}
    344 		} else {
    345 			int next = ++radix->num_added_node;
    346 			if (fam == AF_UNSPEC) {
    347 				/* "any" or "none" */
    348 				for (i = 0; i < RADIX_FAMILIES; i++) {
    349 					node->node_num[i] = next;
    350 				}
    351 			} else {
    352 				node->node_num[ISC_RADIX_FAMILY(prefix)] = next;
    353 			}
    354 
    355 			memset(node->data, 0, sizeof(node->data));
    356 		}
    357 		radix->head = node;
    358 		radix->num_active_node++;
    359 		*target = node;
    360 		return ISC_R_SUCCESS;
    361 	}
    362 
    363 	addr = isc_prefix_touchar(prefix);
    364 	node = radix->head;
    365 
    366 	while (node->bit < bitlen || node->prefix == NULL) {
    367 		if (node->bit < radix->maxbits &&
    368 		    BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
    369 		{
    370 			if (node->r == NULL) {
    371 				break;
    372 			}
    373 			node = node->r;
    374 		} else {
    375 			if (node->l == NULL) {
    376 				break;
    377 			}
    378 			node = node->l;
    379 		}
    380 
    381 		INSIST(node != NULL);
    382 	}
    383 
    384 	INSIST(node->prefix != NULL);
    385 
    386 	test_addr = isc_prefix_touchar(node->prefix);
    387 	/* Find the first bit different. */
    388 	check_bit = (node->bit < bitlen) ? node->bit : bitlen;
    389 	differ_bit = 0;
    390 	for (i = 0; i * 8 < check_bit; i++) {
    391 		if ((r = (addr[i] ^ test_addr[i])) == 0) {
    392 			differ_bit = (i + 1) * 8;
    393 			continue;
    394 		}
    395 		/* I know the better way, but for now. */
    396 		for (j = 0; j < 8; j++) {
    397 			if (BIT_TEST(r, 0x80 >> j)) {
    398 				break;
    399 			}
    400 		}
    401 		/* Must be found. */
    402 		INSIST(j < 8);
    403 		differ_bit = i * 8 + j;
    404 		break;
    405 	}
    406 
    407 	if (differ_bit > check_bit) {
    408 		differ_bit = check_bit;
    409 	}
    410 
    411 	parent = node->parent;
    412 	while (parent != NULL && parent->bit >= differ_bit) {
    413 		node = parent;
    414 		parent = node->parent;
    415 	}
    416 
    417 	if (differ_bit == bitlen && node->bit == bitlen) {
    418 		if (node->prefix != NULL) {
    419 			/* Set node_num only if it hasn't been set before */
    420 			if (source != NULL) {
    421 				/* Merging nodes */
    422 				for (i = 0; i < RADIX_FAMILIES; i++) {
    423 					if (node->node_num[i] == -1 &&
    424 					    source->node_num[i] != -1)
    425 					{
    426 						node->node_num[i] =
    427 							radix->num_added_node +
    428 							source->node_num[i];
    429 						node->data[i] = source->data[i];
    430 					}
    431 				}
    432 			} else {
    433 				if (fam == AF_UNSPEC) {
    434 					/* "any" or "none" */
    435 					int next = radix->num_added_node + 1;
    436 					for (i = 0; i < RADIX_FAMILIES; i++) {
    437 						if (node->node_num[i] == -1) {
    438 							node->node_num[i] =
    439 								next;
    440 							radix->num_added_node =
    441 								next;
    442 						}
    443 					}
    444 				} else {
    445 					int foff = ISC_RADIX_FAMILY(prefix);
    446 					if (node->node_num[foff] == -1) {
    447 						node->node_num[foff] =
    448 							++radix->num_added_node;
    449 					}
    450 				}
    451 			}
    452 			*target = node;
    453 			return ISC_R_SUCCESS;
    454 		} else {
    455 			result = _ref_prefix(radix->mctx, &node->prefix,
    456 					     prefix);
    457 			if (result != ISC_R_SUCCESS) {
    458 				return result;
    459 			}
    460 		}
    461 		INSIST(node->data[RADIX_V4] == NULL &&
    462 		       node->node_num[RADIX_V4] == -1 &&
    463 		       node->data[RADIX_V4] == NULL &&
    464 		       node->node_num[RADIX_V4] == -1);
    465 		if (source != NULL) {
    466 			/* Merging node */
    467 			for (i = 0; i < RADIX_FAMILIES; i++) {
    468 				int cur = radix->num_added_node;
    469 				if (source->node_num[i] != -1) {
    470 					node->node_num[i] =
    471 						source->node_num[i] + cur;
    472 					node->data[i] = source->data[i];
    473 				}
    474 			}
    475 		} else {
    476 			int next = ++radix->num_added_node;
    477 			if (fam == AF_UNSPEC) {
    478 				/* "any" or "none" */
    479 				for (i = 0; i < RADIX_FAMILIES; i++) {
    480 					node->node_num[i] = next;
    481 				}
    482 			} else {
    483 				node->node_num[ISC_RADIX_FAMILY(prefix)] = next;
    484 			}
    485 		}
    486 		*target = node;
    487 		return ISC_R_SUCCESS;
    488 	}
    489 
    490 	new_node = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
    491 	if (node->bit != differ_bit && bitlen != differ_bit) {
    492 		glue = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
    493 	}
    494 	new_node->bit = bitlen;
    495 	new_node->prefix = NULL;
    496 	result = _ref_prefix(radix->mctx, &new_node->prefix, prefix);
    497 	if (result != ISC_R_SUCCESS) {
    498 		isc_mem_put(radix->mctx, new_node, sizeof(isc_radix_node_t));
    499 		if (glue != NULL) {
    500 			isc_mem_put(radix->mctx, glue,
    501 				    sizeof(isc_radix_node_t));
    502 		}
    503 		return result;
    504 	}
    505 	new_node->parent = NULL;
    506 	new_node->l = new_node->r = NULL;
    507 	for (i = 0; i < RADIX_FAMILIES; i++) {
    508 		new_node->node_num[i] = -1;
    509 		new_node->data[i] = NULL;
    510 	}
    511 	radix->num_active_node++;
    512 
    513 	if (source != NULL) {
    514 		/* Merging node */
    515 		for (i = 0; i < RADIX_FAMILIES; i++) {
    516 			int cur = radix->num_added_node;
    517 			if (source->node_num[i] != -1) {
    518 				new_node->node_num[i] = source->node_num[i] +
    519 							cur;
    520 				new_node->data[i] = source->data[i];
    521 			}
    522 		}
    523 	} else {
    524 		int next = ++radix->num_added_node;
    525 		if (fam == AF_UNSPEC) {
    526 			/* "any" or "none" */
    527 			for (i = 0; i < RADIX_FAMILIES; i++) {
    528 				new_node->node_num[i] = next;
    529 			}
    530 		} else {
    531 			new_node->node_num[ISC_RADIX_FAMILY(prefix)] = next;
    532 		}
    533 		memset(new_node->data, 0, sizeof(new_node->data));
    534 	}
    535 
    536 	if (node->bit == differ_bit) {
    537 		INSIST(glue == NULL);
    538 		new_node->parent = node;
    539 		if (node->bit < radix->maxbits &&
    540 		    BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
    541 		{
    542 			INSIST(node->r == NULL);
    543 			node->r = new_node;
    544 		} else {
    545 			INSIST(node->l == NULL);
    546 			node->l = new_node;
    547 		}
    548 		*target = new_node;
    549 		return ISC_R_SUCCESS;
    550 	}
    551 
    552 	if (bitlen == differ_bit) {
    553 		INSIST(glue == NULL);
    554 		if (bitlen < radix->maxbits &&
    555 		    BIT_TEST(test_addr[bitlen >> 3], 0x80 >> (bitlen & 0x07)))
    556 		{
    557 			new_node->r = node;
    558 		} else {
    559 			new_node->l = node;
    560 		}
    561 		new_node->parent = node->parent;
    562 		if (node->parent == NULL) {
    563 			INSIST(radix->head == node);
    564 			radix->head = new_node;
    565 		} else if (node->parent->r == node) {
    566 			node->parent->r = new_node;
    567 		} else {
    568 			node->parent->l = new_node;
    569 		}
    570 		node->parent = new_node;
    571 	} else {
    572 		INSIST(glue != NULL);
    573 		glue->bit = differ_bit;
    574 		glue->prefix = NULL;
    575 		glue->parent = node->parent;
    576 		for (i = 0; i < RADIX_FAMILIES; i++) {
    577 			glue->data[i] = NULL;
    578 			glue->node_num[i] = -1;
    579 		}
    580 		radix->num_active_node++;
    581 		if (differ_bit < radix->maxbits &&
    582 		    BIT_TEST(addr[differ_bit >> 3], 0x80 >> (differ_bit & 07)))
    583 		{
    584 			glue->r = new_node;
    585 			glue->l = node;
    586 		} else {
    587 			glue->r = node;
    588 			glue->l = new_node;
    589 		}
    590 		new_node->parent = glue;
    591 
    592 		if (node->parent == NULL) {
    593 			INSIST(radix->head == node);
    594 			radix->head = glue;
    595 		} else if (node->parent->r == node) {
    596 			node->parent->r = glue;
    597 		} else {
    598 			node->parent->l = glue;
    599 		}
    600 		node->parent = glue;
    601 	}
    602 
    603 	*target = new_node;
    604 	return ISC_R_SUCCESS;
    605 }
    606 
    607 void
    608 isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) {
    609 	isc_radix_node_t *parent, *child;
    610 
    611 	REQUIRE(radix != NULL);
    612 	REQUIRE(node != NULL);
    613 
    614 	if (node->r && node->l) {
    615 		/*
    616 		 * This might be a placeholder node -- have to check and
    617 		 * make sure there is a prefix associated with it!
    618 		 */
    619 		if (node->prefix != NULL) {
    620 			_deref_prefix(node->prefix);
    621 		}
    622 
    623 		node->prefix = NULL;
    624 		memset(node->data, 0, sizeof(node->data));
    625 		return;
    626 	}
    627 
    628 	if (node->r == NULL && node->l == NULL) {
    629 		parent = node->parent;
    630 		_deref_prefix(node->prefix);
    631 
    632 		if (parent == NULL) {
    633 			INSIST(radix->head == node);
    634 			radix->head = NULL;
    635 			isc_mem_put(radix->mctx, node, sizeof(*node));
    636 			radix->num_active_node--;
    637 			return;
    638 		}
    639 
    640 		if (parent->r == node) {
    641 			parent->r = NULL;
    642 			child = parent->l;
    643 		} else {
    644 			INSIST(parent->l == node);
    645 			parent->l = NULL;
    646 			child = parent->r;
    647 		}
    648 
    649 		isc_mem_put(radix->mctx, node, sizeof(*node));
    650 		radix->num_active_node--;
    651 
    652 		if (parent->prefix) {
    653 			return;
    654 		}
    655 
    656 		/* We need to remove parent too. */
    657 		if (parent->parent == NULL) {
    658 			INSIST(radix->head == parent);
    659 			radix->head = child;
    660 		} else if (parent->parent->r == parent) {
    661 			parent->parent->r = child;
    662 		} else {
    663 			INSIST(parent->parent->l == parent);
    664 			parent->parent->l = child;
    665 		}
    666 
    667 		child->parent = parent->parent;
    668 		isc_mem_put(radix->mctx, parent, sizeof(*parent));
    669 		radix->num_active_node--;
    670 		return;
    671 	}
    672 
    673 	if (node->r) {
    674 		child = node->r;
    675 	} else {
    676 		INSIST(node->l != NULL);
    677 		child = node->l;
    678 	}
    679 
    680 	parent = node->parent;
    681 	child->parent = parent;
    682 
    683 	_deref_prefix(node->prefix);
    684 
    685 	if (parent == NULL) {
    686 		INSIST(radix->head == node);
    687 		radix->head = child;
    688 		isc_mem_put(radix->mctx, node, sizeof(*node));
    689 		radix->num_active_node--;
    690 		return;
    691 	}
    692 
    693 	if (parent->r == node) {
    694 		parent->r = child;
    695 	} else {
    696 		INSIST(parent->l == node);
    697 		parent->l = child;
    698 	}
    699 
    700 	isc_mem_put(radix->mctx, node, sizeof(*node));
    701 	radix->num_active_node--;
    702 }
    703