1 | /***************************************
2 | $Revision: 1.13 $
3 |
4 | Radix tree (rx). rxroutines.h - header file for radix tree handling module.
5 |
6 | Status: NOT REVUED, TESTED
7 |
8 | Design and implementation by: marek
9 |
10 | ******************/ /******************
11 | Copyright (c) 1999 RIPE NCC
12 |
13 | All Rights Reserved
14 |
15 | Permission to use, copy, modify, and distribute this software and its
16 | documentation for any purpose and without fee is hereby granted,
17 | provided that the above copyright notice appear in all copies and that
18 | both that copyright notice and this permission notice appear in
19 | supporting documentation, and that the name of the author not be
20 | used in advertising or publicity pertaining to distribution of the
21 | software without specific, written prior permission.
22 |
23 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
25 | AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
26 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
27 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
28 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29 | ***************************************/
30 |
31 | #ifndef _RX_H
32 | #define _RX_H
33 |
34 | #include <glib.h>
35 | #ifndef G_THREADS_ENABLED
36 | #error "GLib must be compiled with thread support enabled to be MT-Safe"
37 | #endif
38 |
39 | #include <pthread.h>
40 | #include <stubs.h>
41 |
42 | #include <memwrap.h>
43 | #include <stdio.h>
44 | #include <iproutines.h>
45 |
46 | #include <rx_globals.h>
47 | #include "socket.h" /*condat*/
48 |
49 | #include "thread.h" /*rwlock*/
50 |
51 | typedef int rx_regid_t;
52 |
53 | typedef enum {
54 | RX_FAM_RT = 1,
55 | RX_FAM_IN,
56 | RX_FAM_BOTH, /*+ used only in asc_search, meaningless otherwise
57 | Relies on the fact that 1+2=3 :-) (bitmask) +*/
58 | RX_FAM_IP /*+ ~RT but no data leaves between node&payload +*/
59 | } rx_fam_t;
60 |
61 | /*+ the node operation modes +*/
62 | typedef enum {
63 | RX_OPER_CRE = 1,
64 | RX_OPER_MOD,
65 | RX_OPER_DEL
66 | } rx_oper_mt;
67 |
68 |
69 | /*+ stack building modes +*/
70 | typedef enum {
71 | RX_STK_CREAT = 1, /*+ - creation = all glue nodes, stop at first non-glue +*/
72 | RX_STK_QUERY_ALLNOD, /*+ - query = all glue nodes, stop when deep enough */
73 | RX_STK_QUERY_NOGLUE /*+ - query = no glue nodes, stop when deep enough */
74 | } rx_stk_mt;
75 |
76 | /*+ the search modes +*/
77 | typedef enum {
78 | RX_SRCH_CREAT = 1, /*+ special search - does not skip glue nodes +*/
79 | RX_SRCH_EXLESS, /*+ the default search +*/
80 | RX_SRCH_EXACT,
81 | RX_SRCH_LESS,
82 | RX_SRCH_MORE, /*+ more specific search +*/
83 | RX_SRCH_DBLS, /*+ special more spec: return only nodes with
84 | more than one data leaves +*/
85 | RX_SRCH_RANG /*+ more specific range search, RPSL style : ^n-m +*/
86 | } rx_srch_mt;
87 |
88 |
89 | // constant to mean 'unlimited number of answers from a search'
90 | #define RX_ANS_ALL (-1)
91 |
92 | #define RX_ALL_DEPTHS 255
93 |
94 |
95 | /*+ radix tree's memory modes -- not yet implemented +*/
96 | typedef enum {
97 | RX_MEM_RAMONLY,
98 | RX_MEM_RAMSQL,
99 | RX_MEM_SQLONLY
100 | } rx_mem_mt;
101 |
102 |
103 |
104 | /*+ subtree modes -- not yet implemented +*/
105 | typedef enum {
106 | RX_SUB_NONE,
107 | RX_SUB_AUTO,
108 | RX_SUB_HAND
109 | } rx_subtree_mt;
110 |
111 | /* modes for tree traversal (walk_tree) */
112 | typedef enum {
113 | RX_WALK_CNTGLU=1, /*+ default: count also glue nodes and make the level
114 | checking aware of them +*/
115 |
116 | RX_WALK_SKPGLU=2, /*+ only real nodes counted & watched in level checks +*/
117 |
118 | RX_WALK_PRFLEN=4, /*+ make level check a check for prefix length;
119 | still only non-glue nodes are counted +*/
120 | RX_WALK_REVERS=8 /*+ reverse the order of traversing the tree
121 | (first link 1 then 0) +*/
122 | } rx_walk_mt;
123 |
124 |
125 | /*+ A struct for data hooked via a double linked list at a radix node.
126 | Must uniquely define the object for lookups in the SQL tables and/or memory.
127 | Must also contain enough info to let the delete_node choose (and remove)
128 | the proper object from the (linked) list +*/
129 |
130 | typedef struct {
131 | ip_range_t iprange; /*+ for inetnums. empty for routes +*/
132 |
133 | char composed; /*+ non-zero for composed inetnums
134 | equal to: the number of prefixes composing
135 | the range - minus 1 +*/
136 |
137 | void *data_ptr; /*+ to in-memory immediate data +*/
138 | int data_len; /*+ and its length +*/
139 |
140 | sql_key_t data_key; /*+ key to the SQL full-text data record +*/
141 | sql_key_t leaf_key; /*+ pointer to the SQL data leaf record +*/
142 | } rx_dataleaf_t;
143 |
144 | /*+
145 | The struct for radix nodes.
146 |
147 | Must contain prefix, parent, left/right child links in memory and sql,
148 | link to the sql version of the node.
149 | And of course data: pointer to a double linked list of rx_data_t's.
150 | +*/
151 |
152 | typedef struct _rx_node_str {
153 | ip_prefix_t prefix; /*+ who am i. +*/
154 |
155 | char glue;
156 | /*+ now this is an indicator for a node that it
157 | is not holding a real prefix,
158 | but is only a glue node +*/
159 |
160 | GList *leaves_ptr; /*+ a double-linked list of rx_data_t structs
161 | the data leaves can be multiple at each node
162 | (due to a user error the inetnum ranges can
163 | overlap, due to multihoming or error routes
164 | can be duplicated ).
165 | So we link a dynamic thing here +*/
166 |
167 | // sql_key_t leaves_key;
168 | /* "linked list" not needed in sql -
169 | the data leaves can be found in node_leaf
170 | table as those that have
171 | node_key in node_id */
172 |
173 | struct _rx_node_str
174 | *parent_ptr, /*+ radix links in memory +*/
175 | *child_ptr[2]; /*+ NULL means empty +*/
176 |
177 | sql_key_t parent_key, /*+ radix links in SQL +*/
178 | child_key[2]; /*+ zero means empty +*/
179 |
180 | sql_key_t node_key; /*+ key of the corresponding SQL radix node +*/
181 |
182 | } rx_node_t;
183 |
184 |
185 | /*+
186 | rx_tree_t - defines a radix tree.
187 |
188 | includes a pointer(key) to the top node,
189 |
190 | names of the corresponding SQL tables
191 | (they can be generated automatically,
192 | but this is the place to store the result)
193 | Data_table is for data_key.
194 | Radix_table is for parent_id, right_id, left_id, node_id.
195 | Leaves_table is for leaves_key (double linked list in SQL).
196 | +*/
197 |
198 | typedef struct _rx_tree_str {
199 | rx_regid_t reg_id; /*+ registry id +*/
200 | ip_space_t space; /*+ one of IPv4, IPv6 +*/
201 | rx_fam_t family; /*+ one of RT, IN +*/
202 |
203 | rx_subtree_mt subtrees; /*+ one of NONE, AUTO, HAND +*/
204 | rx_mem_mt mem_mode; /*+ where the tree will sit - SQL or RAM +*/
205 | struct rx_tree_str
206 | *parent_tree; /*+ pointer to the parent tree +*/
207 |
208 | ip_prefix_t prefix; /*+ of the IP space this tree covers +*/
209 |
210 | int maxbits; /*+ max depth of this tree
211 | (depends on the space, so it is redundant)+*/
212 | sql_tblnam_t data_table;
213 | sql_tblnam_t radix_table;
214 | sql_tblnam_t leaves_table;
215 |
216 | int num_nodes; /*+ number of nodes in tree - for assertions +*/
217 |
218 | rx_node_t *top_ptr; /*+ pointer to the top node +*/
219 | long top_key; /*+ the same in SQL +*/
220 |
221 | rw_lock_t rwlock; /*+ per-tree reader/writer lock +*/
222 |
223 | } rx_tree_t;
224 |
225 |
226 | /*+ this is a definition of a node copy used for:
227 |
228 | * stack elements returned from rx_stack_build,
229 |
230 | * answer elements from an rx_nod_search.
231 |
232 | It *must* hold pointers to the original locations of it (in terms of
233 | memory and SQL) so that one could actually modify the node...
234 | In SQL tree mode it holds also a copy of a node.
235 | This seems to be unnecessary for in-memory radix trees but is a must
236 | for sql ones.
237 |
238 | WARNING!!!!! The fact that pointers to tree and memory / SQL nodes are
239 | here is a subject to race condition. The location of the tree in the
240 | forest list and the node in memory must not change.
241 |
242 | +*/
243 |
244 | typedef struct {
245 | rx_tree_t *tree; /*+ contains registry_id, space_id, sql table names +*/
246 | rx_node_t *srcptr;
247 | sql_key_t srckey;
248 | rx_node_t cpy; /*+ filled in if the tree is kept in SQL only mode +*/
249 | } rx_nodcpy_t;
250 |
251 |
252 | /*+
253 | This represents one data leaf (by reference). It's used for returning data
254 | from rx_bin_search() to rx_asc_search().
255 | +*/
256 | typedef struct {
257 | sql_key_t srckey;
258 | rx_dataleaf_t *leafptr;
259 | } rx_datref_t;
260 |
261 |
262 | /*+ this is a structure used for returning the data from the search.
263 | It contains a copy of the dataleaf and a pointer to the source +*/
264 | typedef struct {
265 | sql_key_t srckey;
266 | rx_dataleaf_t leafcpy;
267 | } rx_datcpy_t;
268 |
269 |
270 | typedef struct {
271 | rx_node_t *node;
272 | int code;
273 | int datatoo;
274 | rx_tree_t *tree;
275 | } rx_treecheck_t;
276 |
277 | /*
278 | * -----------------------------------------------------------------------
279 | *
280 | * now, THIS is a scrap heap for things that MAY BE useful
281 | */
282 |
283 | /* a definite pointer to an sql object: table name + key
284 | However, it might be nice to include the table TYPE so that one knows
285 | what data it holds :-)
286 | */
287 | typedef struct {
288 | sql_tblnam_t name;
289 | sql_key_t key;
290 | } rx_sqlobj_t;
291 |
292 |
293 | typedef struct {
294 | GList **nodlist;
295 | rx_tree_t *tree;
296 | ip_prefix_t *prefix;
297 | } hook_addnode_userdat_t;
298 |
299 | /********************* P R O T O T Y P E S **********************/
300 |
301 |
302 | void rx_free_list_element(void *cpy, void *trash);
303 | void RX_attach2forest(rx_tree_t *newtree);
304 | er_ret_t
305 | RX_tree_cre (
306 | rx_regid_t reg_id,
307 | ip_space_t spc_id,
308 | rx_fam_t fam_id,
309 | char *prefixstr,
310 | rx_mem_mt mem_mode, // memory only, memory+sql, sql only
311 | rx_subtree_mt subtrees, // NONE, AUTO, HAND
312 | rx_tree_t **treeptr
313 | );
314 | er_ret_t
315 | RX_get_tree ( rx_tree_t **treeptr,
316 | rx_regid_t reg_id,
317 | ip_space_t spc_id,
318 | rx_fam_t fam_id
319 | );
320 |
321 | er_ret_t
322 | RX_bin_search (
323 | rx_srch_mt search_mode,
324 | int par_a,
325 | int par_b,
326 | rx_tree_t *tree, // tree ptr
327 | ip_prefix_t *prefix, // binary prefix
328 | GList **datleaves, // data leaves go here
329 | int max_count
330 | );
331 | er_ret_t
332 | RX_asc_search (
333 | rx_srch_mt search_mode,
334 | int par_a,
335 | int par_b,
336 | char *key, /*+ search term: prefix/range/IP +*/
337 | int reg_id,
338 | ip_space_t spc_id, /*+ space id, one of IPv4 IPv6. +*/
339 | rx_fam_t fam_id, /*+ RX_FAM_RT or RX_FAM_IN +*/
340 | GList **anslist, /*+ answers go here, please +*/
341 | int max_count /*+ # of answers. +*/
342 | );
343 |
344 | er_ret_t
345 | RX_asc_node ( rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/
346 | char *rangstr, /*+ string prefix/range/IP +*/
347 | rx_regid_t reg_id, /*+ id of the registry +*/
348 | ip_space_t spc_id, /*+ type of space (ipv4/ipv6) +*/
349 | rx_fam_t fam_id, /*+ family of objects (route/inetnum) +*/
350 | void *data /*+ pointer to the payload +*/
351 | );
352 | er_ret_t
353 | RX_bin_node (
354 | rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/
355 | ip_prefix_t *newpref, /*+ prefix of the node +*/
356 | rx_tree_t *tree, /*+ pointer to the tree structure +*/
357 | rx_dataleaf_t *dataleaf /*+ dataleaf to attach at the node +*/
358 | );
359 |
360 | er_ret_t
361 | RX_inum_node( rx_oper_mt mode, /*+ MODE={cre|mod|del} +*/
362 | ip_range_t *rang, /*+ range of IP addresses +*/
363 | rx_tree_t *tree, /*+ pointer to the tree structure +*/
364 | rx_dataleaf_t *leafptr /*+ dataleaf to attach at the node +*/
365 | );
366 |
367 | er_ret_t
368 | rx_build_stack(rx_nodcpy_t stack[],
369 | int *maxdepth,
370 | rx_tree_t *tree,
371 | ip_prefix_t *newpref,
372 | rx_stk_mt dmode
373 | );
374 |
375 | er_ret_t
376 | rx_nod_search (
377 | rx_srch_mt search_mode,
378 | int par_a,
379 | int par_b,
380 | /* see rx_asc_search() for explanation */
381 | rx_tree_t *tree, // tree ptr
382 | ip_prefix_t *prefix, // binary prefix
383 |
384 | rx_nodcpy_t stack[], // stack==array of node_copies
385 | int stackcount, // number of element on the stack,
386 | // can come from a creat stack!
387 |
388 | GList **nodlist, // answers go here
389 | int max_count // max # of answers
390 | );
391 | int
392 | rx_walk_tree(rx_node_t *node,
393 | er_ret_t (*func)(rx_node_t *node, int level, int nodecounter,
394 | void *userptr),
395 | rx_walk_mt walk_mode,
396 | int maxlevel,
397 | int level,
398 | int nodecounter,
399 | void *userptr,
400 | er_ret_t *err);
401 |
402 |
403 |
404 | er_ret_t rx_tree_print( sk_conn_st *condat,rx_tree_t *tree );
405 | void rx_space_list(sk_conn_st *condat);
406 | void rx_nod_print( rx_node_t *node, char *buf, int maxchar );
407 | void rx_stk_print( rx_nodcpy_t stack[], int stackdepth );
408 |
409 | #undef EXTDEF
410 | #endif /* _RX_H */