radix.c revision a05abc17674c6b528caf3082680d45a5a63d734e
2dd6ffb5cb356956685484160b0fdf157e2e9787Tinderbox User * Copyright (C) 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Permission to use, copy, modify, and/or distribute this software for any
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater * purpose with or without fee is hereby granted, provided that the above
1633838b8255282d10af15c5c84cee5a51466712Bob Halley * copyright notice and this permission notice appear in all copies.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * PERFORMANCE OF THIS SOFTWARE.
0fc87fa2f38df7b293b650deacfa5e6c3d50eff9Bob Halley/* $Id: radix.c,v 1.22 2009/01/18 00:46:01 fdupont Exp $ */
d25afd60ee2286cb171c4960a790f3d7041b6f85Bob Halley * This source was adapted from MRT's RCS Ids:
d25afd60ee2286cb171c4960a790f3d7041b6f85Bob Halley * Id: radix.c,v 1.10.2.1 1999/11/29 05:16:24 masaki Exp
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * Id: prefix.c,v 1.37.2.9 2000/03/10 02:53:19 labovit Exp
a147de10fe5e19e593d42152ffd6879eca69860dEvan Hunt_new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family,
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence_deref_prefix(isc_mem_t *mctx, isc_prefix_t *prefix);
11d732daac76a24a0f3e5948a2758a4b866a0825David Lawrence_ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix);
11d732daac76a24a0f3e5948a2758a4b866a0825David Lawrence_comp_with_mask(void *addr, void *dest, u_int mask);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer_clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer_new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family, void *dest,
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley if (family != AF_INET6 && family != AF_INET && family != AF_UNSPEC)
27809a2ee5db141b684e53bf1d94da26e9f92d3aMark Andrews prefix = isc_mem_get(mctx, sizeof(isc_prefix_t));
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson prefix->bitlen = (bitlen >= 0) ? bitlen : 128;
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley /* AF_UNSPEC is "any" or "none"--treat it as AF_INET */
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley_deref_prefix(isc_mem_t *mctx, isc_prefix_t *prefix) {
8343d55b3d97923fa444ea9b92aae2ec60ffd40fMark Andrews isc_refcount_decrement(&prefix->refcount, &refs);
8343d55b3d97923fa444ea9b92aae2ec60ffd40fMark Andrews isc_mem_put(mctx, prefix, sizeof(isc_prefix_t));
dc1cfff92a77c5b47e5665a3c2f0153d79074f47Evan Hunt_ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix) {
8343d55b3d97923fa444ea9b92aae2ec60ffd40fMark Andrews INSIST((prefix->family == AF_INET && prefix->bitlen <= 32) ||
ed9ca2306508e3106e3d111d7cf39bf82f8689d0Mark Andrews (prefix->family == AF_INET6 && prefix->bitlen <= 128) ||
8343d55b3d97923fa444ea9b92aae2ec60ffd40fMark Andrews (prefix->family == AF_UNSPEC && prefix->bitlen == 0));
8343d55b3d97923fa444ea9b92aae2ec60ffd40fMark Andrews * If this prefix is a static allocation, copy it into new memory.
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley * (Note, the refcount still has to be destroyed by the calling
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley if (isc_refcount_current(&prefix->refcount) == 0) {
355cc22e32085faeb553fe6c37de69e83b9d5191Andreas Gustafsson ret = _new_prefix(mctx, target, prefix->family,
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley_comp_with_mask(void *addr, void *dest, u_int mask) {
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrence /* Mask length of zero matches everything */
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrence (((u_char *)addr)[n] & m) == (((u_char *)dest)[n] & m))
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrenceisc_radix_create(isc_mem_t *mctx, isc_radix_tree_t **target, int maxbits) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer radix = isc_mem_get(mctx, sizeof(isc_radix_tree_t));
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrence RUNTIME_CHECK(maxbits <= RADIX_MAXBITS); /* XXX */
0fc87fa2f38df7b293b650deacfa5e6c3d50eff9Bob Halley * if func is supplied, it will be called as func(node->data)
0fc87fa2f38df7b293b650deacfa5e6c3d50eff9Bob Halley * before deleting the node
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrence_clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) {
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrence } else if (r != NULL) {
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrenceisc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func)
d3e7d196cd14fc3095ce97846a66cd49fc6fee6dDavid Lawrence * func will be called as func(node->prefix, node->data)
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrenceisc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func)
1d9958c6cc291916010779792f0fbdf6cd5ba368Mark Andrewsisc_radix_search(isc_radix_tree_t *radix, isc_radix_node_t **target,
1bb2f53b9f74a8ca9812cbe9243ef41190b4da14Evan Hunt if (BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
ff8cd3afa7f900d7986ccbc3638235cb8ad6f1ecAndreas Gustafsson while (--cnt >= 0) {
b38ab99bdc833da490c0ca0cbd05fb9d54dff997Andreas Gustafsson if (_comp_with_mask(isc_prefix_tochar(node->prefix),
ff8cd3afa7f900d7986ccbc3638235cb8ad6f1ecAndreas Gustafsson if (node->node_num[ISC_IS6(prefix->family)] != -1 &&
186e7f37c9fc985a7a7264cc8170e48a25bed434Mark Andrewsisc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
186e7f37c9fc985a7a7264cc8170e48a25bed434Mark Andrews isc_radix_node_t *source, isc_prefix_t *prefix)
6ebd91a0c7f4c62a501b67adce4a6800d8b7dfacAutomatic Updater isc_radix_node_t *node, *new_node, *parent, *glue = NULL;
186e7f37c9fc985a7a7264cc8170e48a25bed434Mark Andrews REQUIRE(prefix != NULL || (source != NULL && source->prefix != NULL));
186e7f37c9fc985a7a7264cc8170e48a25bed434Mark Andrews RUNTIME_CHECK(prefix == NULL || prefix->bitlen <= radix->maxbits);
1bb2f53b9f74a8ca9812cbe9243ef41190b4da14Evan Hunt node = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
1bb2f53b9f74a8ca9812cbe9243ef41190b4da14Evan Hunt result = _ref_prefix(radix->mctx, &node->prefix, prefix);
aeff7de836558fa8002ab5db35292d2bb6450da8Evan Hunt * If source is non-NULL, then we're merging in a
aeff7de836558fa8002ab5db35292d2bb6450da8Evan Hunt * node from an existing radix tree. To keep
aeff7de836558fa8002ab5db35292d2bb6450da8Evan Hunt * the node_num values consistent, the calling
aeff7de836558fa8002ab5db35292d2bb6450da8Evan Hunt * function will add the total number of nodes
aeff7de836558fa8002ab5db35292d2bb6450da8Evan Hunt * added to num_added_node at the end of
aeff7de836558fa8002ab5db35292d2bb6450da8Evan Hunt * the merge operation--we don't do it here.
aeff7de836558fa8002ab5db35292d2bb6450da8Evan Hunt /* "any" or "none" */
return (ISC_R_SUCCESS);
differ_bit = 0;
return (ISC_R_SUCCESS);
result =
return (result);
return (ISC_R_SUCCESS);
return (ISC_R_NOMEMORY);
sizeof(isc_radix_node_t));
return (ISC_R_NOMEMORY);
sizeof(isc_radix_node_t));
return (result);
return (ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
if (node->r) {