1b7579f77SDag-Erling Smørgrav /* 2b7579f77SDag-Erling Smørgrav * util/storage/dnstree.c - support for rbtree types suitable for DNS code. 3b7579f77SDag-Erling Smørgrav * 4b7579f77SDag-Erling Smørgrav * Copyright (c) 2008, NLnet Labs. All rights reserved. 5b7579f77SDag-Erling Smørgrav * 6b7579f77SDag-Erling Smørgrav * This software is open source. 7b7579f77SDag-Erling Smørgrav * 8b7579f77SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 9b7579f77SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 10b7579f77SDag-Erling Smørgrav * are met: 11b7579f77SDag-Erling Smørgrav * 12b7579f77SDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice, 13b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer. 14b7579f77SDag-Erling Smørgrav * 15b7579f77SDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice, 16b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation 17b7579f77SDag-Erling Smørgrav * and/or other materials provided with the distribution. 18b7579f77SDag-Erling Smørgrav * 19b7579f77SDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may 20b7579f77SDag-Erling Smørgrav * be used to endorse or promote products derived from this software without 21b7579f77SDag-Erling Smørgrav * specific prior written permission. 22b7579f77SDag-Erling Smørgrav * 23b7579f77SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2417d15b25SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2517d15b25SDag-Erling Smørgrav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2617d15b25SDag-Erling Smørgrav * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2717d15b25SDag-Erling Smørgrav * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2817d15b25SDag-Erling Smørgrav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2917d15b25SDag-Erling Smørgrav * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 3017d15b25SDag-Erling Smørgrav * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 3117d15b25SDag-Erling Smørgrav * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 3217d15b25SDag-Erling Smørgrav * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3317d15b25SDag-Erling Smørgrav * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34b7579f77SDag-Erling Smørgrav */ 35b7579f77SDag-Erling Smørgrav 36b7579f77SDag-Erling Smørgrav /** 37b7579f77SDag-Erling Smørgrav * \file 38b7579f77SDag-Erling Smørgrav * 39b7579f77SDag-Erling Smørgrav * This file contains structures combining types and functions to 40b7579f77SDag-Erling Smørgrav * manipulate those structures that help building DNS lookup trees. 41b7579f77SDag-Erling Smørgrav */ 42b7579f77SDag-Erling Smørgrav #include "config.h" 43b7579f77SDag-Erling Smørgrav #include "util/storage/dnstree.h" 44b7579f77SDag-Erling Smørgrav #include "util/data/dname.h" 45b7579f77SDag-Erling Smørgrav #include "util/net_help.h" 46b7579f77SDag-Erling Smørgrav 47b7579f77SDag-Erling Smørgrav int name_tree_compare(const void* k1, const void* k2) 48b7579f77SDag-Erling Smørgrav { 49b7579f77SDag-Erling Smørgrav struct name_tree_node* x = (struct name_tree_node*)k1; 50b7579f77SDag-Erling Smørgrav struct name_tree_node* y = (struct name_tree_node*)k2; 51b7579f77SDag-Erling Smørgrav int m; 52b7579f77SDag-Erling Smørgrav if(x->dclass != y->dclass) { 53b7579f77SDag-Erling Smørgrav if(x->dclass < y->dclass) 54b7579f77SDag-Erling Smørgrav return -1; 55b7579f77SDag-Erling Smørgrav return 1; 56b7579f77SDag-Erling Smørgrav } 57b7579f77SDag-Erling Smørgrav return dname_lab_cmp(x->name, x->labs, y->name, y->labs, &m); 58b7579f77SDag-Erling Smørgrav } 59b7579f77SDag-Erling Smørgrav 60b7579f77SDag-Erling Smørgrav int addr_tree_compare(const void* k1, const void* k2) 61b7579f77SDag-Erling Smørgrav { 62b7579f77SDag-Erling Smørgrav struct addr_tree_node* n1 = (struct addr_tree_node*)k1; 63b7579f77SDag-Erling Smørgrav struct addr_tree_node* n2 = (struct addr_tree_node*)k2; 64b7579f77SDag-Erling Smørgrav int r = sockaddr_cmp_addr(&n1->addr, n1->addrlen, &n2->addr, 65b7579f77SDag-Erling Smørgrav n2->addrlen); 66b7579f77SDag-Erling Smørgrav if(r != 0) return r; 67b7579f77SDag-Erling Smørgrav if(n1->net < n2->net) 68b7579f77SDag-Erling Smørgrav return -1; 69b7579f77SDag-Erling Smørgrav if(n1->net > n2->net) 70b7579f77SDag-Erling Smørgrav return 1; 71b7579f77SDag-Erling Smørgrav return 0; 72b7579f77SDag-Erling Smørgrav } 73b7579f77SDag-Erling Smørgrav 74865f46b2SCy Schubert int addr_tree_addrport_compare(const void* k1, const void* k2) 75865f46b2SCy Schubert { 76865f46b2SCy Schubert struct addr_tree_node* n1 = (struct addr_tree_node*)k1; 77865f46b2SCy Schubert struct addr_tree_node* n2 = (struct addr_tree_node*)k2; 78*be771a7bSCy Schubert return sockaddr_cmp_scopeid(&n1->addr, n1->addrlen, &n2->addr, 79865f46b2SCy Schubert n2->addrlen); 80865f46b2SCy Schubert } 81865f46b2SCy Schubert 823005e0a3SDag-Erling Smørgrav void name_tree_init(rbtree_type* tree) 83b7579f77SDag-Erling Smørgrav { 84b7579f77SDag-Erling Smørgrav rbtree_init(tree, &name_tree_compare); 85b7579f77SDag-Erling Smørgrav } 86b7579f77SDag-Erling Smørgrav 873005e0a3SDag-Erling Smørgrav void addr_tree_init(rbtree_type* tree) 88b7579f77SDag-Erling Smørgrav { 89b7579f77SDag-Erling Smørgrav rbtree_init(tree, &addr_tree_compare); 90b7579f77SDag-Erling Smørgrav } 91b7579f77SDag-Erling Smørgrav 92865f46b2SCy Schubert void addr_tree_addrport_init(rbtree_type* tree) 93865f46b2SCy Schubert { 94865f46b2SCy Schubert rbtree_init(tree, &addr_tree_addrport_compare); 95865f46b2SCy Schubert } 96865f46b2SCy Schubert 973005e0a3SDag-Erling Smørgrav int name_tree_insert(rbtree_type* tree, struct name_tree_node* node, 98b7579f77SDag-Erling Smørgrav uint8_t* name, size_t len, int labs, uint16_t dclass) 99b7579f77SDag-Erling Smørgrav { 100b7579f77SDag-Erling Smørgrav node->node.key = node; 101b7579f77SDag-Erling Smørgrav node->name = name; 102b7579f77SDag-Erling Smørgrav node->len = len; 103b7579f77SDag-Erling Smørgrav node->labs = labs; 104b7579f77SDag-Erling Smørgrav node->dclass = dclass; 105b7579f77SDag-Erling Smørgrav node->parent = NULL; 106b7579f77SDag-Erling Smørgrav return rbtree_insert(tree, &node->node) != NULL; 107b7579f77SDag-Erling Smørgrav } 108b7579f77SDag-Erling Smørgrav 1093005e0a3SDag-Erling Smørgrav int addr_tree_insert(rbtree_type* tree, struct addr_tree_node* node, 110b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen, int net) 111b7579f77SDag-Erling Smørgrav { 112b7579f77SDag-Erling Smørgrav node->node.key = node; 113b7579f77SDag-Erling Smørgrav memcpy(&node->addr, addr, addrlen); 114b7579f77SDag-Erling Smørgrav node->addrlen = addrlen; 115b7579f77SDag-Erling Smørgrav node->net = net; 116b7579f77SDag-Erling Smørgrav node->parent = NULL; 117b7579f77SDag-Erling Smørgrav return rbtree_insert(tree, &node->node) != NULL; 118b7579f77SDag-Erling Smørgrav } 119b7579f77SDag-Erling Smørgrav 120091e9e46SCy Schubert void addr_tree_init_parents_node(struct addr_tree_node* node) 121b7579f77SDag-Erling Smørgrav { 122091e9e46SCy Schubert struct addr_tree_node* prev = NULL, *p; 123b7579f77SDag-Erling Smørgrav int m; 124091e9e46SCy Schubert for(; (rbnode_type*)node != RBTREE_NULL; 125091e9e46SCy Schubert node = (struct addr_tree_node*)rbtree_next((rbnode_type*)node)) { 126b7579f77SDag-Erling Smørgrav node->parent = NULL; 127b7579f77SDag-Erling Smørgrav if(!prev || prev->addrlen != node->addrlen) { 128b7579f77SDag-Erling Smørgrav prev = node; 129b7579f77SDag-Erling Smørgrav continue; 130b7579f77SDag-Erling Smørgrav } 131b7579f77SDag-Erling Smørgrav m = addr_in_common(&prev->addr, prev->net, &node->addr, 132b7579f77SDag-Erling Smørgrav node->net, node->addrlen); 133b7579f77SDag-Erling Smørgrav /* sort order like: ::/0, 1::/2, 1::/4, ... 2::/2 */ 134b7579f77SDag-Erling Smørgrav /* find the previous, or parent-parent-parent */ 135b7579f77SDag-Erling Smørgrav for(p = prev; p; p = p->parent) 136b7579f77SDag-Erling Smørgrav if(p->net <= m) { 137b7579f77SDag-Erling Smørgrav /* ==: since prev matched m, this is closest*/ 138b7579f77SDag-Erling Smørgrav /* <: prev matches more, but is not a parent, 139b7579f77SDag-Erling Smørgrav * this one is a (grand)parent */ 140b7579f77SDag-Erling Smørgrav node->parent = p; 141b7579f77SDag-Erling Smørgrav break; 142b7579f77SDag-Erling Smørgrav } 143b7579f77SDag-Erling Smørgrav prev = node; 144b7579f77SDag-Erling Smørgrav } 145b7579f77SDag-Erling Smørgrav } 146b7579f77SDag-Erling Smørgrav 147091e9e46SCy Schubert void addr_tree_init_parents(rbtree_type* tree) 148091e9e46SCy Schubert { 149091e9e46SCy Schubert addr_tree_init_parents_node( 150091e9e46SCy Schubert (struct addr_tree_node*)rbtree_first(tree)); 151091e9e46SCy Schubert } 152091e9e46SCy Schubert 1533005e0a3SDag-Erling Smørgrav void name_tree_init_parents(rbtree_type* tree) 154b7579f77SDag-Erling Smørgrav { 155b7579f77SDag-Erling Smørgrav struct name_tree_node* node, *prev = NULL, *p; 156b7579f77SDag-Erling Smørgrav int m; 157b7579f77SDag-Erling Smørgrav RBTREE_FOR(node, struct name_tree_node*, tree) { 158b7579f77SDag-Erling Smørgrav node->parent = NULL; 159b7579f77SDag-Erling Smørgrav if(!prev || prev->dclass != node->dclass) { 160b7579f77SDag-Erling Smørgrav prev = node; 161b7579f77SDag-Erling Smørgrav continue; 162b7579f77SDag-Erling Smørgrav } 163b7579f77SDag-Erling Smørgrav (void)dname_lab_cmp(prev->name, prev->labs, node->name, 164b7579f77SDag-Erling Smørgrav node->labs, &m); /* we know prev is smaller */ 165b7579f77SDag-Erling Smørgrav /* sort order like: . com. bla.com. zwb.com. net. */ 166b7579f77SDag-Erling Smørgrav /* find the previous, or parent-parent-parent */ 167b7579f77SDag-Erling Smørgrav for(p = prev; p; p = p->parent) 168b7579f77SDag-Erling Smørgrav if(p->labs <= m) { 169b7579f77SDag-Erling Smørgrav /* ==: since prev matched m, this is closest*/ 170b7579f77SDag-Erling Smørgrav /* <: prev matches more, but is not a parent, 171b7579f77SDag-Erling Smørgrav * this one is a (grand)parent */ 172b7579f77SDag-Erling Smørgrav node->parent = p; 173b7579f77SDag-Erling Smørgrav break; 174b7579f77SDag-Erling Smørgrav } 175b7579f77SDag-Erling Smørgrav prev = node; 176b7579f77SDag-Erling Smørgrav } 177b7579f77SDag-Erling Smørgrav } 178b7579f77SDag-Erling Smørgrav 1793005e0a3SDag-Erling Smørgrav struct name_tree_node* name_tree_find(rbtree_type* tree, uint8_t* name, 180b7579f77SDag-Erling Smørgrav size_t len, int labs, uint16_t dclass) 181b7579f77SDag-Erling Smørgrav { 182b7579f77SDag-Erling Smørgrav struct name_tree_node key; 183b7579f77SDag-Erling Smørgrav key.node.key = &key; 184b7579f77SDag-Erling Smørgrav key.name = name; 185b7579f77SDag-Erling Smørgrav key.len = len; 186b7579f77SDag-Erling Smørgrav key.labs = labs; 187b7579f77SDag-Erling Smørgrav key.dclass = dclass; 188b7579f77SDag-Erling Smørgrav return (struct name_tree_node*)rbtree_search(tree, &key); 189b7579f77SDag-Erling Smørgrav } 190b7579f77SDag-Erling Smørgrav 1913005e0a3SDag-Erling Smørgrav struct name_tree_node* name_tree_lookup(rbtree_type* tree, uint8_t* name, 192b7579f77SDag-Erling Smørgrav size_t len, int labs, uint16_t dclass) 193b7579f77SDag-Erling Smørgrav { 1943005e0a3SDag-Erling Smørgrav rbnode_type* res = NULL; 195b7579f77SDag-Erling Smørgrav struct name_tree_node *result; 196b7579f77SDag-Erling Smørgrav struct name_tree_node key; 197b7579f77SDag-Erling Smørgrav key.node.key = &key; 198b7579f77SDag-Erling Smørgrav key.name = name; 199b7579f77SDag-Erling Smørgrav key.len = len; 200b7579f77SDag-Erling Smørgrav key.labs = labs; 201b7579f77SDag-Erling Smørgrav key.dclass = dclass; 202b7579f77SDag-Erling Smørgrav if(rbtree_find_less_equal(tree, &key, &res)) { 203b7579f77SDag-Erling Smørgrav /* exact */ 204b7579f77SDag-Erling Smørgrav result = (struct name_tree_node*)res; 205b7579f77SDag-Erling Smørgrav } else { 206b7579f77SDag-Erling Smørgrav /* smaller element (or no element) */ 207b7579f77SDag-Erling Smørgrav int m; 208b7579f77SDag-Erling Smørgrav result = (struct name_tree_node*)res; 209b7579f77SDag-Erling Smørgrav if(!result || result->dclass != dclass) 210b7579f77SDag-Erling Smørgrav return NULL; 211b7579f77SDag-Erling Smørgrav /* count number of labels matched */ 212b7579f77SDag-Erling Smørgrav (void)dname_lab_cmp(result->name, result->labs, key.name, 213b7579f77SDag-Erling Smørgrav key.labs, &m); 214b7579f77SDag-Erling Smørgrav while(result) { /* go up until qname is subdomain of stub */ 215b7579f77SDag-Erling Smørgrav if(result->labs <= m) 216b7579f77SDag-Erling Smørgrav break; 217b7579f77SDag-Erling Smørgrav result = result->parent; 218b7579f77SDag-Erling Smørgrav } 219b7579f77SDag-Erling Smørgrav } 220b7579f77SDag-Erling Smørgrav return result; 221b7579f77SDag-Erling Smørgrav } 222b7579f77SDag-Erling Smørgrav 2233005e0a3SDag-Erling Smørgrav struct addr_tree_node* addr_tree_lookup(rbtree_type* tree, 224b7579f77SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen) 225b7579f77SDag-Erling Smørgrav { 2263005e0a3SDag-Erling Smørgrav rbnode_type* res = NULL; 227b7579f77SDag-Erling Smørgrav struct addr_tree_node* result; 228b7579f77SDag-Erling Smørgrav struct addr_tree_node key; 229b7579f77SDag-Erling Smørgrav key.node.key = &key; 230b7579f77SDag-Erling Smørgrav memcpy(&key.addr, addr, addrlen); 231b7579f77SDag-Erling Smørgrav key.addrlen = addrlen; 232b7579f77SDag-Erling Smørgrav key.net = (addr_is_ip6(addr, addrlen)?128:32); 233b7579f77SDag-Erling Smørgrav if(rbtree_find_less_equal(tree, &key, &res)) { 234b7579f77SDag-Erling Smørgrav /* exact */ 235b7579f77SDag-Erling Smørgrav return (struct addr_tree_node*)res; 236b7579f77SDag-Erling Smørgrav } else { 237b7579f77SDag-Erling Smørgrav /* smaller element (or no element) */ 238b7579f77SDag-Erling Smørgrav int m; 239b7579f77SDag-Erling Smørgrav result = (struct addr_tree_node*)res; 240b7579f77SDag-Erling Smørgrav if(!result || result->addrlen != addrlen) 241b7579f77SDag-Erling Smørgrav return 0; 242b7579f77SDag-Erling Smørgrav /* count number of bits matched */ 243b7579f77SDag-Erling Smørgrav m = addr_in_common(&result->addr, result->net, addr, 244b7579f77SDag-Erling Smørgrav key.net, addrlen); 245b7579f77SDag-Erling Smørgrav while(result) { /* go up until addr is inside netblock */ 246b7579f77SDag-Erling Smørgrav if(result->net <= m) 247b7579f77SDag-Erling Smørgrav break; 248b7579f77SDag-Erling Smørgrav result = result->parent; 249b7579f77SDag-Erling Smørgrav } 250b7579f77SDag-Erling Smørgrav } 251b7579f77SDag-Erling Smørgrav return result; 252b7579f77SDag-Erling Smørgrav } 253b7579f77SDag-Erling Smørgrav 2543005e0a3SDag-Erling Smørgrav struct addr_tree_node* addr_tree_find(rbtree_type* tree, 255b5663de9SDag-Erling Smørgrav struct sockaddr_storage* addr, socklen_t addrlen, int net) 256b5663de9SDag-Erling Smørgrav { 2573005e0a3SDag-Erling Smørgrav rbnode_type* res = NULL; 258b5663de9SDag-Erling Smørgrav struct addr_tree_node key; 259b5663de9SDag-Erling Smørgrav key.node.key = &key; 260b5663de9SDag-Erling Smørgrav memcpy(&key.addr, addr, addrlen); 261b5663de9SDag-Erling Smørgrav key.addrlen = addrlen; 262b5663de9SDag-Erling Smørgrav key.net = net; 263b5663de9SDag-Erling Smørgrav res = rbtree_search(tree, &key); 264b5663de9SDag-Erling Smørgrav return (struct addr_tree_node*)res; 265b5663de9SDag-Erling Smørgrav } 266b5663de9SDag-Erling Smørgrav 267b7579f77SDag-Erling Smørgrav int 2683005e0a3SDag-Erling Smørgrav name_tree_next_root(rbtree_type* tree, uint16_t* dclass) 269b7579f77SDag-Erling Smørgrav { 270b7579f77SDag-Erling Smørgrav struct name_tree_node key; 2713005e0a3SDag-Erling Smørgrav rbnode_type* n; 272b7579f77SDag-Erling Smørgrav struct name_tree_node* p; 273b7579f77SDag-Erling Smørgrav if(*dclass == 0) { 274b7579f77SDag-Erling Smørgrav /* first root item is first item in tree */ 275b7579f77SDag-Erling Smørgrav n = rbtree_first(tree); 276b7579f77SDag-Erling Smørgrav if(n == RBTREE_NULL) 277b7579f77SDag-Erling Smørgrav return 0; 278b7579f77SDag-Erling Smørgrav p = (struct name_tree_node*)n; 279b7579f77SDag-Erling Smørgrav if(dname_is_root(p->name)) { 280b7579f77SDag-Erling Smørgrav *dclass = p->dclass; 281b7579f77SDag-Erling Smørgrav return 1; 282b7579f77SDag-Erling Smørgrav } 283b7579f77SDag-Erling Smørgrav /* root not first item? search for higher items */ 284b7579f77SDag-Erling Smørgrav *dclass = p->dclass + 1; 285b7579f77SDag-Erling Smørgrav return name_tree_next_root(tree, dclass); 286b7579f77SDag-Erling Smørgrav } 287b7579f77SDag-Erling Smørgrav /* find class n in tree, we may get a direct hit, or if we don't 288b7579f77SDag-Erling Smørgrav * this is the last item of the previous class so rbtree_next() takes 289b7579f77SDag-Erling Smørgrav * us to the next root (if any) */ 290b7579f77SDag-Erling Smørgrav key.node.key = &key; 291b7579f77SDag-Erling Smørgrav key.name = (uint8_t*)"\000"; 292b7579f77SDag-Erling Smørgrav key.len = 1; 293b7579f77SDag-Erling Smørgrav key.labs = 0; 294b7579f77SDag-Erling Smørgrav key.dclass = *dclass; 295b7579f77SDag-Erling Smørgrav n = NULL; 296b7579f77SDag-Erling Smørgrav if(rbtree_find_less_equal(tree, &key, &n)) { 297b7579f77SDag-Erling Smørgrav /* exact */ 298b7579f77SDag-Erling Smørgrav return 1; 299b7579f77SDag-Erling Smørgrav } else { 300b7579f77SDag-Erling Smørgrav /* smaller element */ 301b7579f77SDag-Erling Smørgrav if(!n || n == RBTREE_NULL) 302b7579f77SDag-Erling Smørgrav return 0; /* nothing found */ 303b7579f77SDag-Erling Smørgrav n = rbtree_next(n); 304b7579f77SDag-Erling Smørgrav if(n == RBTREE_NULL) 305b7579f77SDag-Erling Smørgrav return 0; /* no higher */ 306b7579f77SDag-Erling Smørgrav p = (struct name_tree_node*)n; 307b7579f77SDag-Erling Smørgrav if(dname_is_root(p->name)) { 308b7579f77SDag-Erling Smørgrav *dclass = p->dclass; 309b7579f77SDag-Erling Smørgrav return 1; 310b7579f77SDag-Erling Smørgrav } 311b7579f77SDag-Erling Smørgrav /* not a root node, return next higher item */ 312b7579f77SDag-Erling Smørgrav *dclass = p->dclass+1; 313b7579f77SDag-Erling Smørgrav return name_tree_next_root(tree, dclass); 314b7579f77SDag-Erling Smørgrav } 315b7579f77SDag-Erling Smørgrav } 316