165b390aaSDag-Erling Smørgrav /* 265b390aaSDag-Erling Smørgrav * edns-subnet/addrtree.h -- radix tree for edns subnet cache. 365b390aaSDag-Erling Smørgrav * 465b390aaSDag-Erling Smørgrav * Copyright (c) 2013, NLnet Labs. All rights reserved. 565b390aaSDag-Erling Smørgrav * 665b390aaSDag-Erling Smørgrav * This software is open source. 765b390aaSDag-Erling Smørgrav * 865b390aaSDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 965b390aaSDag-Erling Smørgrav * modification, are permitted provided that the following conditions 1065b390aaSDag-Erling Smørgrav * are met: 1165b390aaSDag-Erling Smørgrav * 1265b390aaSDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice, 1365b390aaSDag-Erling Smørgrav * this list of conditions and the following disclaimer. 1465b390aaSDag-Erling Smørgrav * 1565b390aaSDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice, 1665b390aaSDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation 1765b390aaSDag-Erling Smørgrav * and/or other materials provided with the distribution. 1865b390aaSDag-Erling Smørgrav * 1965b390aaSDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may 2065b390aaSDag-Erling Smørgrav * be used to endorse or promote products derived from this software without 2165b390aaSDag-Erling Smørgrav * specific prior written permission. 2265b390aaSDag-Erling Smørgrav * 2365b390aaSDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2465b390aaSDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2565b390aaSDag-Erling Smørgrav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2665b390aaSDag-Erling Smørgrav * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2765b390aaSDag-Erling Smørgrav * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2865b390aaSDag-Erling Smørgrav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2965b390aaSDag-Erling Smørgrav * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 3065b390aaSDag-Erling Smørgrav * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 3165b390aaSDag-Erling Smørgrav * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 3265b390aaSDag-Erling Smørgrav * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3365b390aaSDag-Erling Smørgrav * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3465b390aaSDag-Erling Smørgrav */ 3565b390aaSDag-Erling Smørgrav 3665b390aaSDag-Erling Smørgrav /** 3765b390aaSDag-Erling Smørgrav * \file 3865b390aaSDag-Erling Smørgrav * The addrtree is a radix tree designed for edns subnet. Most notable 3965b390aaSDag-Erling Smørgrav * is the addition of 'scope' to a node. Scope is only relevant for 4065b390aaSDag-Erling Smørgrav * nodes with elem set, it indicates the number of bits the authority 4165b390aaSDag-Erling Smørgrav * desires. 4265b390aaSDag-Erling Smørgrav * 4365b390aaSDag-Erling Smørgrav * For retrieving data one needs an address and address length 4465b390aaSDag-Erling Smørgrav * (sourcemask). While traversing the tree the first matching node is 4565b390aaSDag-Erling Smørgrav * returned. A node matches when 4665b390aaSDag-Erling Smørgrav * node.scope<=sourcemask && node.elem!=NULL 4765b390aaSDag-Erling Smørgrav * (This is the most specific answer the authority has.) 4865b390aaSDag-Erling Smørgrav * or 4965b390aaSDag-Erling Smørgrav * node.sourcemask==sourcemask && node.elem!=NULL 5065b390aaSDag-Erling Smørgrav * (This is the most specific question the client can ask.) 5165b390aaSDag-Erling Smørgrav * 5265b390aaSDag-Erling Smørgrav * Insertion needs an address, sourcemask and scope. The length of the 5365b390aaSDag-Erling Smørgrav * address is capped by min(sourcemask, scope). While traversing the 5465b390aaSDag-Erling Smørgrav * tree the scope of all visited nodes is updated. This ensures we are 5565b390aaSDag-Erling Smørgrav * always able to find the most specific answer available. 5665b390aaSDag-Erling Smørgrav */ 5765b390aaSDag-Erling Smørgrav 5865b390aaSDag-Erling Smørgrav #ifndef ADDRTREE_H 5965b390aaSDag-Erling Smørgrav #define ADDRTREE_H 6065b390aaSDag-Erling Smørgrav 6165b390aaSDag-Erling Smørgrav typedef uint8_t addrlen_t; 6265b390aaSDag-Erling Smørgrav typedef uint8_t addrkey_t; 6365b390aaSDag-Erling Smørgrav #define KEYWIDTH 8 6465b390aaSDag-Erling Smørgrav 6565b390aaSDag-Erling Smørgrav struct addrtree { 6665b390aaSDag-Erling Smørgrav struct addrnode *root; 6765b390aaSDag-Erling Smørgrav /** Number of elements in the tree (not always equal to number of 6865b390aaSDag-Erling Smørgrav * nodes) */ 69e86b9096SDag-Erling Smørgrav uint32_t node_count; 7065b390aaSDag-Erling Smørgrav /** Maximum number of allowed nodes, will be enforced by LRU list. 7165b390aaSDag-Erling Smørgrav * Excluding the root node, 0 for unlimited */ 72e86b9096SDag-Erling Smørgrav uint32_t max_node_count; 7365b390aaSDag-Erling Smørgrav /** Size of tree in bytes */ 7465b390aaSDag-Erling Smørgrav size_t size_bytes; 7565b390aaSDag-Erling Smørgrav /** Maximum prefix length we are willing to cache. */ 7665b390aaSDag-Erling Smørgrav addrlen_t max_depth; 7765b390aaSDag-Erling Smørgrav /** External function to delete elem. Called as 7865b390aaSDag-Erling Smørgrav * delfunc(addrnode->elem, addrtree->env) */ 7965b390aaSDag-Erling Smørgrav void (*delfunc)(void *, void *); 8065b390aaSDag-Erling Smørgrav /** Environment for delfunc */ 8165b390aaSDag-Erling Smørgrav void *env; 8265b390aaSDag-Erling Smørgrav /** External function returning size of elem. Called as 8365b390aaSDag-Erling Smørgrav * sizefunc(addrnode->elem) */ 8465b390aaSDag-Erling Smørgrav size_t (*sizefunc)(void *); 8565b390aaSDag-Erling Smørgrav /** first node in LRU list, first candidate to go */ 8665b390aaSDag-Erling Smørgrav struct addrnode* first; 8765b390aaSDag-Erling Smørgrav /** last node in LRU list, last candidate to go */ 8865b390aaSDag-Erling Smørgrav struct addrnode *last; 8965b390aaSDag-Erling Smørgrav }; 9065b390aaSDag-Erling Smørgrav 9165b390aaSDag-Erling Smørgrav struct addrnode { 9265b390aaSDag-Erling Smørgrav /** Payload of node, may be NULL */ 9365b390aaSDag-Erling Smørgrav void *elem; 9465b390aaSDag-Erling Smørgrav /** Abs time in seconds in which elem is meaningful */ 9565b390aaSDag-Erling Smørgrav time_t ttl; 9665b390aaSDag-Erling Smørgrav /** Number of significant bits in address. */ 9765b390aaSDag-Erling Smørgrav addrlen_t scope; 98*865f46b2SCy Schubert /** Only use the element for queries for subnet/0. Set if the query 99*865f46b2SCy Schubert * for /0 was answered with scope 0. For query /x answer scope 0, 100*865f46b2SCy Schubert * they can match anything and this is false. */ 101*865f46b2SCy Schubert int only_match_scope_zero; 10265b390aaSDag-Erling Smørgrav /** A node can have 0-2 edges, set to NULL for unused */ 10365b390aaSDag-Erling Smørgrav struct addredge *edge[2]; 10465b390aaSDag-Erling Smørgrav /** edge between this node and parent */ 10565b390aaSDag-Erling Smørgrav struct addredge *parent_edge; 10665b390aaSDag-Erling Smørgrav /** previous node in LRU list */ 10765b390aaSDag-Erling Smørgrav struct addrnode *prev; 10865b390aaSDag-Erling Smørgrav /** next node in LRU list */ 10965b390aaSDag-Erling Smørgrav struct addrnode *next; 11065b390aaSDag-Erling Smørgrav }; 11165b390aaSDag-Erling Smørgrav 11265b390aaSDag-Erling Smørgrav struct addredge { 11365b390aaSDag-Erling Smørgrav /** address of connected node */ 11465b390aaSDag-Erling Smørgrav addrkey_t *str; 1158a384985SDag-Erling Smørgrav /** length in bits of str */ 11665b390aaSDag-Erling Smørgrav addrlen_t len; 11765b390aaSDag-Erling Smørgrav /** child node this edge is connected to */ 11865b390aaSDag-Erling Smørgrav struct addrnode *node; 11965b390aaSDag-Erling Smørgrav /** Parent node this ege is connected to */ 12065b390aaSDag-Erling Smørgrav struct addrnode *parent_node; 12165b390aaSDag-Erling Smørgrav /** Index of this edge in parent_node */ 12265b390aaSDag-Erling Smørgrav int parent_index; 12365b390aaSDag-Erling Smørgrav }; 12465b390aaSDag-Erling Smørgrav 12565b390aaSDag-Erling Smørgrav /** 12665b390aaSDag-Erling Smørgrav * Size of tree in bytes. 12765b390aaSDag-Erling Smørgrav * @param tree: Tree. 12865b390aaSDag-Erling Smørgrav * @return size of tree in bytes. 12965b390aaSDag-Erling Smørgrav */ 13065b390aaSDag-Erling Smørgrav size_t addrtree_size(const struct addrtree *tree); 13165b390aaSDag-Erling Smørgrav 13265b390aaSDag-Erling Smørgrav /** 13365b390aaSDag-Erling Smørgrav * Create a new tree. 13465b390aaSDag-Erling Smørgrav * @param max_depth: Tree will cap keys to this length. 13565b390aaSDag-Erling Smørgrav * @param delfunc: f(element, env) delete element. 13665b390aaSDag-Erling Smørgrav * @param sizefunc: f(element) returning the size of element. 13765b390aaSDag-Erling Smørgrav * @param env: Module environment for alloc information. 13865b390aaSDag-Erling Smørgrav * @param max_node_count: Maximum size of this data structure in nodes. 13965b390aaSDag-Erling Smørgrav * 0 for unlimited. 14065b390aaSDag-Erling Smørgrav * @return new addrtree or NULL on failure. 14165b390aaSDag-Erling Smørgrav */ 14265b390aaSDag-Erling Smørgrav struct addrtree * 14365b390aaSDag-Erling Smørgrav addrtree_create(addrlen_t max_depth, void (*delfunc)(void *, void *), 144e86b9096SDag-Erling Smørgrav size_t (*sizefunc)(void *), void *env, uint32_t max_node_count); 14565b390aaSDag-Erling Smørgrav 14665b390aaSDag-Erling Smørgrav /** 14765b390aaSDag-Erling Smørgrav * Free tree and all nodes below. 14865b390aaSDag-Erling Smørgrav * @param tree: Tree to be freed. 14965b390aaSDag-Erling Smørgrav */ 15065b390aaSDag-Erling Smørgrav void addrtree_delete(struct addrtree *tree); 15165b390aaSDag-Erling Smørgrav 15265b390aaSDag-Erling Smørgrav /** 15365b390aaSDag-Erling Smørgrav * Insert an element in the tree. Failures are silent. Sourcemask and 15465b390aaSDag-Erling Smørgrav * scope might be changed according to local policy. Caller should no 15565b390aaSDag-Erling Smørgrav * longer access elem, it could be free'd now or later during future 15665b390aaSDag-Erling Smørgrav * inserts. 15765b390aaSDag-Erling Smørgrav * 15865b390aaSDag-Erling Smørgrav * @param tree: Tree insert elem in. 15965b390aaSDag-Erling Smørgrav * @param addr: key for element lookup. 16065b390aaSDag-Erling Smørgrav * @param sourcemask: Length of addr in bits. 16165b390aaSDag-Erling Smørgrav * @param scope: Number of significant bits in addr. 16265b390aaSDag-Erling Smørgrav * @param elem: data to store in the tree. 16365b390aaSDag-Erling Smørgrav * @param ttl: elem is valid up to this time, seconds. 164*865f46b2SCy Schubert * @param only_match_scope_zero: set for when query /0 has scope /0 answer. 16565b390aaSDag-Erling Smørgrav * @param now: Current time in seconds. 16665b390aaSDag-Erling Smørgrav */ 16765b390aaSDag-Erling Smørgrav void addrtree_insert(struct addrtree *tree, const addrkey_t *addr, 16865b390aaSDag-Erling Smørgrav addrlen_t sourcemask, addrlen_t scope, void *elem, time_t ttl, 169*865f46b2SCy Schubert time_t now, int only_match_scope_zero); 17065b390aaSDag-Erling Smørgrav 17165b390aaSDag-Erling Smørgrav /** 17265b390aaSDag-Erling Smørgrav * Find a node containing an element in the tree. 17365b390aaSDag-Erling Smørgrav * 17465b390aaSDag-Erling Smørgrav * @param tree: Tree to search. 17565b390aaSDag-Erling Smørgrav * @param addr: key for element lookup. 17665b390aaSDag-Erling Smørgrav * @param sourcemask: Length of addr in bits. 17765b390aaSDag-Erling Smørgrav * @param now: Current time in seconds. 17865b390aaSDag-Erling Smørgrav * @return addrnode or NULL on miss. 17965b390aaSDag-Erling Smørgrav */ 18065b390aaSDag-Erling Smørgrav struct addrnode * addrtree_find(struct addrtree *tree, 18165b390aaSDag-Erling Smørgrav const addrkey_t *addr, addrlen_t sourcemask, time_t now); 18265b390aaSDag-Erling Smørgrav 18365b390aaSDag-Erling Smørgrav /** Wrappers for static functions to unit test */ 18465b390aaSDag-Erling Smørgrav int unittest_wrapper_addrtree_cmpbit(const addrkey_t *key1, 18565b390aaSDag-Erling Smørgrav const addrkey_t *key2, addrlen_t n); 18665b390aaSDag-Erling Smørgrav addrlen_t unittest_wrapper_addrtree_bits_common(const addrkey_t *s1, 18765b390aaSDag-Erling Smørgrav addrlen_t l1, const addrkey_t *s2, addrlen_t l2, addrlen_t skip); 18865b390aaSDag-Erling Smørgrav int unittest_wrapper_addrtree_getbit(const addrkey_t *addr, 18965b390aaSDag-Erling Smørgrav addrlen_t addrlen, addrlen_t n); 19065b390aaSDag-Erling Smørgrav int unittest_wrapper_addrtree_issub(const addrkey_t *s1, addrlen_t l1, 19165b390aaSDag-Erling Smørgrav const addrkey_t *s2, addrlen_t l2, addrlen_t skip); 19265b390aaSDag-Erling Smørgrav #endif /* ADDRTREE_H */ 193