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