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 |