00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "dhcpd.h"
00031
00032 #include <omapip/omapip_p.h>
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 omapi_handle_table_t *omapi_handle_table;
00059 omapi_handle_t omapi_next_handle = 1;
00060
00061 #define FIND_HAND 0
00062 #define CLEAR_HAND 1
00063
00064 static isc_result_t omapi_handle_lookup_in (omapi_object_t **,
00065 omapi_handle_t,
00066 omapi_handle_table_t *,
00067 int);
00068 static isc_result_t omapi_object_handle_in_table (omapi_handle_t,
00069 omapi_handle_table_t *,
00070 omapi_object_t *);
00071 static isc_result_t omapi_handle_table_enclose (omapi_handle_table_t **);
00072
00073 isc_result_t omapi_object_handle (omapi_handle_t *h, omapi_object_t *o)
00074 {
00075 isc_result_t status;
00076
00077 if (o -> handle) {
00078 *h = o -> handle;
00079 return ISC_R_SUCCESS;
00080 }
00081
00082 if (!omapi_handle_table) {
00083 omapi_handle_table = dmalloc (sizeof *omapi_handle_table, MDL);
00084 if (!omapi_handle_table)
00085 return ISC_R_NOMEMORY;
00086 memset (omapi_handle_table, 0, sizeof *omapi_handle_table);
00087 omapi_handle_table -> first = 0;
00088 omapi_handle_table -> limit = OMAPI_HANDLE_TABLE_SIZE;
00089 omapi_handle_table -> leafp = 1;
00090 }
00091
00092
00093
00094
00095
00096
00097
00098 while (omapi_next_handle >= omapi_handle_table -> limit) {
00099 omapi_handle_table_t *new;
00100
00101 new = dmalloc (sizeof *new, MDL);
00102 if (!new)
00103 return ISC_R_NOMEMORY;
00104 memset (new, 0, sizeof *new);
00105 new -> first = 0;
00106 new -> limit = (omapi_handle_table -> limit *
00107 OMAPI_HANDLE_TABLE_SIZE);
00108 new -> leafp = 0;
00109 new -> children [0].table = omapi_handle_table;
00110 omapi_handle_table = new;
00111 }
00112
00113
00114 status = omapi_object_handle_in_table (omapi_next_handle,
00115 omapi_handle_table, o);
00116
00117 if (status == ISC_R_SUCCESS) {
00118 *h = omapi_next_handle;
00119 omapi_next_handle++;
00120 return ISC_R_SUCCESS;
00121 }
00122 if (status != ISC_R_NOSPACE)
00123 return status;
00124
00125 status = omapi_handle_table_enclose (&omapi_handle_table);
00126 if (status != ISC_R_SUCCESS)
00127 return status;
00128
00129 status = omapi_object_handle_in_table (omapi_next_handle,
00130 omapi_handle_table, o);
00131 if (status != ISC_R_SUCCESS)
00132 return status;
00133 *h = omapi_next_handle;
00134 omapi_next_handle++;
00135
00136 return ISC_R_SUCCESS;
00137 }
00138
00139 static isc_result_t omapi_object_handle_in_table (omapi_handle_t h,
00140 omapi_handle_table_t *table,
00141 omapi_object_t *o)
00142 {
00143 omapi_handle_table_t *inner;
00144 omapi_handle_t scale, index;
00145 isc_result_t status;
00146
00147 if (table -> first > h || table -> limit <= h)
00148 return ISC_R_NOSPACE;
00149
00150
00151
00152 if (table -> leafp) {
00153 status = (omapi_object_reference
00154 (&table -> children [h - table -> first].object,
00155 o, MDL));
00156 if (status != ISC_R_SUCCESS)
00157 return status;
00158 o -> handle = h;
00159 return ISC_R_SUCCESS;
00160 }
00161
00162
00163
00164
00165 scale = (table -> limit - table -> first) / OMAPI_HANDLE_TABLE_SIZE;
00166
00167
00168
00169
00170 index = (h - table -> first) / scale;
00171 inner = table -> children [index].table;
00172
00173
00174
00175 if (!inner) {
00176 inner = dmalloc (sizeof *inner, MDL);
00177 if (!inner)
00178 return ISC_R_NOMEMORY;
00179 memset (inner, 0, sizeof *inner);
00180 inner -> first = index * scale + table -> first;
00181 inner -> limit = inner -> first + scale;
00182 if (scale == OMAPI_HANDLE_TABLE_SIZE)
00183 inner -> leafp = 1;
00184 table -> children [index].table = inner;
00185 }
00186
00187 status = omapi_object_handle_in_table (h, inner, o);
00188 if (status == ISC_R_NOSPACE) {
00189 status = (omapi_handle_table_enclose
00190 (&table -> children [index].table));
00191 if (status != ISC_R_SUCCESS)
00192 return status;
00193
00194 return omapi_object_handle_in_table
00195 (h, table -> children [index].table, o);
00196 }
00197 return status;
00198 }
00199
00200 static isc_result_t omapi_handle_table_enclose (omapi_handle_table_t **table)
00201 {
00202 omapi_handle_table_t *inner = *table;
00203 omapi_handle_table_t *new;
00204 int index, base, scale;
00205
00206
00207
00208
00209
00210 scale = (inner -> first - inner -> limit) * OMAPI_HANDLE_TABLE_SIZE;
00211
00212
00213
00214
00215
00216
00217
00218 base = inner -> first - inner -> first % scale;
00219
00220
00221
00222
00223
00224 index = (base - inner -> first) / OMAPI_HANDLE_TABLE_SIZE;
00225
00226 new = dmalloc (sizeof *new, MDL);
00227 if (!new)
00228 return ISC_R_NOMEMORY;
00229 memset (new, 0, sizeof *new);
00230 new -> first = base;
00231 new -> limit = base + scale;
00232 if (scale == OMAPI_HANDLE_TABLE_SIZE)
00233 new -> leafp = 0;
00234 new -> children [index].table = inner;
00235 *table = new;
00236 return ISC_R_SUCCESS;
00237 }
00238
00239 isc_result_t omapi_handle_lookup (omapi_object_t **o, omapi_handle_t h)
00240 {
00241 return(omapi_handle_lookup_in(o, h, omapi_handle_table, FIND_HAND));
00242 }
00243
00244 static isc_result_t omapi_handle_lookup_in (omapi_object_t **o,
00245 omapi_handle_t h,
00246 omapi_handle_table_t *table,
00247 int op)
00248 {
00249 omapi_handle_t scale, index;
00250
00251 if (!table || table->first > h || table->limit <= h)
00252 return(ISC_R_NOTFOUND);
00253
00254
00255 if (table->leafp) {
00256
00257 if (!table->children[h - table->first].object)
00258 return(ISC_R_NOTFOUND);
00259 if (op == CLEAR_HAND) {
00260 table->children[h - table->first].object = NULL;
00261 return(ISC_R_SUCCESS);
00262 } else {
00263 return(omapi_object_reference
00264 (o, table->children[h - table->first].object,
00265 MDL));
00266 }
00267 }
00268
00269
00270
00271
00272 scale = (table->limit - table->first) / OMAPI_HANDLE_TABLE_SIZE;
00273
00274
00275
00276
00277 index = (h - table->first) / scale;
00278
00279 return(omapi_handle_lookup_in(o, h, table->children[index].table, op));
00280 }
00281
00282
00283 isc_result_t omapi_handle_td_lookup (omapi_object_t **obj,
00284 omapi_typed_data_t *handle)
00285 {
00286 omapi_handle_t h;
00287
00288 if (handle->type == omapi_datatype_int)
00289 h = handle->u.integer;
00290 else if (handle->type == omapi_datatype_data &&
00291 handle->u.buffer.len == sizeof h) {
00292 memcpy(&h, handle->u.buffer.value, sizeof h);
00293 h = ntohl(h);
00294 } else
00295 return(DHCP_R_INVALIDARG);
00296 return(omapi_handle_lookup(obj, h));
00297 }
00298
00299 isc_result_t omapi_handle_clear(omapi_handle_t h)
00300 {
00301 return(omapi_handle_lookup_in(NULL, h, omapi_handle_table, CLEAR_HAND));
00302 }