1    | /***************************************
2    |   $Revision: 1.26 $
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,2000,2001,2002               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   | #include <erroutines.h>
46   | 
47   | #include "sk.h" /*condat*/
48   | 
49   | #include "thread.h" /*rwlock*/
50   | 
51   | 
52   | typedef enum {
53   |   RX_FAM_RT = 1,
54   |   RX_FAM_IN = 2,
55   |   RX_FAM_IP = 4
56   | } rx_fam_t;
57   | 
58   |       
59   | /*+ the node operation modes +*/
60   | typedef enum {
61   |   RX_OPER_CRE = 1,
62   |   RX_OPER_DEL
63   | } rx_oper_mt;
64   | 
65   | 
66   | /*+ stack building modes +*/
67   | typedef enum {
68   |   RX_STK_CREAT = 1, /*+ - creation = all glue nodes, stop at first non-glue +*/
69   |   RX_STK_QUERY_ALLNOD,   /*+ - query = all glue nodes, stop when deep enough */
70   |   RX_STK_QUERY_NOGLUE    /*+ - query = no glue nodes, stop when deep enough */
71   | } rx_stk_mt;
72   | 
73   | /*+ the search modes +*/
74   | typedef enum {
75   |   RX_SRCH_CREAT = 1,      /*+ special search - does not skip glue nodes +*/
76   |   RX_SRCH_EXLESS,         /*+ the default search +*/
77   |   RX_SRCH_EXACT,
78   |   RX_SRCH_LESS,
79   |   RX_SRCH_MORE,           /*+ more specific search +*/
80   |   RX_SRCH_DBLS,           /*+ special more spec: return only nodes with
81   | 			     more than one data leaves +*/
82   |   RX_SRCH_RANG            /*+ more specific range search, RPSL style : ^n-m +*/
83   | } rx_srch_mt;
84   | 
85   | 
86   | #ifdef RX_IMPL_PRINT
87   | char *rx_srch_mode_text[]={
88   |   "", /* begins with 1 */
89   |   "CREAT",
90   |   "EXLESS",       
91   |   "EXACT",	
92   |   "LESS",		
93   |   "MORE",         
94   |   "DBLS",         
95   |   "RANG"      
96   | };
97   | #endif
98   | 
99   | /* constant to mean 'unlimited number of answers from a search' */
100  | #define RX_ANS_ALL (-1)
101  | 
102  | #define RX_ALL_DEPTHS 255
103  | 
104  | 
105  | /*+ radix tree's memory modes -- not yet implemented +*/
106  | typedef enum {
107  |   RX_MEM_RAMONLY,
108  |   RX_MEM_RAMSQL,
109  |   RX_MEM_SQLONLY
110  | } rx_mem_mt;
111  | 
112  | 
113  | 
114  | /*+ subtree modes -- not yet implemented +*/
115  | typedef enum {
116  |   RX_SUB_NONE,
117  |   RX_SUB_AUTO,
118  |   RX_SUB_HAND
119  | } rx_subtree_mt;
120  | 
121  | /* modes for tree traversal (walk_tree) */
122  | typedef enum {
123  |   RX_WALK_CNTGLU=1,  /*+ default: count also glue nodes and make the level
124  | 			   checking aware of them +*/
125  | 
126  |   RX_WALK_SKPGLU=2,  /*+ only real nodes counted & watched in level checks +*/
127  | 
128  |   RX_WALK_PRFLEN=4,  /*+ make level check a check for prefix length;
129  | 		       still only non-glue nodes are counted +*/
130  |   RX_WALK_REVERS=8   /*+ reverse the order of traversing the tree 
131  | 		       (first link 1 then 0) +*/
132  | } rx_walk_mt;
133  | 
134  | 
135  | /*+  A struct for data hooked via a double linked list at a radix node. 
136  | Must uniquely define the object for lookups in the SQL tables and/or memory. 
137  | Must also contain enough info to let the delete_node choose (and remove) 
138  | the proper object from the (linked) list +*/
139  | 
140  | typedef struct { 
141  |   ip_range_t      iprange;      /*+ filled for all trees. Used in rp_search
142  | 				   for determining exact matches (all trees)
143  | 				   and to see if an address is in range
144  | 				   (only IPv4 inetnum trees) +*/
145  |   unsigned char   preflen;      /* to avoid arithmetics on IPv6 ranges,
146  | 				   we have to store prefix length to
147  | 				   determine the shortest object in search.
148  | 				   This is filled in for all route trees
149  | 				*/
150  | 
151  |   char            composed;	/*+ non-zero for composed inetnums 
152  | 				  equal to: the number of prefixes composing
153  | 				  the range - minus 1 +*/
154  | 
155  |   void           *data_ptr;	/*+ to in-memory immediate data +*/
156  |   unsigned        data_len;     /*+ and its length +*/
157  | 
158  |   sql_key_t       data_key;	/*+ key to the SQL full-text data record +*/
159  |   sql_key_t       leaf_key;     /*+ pointer to the SQL data leaf record  +*/
160  | } rx_dataleaf_t;
161  | 
162  | /*+ 
163  | The struct for radix nodes.
164  | 
165  | Must contain prefix, parent, left/right child links in memory and sql, 
166  | link to the sql version of the node. 
167  | And of course data: pointer to a double linked list of rx_data_t's. 
168  | +*/
169  | 
170  | typedef struct _rx_node_str {
171  |   ip_prefix_t     prefix;	/*+ who am i. +*/
172  | 
173  |   char            glue;         
174  |                                 /*+ now this is an indicator for a node that it
175  | 				   is not holding a real prefix, 
176  | 				   but is only a glue node +*/
177  |   
178  |   GList          *leaves_ptr;	/*+ a double-linked list of rx_data_t structs 
179  |                                    the data leaves can be multiple at each node
180  | 				   (due to a user error the inetnum ranges can
181  | 				   overlap, due to multihoming or error routes 
182  | 				   can be duplicated ). 
183  | 				   So we link a dynamic thing here +*/
184  | 
185  |   /*  sql_key_t       leaves_key;   */
186  |                                 /* "linked list" not needed in sql - 
187  | 				   the data leaves can be found in node_leaf 
188  | 				   table as those that have 
189  | 				   node_key in node_id  */
190  | 
191  |   struct _rx_node_str
192  |                  *parent_ptr,	/*+ radix links in memory +*/
193  |                  *child_ptr[2];	/*+ NULL means empty +*/
194  | 
195  |   sql_key_t       parent_key,	/*+ radix links in SQL +*/
196  |                   child_key[2];	/*+ zero means empty +*/
197  | 
198  |   sql_key_t       node_key;	/*+ key of the corresponding SQL radix node +*/
199  | 
200  | } rx_node_t;
201  | 
202  | 
203  | /*+
204  |  rx_tree_t - defines a radix tree.
205  | 
206  |  includes a pointer(key) to the top node, 
207  |  
208  |  names of the corresponding SQL tables 
209  |     (they can be generated automatically, 
210  |     but this is the place to store the result)
211  |     Data_table  is for data_key.
212  |     Radix_table is for parent_id, right_id, left_id, node_id.
213  |     Leaves_table is for leaves_key (double linked list in SQL).
214  |  +*/
215  | 
216  | typedef struct _rx_tree_str {  
217  |   ip_space_t      space;	/*+ one of IPv4, IPv6 +*/
218  |   rx_fam_t        family;       /*+ one of RT, IN +*/
219  | 
220  |   rx_subtree_mt   subtrees;	/*+ one of NONE, AUTO, HAND +*/
221  |   rx_mem_mt       mem_mode;     /*+ where the tree will sit - SQL or RAM +*/
222  |   struct rx_tree_str 
223  |                  *parent_tree;  /*+ pointer to the parent tree +*/
224  | 
225  |   ip_prefix_t     prefix;	/*+ of the IP space this tree covers +*/
226  | 
227  |   int             maxbits;	/*+ max depth of this tree 
228  | 				   (depends on the space, so it is redundant)+*/
229  |   sql_tblnam_t    data_table;
230  |   sql_tblnam_t    radix_table; 
231  |   sql_tblnam_t    leaves_table;
232  | 
233  |   int             num_nodes;	/*+ number of nodes in tree - for assertions +*/
234  | 
235  |   rx_node_t      *top_ptr;	/*+ pointer to the top node +*/
236  |   long            top_key;	/*+ the same in SQL +*/
237  | 
238  |   rw_lock_t      rwlock;	/*+ per-tree reader/writer lock +*/
239  | 
240  | } rx_tree_t;
241  | 
242  | 
243  | /*+ this is a definition of a node copy used for:
244  | 
245  |  * stack elements returned from rx_stack_build,
246  | 
247  |  * answer elements from an rx_nod_search.
248  |    
249  |    It *must* hold pointers to the original locations of it (in terms of 
250  |    memory and SQL) so that one could actually modify the node...
251  |    In SQL tree mode it holds also a copy of a node.
252  |    This seems to be unnecessary for in-memory radix trees but is a must
253  |    for sql ones.
254  | 
255  |    WARNING!!!!! The fact that pointers to tree and memory / SQL nodes are
256  |    here is a subject to race condition. The location of the tree in the 
257  |    forest list and the node in memory must not change.
258  | 
259  | +*/
260  | 
261  | typedef struct {
262  |   rx_tree_t   *tree;  /*+ contains registry_id, space_id, sql table names +*/
263  |   rx_node_t *srcptr;
264  |   sql_key_t srckey;
265  |   rx_node_t cpy;      /*+ filled in if the tree is kept in SQL only mode +*/
266  | } rx_nodcpy_t;
267  | 
268  | 
269  | /*+ 
270  |   This represents one data leaf (by reference). It's used for returning data 
271  | from rx_bin_search() to rx_asc_search().
272  | +*/
273  | typedef struct {
274  |   sql_key_t      srckey;
275  |   rx_dataleaf_t *leafptr;
276  | } rx_datref_t;
277  | 
278  | 
279  | /*+ this is a structure used for returning the data from the search.
280  |    It contains a copy of the dataleaf and a pointer to the source +*/
281  | typedef struct {
282  |   sql_key_t      srckey;
283  |   rx_dataleaf_t  leafcpy;
284  | } rx_datcpy_t;
285  | 
286  | typedef struct {
287  |   rx_node_t *node;
288  |   int        code;
289  |   int     datatoo;
290  |   rx_tree_t *tree; 
291  | } rx_treecheck_t;
292  | 
293  | /* 
294  |  * -----------------------------------------------------------------------
295  |  *  
296  |  *       now, THIS is a scrap heap for things that MAY BE useful 
297  |  */
298  | 
299  | /* a definite pointer to an sql object: table name + key
300  | However, it might be nice to include the table TYPE so that one knows 
301  | what data it holds :-) 
302  |  */
303  | typedef struct {
304  |   sql_tblnam_t  name;
305  |   sql_key_t     key;
306  | } rx_sqlobj_t;
307  | 
308  | 
309  | typedef struct {
310  |   GList        **nodlist;
311  |   rx_tree_t     *tree; 
312  |   ip_prefix_t   *prefix;
313  | } hook_addnode_userdat_t;
314  | 
315  | /********************* P R O T O T Y P E S **********************/
316  | 
317  | 
318  | void rx_free_list_element(void *cpy, void *trash);
319  | 
320  | 
321  | 
322  | er_ret_t
323  | RX_treecheck( rx_tree_t *tree, int datatoo, rx_treecheck_t *errorfound);
324  | 
325  | er_ret_t 
326  | RX_tree_cre (
327  | 	      char      *prefixstr, /*+ prefix the tree will cover (string) +*/
328  | 	      rx_fam_t   fam_id,
329  | 	      rx_mem_mt   mem_mode, /* memory only, memory+sql, sql only +*/
330  | 	      rx_subtree_mt subtrees,	/*+ one of NONE, AUTO, HAND +*/
331  | 	      rx_tree_t **treestore /* store the tree pointer here */
332  | 	     );
333  | 
334  | er_ret_t
335  | RX_bin_search (
336  | 	       rx_srch_mt  search_mode,
337  | 	       int     	   par_a,
338  | 	       int         par_b,
339  | 	       rx_tree_t  *tree,           /* tree ptr */
340  | 	       ip_prefix_t *prefix,        /* binary prefix */
341  | 	       GList       **datleaves,    /* data leaves go here */
342  | 	       int         max_count 
343  | 	       );
344  | er_ret_t
345  | rx_bin_node (
346  | 	     rx_oper_mt   mode,       /*+ MODE={cre|mod|del} +*/
347  | 	     ip_prefix_t *newpref,    /*+ prefix of the node +*/
348  | 	     rx_tree_t	*tree,        /*+ pointer to the tree structure +*/
349  | 	     rx_dataleaf_t *dataleaf  /*+ dataleaf to attach at the node +*/
350  | 	     );
351  | er_ret_t
352  | RX_rt_node (
353  | 	     rx_oper_mt   mode,       /*+ MODE={cre|mod|del} +*/
354  | 	     ip_prefix_t *newpref,    /*+ prefix of the node +*/
355  | 	     rx_tree_t	*tree,        /*+ pointer to the tree structure +*/
356  | 	     rx_dataleaf_t *dataleaf  /*+ dataleaf to attach at the node +*/
357  | 	     );
358  | er_ret_t
359  | RX_in_node(   rx_oper_mt mode,       /*+ MODE={cre|mod|del} +*/
360  | 	      ip_range_t *rang,      /*+ range of IP addresses +*/
361  | 	      rx_tree_t *tree,       /*+ pointer to the tree structure +*/
362  | 	      rx_dataleaf_t *leafptr /*+ dataleaf to attach at the node +*/
363  | 	      );
364  | er_ret_t
365  | rx_build_stack(rx_nodcpy_t    stack[], 
366  | 	       int            *maxdepth, 
367  | 	       rx_tree_t      *tree, 
368  | 	       ip_prefix_t    *newpref,
369  | 	       rx_stk_mt      dmode
370  | 	       );
371  | 
372  | er_ret_t
373  | rx_nod_search (
374  | 	       rx_srch_mt  search_mode,
375  | 	       int     	   par_a,
376  | 	       int         par_b,
377  | 	       /* see rx_asc_search() for explanation */
378  | 	       rx_tree_t  *tree,           /* tree ptr */
379  | 	       ip_prefix_t  *prefix,        /* binary prefix */
380  | 	       
381  | 	       rx_nodcpy_t stack[],         /* stack==array of node_copies */
382  | 	       int         stackcount,      /* number of element on the stack*/
383  | 	                                    /* can be set in creat stack */
384  | 
385  | 	       GList	   **nodlist,	    /* answers go here */
386  | 	       int         max_count        /* max # of answers */
387  | 	       );
388  | int
389  | rx_walk_tree(rx_node_t *node, 
390  | 	     er_ret_t (*func)(rx_node_t *node, int level, int nodecounter,
391  | 			      void *userptr), 
392  | 	     rx_walk_mt walk_mode, 
393  | 	     int maxlevel, 
394  | 	     int level, 
395  | 	     int nodecounter,
396  | 	     void *userptr,
397  | 	     er_ret_t *err);
398  | 
399  | 
400  | er_ret_t rx_tree_print( sk_conn_st *condat,rx_tree_t     *tree );
401  | void rx_space_list(sk_conn_st *condat);
402  | void rx_nod_print( rx_node_t *node, char *buf, unsigned maxchar );
403  | void rx_stk_print( rx_nodcpy_t   stack[], int stackdepth );
404  | const char *RX_text_srch_mode(rx_srch_mt mode);
405  | 
406  | 
407  | /* Function needed to delete radix tree */
408  | void 
409  | rx_delete_treenode(rx_tree_t *tree, rx_node_t *curnode);
410  | 
411  | int
412  | rx_delete_tree(rx_tree_t *tree, rx_node_t *node,
413  |              int maxlevel, 
414  | 	     int level, 
415  | 	     int nodecounter,
416  | 	     void *userptr);
417  | 
418  | 
419  | #undef EXTDEF
420  | #endif /* _RX_H */