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;
98865f46b2SCy Schubert 	/** Only use the element for queries for subnet/0. Set if the query
99865f46b2SCy Schubert 	 * for /0 was answered with scope 0. For query /x answer scope 0,
100865f46b2SCy Schubert 	 * they can match anything and this is false. */
101865f46b2SCy 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.
164865f46b2SCy 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,
169865f46b2SCy 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