1/*
2 * Copyright (C) 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17/* $Id: radix.h,v 1.13 2008/12/01 23:47:45 tbox Exp $ */
18
19/*
20 * This source was adapted from MRT's RCS Ids:
21 * Id: radix.h,v 1.6 1999/08/03 03:32:53 masaki Exp
22 * Id: mrt.h,v 1.57.2.6 1999/12/28 23:41:27 labovit Exp
23 * Id: defs.h,v 1.5.2.2 2000/01/15 14:19:16 masaki Exp
24 */
25
26#include <isc/magic.h>
27#include <isc/types.h>
28#include <isc/mutex.h>
29#include <isc/net.h>
30#include <isc/refcount.h>
31
32#include <string.h>
33
34#ifndef _RADIX_H
35#define _RADIX_H
36
37#define NETADDR_TO_PREFIX_T(na,pt,bits) \
38	do { \
39		memset(&(pt), 0, sizeof(pt)); \
40		if((na) != NULL) { \
41			(pt).family = (na)->family; \
42			(pt).bitlen = (bits); \
43			if ((pt).family == AF_INET6) { \
44				memcpy(&(pt).add.sin6, &(na)->type.in6, \
45				       ((bits)+7)/8); \
46			} else \
47				memcpy(&(pt).add.sin, &(na)->type.in, \
48				       ((bits)+7)/8); \
49		} else { \
50			(pt).family = AF_UNSPEC; \
51			(pt).bitlen = 0; \
52		} \
53		isc_refcount_init(&(pt).refcount, 0); \
54	} while(0)
55
56typedef struct isc_prefix {
57    unsigned int family;	/* AF_INET | AF_INET6, or AF_UNSPEC for "any" */
58    unsigned int bitlen;	/* 0 for "any" */
59    isc_refcount_t refcount;
60    union {
61		struct in_addr sin;
62		struct in6_addr sin6;
63    } add;
64} isc_prefix_t;
65
66typedef void (*isc_radix_destroyfunc_t)(void *);
67typedef void (*isc_radix_processfunc_t)(isc_prefix_t *, void **);
68
69#define isc_prefix_tochar(prefix) ((char *)&(prefix)->add.sin)
70#define isc_prefix_touchar(prefix) ((u_char *)&(prefix)->add.sin)
71
72#define BIT_TEST(f, b)  ((f) & (b))
73
74/*
75 * We need "first match" when we search the radix tree to preserve
76 * compatibility with the existing ACL implementation. Radix trees
77 * naturally lend themselves to "best match". In order to get "first match"
78 * behavior, we keep track of the order in which entries are added to the
79 * tree--and when a search is made, we find all matching entries, and
80 * return the one that was added first.
81 *
82 * An IPv4 prefix and an IPv6 prefix may share a radix tree node if they
83 * have the same length and bit pattern (e.g., 127/8 and 7f::/8).  To
84 * disambiguate between them, node_num and data are two-element arrays;
85 * node_num[0] and data[0] are used for IPv4 addresses, node_num[1]
86 * and data[1] for IPv6 addresses.  The only exception is a prefix of
87 * 0/0 (aka "any" or "none"), which is always stored as IPv4 but matches
88 * IPv6 addresses too.
89 */
90
91#define ISC_IS6(family) ((family) == AF_INET6 ? 1 : 0)
92typedef struct isc_radix_node {
93   isc_uint32_t bit;			/* bit length of the prefix */
94   isc_prefix_t *prefix;		/* who we are in radix tree */
95   struct isc_radix_node *l, *r;	/* left and right children */
96   struct isc_radix_node *parent;	/* may be used */
97   void *data[2];			/* pointers to IPv4 and IPV6 data */
98   int node_num[2];			/* which node this was in the tree,
99					   or -1 for glue nodes */
100} isc_radix_node_t;
101
102#define RADIX_TREE_MAGIC         ISC_MAGIC('R','d','x','T');
103#define RADIX_TREE_VALID(a)      ISC_MAGIC_VALID(a, RADIX_TREE_MAGIC);
104
105typedef struct isc_radix_tree {
106   unsigned int		magic;
107   isc_mem_t		*mctx;
108   isc_radix_node_t 	*head;
109   isc_uint32_t		maxbits;	/* for IP, 32 bit addresses */
110   int num_active_node;			/* for debugging purposes */
111   int num_added_node;			/* total number of nodes */
112} isc_radix_tree_t;
113
114isc_result_t
115isc_radix_search(isc_radix_tree_t *radix, isc_radix_node_t **target,
116		 isc_prefix_t *prefix);
117/*%<
118 * Search 'radix' for the best match to 'prefix'.
119 * Return the node found in '*target'.
120 *
121 * Requires:
122 * \li	'radix' to be valid.
123 * \li	'target' is not NULL and "*target" is NULL.
124 * \li	'prefix' to be valid.
125 *
126 * Returns:
127 * \li	ISC_R_NOTFOUND
128 * \li	ISC_R_SUCCESS
129 */
130
131isc_result_t
132isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
133		 isc_radix_node_t *source, isc_prefix_t *prefix);
134/*%<
135 * Insert 'source' or 'prefix' into the radix tree 'radix'.
136 * Return the node added in 'target'.
137 *
138 * Requires:
139 * \li	'radix' to be valid.
140 * \li	'target' is not NULL and "*target" is NULL.
141 * \li	'prefix' to be valid or 'source' to be non NULL and contain
142 *	a valid prefix.
143 *
144 * Returns:
145 * \li	ISC_R_NOMEMORY
146 * \li	ISC_R_SUCCESS
147 */
148
149void
150isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node);
151/*%<
152 * Remove the node 'node' from the radix tree 'radix'.
153 *
154 * Requires:
155 * \li	'radix' to be valid.
156 * \li	'node' to be valid.
157 */
158
159isc_result_t
160isc_radix_create(isc_mem_t *mctx, isc_radix_tree_t **target, int maxbits);
161/*%<
162 * Create a radix tree with a maximum depth of 'maxbits';
163 *
164 * Requires:
165 * \li	'mctx' to be valid.
166 * \li	'target' to be non NULL and '*target' to be NULL.
167 * \li	'maxbits' to be less than or equal to RADIX_MAXBITS.
168 *
169 * Returns:
170 * \li	ISC_R_NOMEMORY
171 * \li	ISC_R_SUCCESS
172 */
173
174void
175isc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func);
176/*%<
177 * Destroy a radix tree optionally calling 'func' to clean up node data.
178 *
179 * Requires:
180 * \li	'radix' to be valid.
181 */
182
183void
184isc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func);
185/*%<
186 * Walk a radix tree calling 'func' to process node data.
187 *
188 * Requires:
189 * \li	'radix' to be valid.
190 * \li	'func' to point to a function.
191 */
192
193#define RADIX_MAXBITS 128
194#define RADIX_NBIT(x)        (0x80 >> ((x) & 0x7f))
195#define RADIX_NBYTE(x)       ((x) >> 3)
196
197#define RADIX_DATA_GET(node, type) (type *)((node)->data)
198#define RADIX_DATA_SET(node, value) ((node)->data = (void *)(value))
199
200#define RADIX_WALK(Xhead, Xnode) \
201    do { \
202	isc_radix_node_t *Xstack[RADIX_MAXBITS+1]; \
203	isc_radix_node_t **Xsp = Xstack; \
204	isc_radix_node_t *Xrn = (Xhead); \
205	while ((Xnode = Xrn)) { \
206	    if (Xnode->prefix)
207
208#define RADIX_WALK_ALL(Xhead, Xnode) \
209do { \
210	isc_radix_node_t *Xstack[RADIX_MAXBITS+1]; \
211	isc_radix_node_t **Xsp = Xstack; \
212	isc_radix_node_t *Xrn = (Xhead); \
213	while ((Xnode = Xrn)) { \
214	    if (1)
215
216#define RADIX_WALK_BREAK { \
217	    if (Xsp != Xstack) { \
218		Xrn = *(--Xsp); \
219	     } else { \
220		Xrn = (radix_node_t *) 0; \
221	    } \
222	    continue; }
223
224#define RADIX_WALK_END \
225	    if (Xrn->l) { \
226		if (Xrn->r) { \
227		    *Xsp++ = Xrn->r; \
228		} \
229		Xrn = Xrn->l; \
230	    } else if (Xrn->r) { \
231		Xrn = Xrn->r; \
232	    } else if (Xsp != Xstack) { \
233		Xrn = *(--Xsp); \
234	    } else { \
235		Xrn = (isc_radix_node_t *) 0; \
236	    } \
237	} \
238    } while (0)
239
240#endif /* _RADIX_H */
241