1*65b390aaSDag-Erling Smørgrav /* 2*65b390aaSDag-Erling Smørgrav * edns-subnet/addrtree.c -- radix tree for edns subnet cache. 3*65b390aaSDag-Erling Smørgrav * 4*65b390aaSDag-Erling Smørgrav * Copyright (c) 2013, NLnet Labs. All rights reserved. 5*65b390aaSDag-Erling Smørgrav * 6*65b390aaSDag-Erling Smørgrav * This software is open source. 7*65b390aaSDag-Erling Smørgrav * 8*65b390aaSDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 9*65b390aaSDag-Erling Smørgrav * modification, are permitted provided that the following conditions 10*65b390aaSDag-Erling Smørgrav * are met: 11*65b390aaSDag-Erling Smørgrav * 12*65b390aaSDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice, 13*65b390aaSDag-Erling Smørgrav * this list of conditions and the following disclaimer. 14*65b390aaSDag-Erling Smørgrav * 15*65b390aaSDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice, 16*65b390aaSDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation 17*65b390aaSDag-Erling Smørgrav * and/or other materials provided with the distribution. 18*65b390aaSDag-Erling Smørgrav * 19*65b390aaSDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may 20*65b390aaSDag-Erling Smørgrav * be used to endorse or promote products derived from this software without 21*65b390aaSDag-Erling Smørgrav * specific prior written permission. 22*65b390aaSDag-Erling Smørgrav * 23*65b390aaSDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24*65b390aaSDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25*65b390aaSDag-Erling Smørgrav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26*65b390aaSDag-Erling Smørgrav * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27*65b390aaSDag-Erling Smørgrav * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28*65b390aaSDag-Erling Smørgrav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29*65b390aaSDag-Erling Smørgrav * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30*65b390aaSDag-Erling Smørgrav * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31*65b390aaSDag-Erling Smørgrav * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32*65b390aaSDag-Erling Smørgrav * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33*65b390aaSDag-Erling Smørgrav * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34*65b390aaSDag-Erling Smørgrav */ 35*65b390aaSDag-Erling Smørgrav /** \file 36*65b390aaSDag-Erling Smørgrav * addrtree -- radix tree for edns subnet cache. 37*65b390aaSDag-Erling Smørgrav */ 38*65b390aaSDag-Erling Smørgrav 39*65b390aaSDag-Erling Smørgrav #include "config.h" 40*65b390aaSDag-Erling Smørgrav #include "util/log.h" 41*65b390aaSDag-Erling Smørgrav #include "util/data/msgreply.h" 42*65b390aaSDag-Erling Smørgrav #include "util/module.h" 43*65b390aaSDag-Erling Smørgrav #include "addrtree.h" 44*65b390aaSDag-Erling Smørgrav 45*65b390aaSDag-Erling Smørgrav /** 46*65b390aaSDag-Erling Smørgrav * Create a new edge 47*65b390aaSDag-Erling Smørgrav * @param node: Child node this edge will connect to. 48*65b390aaSDag-Erling Smørgrav * @param addr: full key to this edge. 49*65b390aaSDag-Erling Smørgrav * @param addrlen: length of relevant part of key for this node 50*65b390aaSDag-Erling Smørgrav * @param parent_node: Parent node for node 51*65b390aaSDag-Erling Smørgrav * @param parent_index: Index of child node at parent node 52*65b390aaSDag-Erling Smørgrav * @return new addredge or NULL on failure 53*65b390aaSDag-Erling Smørgrav */ 54*65b390aaSDag-Erling Smørgrav static struct addredge * 55*65b390aaSDag-Erling Smørgrav edge_create(struct addrnode *node, const addrkey_t *addr, 56*65b390aaSDag-Erling Smørgrav addrlen_t addrlen, struct addrnode *parent_node, int parent_index) 57*65b390aaSDag-Erling Smørgrav { 58*65b390aaSDag-Erling Smørgrav size_t n; 59*65b390aaSDag-Erling Smørgrav struct addredge *edge = (struct addredge *)malloc( sizeof (*edge) ); 60*65b390aaSDag-Erling Smørgrav if (!edge) 61*65b390aaSDag-Erling Smørgrav return NULL; 62*65b390aaSDag-Erling Smørgrav edge->node = node; 63*65b390aaSDag-Erling Smørgrav edge->len = addrlen; 64*65b390aaSDag-Erling Smørgrav edge->parent_index = parent_index; 65*65b390aaSDag-Erling Smørgrav edge->parent_node = parent_node; 66*65b390aaSDag-Erling Smørgrav /* ceil() */ 67*65b390aaSDag-Erling Smørgrav n = (size_t)((addrlen / KEYWIDTH) + ((addrlen % KEYWIDTH != 0)?1:0)); 68*65b390aaSDag-Erling Smørgrav edge->str = (addrkey_t *)calloc(n, sizeof (addrkey_t)); 69*65b390aaSDag-Erling Smørgrav if (!edge->str) { 70*65b390aaSDag-Erling Smørgrav free(edge); 71*65b390aaSDag-Erling Smørgrav return NULL; 72*65b390aaSDag-Erling Smørgrav } 73*65b390aaSDag-Erling Smørgrav memcpy(edge->str, addr, n * sizeof (addrkey_t)); 74*65b390aaSDag-Erling Smørgrav /* Only manipulate other objects after successful alloc */ 75*65b390aaSDag-Erling Smørgrav node->parent_edge = edge; 76*65b390aaSDag-Erling Smørgrav log_assert(parent_node->edge[parent_index] == NULL); 77*65b390aaSDag-Erling Smørgrav parent_node->edge[parent_index] = edge; 78*65b390aaSDag-Erling Smørgrav return edge; 79*65b390aaSDag-Erling Smørgrav } 80*65b390aaSDag-Erling Smørgrav 81*65b390aaSDag-Erling Smørgrav /** 82*65b390aaSDag-Erling Smørgrav * Create a new node 83*65b390aaSDag-Erling Smørgrav * @param tree: Tree the node lives in. 84*65b390aaSDag-Erling Smørgrav * @param elem: Element to store at this node 85*65b390aaSDag-Erling Smørgrav * @param scope: Scopemask from server reply 86*65b390aaSDag-Erling Smørgrav * @param ttl: Element is valid up to this time. Absolute, seconds 87*65b390aaSDag-Erling Smørgrav * @return new addrnode or NULL on failure 88*65b390aaSDag-Erling Smørgrav */ 89*65b390aaSDag-Erling Smørgrav static struct addrnode * 90*65b390aaSDag-Erling Smørgrav node_create(struct addrtree *tree, void *elem, addrlen_t scope, 91*65b390aaSDag-Erling Smørgrav time_t ttl) 92*65b390aaSDag-Erling Smørgrav { 93*65b390aaSDag-Erling Smørgrav struct addrnode* node = (struct addrnode *)malloc( sizeof (*node) ); 94*65b390aaSDag-Erling Smørgrav if (!node) 95*65b390aaSDag-Erling Smørgrav return NULL; 96*65b390aaSDag-Erling Smørgrav node->elem = elem; 97*65b390aaSDag-Erling Smørgrav tree->node_count++; 98*65b390aaSDag-Erling Smørgrav node->scope = scope; 99*65b390aaSDag-Erling Smørgrav node->ttl = ttl; 100*65b390aaSDag-Erling Smørgrav node->edge[0] = NULL; 101*65b390aaSDag-Erling Smørgrav node->edge[1] = NULL; 102*65b390aaSDag-Erling Smørgrav node->parent_edge = NULL; 103*65b390aaSDag-Erling Smørgrav node->next = NULL; 104*65b390aaSDag-Erling Smørgrav node->prev = NULL; 105*65b390aaSDag-Erling Smørgrav return node; 106*65b390aaSDag-Erling Smørgrav } 107*65b390aaSDag-Erling Smørgrav 108*65b390aaSDag-Erling Smørgrav /** Size in bytes of node and parent edge 109*65b390aaSDag-Erling Smørgrav * @param tree: tree the node lives in 110*65b390aaSDag-Erling Smørgrav * @param n: node which size must be calculated 111*65b390aaSDag-Erling Smørgrav * @return size in bytes. 112*65b390aaSDag-Erling Smørgrav **/ 113*65b390aaSDag-Erling Smørgrav static inline size_t 114*65b390aaSDag-Erling Smørgrav node_size(const struct addrtree *tree, const struct addrnode *n) 115*65b390aaSDag-Erling Smørgrav { 116*65b390aaSDag-Erling Smørgrav return sizeof *n + sizeof *n->parent_edge + n->parent_edge->len + 117*65b390aaSDag-Erling Smørgrav (n->elem?tree->sizefunc(n->elem):0); 118*65b390aaSDag-Erling Smørgrav } 119*65b390aaSDag-Erling Smørgrav 120*65b390aaSDag-Erling Smørgrav struct addrtree * 121*65b390aaSDag-Erling Smørgrav addrtree_create(addrlen_t max_depth, void (*delfunc)(void *, void *), 122*65b390aaSDag-Erling Smørgrav size_t (*sizefunc)(void *), void *env, unsigned int max_node_count) 123*65b390aaSDag-Erling Smørgrav { 124*65b390aaSDag-Erling Smørgrav struct addrtree *tree; 125*65b390aaSDag-Erling Smørgrav log_assert(delfunc != NULL); 126*65b390aaSDag-Erling Smørgrav log_assert(sizefunc != NULL); 127*65b390aaSDag-Erling Smørgrav tree = (struct addrtree *)calloc(1, sizeof(*tree)); 128*65b390aaSDag-Erling Smørgrav if (!tree) 129*65b390aaSDag-Erling Smørgrav return NULL; 130*65b390aaSDag-Erling Smørgrav tree->root = node_create(tree, NULL, 0, 0); 131*65b390aaSDag-Erling Smørgrav if (!tree->root) { 132*65b390aaSDag-Erling Smørgrav free(tree); 133*65b390aaSDag-Erling Smørgrav return NULL; 134*65b390aaSDag-Erling Smørgrav } 135*65b390aaSDag-Erling Smørgrav tree->size_bytes = sizeof *tree + sizeof *tree->root; 136*65b390aaSDag-Erling Smørgrav tree->first = NULL; 137*65b390aaSDag-Erling Smørgrav tree->last = NULL; 138*65b390aaSDag-Erling Smørgrav tree->max_depth = max_depth; 139*65b390aaSDag-Erling Smørgrav tree->delfunc = delfunc; 140*65b390aaSDag-Erling Smørgrav tree->sizefunc = sizefunc; 141*65b390aaSDag-Erling Smørgrav tree->env = env; 142*65b390aaSDag-Erling Smørgrav tree->node_count = 0; 143*65b390aaSDag-Erling Smørgrav tree->max_node_count = max_node_count; 144*65b390aaSDag-Erling Smørgrav return tree; 145*65b390aaSDag-Erling Smørgrav } 146*65b390aaSDag-Erling Smørgrav 147*65b390aaSDag-Erling Smørgrav /** 148*65b390aaSDag-Erling Smørgrav * Scrub a node clean of elem 149*65b390aaSDag-Erling Smørgrav * @param tree: tree the node lives in. 150*65b390aaSDag-Erling Smørgrav * @param node: node to be cleaned. 151*65b390aaSDag-Erling Smørgrav */ 152*65b390aaSDag-Erling Smørgrav static void 153*65b390aaSDag-Erling Smørgrav clean_node(struct addrtree *tree, struct addrnode *node) 154*65b390aaSDag-Erling Smørgrav { 155*65b390aaSDag-Erling Smørgrav if (!node->elem) return; 156*65b390aaSDag-Erling Smørgrav tree->size_bytes -= tree->sizefunc(node->elem); 157*65b390aaSDag-Erling Smørgrav tree->delfunc(tree->env, node->elem); 158*65b390aaSDag-Erling Smørgrav node->elem = NULL; 159*65b390aaSDag-Erling Smørgrav } 160*65b390aaSDag-Erling Smørgrav 161*65b390aaSDag-Erling Smørgrav /** Remove specified node from LRU list */ 162*65b390aaSDag-Erling Smørgrav static void 163*65b390aaSDag-Erling Smørgrav lru_pop(struct addrtree *tree, struct addrnode *node) 164*65b390aaSDag-Erling Smørgrav { 165*65b390aaSDag-Erling Smørgrav if (node == tree->first) { 166*65b390aaSDag-Erling Smørgrav if (!node->next) { /* it is the last as well */ 167*65b390aaSDag-Erling Smørgrav tree->first = NULL; 168*65b390aaSDag-Erling Smørgrav tree->last = NULL; 169*65b390aaSDag-Erling Smørgrav } else { 170*65b390aaSDag-Erling Smørgrav tree->first = node->next; 171*65b390aaSDag-Erling Smørgrav tree->first->prev = NULL; 172*65b390aaSDag-Erling Smørgrav } 173*65b390aaSDag-Erling Smørgrav } else if (node == tree->last) { /* but not the first */ 174*65b390aaSDag-Erling Smørgrav tree->last = node->prev; 175*65b390aaSDag-Erling Smørgrav tree->last->next = NULL; 176*65b390aaSDag-Erling Smørgrav } else { 177*65b390aaSDag-Erling Smørgrav node->prev->next = node->next; 178*65b390aaSDag-Erling Smørgrav node->next->prev = node->prev; 179*65b390aaSDag-Erling Smørgrav } 180*65b390aaSDag-Erling Smørgrav } 181*65b390aaSDag-Erling Smørgrav 182*65b390aaSDag-Erling Smørgrav /** Add node to LRU list as most recently used. */ 183*65b390aaSDag-Erling Smørgrav static void 184*65b390aaSDag-Erling Smørgrav lru_push(struct addrtree *tree, struct addrnode *node) 185*65b390aaSDag-Erling Smørgrav { 186*65b390aaSDag-Erling Smørgrav if (!tree->first) { 187*65b390aaSDag-Erling Smørgrav tree->first = node; 188*65b390aaSDag-Erling Smørgrav node->prev = NULL; 189*65b390aaSDag-Erling Smørgrav } else { 190*65b390aaSDag-Erling Smørgrav tree->last->next = node; 191*65b390aaSDag-Erling Smørgrav node->prev = tree->last; 192*65b390aaSDag-Erling Smørgrav } 193*65b390aaSDag-Erling Smørgrav tree->last = node; 194*65b390aaSDag-Erling Smørgrav node->next = NULL; 195*65b390aaSDag-Erling Smørgrav } 196*65b390aaSDag-Erling Smørgrav 197*65b390aaSDag-Erling Smørgrav /** Move node to the end of LRU list */ 198*65b390aaSDag-Erling Smørgrav static void 199*65b390aaSDag-Erling Smørgrav lru_update(struct addrtree *tree, struct addrnode *node) 200*65b390aaSDag-Erling Smørgrav { 201*65b390aaSDag-Erling Smørgrav if (tree->root == node) return; 202*65b390aaSDag-Erling Smørgrav lru_pop(tree, node); 203*65b390aaSDag-Erling Smørgrav lru_push(tree, node); 204*65b390aaSDag-Erling Smørgrav } 205*65b390aaSDag-Erling Smørgrav 206*65b390aaSDag-Erling Smørgrav /** 207*65b390aaSDag-Erling Smørgrav * Purge a node from the tree. Node and parentedge are cleaned and 208*65b390aaSDag-Erling Smørgrav * free'd. 209*65b390aaSDag-Erling Smørgrav * @param tree: Tree the node lives in. 210*65b390aaSDag-Erling Smørgrav * @param node: Node to be freed 211*65b390aaSDag-Erling Smørgrav */ 212*65b390aaSDag-Erling Smørgrav static void 213*65b390aaSDag-Erling Smørgrav purge_node(struct addrtree *tree, struct addrnode *node) 214*65b390aaSDag-Erling Smørgrav { 215*65b390aaSDag-Erling Smørgrav struct addredge *parent_edge, *child_edge = NULL; 216*65b390aaSDag-Erling Smørgrav int index; 217*65b390aaSDag-Erling Smørgrav int keep = node->edge[0] && node->edge[1]; 218*65b390aaSDag-Erling Smørgrav 219*65b390aaSDag-Erling Smørgrav clean_node(tree, node); 220*65b390aaSDag-Erling Smørgrav parent_edge = node->parent_edge; 221*65b390aaSDag-Erling Smørgrav if (keep || !parent_edge) return; 222*65b390aaSDag-Erling Smørgrav tree->node_count--; 223*65b390aaSDag-Erling Smørgrav index = parent_edge->parent_index; 224*65b390aaSDag-Erling Smørgrav child_edge = node->edge[!node->edge[0]]; 225*65b390aaSDag-Erling Smørgrav if (child_edge) { 226*65b390aaSDag-Erling Smørgrav child_edge->parent_node = parent_edge->parent_node; 227*65b390aaSDag-Erling Smørgrav child_edge->parent_index = index; 228*65b390aaSDag-Erling Smørgrav } 229*65b390aaSDag-Erling Smørgrav parent_edge->parent_node->edge[index] = child_edge; 230*65b390aaSDag-Erling Smørgrav tree->size_bytes -= node_size(tree, node); 231*65b390aaSDag-Erling Smørgrav free(parent_edge->str); 232*65b390aaSDag-Erling Smørgrav free(parent_edge); 233*65b390aaSDag-Erling Smørgrav lru_pop(tree, node); 234*65b390aaSDag-Erling Smørgrav free(node); 235*65b390aaSDag-Erling Smørgrav } 236*65b390aaSDag-Erling Smørgrav 237*65b390aaSDag-Erling Smørgrav /** 238*65b390aaSDag-Erling Smørgrav * If a limit is set remove old nodes while above that limit. 239*65b390aaSDag-Erling Smørgrav * @param tree: Tree to be cleaned up. 240*65b390aaSDag-Erling Smørgrav */ 241*65b390aaSDag-Erling Smørgrav static void 242*65b390aaSDag-Erling Smørgrav lru_cleanup(struct addrtree *tree) 243*65b390aaSDag-Erling Smørgrav { 244*65b390aaSDag-Erling Smørgrav struct addrnode *n, *p; 245*65b390aaSDag-Erling Smørgrav int children; 246*65b390aaSDag-Erling Smørgrav if (tree->max_node_count == 0) return; 247*65b390aaSDag-Erling Smørgrav while (tree->node_count > tree->max_node_count) { 248*65b390aaSDag-Erling Smørgrav n = tree->first; 249*65b390aaSDag-Erling Smørgrav if (!n) break; 250*65b390aaSDag-Erling Smørgrav children = (n->edge[0] != NULL) + (n->edge[1] != NULL); 251*65b390aaSDag-Erling Smørgrav /** Don't remove this node, it is either the root or we can't 252*65b390aaSDag-Erling Smørgrav * do without it because it has 2 children */ 253*65b390aaSDag-Erling Smørgrav if (children == 2 || !n->parent_edge) { 254*65b390aaSDag-Erling Smørgrav lru_update(tree, n); 255*65b390aaSDag-Erling Smørgrav continue; 256*65b390aaSDag-Erling Smørgrav } 257*65b390aaSDag-Erling Smørgrav p = n->parent_edge->parent_node; 258*65b390aaSDag-Erling Smørgrav purge_node(tree, n); 259*65b390aaSDag-Erling Smørgrav /** Since we removed n, n's parent p is eligible for deletion 260*65b390aaSDag-Erling Smørgrav * if it is not the root node, caries no data and has only 1 261*65b390aaSDag-Erling Smørgrav * child */ 262*65b390aaSDag-Erling Smørgrav children = (p->edge[0] != NULL) + (p->edge[1] != NULL); 263*65b390aaSDag-Erling Smørgrav if (!p->elem && children == 1 && p->parent_edge) { 264*65b390aaSDag-Erling Smørgrav purge_node(tree, p); 265*65b390aaSDag-Erling Smørgrav } 266*65b390aaSDag-Erling Smørgrav } 267*65b390aaSDag-Erling Smørgrav } 268*65b390aaSDag-Erling Smørgrav 269*65b390aaSDag-Erling Smørgrav inline size_t 270*65b390aaSDag-Erling Smørgrav addrtree_size(const struct addrtree *tree) 271*65b390aaSDag-Erling Smørgrav { 272*65b390aaSDag-Erling Smørgrav return tree?tree->size_bytes:0; 273*65b390aaSDag-Erling Smørgrav } 274*65b390aaSDag-Erling Smørgrav 275*65b390aaSDag-Erling Smørgrav void addrtree_delete(struct addrtree *tree) 276*65b390aaSDag-Erling Smørgrav { 277*65b390aaSDag-Erling Smørgrav struct addrnode *n; 278*65b390aaSDag-Erling Smørgrav if (!tree) return; 279*65b390aaSDag-Erling Smørgrav clean_node(tree, tree->root); 280*65b390aaSDag-Erling Smørgrav free(tree->root); 281*65b390aaSDag-Erling Smørgrav tree->size_bytes -= sizeof(struct addrnode); 282*65b390aaSDag-Erling Smørgrav while ((n = tree->first)) { 283*65b390aaSDag-Erling Smørgrav tree->first = n->next; 284*65b390aaSDag-Erling Smørgrav clean_node(tree, n); 285*65b390aaSDag-Erling Smørgrav tree->size_bytes -= node_size(tree, n); 286*65b390aaSDag-Erling Smørgrav free(n->parent_edge->str); 287*65b390aaSDag-Erling Smørgrav free(n->parent_edge); 288*65b390aaSDag-Erling Smørgrav free(n); 289*65b390aaSDag-Erling Smørgrav } 290*65b390aaSDag-Erling Smørgrav log_assert(sizeof *tree == addrtree_size(tree)); 291*65b390aaSDag-Erling Smørgrav free(tree); 292*65b390aaSDag-Erling Smørgrav } 293*65b390aaSDag-Erling Smørgrav 294*65b390aaSDag-Erling Smørgrav /** 295*65b390aaSDag-Erling Smørgrav * Get N'th bit from address 296*65b390aaSDag-Erling Smørgrav * @param addr: address to inspect 297*65b390aaSDag-Erling Smørgrav * @param addrlen: length of addr in bits 298*65b390aaSDag-Erling Smørgrav * @param n: index of bit to test. Must be in range [0, addrlen) 299*65b390aaSDag-Erling Smørgrav * @return 0 or 1 300*65b390aaSDag-Erling Smørgrav */ 301*65b390aaSDag-Erling Smørgrav static int 302*65b390aaSDag-Erling Smørgrav getbit(const addrkey_t *addr, addrlen_t addrlen, addrlen_t n) 303*65b390aaSDag-Erling Smørgrav { 304*65b390aaSDag-Erling Smørgrav log_assert(addrlen > n); 305*65b390aaSDag-Erling Smørgrav return (int)(addr[n/KEYWIDTH]>>((KEYWIDTH-1)-(n%KEYWIDTH))) & 1; 306*65b390aaSDag-Erling Smørgrav } 307*65b390aaSDag-Erling Smørgrav 308*65b390aaSDag-Erling Smørgrav /** 309*65b390aaSDag-Erling Smørgrav * Test for equality on N'th bit. 310*65b390aaSDag-Erling Smørgrav * @return 0 for equal, 1 otherwise 311*65b390aaSDag-Erling Smørgrav */ 312*65b390aaSDag-Erling Smørgrav static inline int 313*65b390aaSDag-Erling Smørgrav cmpbit(const addrkey_t *key1, const addrkey_t *key2, addrlen_t n) 314*65b390aaSDag-Erling Smørgrav { 315*65b390aaSDag-Erling Smørgrav addrkey_t c = key1[n/KEYWIDTH] ^ key2[n/KEYWIDTH]; 316*65b390aaSDag-Erling Smørgrav return (int)(c >> ((KEYWIDTH-1)-(n%KEYWIDTH))) & 1; 317*65b390aaSDag-Erling Smørgrav } 318*65b390aaSDag-Erling Smørgrav 319*65b390aaSDag-Erling Smørgrav /** 320*65b390aaSDag-Erling Smørgrav * Common number of bits in prefix. 321*65b390aaSDag-Erling Smørgrav * @param s1: first prefix. 322*65b390aaSDag-Erling Smørgrav * @param l1: length of s1 in bits. 323*65b390aaSDag-Erling Smørgrav * @param s2: second prefix. 324*65b390aaSDag-Erling Smørgrav * @param l2: length of s2 in bits. 325*65b390aaSDag-Erling Smørgrav * @param skip: nr of bits already checked. 326*65b390aaSDag-Erling Smørgrav * @return common number of bits. 327*65b390aaSDag-Erling Smørgrav */ 328*65b390aaSDag-Erling Smørgrav static addrlen_t 329*65b390aaSDag-Erling Smørgrav bits_common(const addrkey_t *s1, addrlen_t l1, 330*65b390aaSDag-Erling Smørgrav const addrkey_t *s2, addrlen_t l2, addrlen_t skip) 331*65b390aaSDag-Erling Smørgrav { 332*65b390aaSDag-Erling Smørgrav addrlen_t len, i; 333*65b390aaSDag-Erling Smørgrav len = (l1 > l2) ? l2 : l1; 334*65b390aaSDag-Erling Smørgrav log_assert(skip < len); 335*65b390aaSDag-Erling Smørgrav for (i = skip; i < len; i++) { 336*65b390aaSDag-Erling Smørgrav if (cmpbit(s1, s2, i)) return i; 337*65b390aaSDag-Erling Smørgrav } 338*65b390aaSDag-Erling Smørgrav return len; 339*65b390aaSDag-Erling Smørgrav } 340*65b390aaSDag-Erling Smørgrav 341*65b390aaSDag-Erling Smørgrav /** 342*65b390aaSDag-Erling Smørgrav * Tests if s1 is a substring of s2 343*65b390aaSDag-Erling Smørgrav * @param s1: first prefix. 344*65b390aaSDag-Erling Smørgrav * @param l1: length of s1 in bits. 345*65b390aaSDag-Erling Smørgrav * @param s2: second prefix. 346*65b390aaSDag-Erling Smørgrav * @param l2: length of s2 in bits. 347*65b390aaSDag-Erling Smørgrav * @param skip: nr of bits already checked. 348*65b390aaSDag-Erling Smørgrav * @return 1 for substring, 0 otherwise 349*65b390aaSDag-Erling Smørgrav */ 350*65b390aaSDag-Erling Smørgrav static int 351*65b390aaSDag-Erling Smørgrav issub(const addrkey_t *s1, addrlen_t l1, 352*65b390aaSDag-Erling Smørgrav const addrkey_t *s2, addrlen_t l2, addrlen_t skip) 353*65b390aaSDag-Erling Smørgrav { 354*65b390aaSDag-Erling Smørgrav return bits_common(s1, l1, s2, l2, skip) == l1; 355*65b390aaSDag-Erling Smørgrav } 356*65b390aaSDag-Erling Smørgrav 357*65b390aaSDag-Erling Smørgrav void 358*65b390aaSDag-Erling Smørgrav addrtree_insert(struct addrtree *tree, const addrkey_t *addr, 359*65b390aaSDag-Erling Smørgrav addrlen_t sourcemask, addrlen_t scope, void *elem, time_t ttl, 360*65b390aaSDag-Erling Smørgrav time_t now) 361*65b390aaSDag-Erling Smørgrav { 362*65b390aaSDag-Erling Smørgrav struct addrnode *newnode, *node; 363*65b390aaSDag-Erling Smørgrav struct addredge *edge; 364*65b390aaSDag-Erling Smørgrav int index; 365*65b390aaSDag-Erling Smørgrav addrlen_t common, depth; 366*65b390aaSDag-Erling Smørgrav 367*65b390aaSDag-Erling Smørgrav node = tree->root; 368*65b390aaSDag-Erling Smørgrav log_assert(node != NULL); 369*65b390aaSDag-Erling Smørgrav 370*65b390aaSDag-Erling Smørgrav /* Protect our cache against too much fine-grained data */ 371*65b390aaSDag-Erling Smørgrav if (tree->max_depth < scope) scope = tree->max_depth; 372*65b390aaSDag-Erling Smørgrav /* Server answer was less specific than question */ 373*65b390aaSDag-Erling Smørgrav if (scope < sourcemask) sourcemask = scope; 374*65b390aaSDag-Erling Smørgrav 375*65b390aaSDag-Erling Smørgrav depth = 0; 376*65b390aaSDag-Erling Smørgrav while (1) { 377*65b390aaSDag-Erling Smørgrav log_assert(depth <= sourcemask); 378*65b390aaSDag-Erling Smørgrav /* Case 1: update existing node */ 379*65b390aaSDag-Erling Smørgrav if (depth == sourcemask) { 380*65b390aaSDag-Erling Smørgrav /* update this node's scope and data */ 381*65b390aaSDag-Erling Smørgrav clean_node(tree, node); 382*65b390aaSDag-Erling Smørgrav node->ttl = ttl; 383*65b390aaSDag-Erling Smørgrav node->elem = elem; 384*65b390aaSDag-Erling Smørgrav node->scope = scope; 385*65b390aaSDag-Erling Smørgrav tree->size_bytes += tree->sizefunc(elem); 386*65b390aaSDag-Erling Smørgrav return; 387*65b390aaSDag-Erling Smørgrav } 388*65b390aaSDag-Erling Smørgrav index = getbit(addr, sourcemask, depth); 389*65b390aaSDag-Erling Smørgrav /* Get an edge to an unexpired node */ 390*65b390aaSDag-Erling Smørgrav edge = node->edge[index]; 391*65b390aaSDag-Erling Smørgrav while (edge) { 392*65b390aaSDag-Erling Smørgrav /* Purge all expired nodes on path */ 393*65b390aaSDag-Erling Smørgrav if (!edge->node->elem || edge->node->ttl >= now) 394*65b390aaSDag-Erling Smørgrav break; 395*65b390aaSDag-Erling Smørgrav purge_node(tree, edge->node); 396*65b390aaSDag-Erling Smørgrav edge = node->edge[index]; 397*65b390aaSDag-Erling Smørgrav } 398*65b390aaSDag-Erling Smørgrav /* Case 2: New leafnode */ 399*65b390aaSDag-Erling Smørgrav if (!edge) { 400*65b390aaSDag-Erling Smørgrav newnode = node_create(tree, elem, scope, ttl); 401*65b390aaSDag-Erling Smørgrav if (!newnode) return; 402*65b390aaSDag-Erling Smørgrav if (!edge_create(newnode, addr, sourcemask, node, 403*65b390aaSDag-Erling Smørgrav index)) { 404*65b390aaSDag-Erling Smørgrav clean_node(tree, newnode); 405*65b390aaSDag-Erling Smørgrav tree->node_count--; 406*65b390aaSDag-Erling Smørgrav free(newnode); 407*65b390aaSDag-Erling Smørgrav return; 408*65b390aaSDag-Erling Smørgrav } 409*65b390aaSDag-Erling Smørgrav tree->size_bytes += node_size(tree, newnode); 410*65b390aaSDag-Erling Smørgrav lru_push(tree, newnode); 411*65b390aaSDag-Erling Smørgrav lru_cleanup(tree); 412*65b390aaSDag-Erling Smørgrav return; 413*65b390aaSDag-Erling Smørgrav } 414*65b390aaSDag-Erling Smørgrav /* Case 3: Traverse edge */ 415*65b390aaSDag-Erling Smørgrav common = bits_common(edge->str, edge->len, addr, sourcemask, 416*65b390aaSDag-Erling Smørgrav depth); 417*65b390aaSDag-Erling Smørgrav if (common == edge->len) { 418*65b390aaSDag-Erling Smørgrav /* We update the scope of intermediate nodes. Apparently 419*65b390aaSDag-Erling Smørgrav * the * authority changed its mind. If we would not do 420*65b390aaSDag-Erling Smørgrav * this we might not be able to reach our new node. */ 421*65b390aaSDag-Erling Smørgrav node->scope = scope; 422*65b390aaSDag-Erling Smørgrav depth = edge->len; 423*65b390aaSDag-Erling Smørgrav node = edge->node; 424*65b390aaSDag-Erling Smørgrav continue; 425*65b390aaSDag-Erling Smørgrav } 426*65b390aaSDag-Erling Smørgrav /* Case 4: split. */ 427*65b390aaSDag-Erling Smørgrav if (!(newnode = node_create(tree, NULL, 0, 0))) 428*65b390aaSDag-Erling Smørgrav return; 429*65b390aaSDag-Erling Smørgrav node->edge[index] = NULL; 430*65b390aaSDag-Erling Smørgrav if (!edge_create(newnode, addr, common, node, index)) { 431*65b390aaSDag-Erling Smørgrav node->edge[index] = edge; 432*65b390aaSDag-Erling Smørgrav clean_node(tree, newnode); 433*65b390aaSDag-Erling Smørgrav tree->node_count--; 434*65b390aaSDag-Erling Smørgrav free(newnode); 435*65b390aaSDag-Erling Smørgrav return; 436*65b390aaSDag-Erling Smørgrav } 437*65b390aaSDag-Erling Smørgrav lru_push(tree, newnode); 438*65b390aaSDag-Erling Smørgrav /* connect existing child to our new node */ 439*65b390aaSDag-Erling Smørgrav index = getbit(edge->str, edge->len, common); 440*65b390aaSDag-Erling Smørgrav newnode->edge[index] = edge; 441*65b390aaSDag-Erling Smørgrav edge->parent_node = newnode; 442*65b390aaSDag-Erling Smørgrav edge->parent_index = (int)index; 443*65b390aaSDag-Erling Smørgrav 444*65b390aaSDag-Erling Smørgrav if (common == sourcemask) { 445*65b390aaSDag-Erling Smørgrav /* Data is stored in the node */ 446*65b390aaSDag-Erling Smørgrav newnode->elem = elem; 447*65b390aaSDag-Erling Smørgrav newnode->scope = scope; 448*65b390aaSDag-Erling Smørgrav newnode->ttl = ttl; 449*65b390aaSDag-Erling Smørgrav } 450*65b390aaSDag-Erling Smørgrav 451*65b390aaSDag-Erling Smørgrav tree->size_bytes += node_size(tree, newnode); 452*65b390aaSDag-Erling Smørgrav 453*65b390aaSDag-Erling Smørgrav if (common != sourcemask) { 454*65b390aaSDag-Erling Smørgrav /* Data is stored in other leafnode */ 455*65b390aaSDag-Erling Smørgrav node = newnode; 456*65b390aaSDag-Erling Smørgrav newnode = node_create(tree, elem, scope, ttl); 457*65b390aaSDag-Erling Smørgrav if (!edge_create(newnode, addr, sourcemask, node, 458*65b390aaSDag-Erling Smørgrav index^1)) { 459*65b390aaSDag-Erling Smørgrav clean_node(tree, newnode); 460*65b390aaSDag-Erling Smørgrav tree->node_count--; 461*65b390aaSDag-Erling Smørgrav free(newnode); 462*65b390aaSDag-Erling Smørgrav return; 463*65b390aaSDag-Erling Smørgrav } 464*65b390aaSDag-Erling Smørgrav tree->size_bytes += node_size(tree, newnode); 465*65b390aaSDag-Erling Smørgrav lru_push(tree, newnode); 466*65b390aaSDag-Erling Smørgrav } 467*65b390aaSDag-Erling Smørgrav lru_cleanup(tree); 468*65b390aaSDag-Erling Smørgrav return; 469*65b390aaSDag-Erling Smørgrav } 470*65b390aaSDag-Erling Smørgrav } 471*65b390aaSDag-Erling Smørgrav 472*65b390aaSDag-Erling Smørgrav struct addrnode * 473*65b390aaSDag-Erling Smørgrav addrtree_find(struct addrtree *tree, const addrkey_t *addr, 474*65b390aaSDag-Erling Smørgrav addrlen_t sourcemask, time_t now) 475*65b390aaSDag-Erling Smørgrav { 476*65b390aaSDag-Erling Smørgrav struct addrnode *node = tree->root; 477*65b390aaSDag-Erling Smørgrav struct addredge *edge = NULL; 478*65b390aaSDag-Erling Smørgrav addrlen_t depth = 0; 479*65b390aaSDag-Erling Smørgrav 480*65b390aaSDag-Erling Smørgrav log_assert(node != NULL); 481*65b390aaSDag-Erling Smørgrav while (1) { 482*65b390aaSDag-Erling Smørgrav /* Current node more specific then question. */ 483*65b390aaSDag-Erling Smørgrav log_assert(depth <= sourcemask); 484*65b390aaSDag-Erling Smørgrav /* does this node have data? if yes, see if we have a match */ 485*65b390aaSDag-Erling Smørgrav if (node->elem && node->ttl >= now) { 486*65b390aaSDag-Erling Smørgrav /* saved at wrong depth */; 487*65b390aaSDag-Erling Smørgrav log_assert(node->scope >= depth) 488*65b390aaSDag-Erling Smørgrav if (depth == node->scope || 489*65b390aaSDag-Erling Smørgrav (node->scope > sourcemask && 490*65b390aaSDag-Erling Smørgrav depth == sourcemask)) { 491*65b390aaSDag-Erling Smørgrav /* Authority indicates it does not have a more 492*65b390aaSDag-Erling Smørgrav * precise answer or we cannot ask a more 493*65b390aaSDag-Erling Smørgrav * specific question. */ 494*65b390aaSDag-Erling Smørgrav lru_update(tree, node); 495*65b390aaSDag-Erling Smørgrav return node; 496*65b390aaSDag-Erling Smørgrav } 497*65b390aaSDag-Erling Smørgrav } 498*65b390aaSDag-Erling Smørgrav /* This is our final depth, but we haven't found an answer. */ 499*65b390aaSDag-Erling Smørgrav if (depth == sourcemask) 500*65b390aaSDag-Erling Smørgrav return NULL; 501*65b390aaSDag-Erling Smørgrav /* Find an edge to traverse */ 502*65b390aaSDag-Erling Smørgrav edge = node->edge[getbit(addr, sourcemask, depth)]; 503*65b390aaSDag-Erling Smørgrav if (!edge || !edge->node) 504*65b390aaSDag-Erling Smørgrav return NULL; 505*65b390aaSDag-Erling Smørgrav if (edge->len > sourcemask ) 506*65b390aaSDag-Erling Smørgrav return NULL; 507*65b390aaSDag-Erling Smørgrav if (!issub(edge->str, edge->len, addr, sourcemask, depth)) 508*65b390aaSDag-Erling Smørgrav return NULL; 509*65b390aaSDag-Erling Smørgrav log_assert(depth < edge->len); 510*65b390aaSDag-Erling Smørgrav depth = edge->len; 511*65b390aaSDag-Erling Smørgrav node = edge->node; 512*65b390aaSDag-Erling Smørgrav } 513*65b390aaSDag-Erling Smørgrav } 514*65b390aaSDag-Erling Smørgrav 515*65b390aaSDag-Erling Smørgrav /** Wrappers for static functions to unit test */ 516*65b390aaSDag-Erling Smørgrav int unittest_wrapper_addrtree_cmpbit(const addrkey_t *key1, 517*65b390aaSDag-Erling Smørgrav const addrkey_t *key2, addrlen_t n) { 518*65b390aaSDag-Erling Smørgrav return cmpbit(key1, key2, n); 519*65b390aaSDag-Erling Smørgrav } 520*65b390aaSDag-Erling Smørgrav addrlen_t unittest_wrapper_addrtree_bits_common(const addrkey_t *s1, 521*65b390aaSDag-Erling Smørgrav addrlen_t l1, const addrkey_t *s2, addrlen_t l2, addrlen_t skip) { 522*65b390aaSDag-Erling Smørgrav return bits_common(s1, l1, s2, l2, skip); 523*65b390aaSDag-Erling Smørgrav } 524*65b390aaSDag-Erling Smørgrav int unittest_wrapper_addrtree_getbit(const addrkey_t *addr, 525*65b390aaSDag-Erling Smørgrav addrlen_t addrlen, addrlen_t n) { 526*65b390aaSDag-Erling Smørgrav return getbit(addr, addrlen, n); 527*65b390aaSDag-Erling Smørgrav } 528*65b390aaSDag-Erling Smørgrav int unittest_wrapper_addrtree_issub(const addrkey_t *s1, addrlen_t l1, 529*65b390aaSDag-Erling Smørgrav const addrkey_t *s2, addrlen_t l2, addrlen_t skip) { 530*65b390aaSDag-Erling Smørgrav return issub(s1, l1, s2, l2, skip); 531*65b390aaSDag-Erling Smørgrav } 532