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 |