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