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) */ 6965b390aaSDag-Erling Smørgrav unsigned int 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 */ 7265b390aaSDag-Erling Smørgrav unsigned int 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; 9865b390aaSDag-Erling Smørgrav /** A node can have 0-2 edges, set to NULL for unused */ 9965b390aaSDag-Erling Smørgrav struct addredge *edge[2]; 10065b390aaSDag-Erling Smørgrav /** edge between this node and parent */ 10165b390aaSDag-Erling Smørgrav struct addredge *parent_edge; 10265b390aaSDag-Erling Smørgrav /** previous node in LRU list */ 10365b390aaSDag-Erling Smørgrav struct addrnode *prev; 10465b390aaSDag-Erling Smørgrav /** next node in LRU list */ 10565b390aaSDag-Erling Smørgrav struct addrnode *next; 10665b390aaSDag-Erling Smørgrav }; 10765b390aaSDag-Erling Smørgrav 10865b390aaSDag-Erling Smørgrav struct addredge { 10965b390aaSDag-Erling Smørgrav /** address of connected node */ 11065b390aaSDag-Erling Smørgrav addrkey_t *str; 111*8a384985SDag-Erling Smørgrav /** length in bits of str */ 11265b390aaSDag-Erling Smørgrav addrlen_t len; 11365b390aaSDag-Erling Smørgrav /** child node this edge is connected to */ 11465b390aaSDag-Erling Smørgrav struct addrnode *node; 11565b390aaSDag-Erling Smørgrav /** Parent node this ege is connected to */ 11665b390aaSDag-Erling Smørgrav struct addrnode *parent_node; 11765b390aaSDag-Erling Smørgrav /** Index of this edge in parent_node */ 11865b390aaSDag-Erling Smørgrav int parent_index; 11965b390aaSDag-Erling Smørgrav }; 12065b390aaSDag-Erling Smørgrav 12165b390aaSDag-Erling Smørgrav /** 12265b390aaSDag-Erling Smørgrav * Size of tree in bytes. 12365b390aaSDag-Erling Smørgrav * @param tree: Tree. 12465b390aaSDag-Erling Smørgrav * @return size of tree in bytes. 12565b390aaSDag-Erling Smørgrav */ 12665b390aaSDag-Erling Smørgrav size_t addrtree_size(const struct addrtree *tree); 12765b390aaSDag-Erling Smørgrav 12865b390aaSDag-Erling Smørgrav /** 12965b390aaSDag-Erling Smørgrav * Create a new tree. 13065b390aaSDag-Erling Smørgrav * @param max_depth: Tree will cap keys to this length. 13165b390aaSDag-Erling Smørgrav * @param delfunc: f(element, env) delete element. 13265b390aaSDag-Erling Smørgrav * @param sizefunc: f(element) returning the size of element. 13365b390aaSDag-Erling Smørgrav * @param env: Module environment for alloc information. 13465b390aaSDag-Erling Smørgrav * @param max_node_count: Maximum size of this data structure in nodes. 13565b390aaSDag-Erling Smørgrav * 0 for unlimited. 13665b390aaSDag-Erling Smørgrav * @return new addrtree or NULL on failure. 13765b390aaSDag-Erling Smørgrav */ 13865b390aaSDag-Erling Smørgrav struct addrtree * 13965b390aaSDag-Erling Smørgrav addrtree_create(addrlen_t max_depth, void (*delfunc)(void *, void *), 14065b390aaSDag-Erling Smørgrav size_t (*sizefunc)(void *), void *env, unsigned int max_node_count); 14165b390aaSDag-Erling Smørgrav 14265b390aaSDag-Erling Smørgrav /** 14365b390aaSDag-Erling Smørgrav * Free tree and all nodes below. 14465b390aaSDag-Erling Smørgrav * @param tree: Tree to be freed. 14565b390aaSDag-Erling Smørgrav */ 14665b390aaSDag-Erling Smørgrav void addrtree_delete(struct addrtree *tree); 14765b390aaSDag-Erling Smørgrav 14865b390aaSDag-Erling Smørgrav /** 14965b390aaSDag-Erling Smørgrav * Insert an element in the tree. Failures are silent. Sourcemask and 15065b390aaSDag-Erling Smørgrav * scope might be changed according to local policy. Caller should no 15165b390aaSDag-Erling Smørgrav * longer access elem, it could be free'd now or later during future 15265b390aaSDag-Erling Smørgrav * inserts. 15365b390aaSDag-Erling Smørgrav * 15465b390aaSDag-Erling Smørgrav * @param tree: Tree insert elem in. 15565b390aaSDag-Erling Smørgrav * @param addr: key for element lookup. 15665b390aaSDag-Erling Smørgrav * @param sourcemask: Length of addr in bits. 15765b390aaSDag-Erling Smørgrav * @param scope: Number of significant bits in addr. 15865b390aaSDag-Erling Smørgrav * @param elem: data to store in the tree. 15965b390aaSDag-Erling Smørgrav * @param ttl: elem is valid up to this time, seconds. 16065b390aaSDag-Erling Smørgrav * @param now: Current time in seconds. 16165b390aaSDag-Erling Smørgrav */ 16265b390aaSDag-Erling Smørgrav void addrtree_insert(struct addrtree *tree, const addrkey_t *addr, 16365b390aaSDag-Erling Smørgrav addrlen_t sourcemask, addrlen_t scope, void *elem, time_t ttl, 16465b390aaSDag-Erling Smørgrav time_t now); 16565b390aaSDag-Erling Smørgrav 16665b390aaSDag-Erling Smørgrav /** 16765b390aaSDag-Erling Smørgrav * Find a node containing an element in the tree. 16865b390aaSDag-Erling Smørgrav * 16965b390aaSDag-Erling Smørgrav * @param tree: Tree to search. 17065b390aaSDag-Erling Smørgrav * @param addr: key for element lookup. 17165b390aaSDag-Erling Smørgrav * @param sourcemask: Length of addr in bits. 17265b390aaSDag-Erling Smørgrav * @param now: Current time in seconds. 17365b390aaSDag-Erling Smørgrav * @return addrnode or NULL on miss. 17465b390aaSDag-Erling Smørgrav */ 17565b390aaSDag-Erling Smørgrav struct addrnode * addrtree_find(struct addrtree *tree, 17665b390aaSDag-Erling Smørgrav const addrkey_t *addr, addrlen_t sourcemask, time_t now); 17765b390aaSDag-Erling Smørgrav 17865b390aaSDag-Erling Smørgrav /** Wrappers for static functions to unit test */ 17965b390aaSDag-Erling Smørgrav int unittest_wrapper_addrtree_cmpbit(const addrkey_t *key1, 18065b390aaSDag-Erling Smørgrav const addrkey_t *key2, addrlen_t n); 18165b390aaSDag-Erling Smørgrav addrlen_t unittest_wrapper_addrtree_bits_common(const addrkey_t *s1, 18265b390aaSDag-Erling Smørgrav addrlen_t l1, const addrkey_t *s2, addrlen_t l2, addrlen_t skip); 18365b390aaSDag-Erling Smørgrav int unittest_wrapper_addrtree_getbit(const addrkey_t *addr, 18465b390aaSDag-Erling Smørgrav addrlen_t addrlen, addrlen_t n); 18565b390aaSDag-Erling Smørgrav int unittest_wrapper_addrtree_issub(const addrkey_t *s1, addrlen_t l1, 18665b390aaSDag-Erling Smørgrav const addrkey_t *s2, addrlen_t l2, addrlen_t skip); 18765b390aaSDag-Erling Smørgrav #endif /* ADDRTREE_H */ 188