1    | /***************************************
2    |   $Revision: 1.4 $
3    | 
4    |   Radix payload (rp) - user level functions for storing data in radix trees
5    | 
6    |   rp_search = search the loaded radix trees using an ascii key
7    | 
8    |   Status: NOT REVIEWED, TESTED
9    |   
10   |   Design and implementation by: Marek Bukowy
11   |   
12   |   ******************/ /******************
13   |   Copyright (c) 1999                              RIPE NCC
14   |  
15   |   All Rights Reserved
16   |   
17   |   Permission to use, copy, modify, and distribute this software and its
18   |   documentation for any purpose and without fee is hereby granted,
19   |   provided that the above copyright notice appear in all copies and that
20   |   both that copyright notice and this permission notice appear in
21   |   supporting documentation, and that the name of the author not be
22   |   used in advertising or publicity pertaining to distribution of the
23   |   software without specific, written prior permission.
24   |   
25   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
26   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
27   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
28   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
29   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
30   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31   |   ***************************************/
32   | 
33   | 
34   | #include <rp.h>
35   | /*+++++++++++++++
36   |   translates a query into a binary prefix (or prefixes, if range).
37   |   for registry+space (or if they are zero, for all
38   |   registries/spaces)
39   |   finds tree 
40   |   calls RX_bin_search (returning node copies).
41   |   will not put duplicate entries (composed inetnums).
42   |   returns some sort of error code :-) 
43   |   
44   |   Cuts the number of answers from RX_bin_search down to max_count,
45   |   but since some of the answers may have been "normalized" in the
46   |   underlying functions (multiple occurences removed), 
47   |   the result is _at_most_ max_count.
48   |   
49   |   appends to a given list of data blocks (not nodes!)
50   | 
51   |   The EXLESS search on inetnum tree should return the shortest range 
52   |   that was found, by means of comparing span (size) of the range.
53   |   If there are more of size equal to the smallest one, they are also
54   |   returned.
55   | 
56   |   returns RX_OK or a code from an underlying function
57   | ++++++++++++*/
58   | /******************************************************************************/
59   | /*+ search +*/
60   | er_ret_t
61   | RP_asc_search ( 
62   |                rx_srch_mt search_mode, 
63   |                int par_a,
64   |                int par_b,
65   |                char *key,          /*+ search term: (string) prefix/range/IP +*/
66   |                int   reg_id,
67   | 	       rp_attr_t  attr,    /*+ extra tree id (within the same reg/spc/fam +*/
68   |                GList **anslist,    /*+ answers go here, please +*/
69   |                int    max_count    /*+ max # of answers. RX_ALLANS == unlimited +*/
70   |                )
71   | { 
72   |   GList    *preflist = NULL;
73   |   GList      *datlist = NULL;
74   |   er_ret_t   err; 
75   |   ip_range_t testrang;
76   |   int        locked = 0;
77   |   rx_srch_mt first_pass_mode = search_mode;
78   |   ip_keytype_t key_type;
79   |   ip_space_t   spc_id;
80   |   rx_fam_t   fam_id = RP_attr2fam( attr );
81   |   rx_tree_t   *mytree;
82   | 
83   |   /*  abort on error (but unlock the tree) */  
84   |   ER_dbg_va(FAC_RX, ASP_RX_SRCH_BOT,
85   | 	    "RP_asc_search:  query: mode %d (par %d) for %s",
86   | 	    search_mode, par_a, key);
87   |   
88   |   /*   0. make a list of prefixes to search for */
89   |   err = rx_asc_make_preflist(search_mode, key, fam_id, 
90   | 			     &preflist, &testrang, &first_pass_mode);
91   |   
92   |   /* 1. find the tree */
93   |   if( NOERR(err) ) {
94   |     spc_id = IP_pref_b2_space( g_list_first(preflist)->data );
95   |     err = RP_tree_get( &mytree, reg_id, spc_id, attr );
96   |   }
97   | 
98   |   if( NOERR(err) ) {
99   |     /* 2. lock the tree */
100  |     TH_acquire_read_lock( &(mytree->rwlock) );
101  |     locked = 1;
102  |     
103  |     /* 3. perform the search on prefixes the query was converted to. */
104  |      err = rx_preflist_search ( first_pass_mode, par_a, par_b, 
105  | 				mytree, &preflist, &datlist);
106  |   }
107  |   if( NOERR(err) ) {
108  |     /* 4. process the data pointers obtained from the search */
109  |     err = rx_asc_process_datlist( first_pass_mode, fam_id, &datlist,
110  | 				  &testrang, anslist );
111  |   }
112  |   if( NOERR(err) ) {
113  |     /* 5. an inetnum/composed/exless was forced to exact in the first go.
114  |        So if the exact did not match yet, an encompassing prefix must 
115  |        be searched in exless mode */
116  |     
117  |     if( first_pass_mode != search_mode && g_list_length(*anslist) == 0 ) {
118  | 
119  |       ER_dbg_va(FAC_RX, ASP_RX_SRCH_DET,
120  | 		"rx_asc_search: doing pass 2 with mode %d", search_mode);
121  |       
122  |       /* clean old lists */
123  |       wr_clear_list( &preflist );
124  |       wr_clear_list( &datlist );
125  |       
126  |       /* mhm. make new prefix list */
127  |       dieif ( IP_smart_conv(key, 0, 1 /* now take encompassing one */,
128  | 			    &preflist, IP_EXPN, &key_type) != IP_OK);
129  |       
130  |       /* search again, this time with the real search_mode */
131  |       err = rx_preflist_search ( search_mode, par_a, par_b, 
132  | 				mytree, &preflist, &datlist);
133  |       
134  |       if( err == RX_OK ) {
135  | 	/*  process the data pointers obtained from the search */
136  | 	err = rx_asc_process_datlist( search_mode, fam_id, &datlist, 
137  | 				      &testrang, anslist );
138  |       }
139  |     }
140  |   }
141  | 
142  |   if( locked ) {
143  |     /* 100. unlock the tree */
144  |     TH_release_read_lock( &(mytree->rwlock) );
145  |   }
146  | 
147  |   /* clean up */
148  |   wr_clear_list( &preflist ); 
149  |   wr_clear_list( &datlist );  
150  | 
151  |   /* NOTE if error occured, anslist may be partly filled in. */
152  |   return err;
153  | }
154  |