From 0bffe620b441c039780d4336a15c8ed4f2ebbbf4 Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Sat, 15 Jan 2022 08:37:37 +0100 Subject: [PATCH] olsrd: add ubus ipc integration to olsrd IPC integration of olsrd with OpenWrt. Allow dynamic adding and removing of interfaces at run-time. We need to rename the avl-tree files, since libubox also defines avl tree. Also add patch to allow meshing via wireguard point-to-point links. The ubus interface offers following functions: - add_inteface '{"ifname":"wg_51820"}' - del_inteface '{"ifname":"wg_51820"}' Signed-off-by: Nick Hainke --- olsrd/Makefile | 2 +- .../patches/100-rename-avl-to-olsrd_avl.patch | 3377 +++++++++++++++++ ...-wireguard-point-to-point-interfaces.patch | 38 + olsrd/patches/600-add-ubus-support.patch | 60 + olsrd/src/src/ubus.c | 210 + olsrd/src/src/ubus.h | 40 + 6 files changed, 3726 insertions(+), 1 deletion(-) create mode 100644 olsrd/patches/100-rename-avl-to-olsrd_avl.patch create mode 100644 olsrd/patches/101-unix-fix-meshing-with-wireguard-point-to-point-interfaces.patch create mode 100644 olsrd/patches/600-add-ubus-support.patch create mode 100644 olsrd/src/src/ubus.c create mode 100644 olsrd/src/src/ubus.h diff --git a/olsrd/Makefile b/olsrd/Makefile index 89cac23..7c8918c 100644 --- a/olsrd/Makefile +++ b/olsrd/Makefile @@ -34,7 +34,7 @@ endef define Package/olsrd $(call Package/olsrd/template) MENU:=1 - DEPENDS:=+libpthread + DEPENDS:=+libpthread +libubus endef define Package/olsrd/conffiles diff --git a/olsrd/patches/100-rename-avl-to-olsrd_avl.patch b/olsrd/patches/100-rename-avl-to-olsrd_avl.patch new file mode 100644 index 0000000..c1d9743 --- /dev/null +++ b/olsrd/patches/100-rename-avl-to-olsrd_avl.patch @@ -0,0 +1,3377 @@ +From 4b91b102eb6edb63472728dd3545e3dff800a5a0 Mon Sep 17 00:00:00 2001 +From: Nick Hainke +Date: Sat, 15 Jan 2022 16:13:24 +0100 +Subject: [PATCH] rename avl to olsrd_avl + +--- + lib/nameservice/src/nameservice.c | 4 +- + lib/netjson/src/olsrd_netjson.c | 12 +- + lib/netjson/src/olsrd_netjson_helpers.c | 74 +++++----- + lib/netjson/src/olsrd_netjson_helpers.h | 18 +-- + src/common/{avl.c => olsrd_avl.c} | 184 ++++++++++++------------ + src/common/{avl.h => olsrd_avl.h} | 90 ++++++------ + src/duplicate_set.c | 18 +-- + src/duplicate_set.h | 12 +- + src/gateway.c | 18 +-- + src/gateway.h | 16 +-- + src/kernel_tunnel.h | 4 +- + src/linux/kernel_tunnel.c | 12 +- + src/lq_packet.c | 6 +- + src/lq_plugin.c | 14 +- + src/lq_plugin.h | 14 +- + src/olsr.c | 12 +- + src/olsr_spf.c | 36 ++--- + src/process_routes.c | 22 +-- + src/routing_table.c | 56 ++++---- + src/routing_table.h | 36 ++--- + src/scheduler.c | 30 ++-- + src/tc_set.c | 30 ++-- + src/tc_set.h | 38 ++--- + 24 files changed, 390 insertions(+), 390 deletions(-) + rename src/common/{avl.c => olsrd_avl.c} (67%) + rename src/common/{avl.h => olsrd_avl.h} (58%) +--- a/lib/nameservice/src/nameservice.c ++++ b/lib/nameservice/src/nameservice.c +@@ -1621,13 +1621,13 @@ void + lookup_defhna_latlon(union olsr_ip_addr *ip) + { + struct rt_entry *rt; +- struct avl_node *rt_tree_node; ++ struct olsrd_avl_node *rt_tree_node; + struct olsr_ip_prefix prefix; + + memset(ip, 0, sizeof(*ip)); + memset(&prefix, 0, sizeof(prefix)); + +- if (NULL != (rt_tree_node = avl_find(&routingtree, &prefix))) { ++ if (NULL != (rt_tree_node = olsrd_avl_find(&routingtree, &prefix))) { + rt = rt_tree2rt(rt_tree_node); + *ip = rt->rt_best->rtp_nexthop.gateway; + } +--- a/lib/netjson/src/olsrd_netjson.c ++++ b/lib/netjson/src/olsrd_netjson.c +@@ -52,7 +52,7 @@ + #include "info/info_types.h" + #include "info/http_headers.h" + #include "info/json_helpers.h" +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + #include "olsr.h" + #include "builddata.h" + #include "routing_table.h" +@@ -161,7 +161,7 @@ void ipc_print_network_routes(struct aut + } + + void ipc_print_network_graph(struct autobuf *abuf) { +- struct avl_tree nodes; ++ struct olsrd_avl_tree nodes; + struct mid_entry mid_self; + struct node_entry * node_self; + struct tc_entry * tc; +@@ -169,7 +169,7 @@ void ipc_print_network_graph(struct auto + struct neighbor_entry * neighbor; + int idx; + +- avl_init(&nodes, (olsr_cnf->ip_version == AF_INET) ? avl_comp_ipv4 : avl_comp_ipv6); ++ olsrd_avl_init(&nodes, (olsr_cnf->ip_version == AF_INET) ? olsrd_avl_comp_ipv4 : olsrd_avl_comp_ipv6); + + /* mandatory */ + abuf_json_string(&json_session, abuf, "type", "NetworkGraph"); +@@ -226,8 +226,8 @@ void ipc_print_network_graph(struct auto + + abuf_json_mark_object(&json_session, true, true, abuf, "nodes"); + while (nodes.count > 0) { +- struct avl_node *node = avl_walk_first(&nodes); +- struct node_entry *node_entry = avlnode2node(node); ++ struct olsrd_avl_node *node = olsrd_avl_walk_first(&nodes); ++ struct node_entry *node_entry = olsrd_avlnode2node(node); + + if (!node_entry->isAlias) { + abuf_json_mark_array_entry(&json_session, true, abuf); +@@ -265,7 +265,7 @@ void ipc_print_network_graph(struct auto + netjson_cleanup_mid_self(node_self); + } + +- avl_delete(&nodes, node); ++ olsrd_avl_delete(&nodes, node); + free(node); + } + abuf_json_mark_object(&json_session, false, true, abuf, NULL); +--- a/lib/netjson/src/olsrd_netjson_helpers.c ++++ b/lib/netjson/src/olsrd_netjson_helpers.c +@@ -57,7 +57,7 @@ struct node_entry * netjson_constructMid + + node_self = olsr_malloc(sizeof(struct node_entry), "netjson NetworkGraph node - MID - self"); + memset(node_self, 0, sizeof(*node_self)); +- node_self->avl.key = &olsr_cnf->main_addr; ++ node_self->olsrd_avl.key = &olsr_cnf->main_addr; + node_self->isAlias = false; + node_self->mid = mid; + +@@ -93,7 +93,7 @@ struct node_entry * netjson_constructMid + + node_self_alias = olsr_malloc(sizeof(struct node_entry), "netjson NetworkGraph node - MID - self alias"); + memset(node_self_alias, 0, sizeof(*node_self_alias)); +- node_self_alias->avl.key = addr; ++ node_self_alias->olsrd_avl.key = addr; + node_self_alias->isAlias = true; + node_self_alias->mid = mid; + +@@ -112,7 +112,7 @@ struct node_entry * netjson_constructMid + } + + void netjson_cleanup_mid_self(struct node_entry *node_entry) { +- if (node_entry->avl.key != &olsr_cnf->main_addr) { ++ if (node_entry->olsrd_avl.key != &olsr_cnf->main_addr) { + return; + } + +@@ -123,21 +123,21 @@ void netjson_cleanup_mid_self(struct nod + } + } + +-void netjson_midIntoNodesTree(struct avl_tree *nodes, struct mid_entry *mid) { +- struct avl_node *avlnode; ++void netjson_midIntoNodesTree(struct olsrd_avl_tree *nodes, struct mid_entry *mid) { ++ struct olsrd_avl_node *olsrd_avlnode; + struct node_entry *node; + struct mid_address *alias; + +- avlnode = avl_find(nodes, &mid->main_addr); +- if (!avlnode) { ++ olsrd_avlnode = olsrd_avl_find(nodes, &mid->main_addr); ++ if (!olsrd_avlnode) { + /* the IP address is not yet known */ + + node = olsr_malloc(sizeof(struct node_entry), "netjson NetworkGraph node - MID - main"); + memset(node, 0, sizeof(*node)); +- node->avl.key = &mid->main_addr; ++ node->olsrd_avl.key = &mid->main_addr; + node->isAlias = false; + node->mid = mid; +- if (avl_insert(nodes, &node->avl, AVL_DUP_NO) == -1) { ++ if (olsrd_avl_insert(nodes, &node->olsrd_avl, OLSRD_AVL_DUP_NO) == -1) { + /* duplicate */ + free(node); + } +@@ -145,16 +145,16 @@ void netjson_midIntoNodesTree(struct avl + + alias = mid->aliases; + while (alias) { +- avlnode = avl_find(nodes, &alias->alias); +- if (!avlnode) { ++ olsrd_avlnode = olsrd_avl_find(nodes, &alias->alias); ++ if (!olsrd_avlnode) { + /* the IP address is not yet known */ + + node = olsr_malloc(sizeof(struct node_entry), "netjson NetworkGraph node - MID - alias"); + memset(node, 0, sizeof(*node)); +- node->avl.key = &alias->alias; ++ node->olsrd_avl.key = &alias->alias; + node->isAlias = true; + node->mid = mid; +- if (avl_insert(nodes, &node->avl, AVL_DUP_NO) == -1) { ++ if (olsrd_avl_insert(nodes, &node->olsrd_avl, OLSRD_AVL_DUP_NO) == -1) { + /* duplicate */ + free(node); + } +@@ -164,12 +164,12 @@ void netjson_midIntoNodesTree(struct avl + } + } + +-void netjson_tcIntoNodesTree(struct avl_tree *nodes, struct tc_entry *tc) { +- struct avl_node *avlnode; ++void netjson_tcIntoNodesTree(struct olsrd_avl_tree *nodes, struct tc_entry *tc) { ++ struct olsrd_avl_node *olsrd_avlnode; + struct node_entry *node; + +- avlnode = avl_find(nodes, &tc->addr); +- if (avlnode) { ++ olsrd_avlnode = olsrd_avl_find(nodes, &tc->addr); ++ if (olsrd_avlnode) { + /* the IP address is already known */ + return; + } +@@ -178,21 +178,21 @@ void netjson_tcIntoNodesTree(struct avl_ + + node = olsr_malloc(sizeof(struct node_entry), "netjson NetworkGraph node - TC - main"); + memset(node, 0, sizeof(*node)); +- node->avl.key = &tc->addr; ++ node->olsrd_avl.key = &tc->addr; + node->isAlias = false; + node->tc = tc; +- if (avl_insert(nodes, &node->avl, AVL_DUP_NO) == -1) { ++ if (olsrd_avl_insert(nodes, &node->olsrd_avl, OLSRD_AVL_DUP_NO) == -1) { + /* duplicate */ + free(node); + } + } + +-void netjson_tcEdgeIntoNodesTree(struct avl_tree *nodes, struct tc_edge_entry *tc_edge) { +- struct avl_node *avlnode; ++void netjson_tcEdgeIntoNodesTree(struct olsrd_avl_tree *nodes, struct tc_edge_entry *tc_edge) { ++ struct olsrd_avl_node *olsrd_avlnode; + struct node_entry *node; + +- avlnode = avl_find(nodes, &tc_edge->T_dest_addr); +- if (avlnode) { ++ olsrd_avlnode = olsrd_avl_find(nodes, &tc_edge->T_dest_addr); ++ if (olsrd_avlnode) { + /* the IP address is already known */ + return; + } +@@ -201,21 +201,21 @@ void netjson_tcEdgeIntoNodesTree(struct + + node = olsr_malloc(sizeof(struct node_entry), "netjson NetworkGraph node - TC - main"); + memset(node, 0, sizeof(*node)); +- node->avl.key = &tc_edge->T_dest_addr; ++ node->olsrd_avl.key = &tc_edge->T_dest_addr; + node->isAlias = false; + node->tc_edge = tc_edge; +- if (avl_insert(nodes, &node->avl, AVL_DUP_NO) == -1) { ++ if (olsrd_avl_insert(nodes, &node->olsrd_avl, OLSRD_AVL_DUP_NO) == -1) { + /* duplicate */ + free(node); + } + } + +-void netjson_linkIntoNodesTree(struct avl_tree *nodes, struct link_entry *link, union olsr_ip_addr *addr) { +- struct avl_node *avlnode; ++void netjson_linkIntoNodesTree(struct olsrd_avl_tree *nodes, struct link_entry *link, union olsr_ip_addr *addr) { ++ struct olsrd_avl_node *olsrd_avlnode; + struct node_entry *node; + +- avlnode = avl_find(nodes, addr); +- if (avlnode) { ++ olsrd_avlnode = olsrd_avl_find(nodes, addr); ++ if (olsrd_avlnode) { + /* the IP address is already known */ + return; + } +@@ -224,21 +224,21 @@ void netjson_linkIntoNodesTree(struct av + + node = olsr_malloc(sizeof(struct node_entry), "netjson NetworkGraph node - link"); + memset(node, 0, sizeof(*node)); +- node->avl.key = addr; ++ node->olsrd_avl.key = addr; + node->isAlias = false; + node->link = link; +- if (avl_insert(nodes, &node->avl, AVL_DUP_NO) == -1) { ++ if (olsrd_avl_insert(nodes, &node->olsrd_avl, OLSRD_AVL_DUP_NO) == -1) { + /* duplicate */ + free(node); + } + } + +-void netjson_neighborIntoNodesTree(struct avl_tree *nodes, struct neighbor_entry *neighbor) { +- struct avl_node *avlnode; ++void netjson_neighborIntoNodesTree(struct olsrd_avl_tree *nodes, struct neighbor_entry *neighbor) { ++ struct olsrd_avl_node *olsrd_avlnode; + struct node_entry *node; + +- avlnode = avl_find(nodes, &neighbor->neighbor_main_addr); +- if (avlnode) { ++ olsrd_avlnode = olsrd_avl_find(nodes, &neighbor->neighbor_main_addr); ++ if (olsrd_avlnode) { + /* the IP address is already known */ + return; + } +@@ -247,10 +247,10 @@ void netjson_neighborIntoNodesTree(struc + + node = olsr_malloc(sizeof(struct node_entry), "netjson NetworkGraph node - neighbor"); + memset(node, 0, sizeof(*node)); +- node->avl.key = &neighbor->neighbor_main_addr; ++ node->olsrd_avl.key = &neighbor->neighbor_main_addr; + node->isAlias = false; + node->neighbor = neighbor; +- if (avl_insert(nodes, &node->avl, AVL_DUP_NO) == -1) { ++ if (olsrd_avl_insert(nodes, &node->olsrd_avl, OLSRD_AVL_DUP_NO) == -1) { + /* duplicate */ + free(node); + } +--- a/lib/netjson/src/olsrd_netjson_helpers.h ++++ b/lib/netjson/src/olsrd_netjson_helpers.h +@@ -48,7 +48,7 @@ + + #include + +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + #include "mid_set.h" + #include "tc_set.h" + #include "link_set.h" +@@ -56,7 +56,7 @@ + #include "olsr_types.h" + + struct node_entry { +- struct avl_node avl; ++ struct olsrd_avl_node olsrd_avl; + bool isAlias; + struct mid_entry *mid; + struct tc_entry *tc; +@@ -65,15 +65,15 @@ struct node_entry { + struct neighbor_entry *neighbor; + }; + +-/* static INLINE struct node_entry * avlnode2node(struct avl_node *ptr) */ +-AVLNODE2STRUCT(avlnode2node, struct node_entry, avl); ++/* static INLINE struct node_entry * olsrd_avlnode2node(struct olsrd_avl_node *ptr) */ ++OLSRD_AVLNODE2STRUCT(olsrd_avlnode2node, struct node_entry, olsrd_avl); + + struct node_entry * netjson_constructMidSelf(struct mid_entry *mid); + void netjson_cleanup_mid_self(struct node_entry *node_entry); +-void netjson_midIntoNodesTree(struct avl_tree *nodes, struct mid_entry *mid); +-void netjson_tcIntoNodesTree(struct avl_tree *nodes, struct tc_entry *tc); +-void netjson_tcEdgeIntoNodesTree(struct avl_tree *nodes, struct tc_edge_entry *tc_edge); +-void netjson_linkIntoNodesTree(struct avl_tree *nodes, struct link_entry *link, union olsr_ip_addr *addr); +-void netjson_neighborIntoNodesTree(struct avl_tree *nodes, struct neighbor_entry *neigh); ++void netjson_midIntoNodesTree(struct olsrd_avl_tree *nodes, struct mid_entry *mid); ++void netjson_tcIntoNodesTree(struct olsrd_avl_tree *nodes, struct tc_entry *tc); ++void netjson_tcEdgeIntoNodesTree(struct olsrd_avl_tree *nodes, struct tc_edge_entry *tc_edge); ++void netjson_linkIntoNodesTree(struct olsrd_avl_tree *nodes, struct link_entry *link, union olsr_ip_addr *addr); ++void netjson_neighborIntoNodesTree(struct olsrd_avl_tree *nodes, struct neighbor_entry *neigh); + + #endif /* LIB_NETJSON_SRC_OLSRD_NETJSON_HELPERS_H_ */ +--- a/src/common/avl.c ++++ /dev/null +@@ -1,664 +0,0 @@ +-/* +- * The olsr.org Optimized Link-State Routing daemon (olsrd) +- * +- * (c) by the OLSR project +- * +- * See our Git repository to find out who worked on this file +- * and thus is a copyright holder on it. +- * +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in +- * the documentation and/or other materials provided with the +- * distribution. +- * * Neither the name of olsr.org, olsrd nor the names of its +- * contributors may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- * +- * Visit http://www.olsr.org for more information. +- * +- * If you find this software useful feel free to make a donation +- * to the project. For more information see the website or contact +- * the copyright holders. +- * +- */ +- +-#include +-#include +-#include +- +-#include "ipcalc.h" +-#include "common/avl.h" +-#include "net_olsr.h" +- +-/* +- * default comparison pointers +- * set to the respective compare function. +- * if avl_comp_default is set to zero, a fast +- * INLINE ipv4 comparison will be executed. +- */ +-avl_tree_comp avl_comp_default = NULL; +-avl_tree_comp avl_comp_prefix_default; +- +-int +-avl_comp_ipv4(const void *ip1, const void *ip2) +-{ +- return ip4cmp(ip1, ip2); +-} +- +-int +-avl_comp_ipv6(const void *ip1, const void *ip2) +-{ +- return ip6cmp(ip1, ip2); +-} +- +-int +-avl_comp_mac(const void *ip1, const void *ip2) +-{ +- return memcmp(ip1, ip2, 6); +-} +- +-void +-avl_init(struct avl_tree *tree, avl_tree_comp comp) +-{ +- tree->root = NULL; +- tree->first = NULL; +- tree->last = NULL; +- tree->count = 0; +- +- tree->comp = comp == avl_comp_ipv4 ? NULL : comp; +-} +- +-static struct avl_node * +-avl_find_rec_ipv4(struct avl_node *node, const void *key) +-{ +- if (*(const unsigned int *)key < *(const unsigned int *)node->key) { +- if (node->left != NULL) +- return avl_find_rec_ipv4(node->left, key); +- } +- +- else if (*(const unsigned int *)key > *(const unsigned int *)node->key) { +- if (node->right != NULL) +- return avl_find_rec_ipv4(node->right, key); +- } +- +- return node; +-} +- +-static struct avl_node * +-avl_find_rec(struct avl_node *node, const void *key, avl_tree_comp comp) +-{ +- int diff; +- +- if (NULL == comp) +- return avl_find_rec_ipv4(node, key); +- +- diff = (*comp) (key, node->key); +- +- if (diff < 0) { +- if (node->left != NULL) +- return avl_find_rec(node->left, key, comp); +- +- return node; +- } +- +- if (diff > 0) { +- if (node->right != NULL) +- return avl_find_rec(node->right, key, comp); +- +- return node; +- } +- +- return node; +-} +- +-struct avl_node * +-avl_find(struct avl_tree *tree, const void *key) +-{ +- struct avl_node *node; +- +- if (tree->root == NULL) +- return NULL; +- +- node = avl_find_rec(tree->root, key, tree->comp); +- +- if (NULL == tree->comp) { +- if (0 != ip4cmp(node->key, key)) +- return NULL; +- } +- +- else { +- if ((*tree->comp) (node->key, key) != 0) +- return NULL; +- } +- +- return node; +-} +- +-static void +-avl_rotate_right(struct avl_tree *tree, struct avl_node *node) +-{ +- struct avl_node *left, *parent; +- +- left = node->left; +- parent = node->parent; +- +- left->parent = parent; +- node->parent = left; +- +- if (parent == NULL) +- tree->root = left; +- +- else { +- if (parent->left == node) +- parent->left = left; +- +- else +- parent->right = left; +- } +- +- node->left = left->right; +- left->right = node; +- +- if (node->left != NULL) +- node->left->parent = node; +- +- node->balance += 1 - MIN(left->balance, 0); +- left->balance += 1 + MAX(node->balance, 0); +-} +- +-static void +-avl_rotate_left(struct avl_tree *tree, struct avl_node *node) +-{ +- struct avl_node *right, *parent; +- +- right = node->right; +- parent = node->parent; +- +- right->parent = parent; +- node->parent = right; +- +- if (parent == NULL) +- tree->root = right; +- +- else { +- if (parent->left == node) +- parent->left = right; +- +- else +- parent->right = right; +- } +- +- node->right = right->left; +- right->left = node; +- +- if (node->right != NULL) +- node->right->parent = node; +- +- node->balance -= 1 + MAX(right->balance, 0); +- right->balance -= 1 - MIN(node->balance, 0); +-} +- +-static void +-post_insert(struct avl_tree *tree, struct avl_node *node) +-{ +- struct avl_node *parent = node->parent; +- +- if (parent == NULL) +- return; +- +- if (node == parent->left) { +- parent->balance--; +- +- if (parent->balance == 0) +- return; +- +- if (parent->balance == -1) { +- post_insert(tree, parent); +- return; +- } +- +- if (node->balance == -1) { +- avl_rotate_right(tree, parent); +- return; +- } +- +- avl_rotate_left(tree, node); +- avl_rotate_right(tree, node->parent->parent); +- return; +- } +- +- parent->balance++; +- +- if (parent->balance == 0) +- return; +- +- if (parent->balance == 1) { +- post_insert(tree, parent); +- return; +- } +- +- if (node->balance == 1) { +- avl_rotate_left(tree, parent); +- return; +- } +- +- avl_rotate_right(tree, node); +- avl_rotate_left(tree, node->parent->parent); +-} +- +-static void +-avl_insert_before(struct avl_tree *tree, struct avl_node *pos_node, struct avl_node *node) +-{ +- if (pos_node->prev != NULL) +- pos_node->prev->next = node; +- else +- tree->first = node; +- +- node->prev = pos_node->prev; +- node->next = pos_node; +- +- pos_node->prev = node; +- +- tree->count++; +-} +- +-static void +-avl_insert_after(struct avl_tree *tree, struct avl_node *pos_node, struct avl_node *node) +-{ +- if (pos_node->next != NULL) +- pos_node->next->prev = node; +- else +- tree->last = node; +- +- node->prev = pos_node; +- node->next = pos_node->next; +- +- pos_node->next = node; +- +- tree->count++; +-} +- +-static void +-avl_remove(struct avl_tree *tree, struct avl_node *node) +-{ +- if (node->prev != NULL) +- node->prev->next = node->next; +- else +- tree->first = node->next; +- +- if (node->next != NULL) +- node->next->prev = node->prev; +- else +- tree->last = node->prev; +- +- tree->count--; +-} +- +-int +-avl_insert(struct avl_tree *tree, struct avl_node *new, int allow_duplicates) +-{ +- struct avl_node *node; +- struct avl_node *last; +- int diff; +- +- new->parent = NULL; +- +- new->left = NULL; +- new->right = NULL; +- +- new->next = NULL; +- new->prev = NULL; +- +- new->balance = 0; +- new->leader = 1; +- +- if (tree->root == NULL) { +- tree->root = new; +- tree->first = new; +- tree->last = new; +- tree->count = 1; +- return 0; +- } +- +- node = avl_find_rec(tree->root, new->key, tree->comp); +- +- last = node; +- +- while (last->next != NULL && last->next->leader == 0) +- last = last->next; +- +- if (NULL == tree->comp) +- diff = ip4cmp(new->key, node->key); +- +- else +- diff = (*tree->comp) (new->key, node->key); +- +- if (diff == 0) { +- if (allow_duplicates == AVL_DUP_NO) +- return -1; +- +- new->leader = 0; +- +- avl_insert_after(tree, last, new); +- return 0; +- } +- +- if (node->balance == 1) { +- avl_insert_before(tree, node, new); +- +- node->balance = 0; +- new->parent = node; +- node->left = new; +- return 0; +- } +- +- if (node->balance == -1) { +- avl_insert_after(tree, last, new); +- +- node->balance = 0; +- new->parent = node; +- node->right = new; +- return 0; +- } +- +- if (diff < 0) { +- avl_insert_before(tree, node, new); +- +- node->balance = -1; +- new->parent = node; +- node->left = new; +- post_insert(tree, node); +- return 0; +- } +- +- avl_insert_after(tree, last, new); +- +- node->balance = 1; +- new->parent = node; +- node->right = new; +- post_insert(tree, node); +- return 0; +-} +- +-static void +-avl_post_delete(struct avl_tree *tree, struct avl_node *node) +-{ +- struct avl_node *parent; +- +- if ((parent = node->parent) == NULL) +- return; +- +- if (node == parent->left) { +- parent->balance++; +- +- if (parent->balance == 0) { +- avl_post_delete(tree, parent); +- return; +- } +- +- if (parent->balance == 1) +- return; +- +- if (parent->right->balance == 0) { +- avl_rotate_left(tree, parent); +- return; +- } +- +- if (parent->right->balance == 1) { +- avl_rotate_left(tree, parent); +- avl_post_delete(tree, parent->parent); +- return; +- } +- +- avl_rotate_right(tree, parent->right); +- avl_rotate_left(tree, parent); +- avl_post_delete(tree, parent->parent); +- return; +- } +- +- parent->balance--; +- +- if (parent->balance == 0) { +- avl_post_delete(tree, parent); +- return; +- } +- +- if (parent->balance == -1) +- return; +- +- if (parent->left->balance == 0) { +- avl_rotate_right(tree, parent); +- return; +- } +- +- if (parent->left->balance == -1) { +- avl_rotate_right(tree, parent); +- avl_post_delete(tree, parent->parent); +- return; +- } +- +- avl_rotate_left(tree, parent->left); +- avl_rotate_right(tree, parent); +- avl_post_delete(tree, parent->parent); +-} +- +-static struct avl_node * +-avl_local_min(struct avl_node *node) +-{ +- while (node->left != NULL) +- node = node->left; +- +- return node; +-} +- +-static void +-avl_delete_worker(struct avl_tree *tree, struct avl_node *node) +-{ +- struct avl_node *parent, *min; +- +- parent = node->parent; +- +- if (node->left == NULL && node->right == NULL) { +- if (parent == NULL) { +- tree->root = NULL; +- return; +- } +- +- if (parent->left == node) { +- parent->left = NULL; +- parent->balance++; +- +- if (parent->balance == 1) +- return; +- +- if (parent->balance == 0) { +- avl_post_delete(tree, parent); +- return; +- } +- +- if (parent->right->balance == 0) { +- avl_rotate_left(tree, parent); +- return; +- } +- +- if (parent->right->balance == 1) { +- avl_rotate_left(tree, parent); +- avl_post_delete(tree, parent->parent); +- return; +- } +- +- avl_rotate_right(tree, parent->right); +- avl_rotate_left(tree, parent); +- avl_post_delete(tree, parent->parent); +- } +- else { +- parent->right = NULL; +- parent->balance--; +- +- if (parent->balance == -1) +- return; +- +- if (parent->balance == 0) { +- avl_post_delete(tree, parent); +- return; +- } +- +- if (parent->left->balance == 0) { +- avl_rotate_right(tree, parent); +- return; +- } +- +- if (parent->left->balance == -1) { +- avl_rotate_right(tree, parent); +- avl_post_delete(tree, parent->parent); +- return; +- } +- +- avl_rotate_left(tree, parent->left); +- avl_rotate_right(tree, parent); +- avl_post_delete(tree, parent->parent); +- } +- return; +- } +- +- if (node->left == NULL) { +- if (parent == NULL) { +- tree->root = node->right; +- node->right->parent = NULL; +- return; +- } +- +- node->right->parent = parent; +- +- if (parent->left == node) +- parent->left = node->right; +- +- else +- parent->right = node->right; +- +- avl_post_delete(tree, node->right); +- return; +- } +- +- if (node->right == NULL) { +- if (parent == NULL) { +- tree->root = node->left; +- node->left->parent = NULL; +- return; +- } +- +- node->left->parent = parent; +- +- if (parent->left == node) +- parent->left = node->left; +- +- else +- parent->right = node->left; +- +- avl_post_delete(tree, node->left); +- return; +- } +- +- min = avl_local_min(node->right); +- avl_delete_worker(tree, min); +- parent = node->parent; +- +- min->balance = node->balance; +- min->parent = parent; +- min->left = node->left; +- min->right = node->right; +- +- if (min->left != NULL) +- min->left->parent = min; +- +- if (min->right != NULL) +- min->right->parent = min; +- +- if (parent == NULL) { +- tree->root = min; +- return; +- } +- +- if (parent->left == node) { +- parent->left = min; +- return; +- } +- +- parent->right = min; +-} +- +-void +-avl_delete(struct avl_tree *tree, struct avl_node *node) +-{ +- struct avl_node *next; +- struct avl_node *parent; +- struct avl_node *left; +- struct avl_node *right; +- +- if (node->leader != 0) { +- next = node->next; +- +- if (next != NULL && next->leader == 0) { +- next->leader = 1; +- next->balance = node->balance; +- +- parent = node->parent; +- left = node->left; +- right = node->right; +- +- next->parent = parent; +- next->left = left; +- next->right = right; +- +- if (parent == NULL) +- tree->root = next; +- +- else { +- if (node == parent->left) +- parent->left = next; +- +- else +- parent->right = next; +- } +- +- if (left != NULL) +- left->parent = next; +- +- if (right != NULL) +- right->parent = next; +- } +- +- else +- avl_delete_worker(tree, node); +- } +- +- avl_remove(tree, node); +-} +- +-/* +- * Local Variables: +- * c-basic-offset: 2 +- * indent-tabs-mode: nil +- * End: +- */ +--- /dev/null ++++ b/src/common/olsrd_avl.c +@@ -0,0 +1,664 @@ ++/* ++ * The olsr.org Optimized Link-State Routing daemon (olsrd) ++ * ++ * (c) by the OLSR project ++ * ++ * See our Git repository to find out who worked on this file ++ * and thus is a copyright holder on it. ++ * ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of olsr.org, olsrd nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ++ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ * ++ * Visit http://www.olsr.org for more information. ++ * ++ * If you find this software useful feel free to make a donation ++ * to the project. For more information see the website or contact ++ * the copyright holders. ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#include "ipcalc.h" ++#include "common/olsrd_avl.h" ++#include "net_olsr.h" ++ ++/* ++ * default comparison pointers ++ * set to the respective compare function. ++ * if olsrd_avl_comp_default is set to zero, a fast ++ * INLINE ipv4 comparison will be executed. ++ */ ++olsrd_avl_tree_comp olsrd_avl_comp_default = NULL; ++olsrd_avl_tree_comp olsrd_avl_comp_prefix_default; ++ ++int ++olsrd_avl_comp_ipv4(const void *ip1, const void *ip2) ++{ ++ return ip4cmp(ip1, ip2); ++} ++ ++int ++olsrd_avl_comp_ipv6(const void *ip1, const void *ip2) ++{ ++ return ip6cmp(ip1, ip2); ++} ++ ++int ++olsrd_avl_comp_mac(const void *ip1, const void *ip2) ++{ ++ return memcmp(ip1, ip2, 6); ++} ++ ++void ++olsrd_avl_init(struct olsrd_avl_tree *tree, olsrd_avl_tree_comp comp) ++{ ++ tree->root = NULL; ++ tree->first = NULL; ++ tree->last = NULL; ++ tree->count = 0; ++ ++ tree->comp = comp == olsrd_avl_comp_ipv4 ? NULL : comp; ++} ++ ++static struct olsrd_avl_node * ++olsrd_avl_find_rec_ipv4(struct olsrd_avl_node *node, const void *key) ++{ ++ if (*(const unsigned int *)key < *(const unsigned int *)node->key) { ++ if (node->left != NULL) ++ return olsrd_avl_find_rec_ipv4(node->left, key); ++ } ++ ++ else if (*(const unsigned int *)key > *(const unsigned int *)node->key) { ++ if (node->right != NULL) ++ return olsrd_avl_find_rec_ipv4(node->right, key); ++ } ++ ++ return node; ++} ++ ++static struct olsrd_avl_node * ++olsrd_avl_find_rec(struct olsrd_avl_node *node, const void *key, olsrd_avl_tree_comp comp) ++{ ++ int diff; ++ ++ if (NULL == comp) ++ return olsrd_avl_find_rec_ipv4(node, key); ++ ++ diff = (*comp) (key, node->key); ++ ++ if (diff < 0) { ++ if (node->left != NULL) ++ return olsrd_avl_find_rec(node->left, key, comp); ++ ++ return node; ++ } ++ ++ if (diff > 0) { ++ if (node->right != NULL) ++ return olsrd_avl_find_rec(node->right, key, comp); ++ ++ return node; ++ } ++ ++ return node; ++} ++ ++struct olsrd_avl_node * ++olsrd_avl_find(struct olsrd_avl_tree *tree, const void *key) ++{ ++ struct olsrd_avl_node *node; ++ ++ if (tree->root == NULL) ++ return NULL; ++ ++ node = olsrd_avl_find_rec(tree->root, key, tree->comp); ++ ++ if (NULL == tree->comp) { ++ if (0 != ip4cmp(node->key, key)) ++ return NULL; ++ } ++ ++ else { ++ if ((*tree->comp) (node->key, key) != 0) ++ return NULL; ++ } ++ ++ return node; ++} ++ ++static void ++olsrd_avl_rotate_right(struct olsrd_avl_tree *tree, struct olsrd_avl_node *node) ++{ ++ struct olsrd_avl_node *left, *parent; ++ ++ left = node->left; ++ parent = node->parent; ++ ++ left->parent = parent; ++ node->parent = left; ++ ++ if (parent == NULL) ++ tree->root = left; ++ ++ else { ++ if (parent->left == node) ++ parent->left = left; ++ ++ else ++ parent->right = left; ++ } ++ ++ node->left = left->right; ++ left->right = node; ++ ++ if (node->left != NULL) ++ node->left->parent = node; ++ ++ node->balance += 1 - MIN(left->balance, 0); ++ left->balance += 1 + MAX(node->balance, 0); ++} ++ ++static void ++olsrd_avl_rotate_left(struct olsrd_avl_tree *tree, struct olsrd_avl_node *node) ++{ ++ struct olsrd_avl_node *right, *parent; ++ ++ right = node->right; ++ parent = node->parent; ++ ++ right->parent = parent; ++ node->parent = right; ++ ++ if (parent == NULL) ++ tree->root = right; ++ ++ else { ++ if (parent->left == node) ++ parent->left = right; ++ ++ else ++ parent->right = right; ++ } ++ ++ node->right = right->left; ++ right->left = node; ++ ++ if (node->right != NULL) ++ node->right->parent = node; ++ ++ node->balance -= 1 + MAX(right->balance, 0); ++ right->balance -= 1 - MIN(node->balance, 0); ++} ++ ++static void ++post_insert(struct olsrd_avl_tree *tree, struct olsrd_avl_node *node) ++{ ++ struct olsrd_avl_node *parent = node->parent; ++ ++ if (parent == NULL) ++ return; ++ ++ if (node == parent->left) { ++ parent->balance--; ++ ++ if (parent->balance == 0) ++ return; ++ ++ if (parent->balance == -1) { ++ post_insert(tree, parent); ++ return; ++ } ++ ++ if (node->balance == -1) { ++ olsrd_avl_rotate_right(tree, parent); ++ return; ++ } ++ ++ olsrd_avl_rotate_left(tree, node); ++ olsrd_avl_rotate_right(tree, node->parent->parent); ++ return; ++ } ++ ++ parent->balance++; ++ ++ if (parent->balance == 0) ++ return; ++ ++ if (parent->balance == 1) { ++ post_insert(tree, parent); ++ return; ++ } ++ ++ if (node->balance == 1) { ++ olsrd_avl_rotate_left(tree, parent); ++ return; ++ } ++ ++ olsrd_avl_rotate_right(tree, node); ++ olsrd_avl_rotate_left(tree, node->parent->parent); ++} ++ ++static void ++olsrd_avl_insert_before(struct olsrd_avl_tree *tree, struct olsrd_avl_node *pos_node, struct olsrd_avl_node *node) ++{ ++ if (pos_node->prev != NULL) ++ pos_node->prev->next = node; ++ else ++ tree->first = node; ++ ++ node->prev = pos_node->prev; ++ node->next = pos_node; ++ ++ pos_node->prev = node; ++ ++ tree->count++; ++} ++ ++static void ++olsrd_avl_insert_after(struct olsrd_avl_tree *tree, struct olsrd_avl_node *pos_node, struct olsrd_avl_node *node) ++{ ++ if (pos_node->next != NULL) ++ pos_node->next->prev = node; ++ else ++ tree->last = node; ++ ++ node->prev = pos_node; ++ node->next = pos_node->next; ++ ++ pos_node->next = node; ++ ++ tree->count++; ++} ++ ++static void ++olsrd_avl_remove(struct olsrd_avl_tree *tree, struct olsrd_avl_node *node) ++{ ++ if (node->prev != NULL) ++ node->prev->next = node->next; ++ else ++ tree->first = node->next; ++ ++ if (node->next != NULL) ++ node->next->prev = node->prev; ++ else ++ tree->last = node->prev; ++ ++ tree->count--; ++} ++ ++int ++olsrd_avl_insert(struct olsrd_avl_tree *tree, struct olsrd_avl_node *new, int allow_duplicates) ++{ ++ struct olsrd_avl_node *node; ++ struct olsrd_avl_node *last; ++ int diff; ++ ++ new->parent = NULL; ++ ++ new->left = NULL; ++ new->right = NULL; ++ ++ new->next = NULL; ++ new->prev = NULL; ++ ++ new->balance = 0; ++ new->leader = 1; ++ ++ if (tree->root == NULL) { ++ tree->root = new; ++ tree->first = new; ++ tree->last = new; ++ tree->count = 1; ++ return 0; ++ } ++ ++ node = olsrd_avl_find_rec(tree->root, new->key, tree->comp); ++ ++ last = node; ++ ++ while (last->next != NULL && last->next->leader == 0) ++ last = last->next; ++ ++ if (NULL == tree->comp) ++ diff = ip4cmp(new->key, node->key); ++ ++ else ++ diff = (*tree->comp) (new->key, node->key); ++ ++ if (diff == 0) { ++ if (allow_duplicates == OLSRD_AVL_DUP_NO) ++ return -1; ++ ++ new->leader = 0; ++ ++ olsrd_avl_insert_after(tree, last, new); ++ return 0; ++ } ++ ++ if (node->balance == 1) { ++ olsrd_avl_insert_before(tree, node, new); ++ ++ node->balance = 0; ++ new->parent = node; ++ node->left = new; ++ return 0; ++ } ++ ++ if (node->balance == -1) { ++ olsrd_avl_insert_after(tree, last, new); ++ ++ node->balance = 0; ++ new->parent = node; ++ node->right = new; ++ return 0; ++ } ++ ++ if (diff < 0) { ++ olsrd_avl_insert_before(tree, node, new); ++ ++ node->balance = -1; ++ new->parent = node; ++ node->left = new; ++ post_insert(tree, node); ++ return 0; ++ } ++ ++ olsrd_avl_insert_after(tree, last, new); ++ ++ node->balance = 1; ++ new->parent = node; ++ node->right = new; ++ post_insert(tree, node); ++ return 0; ++} ++ ++static void ++olsrd_avl_post_delete(struct olsrd_avl_tree *tree, struct olsrd_avl_node *node) ++{ ++ struct olsrd_avl_node *parent; ++ ++ if ((parent = node->parent) == NULL) ++ return; ++ ++ if (node == parent->left) { ++ parent->balance++; ++ ++ if (parent->balance == 0) { ++ olsrd_avl_post_delete(tree, parent); ++ return; ++ } ++ ++ if (parent->balance == 1) ++ return; ++ ++ if (parent->right->balance == 0) { ++ olsrd_avl_rotate_left(tree, parent); ++ return; ++ } ++ ++ if (parent->right->balance == 1) { ++ olsrd_avl_rotate_left(tree, parent); ++ olsrd_avl_post_delete(tree, parent->parent); ++ return; ++ } ++ ++ olsrd_avl_rotate_right(tree, parent->right); ++ olsrd_avl_rotate_left(tree, parent); ++ olsrd_avl_post_delete(tree, parent->parent); ++ return; ++ } ++ ++ parent->balance--; ++ ++ if (parent->balance == 0) { ++ olsrd_avl_post_delete(tree, parent); ++ return; ++ } ++ ++ if (parent->balance == -1) ++ return; ++ ++ if (parent->left->balance == 0) { ++ olsrd_avl_rotate_right(tree, parent); ++ return; ++ } ++ ++ if (parent->left->balance == -1) { ++ olsrd_avl_rotate_right(tree, parent); ++ olsrd_avl_post_delete(tree, parent->parent); ++ return; ++ } ++ ++ olsrd_avl_rotate_left(tree, parent->left); ++ olsrd_avl_rotate_right(tree, parent); ++ olsrd_avl_post_delete(tree, parent->parent); ++} ++ ++static struct olsrd_avl_node * ++olsrd_avl_local_min(struct olsrd_avl_node *node) ++{ ++ while (node->left != NULL) ++ node = node->left; ++ ++ return node; ++} ++ ++static void ++olsrd_avl_delete_worker(struct olsrd_avl_tree *tree, struct olsrd_avl_node *node) ++{ ++ struct olsrd_avl_node *parent, *min; ++ ++ parent = node->parent; ++ ++ if (node->left == NULL && node->right == NULL) { ++ if (parent == NULL) { ++ tree->root = NULL; ++ return; ++ } ++ ++ if (parent->left == node) { ++ parent->left = NULL; ++ parent->balance++; ++ ++ if (parent->balance == 1) ++ return; ++ ++ if (parent->balance == 0) { ++ olsrd_avl_post_delete(tree, parent); ++ return; ++ } ++ ++ if (parent->right->balance == 0) { ++ olsrd_avl_rotate_left(tree, parent); ++ return; ++ } ++ ++ if (parent->right->balance == 1) { ++ olsrd_avl_rotate_left(tree, parent); ++ olsrd_avl_post_delete(tree, parent->parent); ++ return; ++ } ++ ++ olsrd_avl_rotate_right(tree, parent->right); ++ olsrd_avl_rotate_left(tree, parent); ++ olsrd_avl_post_delete(tree, parent->parent); ++ } ++ else { ++ parent->right = NULL; ++ parent->balance--; ++ ++ if (parent->balance == -1) ++ return; ++ ++ if (parent->balance == 0) { ++ olsrd_avl_post_delete(tree, parent); ++ return; ++ } ++ ++ if (parent->left->balance == 0) { ++ olsrd_avl_rotate_right(tree, parent); ++ return; ++ } ++ ++ if (parent->left->balance == -1) { ++ olsrd_avl_rotate_right(tree, parent); ++ olsrd_avl_post_delete(tree, parent->parent); ++ return; ++ } ++ ++ olsrd_avl_rotate_left(tree, parent->left); ++ olsrd_avl_rotate_right(tree, parent); ++ olsrd_avl_post_delete(tree, parent->parent); ++ } ++ return; ++ } ++ ++ if (node->left == NULL) { ++ if (parent == NULL) { ++ tree->root = node->right; ++ node->right->parent = NULL; ++ return; ++ } ++ ++ node->right->parent = parent; ++ ++ if (parent->left == node) ++ parent->left = node->right; ++ ++ else ++ parent->right = node->right; ++ ++ olsrd_avl_post_delete(tree, node->right); ++ return; ++ } ++ ++ if (node->right == NULL) { ++ if (parent == NULL) { ++ tree->root = node->left; ++ node->left->parent = NULL; ++ return; ++ } ++ ++ node->left->parent = parent; ++ ++ if (parent->left == node) ++ parent->left = node->left; ++ ++ else ++ parent->right = node->left; ++ ++ olsrd_avl_post_delete(tree, node->left); ++ return; ++ } ++ ++ min = olsrd_avl_local_min(node->right); ++ olsrd_avl_delete_worker(tree, min); ++ parent = node->parent; ++ ++ min->balance = node->balance; ++ min->parent = parent; ++ min->left = node->left; ++ min->right = node->right; ++ ++ if (min->left != NULL) ++ min->left->parent = min; ++ ++ if (min->right != NULL) ++ min->right->parent = min; ++ ++ if (parent == NULL) { ++ tree->root = min; ++ return; ++ } ++ ++ if (parent->left == node) { ++ parent->left = min; ++ return; ++ } ++ ++ parent->right = min; ++} ++ ++void ++olsrd_avl_delete(struct olsrd_avl_tree *tree, struct olsrd_avl_node *node) ++{ ++ struct olsrd_avl_node *next; ++ struct olsrd_avl_node *parent; ++ struct olsrd_avl_node *left; ++ struct olsrd_avl_node *right; ++ ++ if (node->leader != 0) { ++ next = node->next; ++ ++ if (next != NULL && next->leader == 0) { ++ next->leader = 1; ++ next->balance = node->balance; ++ ++ parent = node->parent; ++ left = node->left; ++ right = node->right; ++ ++ next->parent = parent; ++ next->left = left; ++ next->right = right; ++ ++ if (parent == NULL) ++ tree->root = next; ++ ++ else { ++ if (node == parent->left) ++ parent->left = next; ++ ++ else ++ parent->right = next; ++ } ++ ++ if (left != NULL) ++ left->parent = next; ++ ++ if (right != NULL) ++ right->parent = next; ++ } ++ ++ else ++ olsrd_avl_delete_worker(tree, node); ++ } ++ ++ olsrd_avl_remove(tree, node); ++} ++ ++/* ++ * Local Variables: ++ * c-basic-offset: 2 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- a/src/common/avl.h ++++ /dev/null +@@ -1,183 +0,0 @@ +-/* +- * The olsr.org Optimized Link-State Routing daemon (olsrd) +- * +- * (c) by the OLSR project +- * +- * See our Git repository to find out who worked on this file +- * and thus is a copyright holder on it. +- * +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in +- * the documentation and/or other materials provided with the +- * distribution. +- * * Neither the name of olsr.org, olsrd nor the names of its +- * contributors may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- * +- * Visit http://www.olsr.org for more information. +- * +- * If you find this software useful feel free to make a donation +- * to the project. For more information see the website or contact +- * the copyright holders. +- * +- */ +- +-#ifndef _AVL_H +-#define _AVL_H +- +-#include +-#include "compiler.h" +-#include "defs.h" +- +-struct avl_node { +- struct avl_node *parent; +- struct avl_node *left; +- struct avl_node *right; +- struct avl_node *next; +- struct avl_node *prev; +- void *key; +- signed char balance; +- unsigned char leader; +-}; +- +-typedef int (*avl_tree_comp) (const void *, const void *); +- +-struct avl_tree { +- struct avl_node *root; +- struct avl_node *first; +- struct avl_node *last; +- unsigned int count; +- avl_tree_comp comp; +-}; +- +-#define AVL_DUP 1 +-#define AVL_DUP_NO 0 +- +-void avl_init(struct avl_tree *, avl_tree_comp); +-struct avl_node *avl_find(struct avl_tree *, const void *); +-int avl_insert(struct avl_tree *, struct avl_node *, int); +-void avl_delete(struct avl_tree *, struct avl_node *); +- +-static INLINE struct avl_node * +-avl_walk_first(struct avl_tree *tree) +-{ +- if (!tree) { +- return NULL; +- } +- +- return tree->first; +-} +-static INLINE struct avl_node * +-avl_walk_last(struct avl_tree *tree) +-{ +- if (!tree) { +- return NULL; +- } +- +- return tree->last; +-} +-static INLINE struct avl_node * +-avl_walk_next(struct avl_node *node) +-{ +- if (!node) { +- return NULL; +- } +- +- return node->next; +-} +-static INLINE struct avl_node * +-avl_walk_prev(struct avl_node *node) +-{ +- if (!node) { +- return NULL; +- } +- +- return node->prev; +-} +- +-/* and const versions*/ +-static INLINE const struct avl_node * +-avl_walk_first_c(const struct avl_tree *tree) +-{ +- if (!tree) { +- return NULL; +- } +- +- return tree->first; +-} +-static INLINE const struct avl_node * +-avl_walk_last_c(const struct avl_tree *tree) +-{ +- if (!tree) { +- return NULL; +- } +- +- return tree->last; +-} +-static INLINE const struct avl_node * +-avl_walk_next_c(const struct avl_node *node) +-{ +- if (!node) { +- return NULL; +- } +- +- return node->next; +-} +-static INLINE const struct avl_node * +-avl_walk_prev_c(const struct avl_node *node) +-{ +- if (!node) { +- return NULL; +- } +- +- return node->prev; +-} +- +-extern avl_tree_comp avl_comp_default; +-extern avl_tree_comp avl_comp_prefix_default; +-extern int avl_comp_ipv4(const void *, const void *); +-extern int avl_comp_ipv6(const void *, const void *); +-extern int avl_comp_mac(const void *, const void *); +- +-/* +- * Macro to define an INLINE function to map from a list_node offset back to the +- * base of the datastructure. That way you save an extra data pointer. +- */ +-#define AVLNODE2STRUCT(funcname, structname, avlnodename) \ +-static INLINE structname * funcname (struct avl_node *ptr)\ +-{\ +- return( \ +- ptr ? \ +- (structname *) (((size_t) ptr) - offsetof(structname, avlnodename)) : \ +- NULL); \ +-} +- +-#endif /* _AVL_H */ +- +-/* +- * Local Variables: +- * c-basic-offset: 2 +- * indent-tabs-mode: nil +- * End: +- */ +--- /dev/null ++++ b/src/common/olsrd_avl.h +@@ -0,0 +1,183 @@ ++/* ++ * The olsr.org Optimized Link-State Routing daemon (olsrd) ++ * ++ * (c) by the OLSR project ++ * ++ * See our Git repository to find out who worked on this file ++ * and thus is a copyright holder on it. ++ * ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of olsr.org, olsrd nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ++ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ * ++ * Visit http://www.olsr.org for more information. ++ * ++ * If you find this software useful feel free to make a donation ++ * to the project. For more information see the website or contact ++ * the copyright holders. ++ * ++ */ ++ ++#ifndef _OLSRD_AVL_H ++#define _OLSRD_AVL_H ++ ++#include ++#include "compiler.h" ++#include "defs.h" ++ ++struct olsrd_avl_node { ++ struct olsrd_avl_node *parent; ++ struct olsrd_avl_node *left; ++ struct olsrd_avl_node *right; ++ struct olsrd_avl_node *next; ++ struct olsrd_avl_node *prev; ++ void *key; ++ signed char balance; ++ unsigned char leader; ++}; ++ ++typedef int (*olsrd_avl_tree_comp) (const void *, const void *); ++ ++struct olsrd_avl_tree { ++ struct olsrd_avl_node *root; ++ struct olsrd_avl_node *first; ++ struct olsrd_avl_node *last; ++ unsigned int count; ++ olsrd_avl_tree_comp comp; ++}; ++ ++#define OLSRD_AVL_DUP 1 ++#define OLSRD_AVL_DUP_NO 0 ++ ++void olsrd_avl_init(struct olsrd_avl_tree *, olsrd_avl_tree_comp); ++struct olsrd_avl_node *olsrd_avl_find(struct olsrd_avl_tree *, const void *); ++int olsrd_avl_insert(struct olsrd_avl_tree *, struct olsrd_avl_node *, int); ++void olsrd_avl_delete(struct olsrd_avl_tree *, struct olsrd_avl_node *); ++ ++static INLINE struct olsrd_avl_node * ++olsrd_avl_walk_first(struct olsrd_avl_tree *tree) ++{ ++ if (!tree) { ++ return NULL; ++ } ++ ++ return tree->first; ++} ++static INLINE struct olsrd_avl_node * ++olsrd_avl_walk_last(struct olsrd_avl_tree *tree) ++{ ++ if (!tree) { ++ return NULL; ++ } ++ ++ return tree->last; ++} ++static INLINE struct olsrd_avl_node * ++olsrd_avl_walk_next(struct olsrd_avl_node *node) ++{ ++ if (!node) { ++ return NULL; ++ } ++ ++ return node->next; ++} ++static INLINE struct olsrd_avl_node * ++olsrd_avl_walk_prev(struct olsrd_avl_node *node) ++{ ++ if (!node) { ++ return NULL; ++ } ++ ++ return node->prev; ++} ++ ++/* and const versions*/ ++static INLINE const struct olsrd_avl_node * ++olsrd_avl_walk_first_c(const struct olsrd_avl_tree *tree) ++{ ++ if (!tree) { ++ return NULL; ++ } ++ ++ return tree->first; ++} ++static INLINE const struct olsrd_avl_node * ++olsrd_avl_walk_last_c(const struct olsrd_avl_tree *tree) ++{ ++ if (!tree) { ++ return NULL; ++ } ++ ++ return tree->last; ++} ++static INLINE const struct olsrd_avl_node * ++olsrd_avl_walk_next_c(const struct olsrd_avl_node *node) ++{ ++ if (!node) { ++ return NULL; ++ } ++ ++ return node->next; ++} ++static INLINE const struct olsrd_avl_node * ++olsrd_avl_walk_prev_c(const struct olsrd_avl_node *node) ++{ ++ if (!node) { ++ return NULL; ++ } ++ ++ return node->prev; ++} ++ ++extern olsrd_avl_tree_comp olsrd_avl_comp_default; ++extern olsrd_avl_tree_comp olsrd_avl_comp_prefix_default; ++extern int olsrd_avl_comp_ipv4(const void *, const void *); ++extern int olsrd_avl_comp_ipv6(const void *, const void *); ++extern int olsrd_avl_comp_mac(const void *, const void *); ++ ++/* ++ * Macro to define an INLINE function to map from a list_node offset back to the ++ * base of the datastructure. That way you save an extra data pointer. ++ */ ++#define OLSRD_AVLNODE2STRUCT(funcname, structname, olsrd_avlnodename) \ ++static INLINE structname * funcname (struct olsrd_avl_node *ptr)\ ++{\ ++ return( \ ++ ptr ? \ ++ (structname *) (((size_t) ptr) - offsetof(structname, olsrd_avlnodename)) : \ ++ NULL); \ ++} ++ ++#endif /* _OLSRD_AVL_H */ ++ ++/* ++ * Local Variables: ++ * c-basic-offset: 2 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- a/src/duplicate_set.c ++++ b/src/duplicate_set.c +@@ -45,7 +45,7 @@ + + #include "duplicate_set.h" + #include "ipcalc.h" +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + #include "olsr.h" + #include "mid_set.h" + #include "scheduler.h" +@@ -53,13 +53,13 @@ + + static void olsr_cleanup_duplicate_entry(void *unused); + +-struct avl_tree duplicate_set; ++struct olsrd_avl_tree duplicate_set; + struct timer_entry *duplicate_cleanup_timer; + + void + olsr_init_duplicate_set(void) + { +- avl_init(&duplicate_set, olsr_cnf->ip_version == AF_INET ? &avl_comp_ipv4 : &avl_comp_ipv6); ++ olsrd_avl_init(&duplicate_set, olsr_cnf->ip_version == AF_INET ? &olsrd_avl_comp_ipv4 : &olsrd_avl_comp_ipv6); + + olsr_set_timer(&duplicate_cleanup_timer, DUPLICATE_CLEANUP_INTERVAL, DUPLICATE_CLEANUP_JITTER, OLSR_TIMER_PERIODIC, + &olsr_cleanup_duplicate_entry, NULL, 0); +@@ -68,7 +68,7 @@ olsr_init_duplicate_set(void) + void olsr_cleanup_duplicates(union olsr_ip_addr *orig) { + struct dup_entry *entry; + +- entry = (struct dup_entry *)avl_find(&duplicate_set, orig); ++ entry = (struct dup_entry *)olsrd_avl_find(&duplicate_set, orig); + if (entry != NULL) { + entry->too_low_counter = DUP_MAX_TOO_LOW - 2; + } +@@ -83,7 +83,7 @@ olsr_create_duplicate_entry(void *ip, ui + memcpy(&entry->ip, ip, olsr_cnf->ip_version == AF_INET ? sizeof(entry->ip.v4) : sizeof(entry->ip.v6)); + entry->seqnr = seqnr; + entry->too_low_counter = 0; +- entry->avl.key = &entry->ip; ++ entry->olsrd_avl.key = &entry->ip; + entry->array = 0; + } + return entry; +@@ -96,7 +96,7 @@ olsr_cleanup_duplicate_entry(void __attr + + OLSR_FOR_ALL_DUP_ENTRIES(entry) { + if (TIMED_OUT(entry->valid_until)) { +- avl_delete(&duplicate_set, &entry->avl); ++ olsrd_avl_delete(&duplicate_set, &entry->olsrd_avl); + free(entry); + } + } +@@ -143,11 +143,11 @@ olsr_message_is_duplicate(union olsr_mes + + valid_until = GET_TIMESTAMP(DUPLICATE_VTIME); + +- entry = (struct dup_entry *)avl_find(&duplicate_set, ip); ++ entry = (struct dup_entry *)olsrd_avl_find(&duplicate_set, ip); + if (entry == NULL) { + entry = olsr_create_duplicate_entry(ip, seqnr); + if (entry != NULL) { +- avl_insert(&duplicate_set, &entry->avl, 0); ++ olsrd_avl_insert(&duplicate_set, &entry->olsrd_avl, 0); + entry->valid_until = valid_until; + } + return false; // okay, we process this package +@@ -209,7 +209,7 @@ olsr_print_duplicate_table(void) + olsr_wallclock_string(), ipwidth, "Node IP", "DupArray", "VTime"); + + OLSR_FOR_ALL_DUP_ENTRIES(entry) { +- OLSR_PRINTF(1, "%-*s %08x %s\n", ipwidth, olsr_ip_to_string(&addrbuf, (union olsr_ip_addr *)(entry->avl.key)), ++ OLSR_PRINTF(1, "%-*s %08x %s\n", ipwidth, olsr_ip_to_string(&addrbuf, (union olsr_ip_addr *)(entry->olsrd_avl.key)), + entry->array, olsr_clock_string(entry->valid_until)); + } OLSR_FOR_ALL_DUP_ENTRIES_END(entry); + } +--- a/src/duplicate_set.h ++++ b/src/duplicate_set.h +@@ -49,7 +49,7 @@ + #include "defs.h" + #include "olsr.h" + #include "mantissa.h" +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + + #define DUPLICATE_CLEANUP_INTERVAL 15000 + #define DUPLICATE_CLEANUP_JITTER 25 +@@ -57,7 +57,7 @@ + #define DUP_MAX_TOO_LOW 16 + + struct dup_entry { +- struct avl_node avl; ++ struct olsrd_avl_node olsrd_avl; + union olsr_ip_addr ip; + uint16_t seqnr; + uint16_t too_low_counter; +@@ -65,7 +65,7 @@ struct dup_entry { + uint32_t valid_until; + }; + +-AVLNODE2STRUCT(duptree2dupentry, struct dup_entry, avl); ++OLSRD_AVLNODE2STRUCT(duptree2dupentry, struct dup_entry, olsrd_avl); + + void olsr_init_duplicate_set(void); + void olsr_cleanup_duplicates(union olsr_ip_addr *orig); +@@ -80,10 +80,10 @@ void olsr_print_duplicate_table(void); + + #define OLSR_FOR_ALL_DUP_ENTRIES(dup) \ + { \ +- struct avl_node *dup_tree_node, *next_dup_tree_node; \ +- for (dup_tree_node = avl_walk_first(&duplicate_set); \ ++ struct olsrd_avl_node *dup_tree_node, *next_dup_tree_node; \ ++ for (dup_tree_node = olsrd_avl_walk_first(&duplicate_set); \ + dup_tree_node; dup_tree_node = next_dup_tree_node) { \ +- next_dup_tree_node = avl_walk_next(dup_tree_node); \ ++ next_dup_tree_node = olsrd_avl_walk_next(dup_tree_node); \ + dup = duptree2dupentry(dup_tree_node); + #define OLSR_FOR_ALL_DUP_ENTRIES_END(dup) }} + +--- a/src/gateway.c ++++ b/src/gateway.c +@@ -45,7 +45,7 @@ + + #ifdef __linux__ + +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + #include "defs.h" + #include "ipcalc.h" + #include "olsr.h" +@@ -89,7 +89,7 @@ static struct olsr_ip_prefix ipv4_slash_ + static struct olsr_ip_prefix ipv4_slash_1_routes[2]; + + /** the gateway tree */ +-struct avl_tree gateway_tree; ++struct olsrd_avl_tree gateway_tree; + + /** gateway cookie */ + static struct olsr_cookie_info *gateway_entry_mem_cookie = NULL; +@@ -713,7 +713,7 @@ static void cleanup_gateway_handler(void + } + + /* remove gateway entry */ +- avl_delete(&gateway_tree, &gw->node); ++ olsrd_avl_delete(&gateway_tree, &gw->node); + olsr_cookie_free(gateway_entry_mem_cookie, gw); + } + +@@ -837,7 +837,7 @@ int olsr_init_gateways(void) { + gw_container_entry_mem_cookie = olsr_alloc_cookie("gw_container_entry_mem_cookie", OLSR_COOKIE_TYPE_MEMORY); + olsr_cookie_set_memory_size(gw_container_entry_mem_cookie, sizeof(struct gw_container_entry)); + +- avl_init(&gateway_tree, avl_comp_default); ++ olsrd_avl_init(&gateway_tree, olsrd_avl_comp_default); + + olsr_gw_list_init(&gw_list_ipv4, olsr_cnf->smart_gw_use_count); + olsr_gw_list_init(&gw_list_ipv6, olsr_cnf->smart_gw_use_count); +@@ -1078,7 +1078,7 @@ void olsr_cleanup_gateways(void) { + OLSR_FOR_ALL_GWS_END(gw); + + /* there should be no more gateways */ +- assert(!avl_walk_first(&gateway_tree)); ++ assert(!olsrd_avl_walk_first(&gateway_tree)); + assert(!current_ipv4_gw); + assert(!current_ipv6_gw); + +@@ -1244,14 +1244,14 @@ void olsr_update_gateway_entry(union ols + struct gw_container_entry * new_gw_in_list; + uint8_t *ptr; + int64_t prev_path_cost = 0; +- struct gateway_entry *gw = node2gateway(avl_find(&gateway_tree, originator)); ++ struct gateway_entry *gw = node2gateway(olsrd_avl_find(&gateway_tree, originator)); + + if (!gw) { + gw = olsr_cookie_malloc(gateway_entry_mem_cookie); + gw->originator = *originator; + gw->node.key = &gw->originator; + +- avl_insert(&gateway_tree, &gw->node, AVL_DUP_NO); ++ olsrd_avl_insert(&gateway_tree, &gw->node, OLSRD_AVL_DUP_NO); + } else if (olsr_seqno_diff(seqno, gw->seqno) <= 0) { + /* ignore older HNAs */ + return; +@@ -1353,7 +1353,7 @@ void olsr_update_gateway_entry(union ols + * gateway tree immediately, else it is removed on a delayed schedule. + */ + void olsr_delete_gateway_entry(union olsr_ip_addr *originator, uint8_t prefixlen, bool immediate) { +- olsr_delete_gateway_tree_entry(node2gateway(avl_find(&gateway_tree, originator)), prefixlen, immediate); ++ olsr_delete_gateway_tree_entry(node2gateway(olsrd_avl_find(&gateway_tree, originator)), prefixlen, immediate); + } + + /** +@@ -1526,7 +1526,7 @@ bool olsr_set_inet_gateway(struct gatewa + return true; + } + +- new_gw = node2gateway(avl_find(&gateway_tree, &chosen_gw->originator)); ++ new_gw = node2gateway(olsrd_avl_find(&gateway_tree, &chosen_gw->originator)); + if (!new_gw) { + /* the originator is not in the gateway tree, we can't set it as gateway */ + return true; +--- a/src/gateway.h ++++ b/src/gateway.h +@@ -46,7 +46,7 @@ + #ifndef GATEWAY_H_ + #define GATEWAY_H_ + +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + #include "common/list.h" + #include "defs.h" + #include "olsr.h" +@@ -96,7 +96,7 @@ enum gateway_hna_fields { + + /** a gateway entry */ + struct gateway_entry { +- struct avl_node node; ++ struct olsrd_avl_node node; + union olsr_ip_addr originator; + struct olsr_ip_prefix external_prefix; + uint32_t uplink; +@@ -129,27 +129,27 @@ struct interfaceName { + #endif /* __linux__ */ + + /** +- * static INLINE struct gateway_entry * node2gateway (struct avl_node *ptr) ++ * static INLINE struct gateway_entry * node2gateway (struct olsrd_avl_node *ptr) + * + * Converts a node into a gateway entry + */ +-AVLNODE2STRUCT(node2gateway, struct gateway_entry, node); ++OLSRD_AVLNODE2STRUCT(node2gateway, struct gateway_entry, node); + + /** + * Loop over all gateway entries and put the iterated gateway entry in gw + */ + #define OLSR_FOR_ALL_GATEWAY_ENTRIES(gw) \ + { \ +- struct avl_node *gw_node, *next_gw_node; \ +- for (gw_node = avl_walk_first(&gateway_tree); \ ++ struct olsrd_avl_node *gw_node, *next_gw_node; \ ++ for (gw_node = olsrd_avl_walk_first(&gateway_tree); \ + gw_node; gw_node = next_gw_node) { \ +- next_gw_node = avl_walk_next(gw_node); \ ++ next_gw_node = olsrd_avl_walk_next(gw_node); \ + gw = node2gateway(gw_node); \ + if (gw) { + #define OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw) }}} + + /** the gateway tree */ +-extern struct avl_tree gateway_tree; ++extern struct olsrd_avl_tree gateway_tree; + + /** the list IPv4 gateways */ + extern struct gw_list gw_list_ipv4; +--- a/src/kernel_tunnel.h ++++ b/src/kernel_tunnel.h +@@ -55,7 +55,7 @@ + + #include "defs.h" + #include "olsr_types.h" +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + + #define TUNNEL_ENDPOINT_IF "tunl0" + #define TUNNEL_ENDPOINT_IF6 "ip6tnl0" +@@ -67,7 +67,7 @@ + #endif + + struct olsr_iptunnel_entry { +- struct avl_node node; ++ struct olsrd_avl_node node; + union olsr_ip_addr target; + + char if_name[IF_NAMESIZE]; +--- a/src/linux/kernel_tunnel.c ++++ b/src/linux/kernel_tunnel.c +@@ -84,12 +84,12 @@ + + static bool store_iptunnel_state; + static struct olsr_cookie_info *tunnel_cookie; +-static struct avl_tree tunnel_tree; ++static struct olsrd_avl_tree tunnel_tree; + + int olsr_os_init_iptunnel(const char * dev) { + tunnel_cookie = olsr_alloc_cookie("iptunnel", OLSR_COOKIE_TYPE_MEMORY); + olsr_cookie_set_memory_size(tunnel_cookie, sizeof(struct olsr_iptunnel_entry)); +- avl_init(&tunnel_tree, avl_comp_default); ++ olsrd_avl_init(&tunnel_tree, olsrd_avl_comp_default); + + store_iptunnel_state = olsr_if_isup(dev); + if (store_iptunnel_state) { +@@ -107,7 +107,7 @@ void olsr_os_cleanup_iptunnel(const char + struct olsr_iptunnel_entry *t; + + /* kill tunnel */ +- t = (struct olsr_iptunnel_entry *)avl_walk_first(&tunnel_tree); ++ t = (struct olsr_iptunnel_entry *)olsrd_avl_walk_first(&tunnel_tree); + t->usage = 1; + + olsr_os_del_ipip_tunnel(t); +@@ -201,7 +201,7 @@ struct olsr_iptunnel_entry *olsr_os_add_ + + assert(olsr_cnf->ip_version == AF_INET6 || transportV4); + +- t = (struct olsr_iptunnel_entry *)avl_find(&tunnel_tree, target); ++ t = (struct olsr_iptunnel_entry *)olsrd_avl_find(&tunnel_tree, target); + if (t == NULL) { + int if_idx; + struct ipaddr_str buf; +@@ -228,7 +228,7 @@ struct olsr_iptunnel_entry *olsr_os_add_ + strscpy(t->if_name, name, sizeof(t->if_name)); + t->if_index = if_idx; + +- avl_insert(&tunnel_tree, &t->node, AVL_DUP_NO); ++ olsrd_avl_insert(&tunnel_tree, &t->node, OLSRD_AVL_DUP_NO); + } + + t->usage++; +@@ -253,7 +253,7 @@ void olsr_os_del_ipip_tunnel(struct olsr + olsr_if_set_state(t->if_name, false); + os_ip_tunnel(t->if_name, NULL); + +- avl_delete(&tunnel_tree, &t->node); ++ olsrd_avl_delete(&tunnel_tree, &t->node); + olsr_cookie_free(tunnel_cookie, t); + } + #endif /* __linux__ */ +--- a/src/lq_packet.c ++++ b/src/lq_packet.c +@@ -272,16 +272,16 @@ create_lq_tc(struct lq_tc_message *lq_tc + + /* Queue the neighbour entry. */ + +- // TODO: ugly hack until neighbor table is ported to avl tree ++ // TODO: ugly hack until neighbor table is ported to olsrd_avl tree + +- if (lq_tc->neigh == NULL || avl_comp_default(&lq_tc->neigh->address, &neigh->address) > 0) { ++ if (lq_tc->neigh == NULL || olsrd_avl_comp_default(&lq_tc->neigh->address, &neigh->address) > 0) { + neigh->next = lq_tc->neigh; + lq_tc->neigh = neigh; + } else { + struct tc_mpr_addr *last = lq_tc->neigh, *n = last->next; + + while (n) { +- if (avl_comp_default(&n->address, &neigh->address) > 0) { ++ if (olsrd_avl_comp_default(&n->address, &neigh->address) > 0) { + break; + } + last = n; +--- a/src/lq_plugin.c ++++ b/src/lq_plugin.c +@@ -50,7 +50,7 @@ + #include "packet.h" + #include "olsr.h" + #include "two_hop_neighbor_table.h" +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + + #include "lq_plugin_default_float.h" + #include "lq_plugin_default_fpm.h" +@@ -64,17 +64,17 @@ + #include + #include + +-struct avl_tree lq_handler_tree; ++struct olsrd_avl_tree lq_handler_tree; + struct lq_handler *active_lq_handler = NULL; + + /** +- * case-insensitive string comparator for avl-trees ++ * case-insensitive string comparator for olsrd_avl-trees + * @param str1 + * @param str2 + * @return + */ + int +-avl_strcasecmp(const void *str1, const void *str2) ++olsrd_avl_strcasecmp(const void *str1, const void *str2) + { + return strcasecmp(str1, str2); + } +@@ -88,7 +88,7 @@ activate_lq_handler(const char *name) + { + struct lq_handler_node *node; + +- node = (struct lq_handler_node *)avl_find(&lq_handler_tree, name); ++ node = (struct lq_handler_node *)olsrd_avl_find(&lq_handler_tree, name); + if (node == NULL) { + char buf[1024]; + snprintf(buf, sizeof(buf), "Error, unknown lq_handler '%s'", name); +@@ -106,7 +106,7 @@ activate_lq_handler(const char *name) + void + init_lq_handler_tree(void) + { +- avl_init(&lq_handler_tree, &avl_strcasecmp); ++ olsrd_avl_init(&lq_handler_tree, &olsrd_avl_strcasecmp); + register_lq_handler(&lq_etx_float_handler, LQ_ALGORITHM_ETX_FLOAT_NAME); + register_lq_handler(&lq_etx_fpm_handler, LQ_ALGORITHM_ETX_FPM_NAME); + register_lq_handler(&lq_etx_ff_handler, LQ_ALGORITHM_ETX_FF_NAME); +@@ -147,7 +147,7 @@ register_lq_handler(struct lq_handler *h + node->node.key = node->name; + node->handler = handler; + +- avl_insert(&lq_handler_tree, &node->node, false); ++ olsrd_avl_insert(&lq_handler_tree, &node->node, false); + } + + /** +--- a/src/lq_plugin.h ++++ b/src/lq_plugin.h +@@ -51,7 +51,7 @@ + #include "olsr_spf.h" + #include "lq_packet.h" + #include "packet.h" +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + + #define LINK_COST_BROKEN (1u<<22) + #define ROUTE_COST_BROKEN (0xffffffffu) +@@ -97,23 +97,23 @@ struct lq_handler { + }; + + struct lq_handler_node { +- struct avl_node node; ++ struct olsrd_avl_node node; + struct lq_handler *handler; + char name[0]; + }; + +-AVLNODE2STRUCT(lq_handler_tree2lq_handler_node, struct lq_handler_node, node); ++OLSRD_AVLNODE2STRUCT(lq_handler_tree2lq_handler_node, struct lq_handler_node, node); + + #define OLSR_FOR_ALL_LQ_HANDLERS(lq) \ + { \ +- struct avl_node *lq_tree_node, *next_lq_tree_node; \ +- for (lq_tree_node = avl_walk_first(&lq_handler_tree); \ ++ struct olsrd_avl_node *lq_tree_node, *next_lq_tree_node; \ ++ for (lq_tree_node = olsrd_avl_walk_first(&lq_handler_tree); \ + lq_tree_node; lq_tree_node = next_lq_tree_node) { \ +- next_lq_tree_node = avl_walk_next(lq_tree_node); \ ++ next_lq_tree_node = olsrd_avl_walk_next(lq_tree_node); \ + lq = lq_handler_tree2lq_handler_node(lq_tree_node); + #define OLSR_FOR_ALL_LQ_HANDLERS_END(tc) }} + +-int avl_strcasecmp(const void *str1, const void *str2); ++int olsrd_avl_strcasecmp(const void *str1, const void *str2); + void init_lq_handler_tree(void); + + void register_lq_handler(struct lq_handler *handler, const char *name); +--- a/src/olsr.c ++++ b/src/olsr.c +@@ -65,7 +65,7 @@ + #include "neighbor_table.h" + #include "log.h" + #include "lq_packet.h" +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + #include "net_olsr.h" + #include "lq_plugin.h" + #include "gateway.h" +@@ -260,13 +260,13 @@ olsr_init_tables(void) + changes_neighborhood = false; + changes_hna = false; + +- /* Set avl tree comparator */ ++ /* Set olsrd_avl tree comparator */ + if (olsr_cnf->ipsize == 4) { +- avl_comp_default = avl_comp_ipv4; +- avl_comp_prefix_default = avl_comp_ipv4_prefix; ++ olsrd_avl_comp_default = olsrd_avl_comp_ipv4; ++ olsrd_avl_comp_prefix_default = olsrd_avl_comp_ipv4_prefix; + } else { +- avl_comp_default = avl_comp_ipv6; +- avl_comp_prefix_default = avl_comp_ipv6_prefix; ++ olsrd_avl_comp_default = olsrd_avl_comp_ipv6; ++ olsrd_avl_comp_prefix_default = olsrd_avl_comp_ipv6_prefix; + } + + /* Initialize lq plugin set */ +--- a/src/olsr_spf.c ++++ b/src/olsr_spf.c +@@ -47,7 +47,7 @@ + * Implementation of Dijkstras algorithm. Initially all nodes + * are initialized to infinite cost. First we put ourselves + * on the heap of reachable nodes. Our heap implementation +- * is based on an AVL tree which gives interesting performance ++ * is based on an OLSRD_AVL tree which gives interesting performance + * characteristics for the frequent operations of minimum key + * extraction and re-keying. Next all neighbors of a node are + * explored and put on the heap if the cost of reaching them is +@@ -67,7 +67,7 @@ + #include "mid_set.h" + #include "hna_set.h" + #include "common/list.h" +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + #include "olsr_spf.h" + #include "net_olsr.h" + #include "lq_plugin.h" +@@ -80,7 +80,7 @@ + struct timer_entry *spf_backoff_timer = NULL; + + /* +- * avl_comp_etx ++ * olsrd_avl_comp_etx + * + * compare two etx metrics. + * return 0 if there is an exact match and +@@ -89,7 +89,7 @@ struct timer_entry *spf_backoff_timer = + * after compiler optimization. + */ + static int +-avl_comp_etx(const void *etx1, const void *etx2) ++olsrd_avl_comp_etx(const void *etx1, const void *etx2) + { + if (*(const olsr_linkcost *)etx1 < *(const olsr_linkcost *)etx2) { + return -1; +@@ -108,7 +108,7 @@ avl_comp_etx(const void *etx1, const voi + * Key an existing vertex to a candidate tree. + */ + static void +-olsr_spf_add_cand_tree(struct avl_tree *tree, struct tc_entry *tc) ++olsr_spf_add_cand_tree(struct olsrd_avl_tree *tree, struct tc_entry *tc) + { + #if !defined(NODEBUG) && defined(DEBUG) + struct ipaddr_str buf; +@@ -121,7 +121,7 @@ olsr_spf_add_cand_tree(struct avl_tree * + get_linkcost_text(tc->path_cost, true, &lqbuffer)); + #endif /* DEBUG */ + +- avl_insert(tree, &tc->cand_tree_node, AVL_DUP); ++ olsrd_avl_insert(tree, &tc->cand_tree_node, OLSRD_AVL_DUP); + } + + /* +@@ -130,7 +130,7 @@ olsr_spf_add_cand_tree(struct avl_tree * + * Unkey an existing vertex from a candidate tree. + */ + static void +-olsr_spf_del_cand_tree(struct avl_tree *tree, struct tc_entry *tc) ++olsr_spf_del_cand_tree(struct olsrd_avl_tree *tree, struct tc_entry *tc) + { + + #ifdef DEBUG +@@ -142,7 +142,7 @@ olsr_spf_del_cand_tree(struct avl_tree * + get_linkcost_text(tc->path_cost, true, &lqbuffer)); + #endif /* DEBUG */ + +- avl_delete(tree, &tc->cand_tree_node); ++ olsrd_avl_delete(tree, &tc->cand_tree_node); + } + + /* +@@ -175,9 +175,9 @@ olsr_spf_add_path_list(struct list_node + * return the node with the minimum pathcost. + */ + static struct tc_entry * +-olsr_spf_extract_best(struct avl_tree *tree) ++olsr_spf_extract_best(struct olsrd_avl_tree *tree) + { +- struct avl_node *node = avl_walk_first(tree); ++ struct olsrd_avl_node *node = olsrd_avl_walk_first(tree); + + return (node ? cand_tree2tc(node) : NULL); + } +@@ -190,9 +190,9 @@ olsr_spf_extract_best(struct avl_tree *t + * path cost is better. + */ + static void +-olsr_spf_relax(struct avl_tree *cand_tree, struct tc_entry *tc) ++olsr_spf_relax(struct olsrd_avl_tree *cand_tree, struct tc_entry *tc) + { +- struct avl_node *edge_node; ++ struct olsrd_avl_node *edge_node; + olsr_linkcost new_cost; + + #ifdef DEBUG +@@ -207,7 +207,7 @@ olsr_spf_relax(struct avl_tree *cand_tre + /* + * loop through all edges of this vertex. + */ +- for (edge_node = avl_walk_first(&tc->edge_tree); edge_node; edge_node = avl_walk_next(edge_node)) { ++ for (edge_node = olsrd_avl_walk_first(&tc->edge_tree); edge_node; edge_node = olsrd_avl_walk_next(edge_node)) { + + struct tc_entry *new_tc; + struct tc_edge_entry *tc_edge = edge_tree2tc_edge(edge_node); +@@ -289,7 +289,7 @@ olsr_spf_relax(struct avl_tree *cand_tre + * on the candidate tree. + */ + static void +-olsr_spf_run_full(struct avl_tree *cand_tree, struct list_node *path_list, int *path_count) ++olsr_spf_run_full(struct olsrd_avl_tree *cand_tree, struct list_node *path_list, int *path_count) + { + struct tc_entry *tc; + +@@ -335,8 +335,8 @@ olsr_calculate_routing_table(bool force) + #ifdef SPF_PROFILING + struct timespec t1, t2, t3, t4, t5, spf_init, spf_run, route, kernel, total; + #endif /* SPF_PROFILING */ +- struct avl_tree cand_tree; +- struct avl_node *rtp_tree_node; ++ struct olsrd_avl_tree cand_tree; ++ struct olsrd_avl_node *rtp_tree_node; + struct list_node path_list; /* head of the path_list */ + struct tc_entry *tc; + struct rt_path *rtp; +@@ -362,7 +362,7 @@ olsr_calculate_routing_table(bool force) + /* + * Prepare the candidate tree and result list. + */ +- avl_init(&cand_tree, avl_comp_etx); ++ olsrd_avl_init(&cand_tree, olsrd_avl_comp_etx); + list_head_init(&path_list); + olsr_bump_routingtree_version(); + +@@ -493,7 +493,7 @@ olsr_calculate_routing_table(bool force) + * If the prefix is already in the RIB, refresh the entry such + * that olsr_delete_outdated_routes() does not purge it off. + */ +- for (rtp_tree_node = avl_walk_first(&tc->prefix_tree); rtp_tree_node; rtp_tree_node = avl_walk_next(rtp_tree_node)) { ++ for (rtp_tree_node = olsrd_avl_walk_first(&tc->prefix_tree); rtp_tree_node; rtp_tree_node = olsrd_avl_walk_next(rtp_tree_node)) { + + rtp = rtp_prefix_tree2rtp(rtp_tree_node); + +--- a/src/process_routes.c ++++ b/src/process_routes.c +@@ -48,7 +48,7 @@ + #include "olsr.h" + #include "log.h" + #include "kernel_routes.h" +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + #include "net_olsr.h" + #include "tc_set.h" + #include "olsr_cookie.h" +@@ -289,13 +289,13 @@ static void + olsr_delete_outdated_routes(struct rt_entry *rt) + { + struct rt_path *rtp; +- struct avl_node *rtp_tree_node, *next_rtp_tree_node; ++ struct olsrd_avl_node *rtp_tree_node, *next_rtp_tree_node; + +- for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = next_rtp_tree_node) { ++ for (rtp_tree_node = olsrd_avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = next_rtp_tree_node) { + /* + * pre-fetch the next node before loosing context. + */ +- next_rtp_tree_node = avl_walk_next(rtp_tree_node); ++ next_rtp_tree_node = olsrd_avl_walk_next(rtp_tree_node); + + rtp = rtp_tree2rtp(rtp_tree_node); + +@@ -305,7 +305,7 @@ olsr_delete_outdated_routes(struct rt_en + */ + if (routingtree_version != rtp->rtp_version) { + /* remove from the originator tree */ +- avl_delete(&rt->rt_path_tree, rtp_tree_node); ++ olsrd_avl_delete(&rt->rt_path_tree, rtp_tree_node); + rtp->rtp_rt = NULL; + + if (rt->rt_best == rtp) { +@@ -341,7 +341,7 @@ olsr_update_rib_routes(void) + + if (olsr_delete_kernel_route(rt) == 0) { + /*only remove if deletion was successful*/ +- avl_delete(&routingtree, &rt->rt_tree_node); ++ olsrd_avl_delete(&routingtree, &rt->rt_tree_node); + olsr_cookie_free(rt_mem_cookie, rt); + } + +@@ -370,21 +370,21 @@ olsr_delete_interface_routes(int if_inde + OLSR_FOR_ALL_RT_ENTRIES(rt) { + bool mightTrigger = false; + struct rt_path *rtp; +- struct avl_node *rtp_tree_node, *next_rtp_tree_node; ++ struct olsrd_avl_node *rtp_tree_node, *next_rtp_tree_node; + + /* run through all routing paths of route */ +- for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = next_rtp_tree_node) { ++ for (rtp_tree_node = olsrd_avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = next_rtp_tree_node) { + /* + * pre-fetch the next node before loosing context. + */ +- next_rtp_tree_node = avl_walk_next(rtp_tree_node); ++ next_rtp_tree_node = olsrd_avl_walk_next(rtp_tree_node); + + rtp = rtp_tree2rtp(rtp_tree_node); + + /* nexthop use lost interface ? */ + if (rtp->rtp_nexthop.iif_index == if_index) { + /* remove from the originator tree */ +- avl_delete(&rt->rt_path_tree, rtp_tree_node); ++ olsrd_avl_delete(&rt->rt_path_tree, rtp_tree_node); + rtp->rtp_rt = NULL; + + if (rt->rt_best == rtp) { +@@ -397,7 +397,7 @@ olsr_delete_interface_routes(int if_inde + if (mightTrigger) { + if (!rt->rt_path_tree.count) { + /* oops, all routes are gone - flush the route head */ +- avl_delete(&routingtree, rt_tree_node); ++ olsrd_avl_delete(&routingtree, rt_tree_node); + + /* do not dequeue route because they are already gone */ + } +--- a/src/routing_table.c ++++ b/src/routing_table.c +@@ -52,7 +52,7 @@ + #include "neighbor_table.h" + #include "olsr.h" + #include "link_set.h" +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + #include "olsr_spf.h" + #include "net_olsr.h" + +@@ -72,7 +72,7 @@ struct olsr_cookie_info *rtp_mem_cookie + static struct rt_path *current_inetgw = NULL; + + /* Root of our RIB */ +-struct avl_tree routingtree; ++struct olsrd_avl_tree routingtree; + + /* + * Keep a version number for detecting outdated elements +@@ -95,7 +95,7 @@ olsr_bump_routingtree_version(void) + } + + /** +- * avl_comp_ipv4_prefix ++ * olsrd_avl_comp_ipv4_prefix + * + * compare two ipv4 prefixes. + * first compare the prefixes, then +@@ -105,7 +105,7 @@ olsr_bump_routingtree_version(void) + * -1 / +1 depending on being smaller or bigger. + */ + int +-avl_comp_ipv4_prefix(const void *prefix1, const void *prefix2) ++olsrd_avl_comp_ipv4_prefix(const void *prefix1, const void *prefix2) + { + const struct olsr_ip_prefix *pfx1 = prefix1; + const struct olsr_ip_prefix *pfx2 = prefix2; +@@ -132,7 +132,7 @@ avl_comp_ipv4_prefix(const void *prefix1 + } + + /** +- * avl_comp_ipv6_prefix ++ * olsrd_avl_comp_ipv6_prefix + * + * compare two ipv6 prefixes. + * first compare the prefixes, then +@@ -142,7 +142,7 @@ avl_comp_ipv4_prefix(const void *prefix1 + * -1 / +1 depending on being smaller or bigger. + */ + int +-avl_comp_ipv6_prefix(const void *prefix1, const void *prefix2) ++olsrd_avl_comp_ipv6_prefix(const void *prefix1, const void *prefix2) + { + int res; + const struct olsr_ip_prefix *pfx1 = prefix1; +@@ -173,7 +173,7 @@ olsr_init_routing_table(void) + OLSR_PRINTF(5, "RIB: init routing tree\n"); + + /* the routing tree */ +- avl_init(&routingtree, avl_comp_prefix_default); ++ olsrd_avl_init(&routingtree, olsrd_avl_comp_prefix_default); + routingtree_version = 0; + + /* +@@ -197,13 +197,13 @@ olsr_init_routing_table(void) + struct rt_entry * + olsr_lookup_routing_table(const union olsr_ip_addr *dst) + { +- struct avl_node *rt_tree_node; ++ struct olsrd_avl_node *rt_tree_node; + struct olsr_ip_prefix prefix; + + prefix.prefix = *dst; + prefix.prefix_len = olsr_cnf->maxplen; + +- rt_tree_node = avl_find(&routingtree, &prefix); ++ rt_tree_node = olsrd_avl_find(&routingtree, &prefix); + + return rt_tree_node ? rt_tree2rt(rt_tree_node) : NULL; + } +@@ -248,10 +248,10 @@ olsr_alloc_rt_entry(struct olsr_ip_prefi + rt->rt_dst = *prefix; + + rt->rt_tree_node.key = &rt->rt_dst; +- avl_insert(&routingtree, &rt->rt_tree_node, AVL_DUP_NO); ++ olsrd_avl_insert(&routingtree, &rt->rt_tree_node, OLSRD_AVL_DUP_NO); + + /* init the originator subtree */ +- avl_init(&rt->rt_path_tree, avl_comp_default); ++ olsrd_avl_init(&rt->rt_path_tree, olsrd_avl_comp_default); + + return rt; + } +@@ -276,7 +276,7 @@ olsr_alloc_rt_path(struct tc_entry *tc, + rtp->rtp_prefix_tree_node.key = &rtp->rtp_dst; + + /* insert to the tc prefix tree */ +- avl_insert(&tc->prefix_tree, &rtp->rtp_prefix_tree_node, AVL_DUP_NO); ++ olsrd_avl_insert(&tc->prefix_tree, &rtp->rtp_prefix_tree_node, OLSRD_AVL_DUP_NO); + olsr_lock_tc_entry(tc); + + /* backlink to the owning tc entry */ +@@ -296,7 +296,7 @@ void + olsr_insert_rt_path(struct rt_path *rtp, struct tc_entry *tc, struct link_entry *link) + { + struct rt_entry *rt; +- struct avl_node *node; ++ struct olsrd_avl_node *node; + + /* + * no unreachable routes please. +@@ -315,7 +315,7 @@ olsr_insert_rt_path(struct rt_path *rtp, + /* + * first check if there is a route_entry for the prefix. + */ +- node = avl_find(&routingtree, &rtp->rtp_dst); ++ node = olsrd_avl_find(&routingtree, &rtp->rtp_dst); + + if (!node) { + +@@ -337,7 +337,7 @@ olsr_insert_rt_path(struct rt_path *rtp, + rtp->rtp_tree_node.key = &rtp->rtp_originator; + + /* insert to the route entry originator tree */ +- avl_insert(&rt->rt_path_tree, &rtp->rtp_tree_node, AVL_DUP_NO); ++ olsrd_avl_insert(&rt->rt_path_tree, &rtp->rtp_tree_node, OLSRD_AVL_DUP_NO); + + /* backlink to the owning route entry */ + rtp->rtp_rt = rt; +@@ -356,13 +356,13 @@ olsr_delete_rt_path(struct rt_path *rtp) + + /* remove from the originator tree */ + if (rtp->rtp_rt) { +- avl_delete(&rtp->rtp_rt->rt_path_tree, &rtp->rtp_tree_node); ++ olsrd_avl_delete(&rtp->rtp_rt->rt_path_tree, &rtp->rtp_tree_node); + rtp->rtp_rt = NULL; + } + + /* remove from the tc prefix tree */ + if (rtp->rtp_tc) { +- avl_delete(&rtp->rtp_tc->prefix_tree, &rtp->rtp_prefix_tree_node); ++ olsrd_avl_delete(&rtp->rtp_tc->prefix_tree, &rtp->rtp_prefix_tree_node); + olsr_unlock_tc_entry(rtp->rtp_tc); + rtp->rtp_tc = NULL; + } +@@ -498,14 +498,14 @@ void + olsr_rt_best(struct rt_entry *rt) + { + /* grab the first entry */ +- struct avl_node *node = avl_walk_first(&rt->rt_path_tree); ++ struct olsrd_avl_node *node = olsrd_avl_walk_first(&rt->rt_path_tree); + + assert(node != 0); /* should not happen */ + + rt->rt_best = rtp_tree2rtp(node); + + /* walk all remaining originator entries */ +- while ((node = avl_walk_next(node))) { ++ while ((node = olsrd_avl_walk_next(node))) { + struct rt_path *rtp = rtp_tree2rtp(node); + + if (olsr_cmp_rtp(rtp, rt->rt_best, current_inetgw)) { +@@ -541,7 +541,7 @@ olsr_insert_routing_table(union olsr_ip_ + #endif /* DEBUG */ + struct tc_entry *tc; + struct rt_path *rtp; +- struct avl_node *node; ++ struct olsrd_avl_node *node; + struct olsr_ip_prefix prefix; + + /* +@@ -567,7 +567,7 @@ olsr_insert_routing_table(union olsr_ip_ + prefix.prefix = *dst; + prefix.prefix_len = plen; + +- node = avl_find(&tc->prefix_tree, &prefix); ++ node = olsrd_avl_find(&tc->prefix_tree, &prefix); + + if (!node) { + +@@ -604,7 +604,7 @@ olsr_delete_routing_table(union olsr_ip_ + + struct tc_entry *tc; + struct rt_path *rtp; +- struct avl_node *node; ++ struct olsrd_avl_node *node; + struct olsr_ip_prefix prefix; + + /* +@@ -625,7 +625,7 @@ olsr_delete_routing_table(union olsr_ip_ + prefix.prefix = *dst; + prefix.prefix_len = plen; + +- node = avl_find(&tc->prefix_tree, &prefix); ++ node = olsrd_avl_find(&tc->prefix_tree, &prefix); + + if (node) { + rtp = rtp_prefix_tree2rtp(node); +@@ -682,16 +682,16 @@ olsr_rtp_to_string(const struct rt_path + */ + #ifndef NODEBUG + void +-olsr_print_routing_table(struct avl_tree *tree) ++olsr_print_routing_table(struct olsrd_avl_tree *tree) + { + /* The whole function makes no sense without it. */ +- struct avl_node *rt_tree_node; ++ struct olsrd_avl_node *rt_tree_node; + struct lqtextbuffer lqbuffer; + + OLSR_PRINTF(6, "ROUTING TABLE\n"); + +- for (rt_tree_node = avl_walk_first(tree); rt_tree_node != NULL; rt_tree_node = avl_walk_next(rt_tree_node)) { +- struct avl_node *rtp_tree_node; ++ for (rt_tree_node = olsrd_avl_walk_first(tree); rt_tree_node != NULL; rt_tree_node = olsrd_avl_walk_next(rt_tree_node)) { ++ struct olsrd_avl_node *rtp_tree_node; + struct ipaddr_str prefixstr, origstr, gwstr; + struct rt_entry *rt = rt_tree2rt(rt_tree_node); + +@@ -700,7 +700,7 @@ olsr_print_routing_table(struct avl_tree + olsr_ip_to_string(&origstr, &rt->rt_nexthop.gateway), olsr_ip_to_string(&gwstr, &rt->rt_best->rtp_originator)); + + /* walk the per-originator path tree of routes */ +- for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = avl_walk_next(rtp_tree_node)) { ++ for (rtp_tree_node = olsrd_avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = olsrd_avl_walk_next(rtp_tree_node)) { + struct rt_path *rtp = rtp_tree2rtp(rtp_tree_node); + OLSR_PRINTF(6, "\tfrom %s, cost %s, metric %u, via %s, %s, v %u\n", olsr_ip_to_string(&origstr, &rtp->rtp_originator), + get_linkcost_text(rtp->rtp_metric.cost, true, &lqbuffer), rtp->rtp_metric.hops, olsr_ip_to_string(&gwstr, +--- a/src/routing_table.h ++++ b/src/routing_table.h +@@ -54,7 +54,7 @@ + #include "hna_set.h" + #include "link_set.h" + #include "olsr_cookie.h" +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + #include "common/list.h" + + #define NETMASK_HOST 0xffffffff +@@ -81,15 +81,15 @@ struct rt_nexthop { + */ + struct rt_entry { + struct olsr_ip_prefix rt_dst; +- struct avl_node rt_tree_node; ++ struct olsrd_avl_node rt_tree_node; + struct rt_path *rt_best; /* shortcut to the best path */ + struct rt_nexthop rt_nexthop; /* nexthop of FIB route */ + struct rt_metric rt_metric; /* metric of FIB route */ +- struct avl_tree rt_path_tree; ++ struct olsrd_avl_tree rt_path_tree; + struct list_node rt_change_node; /* queue for kernel FIB add/chg/del */ + }; + +-AVLNODE2STRUCT(rt_tree2rt, struct rt_entry, rt_tree_node); ++OLSRD_AVLNODE2STRUCT(rt_tree2rt, struct rt_entry, rt_tree_node); + LISTNODE2STRUCT(changelist2rt, struct rt_entry, rt_change_node); + + /* +@@ -105,16 +105,16 @@ struct rt_path { + struct tc_entry *rtp_tc; /* backpointer to owning tc entry */ + struct rt_nexthop rtp_nexthop; + struct rt_metric rtp_metric; +- struct avl_node rtp_tree_node; /* global rtp node */ ++ struct olsrd_avl_node rtp_tree_node; /* global rtp node */ + union olsr_ip_addr rtp_originator; /* originator of the route */ +- struct avl_node rtp_prefix_tree_node; /* tc entry rtp node */ ++ struct olsrd_avl_node rtp_prefix_tree_node; /* tc entry rtp node */ + struct olsr_ip_prefix rtp_dst; /* the prefix */ + uint32_t rtp_version; /* for detection of outdated rt_paths */ + uint8_t rtp_origin; /* internal, MID or HNA */ + }; + +-AVLNODE2STRUCT(rtp_tree2rtp, struct rt_path, rtp_tree_node); +-AVLNODE2STRUCT(rtp_prefix_tree2rtp, struct rt_path, rtp_prefix_tree_node); ++OLSRD_AVLNODE2STRUCT(rtp_tree2rtp, struct rt_path, rtp_tree_node); ++OLSRD_AVLNODE2STRUCT(rtp_prefix_tree2rtp, struct rt_path, rtp_prefix_tree_node); + + /* + * In olsrd we have three different route types. +@@ -143,10 +143,10 @@ enum olsr_rt_origin { + */ + #define OLSR_FOR_ALL_RT_ENTRIES(rt) \ + { \ +- struct avl_node *rt_tree_node, *next_rt_tree_node; \ +- for (rt_tree_node = avl_walk_first(&routingtree); \ ++ struct olsrd_avl_node *rt_tree_node, *next_rt_tree_node; \ ++ for (rt_tree_node = olsrd_avl_walk_first(&routingtree); \ + rt_tree_node; rt_tree_node = next_rt_tree_node) { \ +- next_rt_tree_node = avl_walk_next(rt_tree_node); \ ++ next_rt_tree_node = olsrd_avl_walk_next(rt_tree_node); \ + rt = rt_tree2rt(rt_tree_node); + #define OLSR_FOR_ALL_RT_ENTRIES_END(rt) }} + +@@ -164,10 +164,10 @@ enum olsr_rt_origin { + */ + #define OLSR_FOR_ALL_HNA_RT_ENTRIES(rt) \ + { \ +- struct avl_node *rt_tree_node, *next_rt_tree_node; \ +- for (rt_tree_node = avl_walk_first(&routingtree); \ ++ struct olsrd_avl_node *rt_tree_node, *next_rt_tree_node; \ ++ for (rt_tree_node = olsrd_avl_walk_first(&routingtree); \ + rt_tree_node; rt_tree_node = next_rt_tree_node) { \ +- next_rt_tree_node = avl_walk_next(rt_tree_node); \ ++ next_rt_tree_node = olsrd_avl_walk_next(rt_tree_node); \ + rt = rt_tree2rt(rt_tree_node); \ + if (rt->rt_best->rtp_origin != OLSR_RT_ORIGIN_HNA) \ + continue; +@@ -190,7 +190,7 @@ union olsr_kernel_route { + } v6; + }; + +-extern struct avl_tree routingtree; ++extern struct olsrd_avl_tree routingtree; + extern unsigned int routingtree_version; + extern struct olsr_cookie_info *rt_mem_cookie; + +@@ -198,8 +198,8 @@ void olsr_init_routing_table(void); + + unsigned int olsr_bump_routingtree_version(void); + +-int avl_comp_ipv4_prefix(const void *, const void *); +-int avl_comp_ipv6_prefix(const void *, const void *); ++int olsrd_avl_comp_ipv4_prefix(const void *, const void *); ++int olsrd_avl_comp_ipv6_prefix(const void *, const void *); + + void olsr_rt_best(struct rt_entry *); + bool olsr_nh_change(const struct rt_nexthop *, const struct rt_nexthop *); +@@ -210,7 +210,7 @@ uint8_t olsr_fib_metric(const struct rt_ + char *olsr_rt_to_string(const struct rt_entry *); + char *olsr_rtp_to_string(const struct rt_path *); + #ifndef NODEBUG +-void olsr_print_routing_table(struct avl_tree *); ++void olsr_print_routing_table(struct olsrd_avl_tree *); + #else + #define olsr_print_routing_table(x) do { } while(0) + #endif +--- a/src/scheduler.c ++++ b/src/scheduler.c +@@ -51,7 +51,7 @@ + #include "net_os.h" + #include "mpr_selector_set.h" + #include "olsr_random.h" +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + + #include + +@@ -89,29 +89,29 @@ static void poll_sockets(void); + static uint32_t calc_jitter(unsigned int rel_time, uint8_t jitter_pct, unsigned int random_val); + static void olsr_cleanup_timer(struct timer_entry *timer); + +-struct avl_tree timer_cleanup_tree; ++struct olsrd_avl_tree timer_cleanup_tree; + + struct timer_cleanup_entry { +- struct avl_node avl; ++ struct olsrd_avl_node olsrd_avl; + struct timer_entry * timer; + }; + +-/* static INLINE struct timer_cleanup_entry * node2timercleanup(struct avl_node *ptr) */ +-AVLNODE2STRUCT(node2timercleanup, struct timer_cleanup_entry, avl); ++/* static INLINE struct timer_cleanup_entry * node2timercleanup(struct olsrd_avl_node *ptr) */ ++OLSRD_AVLNODE2STRUCT(node2timercleanup, struct timer_cleanup_entry, olsrd_avl); + + /** + * Loop over all timer cleanup entries and put the iterated entry in timer + */ + #define OLSR_FOR_ALL_TIMERS_CLEANUP(timer) \ + { \ +- struct avl_node *timer_avl_node, *timer_avl_node_next; \ +- for (timer_avl_node = avl_walk_first(&timer_cleanup_tree); \ +- timer_avl_node; timer_avl_node = timer_avl_node_next) { \ +- timer_avl_node_next = avl_walk_next(timer_avl_node); \ +- timer = node2timercleanup(timer_avl_node); ++ struct olsrd_avl_node *timer_olsrd_avl_node, *timer_olsrd_avl_node_next; \ ++ for (timer_olsrd_avl_node = olsrd_avl_walk_first(&timer_cleanup_tree); \ ++ timer_olsrd_avl_node; timer_olsrd_avl_node = timer_olsrd_avl_node_next) { \ ++ timer_olsrd_avl_node_next = olsrd_avl_walk_next(timer_olsrd_avl_node); \ ++ timer = node2timercleanup(timer_olsrd_avl_node); + #define OLSR_FOR_ALL_TIMER_CLEANUP_END(timer) }} + +-static int avl_comp_timer(const void *entry1, const void *entry2) { ++static int olsrd_avl_comp_timer(const void *entry1, const void *entry2) { + if (entry1 < entry2) { + return -1; + } +@@ -638,7 +638,7 @@ olsr_init_timers(void) + last_tv = first_tv; + now_times = olsr_times(); + +- avl_init(&timer_cleanup_tree, avl_comp_timer); ++ olsrd_avl_init(&timer_cleanup_tree, olsrd_avl_comp_timer); + + for (idx = 0; idx < TIMER_WHEEL_SLOTS; idx++) { + list_head_init(&timer_wheel[idx]); +@@ -760,7 +760,7 @@ static void walk_timers_cleanup(void) { + + OLSR_FOR_ALL_TIMERS_CLEANUP(timer) { + olsr_cleanup_timer(timer->timer); +- avl_delete(&timer_cleanup_tree, &timer->avl); ++ olsrd_avl_delete(&timer_cleanup_tree, &timer->olsrd_avl); + free(timer); + } OLSR_FOR_ALL_TIMER_CLEANUP_END(slot) + } +@@ -969,9 +969,9 @@ olsr_stop_timer(struct timer_entry *time + + { + struct timer_cleanup_entry * node = olsr_malloc(sizeof(struct timer_cleanup_entry), "timer cleanup entry"); +- node->avl.key = timer; ++ node->olsrd_avl.key = timer; + node->timer = timer; +- if (avl_insert(&timer_cleanup_tree, &node->avl, AVL_DUP_NO) == -1) { ++ if (olsrd_avl_insert(&timer_cleanup_tree, &node->olsrd_avl, OLSRD_AVL_DUP_NO) == -1) { + /* duplicate */ + free(node); + } +--- a/src/tc_set.c ++++ b/src/tc_set.c +@@ -50,7 +50,7 @@ + #include "olsr.h" + #include "scheduler.h" + #include "olsr_spf.h" +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + #include "lq_packet.h" + #include "net_olsr.h" + #include "lq_plugin.h" +@@ -61,7 +61,7 @@ + #include + + /* Root of the link state database */ +-struct avl_tree tc_tree; ++struct olsrd_avl_tree tc_tree; + struct tc_entry *tc_myself; /* Shortcut to ourselves */ + + /* Some cookies for stats keeping */ +@@ -165,14 +165,14 @@ olsr_add_tc_entry(union olsr_ip_addr *ad + /* + * Insert into the global tc tree. + */ +- avl_insert(&tc_tree, &tc->vertex_node, AVL_DUP_NO); ++ olsrd_avl_insert(&tc_tree, &tc->vertex_node, OLSRD_AVL_DUP_NO); + olsr_lock_tc_entry(tc); + + /* + * Initialize subtrees for edges and prefixes. + */ +- avl_init(&tc->edge_tree, avl_comp_default); +- avl_init(&tc->prefix_tree, avl_comp_prefix_default); ++ olsrd_avl_init(&tc->edge_tree, olsrd_avl_comp_default); ++ olsrd_avl_init(&tc->prefix_tree, olsrd_avl_comp_prefix_default); + + /* + * Add a rt_path for ourselves. +@@ -191,7 +191,7 @@ olsr_init_tc(void) + { + OLSR_PRINTF(5, "TC: init topo\n"); + +- avl_init(&tc_tree, avl_comp_default); ++ olsrd_avl_init(&tc_tree, olsrd_avl_comp_default); + + /* + * Get some cookies for getting stats to ease troubleshooting. +@@ -308,7 +308,7 @@ olsr_delete_tc_entry(struct tc_entry *tc + olsr_stop_timer(tc->validity_timer); + tc->validity_timer = NULL; + +- avl_delete(&tc_tree, &tc->vertex_node); ++ olsrd_avl_delete(&tc_tree, &tc->vertex_node); + olsr_unlock_tc_entry(tc); + } + +@@ -321,9 +321,9 @@ olsr_delete_tc_entry(struct tc_entry *tc + struct tc_entry * + olsr_lookup_tc_entry(union olsr_ip_addr *adr) + { +- struct avl_node *node; ++ struct olsrd_avl_node *node; + +- node = avl_find(&tc_tree, adr); ++ node = olsrd_avl_find(&tc_tree, adr); + + return (node ? vertex_tree2tc(node) : NULL); + } +@@ -454,7 +454,7 @@ olsr_add_tc_edge_entry(struct tc_entry * + /* + * Insert into the edge tree. + */ +- avl_insert(&tc->edge_tree, &tc_edge->edge_node, AVL_DUP_NO); ++ olsrd_avl_insert(&tc->edge_tree, &tc_edge->edge_node, OLSRD_AVL_DUP_NO); + olsr_lock_tc_entry(tc); + + /* +@@ -515,7 +515,7 @@ olsr_delete_tc_edge_entry(struct tc_edge + #endif /* DEBUG */ + + tc = tc_edge->tc; +- avl_delete(&tc->edge_tree, &tc_edge->edge_node); ++ olsrd_avl_delete(&tc->edge_tree, &tc_edge->edge_node); + olsr_unlock_tc_entry(tc); + + /* +@@ -572,7 +572,7 @@ olsr_delete_revoked_tc_edges(struct tc_e + + OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) { + if (!passedLowerBorder) { +- if (avl_comp_default(lower_border, &tc_edge->T_dest_addr) <= 0) { ++ if (olsrd_avl_comp_default(lower_border, &tc_edge->T_dest_addr) <= 0) { + passedLowerBorder = true; + } else { + continue; +@@ -580,7 +580,7 @@ olsr_delete_revoked_tc_edges(struct tc_e + } + + if (passedLowerBorder) { +- if (avl_comp_default(upper_border, &tc_edge->T_dest_addr) <= 0) { ++ if (olsrd_avl_comp_default(upper_border, &tc_edge->T_dest_addr) <= 0) { + break; + } + } +@@ -680,9 +680,9 @@ olsr_tc_update_edge(struct tc_entry *tc, + struct tc_edge_entry * + olsr_lookup_tc_edge(struct tc_entry *tc, union olsr_ip_addr *edge_addr) + { +- struct avl_node *edge_node; ++ struct olsrd_avl_node *edge_node; + +- edge_node = avl_find(&tc->edge_tree, edge_addr); ++ edge_node = olsrd_avl_find(&tc->edge_tree, edge_addr); + + return (edge_node ? edge_tree2tc_edge(edge_node) : NULL); + } +--- a/src/tc_set.h ++++ b/src/tc_set.h +@@ -48,7 +48,7 @@ + + #include "defs.h" + #include "packet.h" +-#include "common/avl.h" ++#include "common/olsrd_avl.h" + #include "common/list.h" + #include "scheduler.h" + +@@ -60,7 +60,7 @@ + */ + + struct tc_edge_entry { +- struct avl_node edge_node; /* edge_tree node in tc_entry */ ++ struct olsrd_avl_node edge_node; /* edge_tree node in tc_entry */ + union olsr_ip_addr T_dest_addr; /* edge_node key */ + struct tc_edge_entry *edge_inv; /* shortcut, used during SPF calculation */ + struct tc_entry *tc; /* backpointer to owning tc entry */ +@@ -69,16 +69,16 @@ struct tc_edge_entry { + uint32_t linkquality[0]; + }; + +-AVLNODE2STRUCT(edge_tree2tc_edge, struct tc_edge_entry, edge_node); ++OLSRD_AVLNODE2STRUCT(edge_tree2tc_edge, struct tc_edge_entry, edge_node); + + struct tc_entry { +- struct avl_node vertex_node; /* node keyed by ip address */ ++ struct olsrd_avl_node vertex_node; /* node keyed by ip address */ + union olsr_ip_addr addr; /* vertex_node key */ +- struct avl_node cand_tree_node; /* SPF candidate heap, node keyed by path_etx */ ++ struct olsrd_avl_node cand_tree_node; /* SPF candidate heap, node keyed by path_etx */ + olsr_linkcost path_cost; /* SPF calculated distance, cand_tree_node key */ + struct list_node path_list_node; /* SPF result list */ +- struct avl_tree edge_tree; /* subtree for edges */ +- struct avl_tree prefix_tree; /* subtree for prefixes */ ++ struct olsrd_avl_tree edge_tree; /* subtree for edges */ ++ struct olsrd_avl_tree prefix_tree; /* subtree for prefixes */ + struct link_entry *next_hop; /* SPF calculated link to the 1st hop neighbor */ + struct timer_entry *edge_gc_timer; /* used for edge garbage collection */ + struct timer_entry *validity_timer; /* tc validity time */ +@@ -102,8 +102,8 @@ struct tc_entry { + + #define OLSR_TC_VTIME_JITTER 5 /* percent */ + +-AVLNODE2STRUCT(vertex_tree2tc, struct tc_entry, vertex_node); +-AVLNODE2STRUCT(cand_tree2tc, struct tc_entry, cand_tree_node); ++OLSRD_AVLNODE2STRUCT(vertex_tree2tc, struct tc_entry, vertex_node); ++OLSRD_AVLNODE2STRUCT(cand_tree2tc, struct tc_entry, cand_tree_node); + LISTNODE2STRUCT(pathlist2tc, struct tc_entry, path_list_node); + + /* +@@ -116,32 +116,32 @@ LISTNODE2STRUCT(pathlist2tc, struct tc_e + */ + #define OLSR_FOR_ALL_TC_ENTRIES(tc) \ + { \ +- struct avl_node *tc_tree_node, *next_tc_tree_node; \ +- for (tc_tree_node = avl_walk_first(&tc_tree); \ ++ struct olsrd_avl_node *tc_tree_node, *next_tc_tree_node; \ ++ for (tc_tree_node = olsrd_avl_walk_first(&tc_tree); \ + tc_tree_node; tc_tree_node = next_tc_tree_node) { \ +- next_tc_tree_node = avl_walk_next(tc_tree_node); \ ++ next_tc_tree_node = olsrd_avl_walk_next(tc_tree_node); \ + tc = vertex_tree2tc(tc_tree_node); + #define OLSR_FOR_ALL_TC_ENTRIES_END(tc) }} + + #define OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) \ + { \ +- struct avl_node *tc_edge_node, *next_tc_edge_node; \ +- for (tc_edge_node = avl_walk_first(&tc->edge_tree); \ ++ struct olsrd_avl_node *tc_edge_node, *next_tc_edge_node; \ ++ for (tc_edge_node = olsrd_avl_walk_first(&tc->edge_tree); \ + tc_edge_node; tc_edge_node = next_tc_edge_node) { \ +- next_tc_edge_node = avl_walk_next(tc_edge_node); \ ++ next_tc_edge_node = olsrd_avl_walk_next(tc_edge_node); \ + tc_edge = edge_tree2tc_edge(tc_edge_node); + #define OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge) }} + + #define OLSR_FOR_ALL_PREFIX_ENTRIES(tc, rtp) \ + { \ +- struct avl_node *rtp_node, *next_rtp_node; \ +- for (rtp_node = avl_walk_first(&tc->prefix_tree); \ ++ struct olsrd_avl_node *rtp_node, *next_rtp_node; \ ++ for (rtp_node = olsrd_avl_walk_first(&tc->prefix_tree); \ + rtp_node; rtp_node = next_rtp_node) { \ +- next_rtp_node = avl_walk_next(rtp_node); \ ++ next_rtp_node = olsrd_avl_walk_next(rtp_node); \ + rtp = rtp_prefix_tree2rtp(rtp_node); + #define OLSR_FOR_ALL_PREFIX_ENTRIES_END(tc, rtp) }} + +-extern struct avl_tree tc_tree; ++extern struct olsrd_avl_tree tc_tree; + extern struct tc_entry *tc_myself; + + void olsr_init_tc(void); diff --git a/olsrd/patches/101-unix-fix-meshing-with-wireguard-point-to-point-interfaces.patch b/olsrd/patches/101-unix-fix-meshing-with-wireguard-point-to-point-interfaces.patch new file mode 100644 index 0000000..caca877 --- /dev/null +++ b/olsrd/patches/101-unix-fix-meshing-with-wireguard-point-to-point-interfaces.patch @@ -0,0 +1,38 @@ +From fcb30aa4da732d279527feba01cacc7dc996d137 Mon Sep 17 00:00:00 2001 +From: Nick Hainke +Date: Sun, 16 Jan 2022 00:08:56 +0100 +Subject: [PATCH] unix: fix meshing with wireguard/point-to-point interfaces + +Wireguard interfaces have no BROADCAST flag. We can also mesh on +point-to-point links. That is why we mesh now also on interfaces with +the IFF_POINTOPOINT flag enabled. + +Signed-off-by: Nick Hainke +--- + src/unix/ifnet.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/src/unix/ifnet.c ++++ b/src/unix/ifnet.c +@@ -184,8 +184,8 @@ chk_if_changed(struct olsr_if *iface) + + /* Check broadcast */ + if ((olsr_cnf->ip_version == AF_INET) && !iface->cnf->ipv4_multicast.v4.s_addr && /* Skip if fixed bcast */ +- (!(ifp->int_flags & IFF_BROADCAST))) { +- OLSR_PRINTF(3, "\tNo broadcast - removing\n"); ++ ((!(ifp->int_flags & IFF_BROADCAST) && !(ifp->int_flags & IFF_POINTOPOINT)))) { ++ OLSR_PRINTF(3, "\tNo broadcast or point-to-point - removing\n"); + goto remove_interface; + } + +@@ -552,8 +552,8 @@ chk_if_up(struct olsr_if *iface, int deb + + /* Check broadcast */ + if ((olsr_cnf->ip_version == AF_INET) && !iface->cnf->ipv4_multicast.v4.s_addr && /* Skip if fixed bcast */ +- (!(ifs.int_flags & IFF_BROADCAST))) { +- OLSR_PRINTF(debuglvl, "\tNo broadcast - skipping\n"); ++ (!(ifs.int_flags & IFF_BROADCAST) && !(ifs.int_flags & IFF_POINTOPOINT))) { ++ OLSR_PRINTF(debuglvl, "\tNo broadcast or point-to-point - skipping\n"); + return 0; + } + diff --git a/olsrd/patches/600-add-ubus-support.patch b/olsrd/patches/600-add-ubus-support.patch new file mode 100644 index 0000000..c43e78d --- /dev/null +++ b/olsrd/patches/600-add-ubus-support.patch @@ -0,0 +1,60 @@ +--- a/src/scheduler.c ++++ b/src/scheduler.c +@@ -59,6 +59,8 @@ + #include + #include + ++#include "ubus.h" ++ + #ifdef __MACH__ + #include "mach/clock_gettime.h" + #endif +@@ -363,6 +365,8 @@ poll_sockets(void) + } + OLSR_FOR_ALL_SOCKETS_END(entry); + ++ hfd = olsrd_ubus_add_read_sock(&ibits, hfd); ++ + /* Running select on the FD set */ + do { + n = olsr_select(hfd, fdsets & SP_PR_READ ? &ibits : NULL, fdsets & SP_PR_WRITE ? &obits : NULL, NULL, &tvp); +@@ -395,6 +399,7 @@ poll_sockets(void) + } + } + OLSR_FOR_ALL_SOCKETS_END(entry); ++ olsrd_ubus_receive(&ibits); + } + + static void +--- a/src/main.c ++++ b/src/main.c +@@ -74,6 +74,8 @@ + #include "lock_file.h" + #include "cli.h" + ++#include "ubus.h" ++ + #if defined(__GLIBC__) && defined(__linux__) && !defined(__ANDROID__) && !defined(__UCLIBC__) + #define OLSR_HAVE_EXECINFO_H + #endif +@@ -771,6 +773,9 @@ int main(int argc, char *argv[]) { + signal(SIGUSR2, SIG_IGN); + #endif /* _WIN32 */ + ++ /* Adding ubus */ ++ olsrd_add_ubus(); ++ + /* Starting scheduler */ + olsr_scheduler(); + +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -252,7 +252,7 @@ else + ifeq ($(OS),win32) + LDFLAGS += -Wl,-export-all-symbols + else +- LDFLAGS += -Wl,-export-dynamic ++ LDFLAGS += -Wl,-export-dynamic,-lubus,-lubox + endif + ifeq ($(NORPATH),0) + LDFLAGS += -Wl,-rpath,$(LIBDIR) diff --git a/olsrd/src/src/ubus.c b/olsrd/src/src/ubus.c new file mode 100644 index 0000000..d344dc3 --- /dev/null +++ b/olsrd/src/src/ubus.c @@ -0,0 +1,210 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ifnet.h" +#include "interfaces.h" +#include "log.h" +#include "olsr.h" +#include "olsr_cfg.h" + +#include "ubus.h" + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +// Shared state maintained throughout calls to handle ubus messages. +static struct ubus_context *shared_ctx; + +enum { INTERFACE_IFNAME, __INTERFACE_MAX }; + +static const struct blobmsg_policy interface_policy[__INTERFACE_MAX] = { + [INTERFACE_IFNAME] = {"ifname", BLOBMSG_TYPE_STRING}, +}; + +static int olsrd_ubus_add_interface(struct ubus_context *ctx_local, + struct ubus_object *obj, + struct ubus_request_data *req, + const char *method, struct blob_attr *msg) { + struct blob_attr *tb[__INTERFACE_MAX]; + struct blob_buf b = {0}; + int ret; + char *ifname; + + blobmsg_parse(interface_policy, __INTERFACE_MAX, tb, blob_data(msg), + blob_len(msg)); + + if (!tb[INTERFACE_IFNAME]) + return UBUS_STATUS_INVALID_ARGUMENT; + + ifname = blobmsg_get_string(tb[INTERFACE_IFNAME]); + + struct interface_olsr *tmp = if_ifwithname(ifname); + if (tmp != NULL) { + return UBUS_STATUS_PERMISSION_DENIED; + } + + struct olsr_if *temp; + for (temp = olsr_cnf->interfaces; temp != NULL; temp = temp->next) { + if (strcmp(temp->name, ifname) == 0) + return UBUS_STATUS_PERMISSION_DENIED; + } + + struct olsr_if *tmp_ifs = olsr_create_olsrif(ifname, false); + struct if_config_options *default_ifcnf = get_default_if_config(); + tmp_ifs->cnf = default_ifcnf; + + blob_buf_init(&b, 0); + blobmsg_add_string(&b, "adding", ifname); + + ret = ubus_send_reply(ctx_local, req, b.head); + if (ret) + olsr_syslog(OLSR_LOG_ERR, "Failed to send reply: %s\n", + ubus_strerror(ret)); + + blob_buf_free(&b); + + return ret; +} + +static int olsrd_ubus_del_interface(struct ubus_context *ctx_local, + struct ubus_object *obj, + struct ubus_request_data *req, + const char *method, struct blob_attr *msg) { + struct blob_attr *tb[__INTERFACE_MAX]; + struct blob_buf b = {0}; + int ret; + char *ifname; + struct olsr_if *tmp_if, *del_if; + + blobmsg_parse(interface_policy, __INTERFACE_MAX, tb, blob_data(msg), + blob_len(msg)); + + if (!tb[INTERFACE_IFNAME]) + return UBUS_STATUS_INVALID_ARGUMENT; + + ifname = blobmsg_get_string(tb[INTERFACE_IFNAME]); + + struct interface_olsr *tmp = if_ifwithname(ifname); + + if (tmp != NULL) { + + struct olsr_if *temp = olsr_cnf->interfaces, *prev; + if (temp != NULL && (strcmp(temp->name, ifname) == 0)) { + olsr_cnf->interfaces = temp->next; + olsr_remove_interface(temp); + goto send_reply; + } + + while (temp != NULL && (strcmp(temp->name, ifname) != 0)) { + prev = temp; + temp = temp->next; + } + + if (temp == NULL) { + goto send_reply; + } + + prev->next = temp->next; + olsr_remove_interface(temp); + } else { + return UBUS_STATUS_PERMISSION_DENIED; + } + +send_reply: + + blob_buf_init(&b, 0); + blobmsg_add_string(&b, "deleting", ifname); + + ret = ubus_send_reply(ctx_local, req, b.head); + if (ret) + olsr_syslog(OLSR_LOG_ERR, "Failed to send reply: %s\n", + ubus_strerror(ret)); + + blob_buf_free(&b); + + return ret; +} + +// List of functions we expose via the ubus bus. +static const struct ubus_method olsrd_methods[] = { + UBUS_METHOD("add_interface", olsrd_ubus_add_interface, interface_policy), + UBUS_METHOD("del_interface", olsrd_ubus_del_interface, interface_policy), +}; + +// Definition of the ubus object type. +static struct ubus_object_type olsrd_object_type = + UBUS_OBJECT_TYPE("olsrd", olsrd_methods); + +// Object we announce via the ubus bus. +static struct ubus_object olsrd_object = { + .name = "olsrd", + .type = &olsrd_object_type, + .methods = olsrd_methods, + .n_methods = ARRAY_SIZE(olsrd_methods), +}; + +// Registers handlers for olsrd methods in the global ubus context. +static bool ubus_init_object() { + int ret; + + ret = ubus_add_object(shared_ctx, &olsrd_object); + if (ret) { + olsr_syslog(OLSR_LOG_ERR, "Failed to add object: %s\n", + ubus_strerror(ret)); + return false; + } + + return true; +} + +// Initializes the global ubus context, connecting to the bus to be able to +// receive and send messages. +static bool olsrd_ubus_init(void) { + if (shared_ctx) + return true; + + shared_ctx = ubus_connect(NULL); + if (!shared_ctx) + return false; + + return true; +} + +void olsrd_ubus_receive(fd_set *readfds) { + if (!shared_ctx) + return; + if (FD_ISSET(shared_ctx->sock.fd, readfds)) + ubus_handle_event(shared_ctx); +} + +int olsrd_ubus_add_read_sock(fd_set *readfds, int maxfd) { + if (!shared_ctx) + return maxfd; + + FD_SET(shared_ctx->sock.fd, readfds); + return MAX(maxfd, shared_ctx->sock.fd + 1); +} + +bool olsrd_add_ubus() { + if (!olsrd_ubus_init()) { + olsr_syslog(OLSR_LOG_ERR, "Failed to initialize ubus!\n"); + return false; + } + if (!ubus_init_object()) { + olsr_syslog(OLSR_LOG_ERR, "Failed to add objects to ubus!\n"); + return false; + } + return true; +} diff --git a/olsrd/src/src/ubus.h b/olsrd/src/src/ubus.h new file mode 100644 index 0000000..d47c98b --- /dev/null +++ b/olsrd/src/src/ubus.h @@ -0,0 +1,40 @@ +/* + IPC integration of olsrd with OpenWrt. + + The ubus interface offers following functions: + - add_inteface '{"ifname":"wg_51820"}' + - del_inteface '{"ifname":"wg_51820"}' +*/ + +#include +#include + +/** + * Initialize ubus interface. + * + * Connect to the ubus daemon and expose the ubus functions. + * + * @return if initializing ubus was successful + */ +bool olsrd_add_ubus(); + +/** + * Add ubus socket to given filedescriptor set. + * + * We need to check repeatedly if the ubus socket has something to read. + * The functions allows to add the ubus socket to the normal while(1)-loop of + * olsrd. + * + * @param readfs: the filedescriptor set + * @param maxfd: the current maximum file descriptor + * @return the maximum file descriptor + */ +int olsrd_ubus_add_read_sock(fd_set *readfds, int maxfd); + +/** + * Check and process ubus socket. + * + * If the ubus-socket signals that data is available, the ubus_handle_event is + * called. + */ +void olsrd_ubus_receive(fd_set *readfds);