1d3fecca9Ssthen /* 2d3fecca9Ssthen * radtree -- generic radix tree for binary strings. 3d3fecca9Ssthen * 4d3fecca9Ssthen * Copyright (c) 2010, NLnet Labs. See LICENSE for license. 5d3fecca9Ssthen */ 6d3fecca9Ssthen #ifndef RADTREE_H 7d3fecca9Ssthen #define RADTREE_H 8d3fecca9Ssthen 9d3fecca9Ssthen struct radnode; 10d3fecca9Ssthen struct region; 11d3fecca9Ssthen 12d3fecca9Ssthen /** length of the binary string */ 13fe5fe5f6Sflorian typedef uint16_t radstrlen_type; 14d3fecca9Ssthen 15d3fecca9Ssthen /** 16d3fecca9Ssthen * The radix tree 17d3fecca9Ssthen * 18d3fecca9Ssthen * The elements are stored based on binary strings(0-255) of a given length. 19d3fecca9Ssthen * They are sorted, a prefix is sorted before its suffixes. 20d3fecca9Ssthen * If you want to know the key string, you should store it yourself, the 21d3fecca9Ssthen * tree stores it in the parts necessary for lookup. 22d3fecca9Ssthen * For binary strings for domain names see the radname routines. 23d3fecca9Ssthen */ 24d3fecca9Ssthen struct radtree { 25d3fecca9Ssthen /** root node in tree */ 26d3fecca9Ssthen struct radnode* root; 27d3fecca9Ssthen /** count of number of elements */ 28d3fecca9Ssthen size_t count; 29d3fecca9Ssthen /** region for allocation */ 30d3fecca9Ssthen struct region* region; 31d3fecca9Ssthen }; 32d3fecca9Ssthen 33d3fecca9Ssthen /** 34d3fecca9Ssthen * A radix tree lookup node. 35d3fecca9Ssthen * The array is malloced separately from the radnode. 36d3fecca9Ssthen */ 37d3fecca9Ssthen struct radnode { 38d3fecca9Ssthen /** data element associated with the binary string up to this node */ 39d3fecca9Ssthen void* elem; 40d3fecca9Ssthen /** parent node (NULL for the root) */ 41d3fecca9Ssthen struct radnode* parent; 42d3fecca9Ssthen /** index in the parent lookup array */ 43d3fecca9Ssthen uint8_t pidx; 44d3fecca9Ssthen /** offset of the lookup array, add to [i] for lookups */ 45d3fecca9Ssthen uint8_t offset; 46d3fecca9Ssthen /** length of the lookup array */ 47d3fecca9Ssthen uint16_t len; 48d3fecca9Ssthen /** capacity of the lookup array (can be larger than length) */ 49d3fecca9Ssthen uint16_t capacity; 50d3fecca9Ssthen /** the lookup array by [byte-offset] */ 51d3fecca9Ssthen struct radsel* array; 52*ee5153b7Sflorian } ATTR_PACKED; 53d3fecca9Ssthen 54d3fecca9Ssthen /** 55d3fecca9Ssthen * radix select edge in array 56d3fecca9Ssthen */ 57d3fecca9Ssthen struct radsel { 58d3fecca9Ssthen /** additional string after the selection-byte for this edge. */ 59d3fecca9Ssthen uint8_t* str; 60d3fecca9Ssthen /** length of the additional string for this edge */ 61fe5fe5f6Sflorian radstrlen_type len; 62d3fecca9Ssthen /** node that deals with byte+str */ 63d3fecca9Ssthen struct radnode* node; 64*ee5153b7Sflorian } ATTR_PACKED; 65d3fecca9Ssthen 66d3fecca9Ssthen /** 67d3fecca9Ssthen * Create new radix tree 68d3fecca9Ssthen * @param region: where to allocate the tree. 69d3fecca9Ssthen * @return new tree or NULL on alloc failure. 70d3fecca9Ssthen */ 71d3fecca9Ssthen struct radtree* radix_tree_create(struct region* region); 72d3fecca9Ssthen 73d3fecca9Ssthen /** 74d3fecca9Ssthen * Init new radix tree. 75d3fecca9Ssthen * @param rt: radix tree to be initialized. 76d3fecca9Ssthen */ 77d3fecca9Ssthen void radix_tree_init(struct radtree* rt); 78d3fecca9Ssthen 79d3fecca9Ssthen /** 80d3fecca9Ssthen * Delete intermediate nodes from radix tree 81d3fecca9Ssthen * @param rt: radix tree to be initialized. 82d3fecca9Ssthen */ 83d3fecca9Ssthen void radix_tree_clear(struct radtree* rt); 84d3fecca9Ssthen 85d3fecca9Ssthen /** 86d3fecca9Ssthen * Delete radix tree. 87d3fecca9Ssthen * @param rt: radix tree to be deleted. 88d3fecca9Ssthen */ 89d3fecca9Ssthen void radix_tree_delete(struct radtree* rt); 90d3fecca9Ssthen 91d3fecca9Ssthen 92d3fecca9Ssthen /** 93d3fecca9Ssthen * Insert element into radix tree. 94d3fecca9Ssthen * @param rt: the radix tree. 95d3fecca9Ssthen * @param key: key string. 96d3fecca9Ssthen * @param len: length of key. 97d3fecca9Ssthen * @param elem: pointer to element data. 98d3fecca9Ssthen * @return NULL on failure - out of memory. 99d3fecca9Ssthen * NULL on failure - duplicate entry. 100d3fecca9Ssthen * On success the new radix node for this element. 101d3fecca9Ssthen */ 102fe5fe5f6Sflorian struct radnode* radix_insert(struct radtree* rt, uint8_t* k, 103fe5fe5f6Sflorian radstrlen_type len, void* elem); 104d3fecca9Ssthen 105d3fecca9Ssthen /** 106d3fecca9Ssthen * Delete element from radix tree. 107d3fecca9Ssthen * @param rt: the radix tree. 108d3fecca9Ssthen * @param n: radix node for that element. 109d3fecca9Ssthen * if NULL, nothing is deleted. 110d3fecca9Ssthen */ 111d3fecca9Ssthen void radix_delete(struct radtree* rt, struct radnode* n); 112d3fecca9Ssthen 113d3fecca9Ssthen /** 114d3fecca9Ssthen * Find radix element in tree. 115d3fecca9Ssthen * @param rt: the radix tree. 116d3fecca9Ssthen * @param key: key string. 117d3fecca9Ssthen * @param len: length of key. 118d3fecca9Ssthen * @return the radix node or NULL if not found. 119d3fecca9Ssthen */ 120fe5fe5f6Sflorian struct radnode* radix_search(struct radtree* rt, uint8_t* k, 121fe5fe5f6Sflorian radstrlen_type len); 122d3fecca9Ssthen 123d3fecca9Ssthen /** 124d3fecca9Ssthen * Find radix element in tree, and if not found, find the closest smaller or 125d3fecca9Ssthen * equal element in the tree. 126d3fecca9Ssthen * @param rt: the radix tree. 127d3fecca9Ssthen * @param key: key string. 128d3fecca9Ssthen * @param len: length of key. 129d3fecca9Ssthen * @param result: returns the radix node or closest match (NULL if key is 130d3fecca9Ssthen * smaller than the smallest key in the tree). 131d3fecca9Ssthen * @return true if exact match, false if no match. 132d3fecca9Ssthen */ 133fe5fe5f6Sflorian int radix_find_less_equal(struct radtree* rt, uint8_t* k, radstrlen_type len, 134d3fecca9Ssthen struct radnode** result); 135d3fecca9Ssthen 136d3fecca9Ssthen /** 137d3fecca9Ssthen * Return the first (smallest) element in the tree. 138d3fecca9Ssthen * @param rt: the radix tree. 139d3fecca9Ssthen * @return: first node or NULL if none. 140d3fecca9Ssthen */ 141d3fecca9Ssthen struct radnode* radix_first(struct radtree* rt); 142d3fecca9Ssthen 143d3fecca9Ssthen /** 144d3fecca9Ssthen * Return the last (largest) element in the tree. 145d3fecca9Ssthen * @param rt: the radix tree. 146d3fecca9Ssthen * @return: last node or NULL if none. 147d3fecca9Ssthen */ 148d3fecca9Ssthen struct radnode* radix_last(struct radtree* rt); 149d3fecca9Ssthen 150d3fecca9Ssthen /** 151d3fecca9Ssthen * Return the next element. 152d3fecca9Ssthen * @param n: the element to go from. 153d3fecca9Ssthen * @return: next node or NULL if none. 154d3fecca9Ssthen */ 155d3fecca9Ssthen struct radnode* radix_next(struct radnode* n); 156d3fecca9Ssthen 157d3fecca9Ssthen /** 158d3fecca9Ssthen * Return the previous element. 159d3fecca9Ssthen * @param n: the element to go from. 160d3fecca9Ssthen * @return: prev node or NULL if none. 161d3fecca9Ssthen */ 162d3fecca9Ssthen struct radnode* radix_prev(struct radnode* n); 163d3fecca9Ssthen 164d3fecca9Ssthen /* 165d3fecca9Ssthen * Perform a walk through all elements of the tree. 166d3fecca9Ssthen * node: variable of type struct radnode*. 167d3fecca9Ssthen * tree: pointer to the tree. 168d3fecca9Ssthen * for(node=radix_first(tree); node; node=radix_next(node)) 169d3fecca9Ssthen */ 170d3fecca9Ssthen 171d3fecca9Ssthen /** 172d3fecca9Ssthen * Create a binary string to represent a domain name 173d3fecca9Ssthen * @param k: string buffer to store into 174d3fecca9Ssthen * @param len: output length, initially, the max, output the result. 175d3fecca9Ssthen * @param dname: the domain name to convert, in wireformat. 176d3fecca9Ssthen * @param dlen: length of space for dname. 177d3fecca9Ssthen */ 178fe5fe5f6Sflorian void radname_d2r(uint8_t* k, radstrlen_type* len, const uint8_t* dname, 179d3fecca9Ssthen size_t dlen); 180d3fecca9Ssthen 181d3fecca9Ssthen /** 182d3fecca9Ssthen * Convert a binary string back to a domain name. 183d3fecca9Ssthen * @param k: the binary string. 184d3fecca9Ssthen * @param len: length of k. 185d3fecca9Ssthen * @param dname: buffer to store domain name into. 186d3fecca9Ssthen * @param dlen: length of dname (including root label). 187d3fecca9Ssthen */ 188fe5fe5f6Sflorian void radname_r2d(uint8_t* k, radstrlen_type len, uint8_t* dname, size_t* dlen); 189d3fecca9Ssthen 190d3fecca9Ssthen /** 191d3fecca9Ssthen * Search the radix tree using a domain name. 192d3fecca9Ssthen * The name is internally converted to a radname. 193d3fecca9Ssthen * @param rt: tree 194d3fecca9Ssthen * @param d: domain name, no compression pointers allowed. 195d3fecca9Ssthen * @param max: max length to go from d. 196d3fecca9Ssthen * @return NULL on parse error or if not found. 197d3fecca9Ssthen */ 198d3fecca9Ssthen struct radnode* radname_search(struct radtree* rt, const uint8_t* d, 199d3fecca9Ssthen size_t max); 200d3fecca9Ssthen 201d3fecca9Ssthen /** 202d3fecca9Ssthen * Find radix element in tree by domain name, and if not found, 203d3fecca9Ssthen * find the closest smaller or equal element in the tree. 204d3fecca9Ssthen * The name is internally converted to a radname (same sorting order). 205d3fecca9Ssthen * @param rt: the radix tree. 206d3fecca9Ssthen * @param d: domain name, no compression pointers allowed. 207d3fecca9Ssthen * @param max: max length to go from d. 208d3fecca9Ssthen * @param result: returns the radix node or closest match (NULL if key is 209d3fecca9Ssthen * smaller than the smallest key in the tree). 210d3fecca9Ssthen * could result in NULL on a parse error as well (with return false). 211d3fecca9Ssthen * @return true if exact match, false if no match. 212d3fecca9Ssthen */ 213d3fecca9Ssthen int radname_find_less_equal(struct radtree* rt, const uint8_t* d, size_t max, 214d3fecca9Ssthen struct radnode** result); 215d3fecca9Ssthen 216d3fecca9Ssthen /** 217d3fecca9Ssthen * Insert radix element by domain name. 218d3fecca9Ssthen * @param rt: the radix tree 219d3fecca9Ssthen * @param d: domain name, no compression pointers. 220d3fecca9Ssthen * @param max: max length from d. 221d3fecca9Ssthen * @param elem: the element pointer to insert. 222d3fecca9Ssthen * @return NULL on failure - out of memory. 223d3fecca9Ssthen * NULL on failure - duplicate entry. 224d3fecca9Ssthen * NULL on failure - parse error. 225d3fecca9Ssthen * On success the radix node for this element. 226d3fecca9Ssthen */ 227d3fecca9Ssthen struct radnode* radname_insert(struct radtree* rt, const uint8_t* d, 228d3fecca9Ssthen size_t max, void* elem); 229d3fecca9Ssthen 230d3fecca9Ssthen /** 231d3fecca9Ssthen * Delete element by domain name from radix tree. 232d3fecca9Ssthen * @param rt: the radix tree. 233d3fecca9Ssthen * @param d: the domain name. If it is not in the tree nothing happens. 234d3fecca9Ssthen * @param max: max length. 235d3fecca9Ssthen */ 236d3fecca9Ssthen void radname_delete(struct radtree* rt, const uint8_t* d, size_t max); 237d3fecca9Ssthen 238d3fecca9Ssthen /** number of bytes in common in strings */ 239fe5fe5f6Sflorian radstrlen_type bstr_common_ext(uint8_t* x, radstrlen_type xlen, uint8_t* y, 240fe5fe5f6Sflorian radstrlen_type ylen); 241d3fecca9Ssthen /** true if one is prefix of the other */ 242fe5fe5f6Sflorian int bstr_is_prefix_ext(uint8_t* p, radstrlen_type plen, uint8_t* x, 243fe5fe5f6Sflorian radstrlen_type xlen); 244d3fecca9Ssthen 245d3fecca9Ssthen #endif /* RADTREE_H */ 246