comparison libfdproto/dictionary.c @ 1451:6c3485887511

Move some structures to a header file for use by dbg_dict_dump_json. Remove trailing whitespace.
author Thomas Klausner <tk@giga.or.at>
date Thu, 27 Feb 2020 15:40:25 +0100
parents ab7cb954f17e
children 566bb46cc73f
comparison
equal deleted inserted replaced
1450:32f158d0d859 1451:6c3485887511
32 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * 32 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF *
33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * 33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
34 *********************************************************************************************************/ 34 *********************************************************************************************************/
35 35
36 #include "fdproto-internal.h" 36 #include "fdproto-internal.h"
37 #include "dictionary-internal.h"
37 #include <inttypes.h> 38 #include <inttypes.h>
38 39
39 /* Names of the base types */ 40 /* Names of the base types */
40 const char * type_base_name[] = { /* must keep in sync with dict_avp_basetype */ 41 const char * type_base_name[] = { /* must keep in sync with dict_avp_basetype */
41 "GROUPED", /* AVP_TYPE_GROUPED */ 42 "GROUPED", /* AVP_TYPE_GROUPED */
46 "UNSIGNED64", /* AVP_TYPE_UNSIGNED64 */ 47 "UNSIGNED64", /* AVP_TYPE_UNSIGNED64 */
47 "FLOAT32", /* AVP_TYPE_FLOAT32 */ 48 "FLOAT32", /* AVP_TYPE_FLOAT32 */
48 "FLOAT64" /* AVP_TYPE_FLOAT64 */ 49 "FLOAT64" /* AVP_TYPE_FLOAT64 */
49 }; 50 };
50 51
51 /* The number of lists in an object */
52 #define NB_LISTS_PER_OBJ 3
53
54 /* Some eye catchers definitions */ 52 /* Some eye catchers definitions */
55 #define OBJECT_EYECATCHER (0x0b13c7) 53 #define OBJECT_EYECATCHER (0x0b13c7)
56 #define DICT_EYECATCHER (0x00d1c7) 54 #define DICT_EYECATCHER (0x00d1c7)
57
58 /* Definition of the dictionary objects */
59 struct dict_object {
60 enum dict_object_type type; /* What type of object is this? */
61 int objeyec;/* eyecatcher for this object */
62 int typeyec;/* eyecatcher for this type of object */
63 struct dictionary *dico; /* The dictionary this object belongs to */
64
65 union {
66 struct dict_vendor_data vendor; /* datastr_len = strlen(vendor_name) */
67 struct dict_application_data application; /* datastr_len = strlen(application_name) */
68 struct dict_type_data type; /* datastr_len = strlen(type_name) */
69 struct dict_enumval_data enumval; /* datastr_len = strlen(enum_name) */
70 struct dict_avp_data avp; /* datastr_len = strlen(avp_name) */
71 struct dict_cmd_data cmd; /* datastr_len = strlen(cmd_name) */
72 struct dict_rule_data rule; /* datastr_len = 0 */
73 } data; /* The data of this object */
74
75 size_t datastr_len; /* cached length of the string inside the data. Saved when the object is created. */
76
77 struct dict_object * parent; /* The parent of this object, if any */
78
79 struct fd_list list[NB_LISTS_PER_OBJ];/* used to chain objects.*/
80 /* More information about the lists :
81
82 - the use for each list depends on the type of object. See detail below.
83
84 - a sentinel for a list has its 'o' field cleared. (this is the criteria to detect end of a loop)
85
86 - The lists are always ordered. The criteria are described below. the functions to order them are referenced in dict_obj_info
87
88 - The dict_lock must be held for any list operation.
89
90 => VENDORS:
91 list[0]: list of the vendors, ordered by their id. The sentinel is g_dict_vendors (vendor with id 0)
92 list[1]: sentinel for the list of AVPs from this vendor, ordered by AVP code.
93 list[2]: sentinel for the list of AVPs from this vendor, ordered by AVP name (fd_os_cmp).
94
95 => APPLICATIONS:
96 list[0]: list of the applications, ordered by their id. The sentinel is g_dict_applications (application with id 0)
97 list[1]: not used
98 list[2]: not used.
99
100 => TYPES:
101 list[0]: list of the types, ordered by their names. The sentinel is g_list_types.
102 list[1]: sentinel for the type_enum list of this type, ordered by their constant name (fd_os_cmp).
103 list[2]: sentinel for the type_enum list of this type, ordered by their constant value.
104
105 => TYPE_ENUMS:
106 list[0]: list of the contants for a given type, ordered by the constant name (fd_os_cmp). Sentinel is a (list[1]) element of a TYPE object.
107 list[1]: list of the contants for a given type, ordered by the constant value. Sentinel is a (list[2]) element of a TYPE object.
108 list[2]: not used
109
110 => AVPS:
111 list[0]: list of the AVP from a given vendor, ordered by avp code. Sentinel is a list[1] element of a VENDOR object.
112 list[1]: list of the AVP from a given vendor, ordered by avp name (fd_os_cmp). Sentinel is a list[2] element of a VENDOR object.
113 list[2]: sentinel for the rule list that apply to this AVP.
114
115 => COMMANDS:
116 list[0]: list of the commands, ordered by their names (fd_os_cmp). The sentinel is g_list_cmd_name.
117 list[1]: list of the commands, ordered by their command code and 'R' flag. The sentinel is g_list_cmd_code.
118 list[2]: sentinel for the rule list that apply to this command.
119
120 => RULES:
121 list[0]: list of the rules for a given (grouped) AVP or Command, ordered by the AVP vendor & code to which they refer. sentinel is list[2] of a command or (grouped) avp.
122 list[1]: not used
123 list[2]: not used.
124
125 */
126
127 /* Sentinel for the dispatch callbacks */
128 struct fd_list disp_cbs;
129
130 };
131
132 /* Definition of the dictionary structure */
133 struct dictionary {
134 int dict_eyec; /* Eye-catcher for the dictionary (DICT_EYECATCHER) */
135
136 pthread_rwlock_t dict_lock; /* The global rwlock for the dictionary */
137
138 struct dict_object dict_vendors; /* Sentinel for the list of vendors, corresponding to vendor 0 */
139 struct dict_object dict_applications; /* Sentinel for the list of applications, corresponding to app 0 */
140 struct fd_list dict_types; /* Sentinel for the list of types */
141 struct fd_list dict_cmd_name; /* Sentinel for the list of commands, ordered by names */
142 struct fd_list dict_cmd_code; /* Sentinel for the list of commands, ordered by codes */
143
144 struct dict_object dict_cmd_error; /* Special command object for answers with the 'E' bit set */
145
146 int dict_count[DICT_TYPE_MAX + 1]; /* Number of objects of each type */
147 };
148 55
149 /* Forward declarations of dump functions */ 56 /* Forward declarations of dump functions */
150 static DECLARE_FD_DUMP_PROTOTYPE(dump_vendor_data, void * data ); 57 static DECLARE_FD_DUMP_PROTOTYPE(dump_vendor_data, void * data );
151 static DECLARE_FD_DUMP_PROTOTYPE(dump_application_data, void * data ); 58 static DECLARE_FD_DUMP_PROTOTYPE(dump_application_data, void * data );
152 static DECLARE_FD_DUMP_PROTOTYPE(dump_type_data, void * data ); 59 static DECLARE_FD_DUMP_PROTOTYPE(dump_type_data, void * data );
175 DECLARE_FD_DUMP_PROTOTYPE( (*dump_data), void * data ); /* The function to dump the data section */ 82 DECLARE_FD_DUMP_PROTOTYPE( (*dump_data), void * data ); /* The function to dump the data section */
176 int (*search_fct)(struct dictionary * dict, int criteria, const void * what, struct dict_object **result );; /* The function to search an object of this type */ 83 int (*search_fct)(struct dictionary * dict, int criteria, const void * what, struct dict_object **result );; /* The function to search an object of this type */
177 int haslist[NB_LISTS_PER_OBJ]; /* Tell if this list is used */ 84 int haslist[NB_LISTS_PER_OBJ]; /* Tell if this list is used */
178 } dict_obj_info[] = { { 0, "(error)", 0, 0, 0, 0, NULL, NULL, {0, 0, 0} } 85 } dict_obj_info[] = { { 0, "(error)", 0, 0, 0, 0, NULL, NULL, {0, 0, 0} }
179 86
180 /* type name datasize parent parenttype 87 /* type name datasize parent parenttype
181 eyecatcher dump_data search_fct, haslist[] */ 88 eyecatcher dump_data search_fct, haslist[] */
182 89
183 ,{ DICT_VENDOR, "VENDOR", sizeof(struct dict_vendor_data), 0, 0, 90 ,{ DICT_VENDOR, "VENDOR", sizeof(struct dict_vendor_data), 0, 0,
184 OBJECT_EYECATCHER + 1, dump_vendor_data, search_vendor, { 1, 0, 0 } } 91 OBJECT_EYECATCHER + 1, dump_vendor_data, search_vendor, { 1, 0, 0 } }
185 92
186 ,{ DICT_APPLICATION, "APPLICATION", sizeof(struct dict_application_data), 1, DICT_VENDOR, 93 ,{ DICT_APPLICATION, "APPLICATION", sizeof(struct dict_application_data), 1, DICT_VENDOR,
187 OBJECT_EYECATCHER + 2, dump_application_data, search_application, { 1, 0, 0 } } 94 OBJECT_EYECATCHER + 2, dump_application_data, search_application, { 1, 0, 0 } }
188 95
189 ,{ DICT_TYPE, "TYPE", sizeof(struct dict_type_data), 1, DICT_APPLICATION, 96 ,{ DICT_TYPE, "TYPE", sizeof(struct dict_type_data), 1, DICT_APPLICATION,
190 OBJECT_EYECATCHER + 3, dump_type_data, search_type, { 1, 0, 0 } } 97 OBJECT_EYECATCHER + 3, dump_type_data, search_type, { 1, 0, 0 } }
191 98
192 ,{ DICT_ENUMVAL, "ENUMVAL", sizeof(struct dict_enumval_data), 2, DICT_TYPE, 99 ,{ DICT_ENUMVAL, "ENUMVAL", sizeof(struct dict_enumval_data), 2, DICT_TYPE,
193 OBJECT_EYECATCHER + 4, NULL, search_enumval, { 1, 1, 0 } } 100 OBJECT_EYECATCHER + 4, NULL, search_enumval, { 1, 1, 0 } }
194 101
195 ,{ DICT_AVP, "AVP", sizeof(struct dict_avp_data), 1, DICT_TYPE, 102 ,{ DICT_AVP, "AVP", sizeof(struct dict_avp_data), 1, DICT_TYPE,
196 OBJECT_EYECATCHER + 5, dump_avp_data, search_avp, { 1, 1, 0 } } 103 OBJECT_EYECATCHER + 5, dump_avp_data, search_avp, { 1, 1, 0 } }
197 104
198 ,{ DICT_COMMAND, "COMMAND", sizeof(struct dict_cmd_data), 1, DICT_APPLICATION, 105 ,{ DICT_COMMAND, "COMMAND", sizeof(struct dict_cmd_data), 1, DICT_APPLICATION,
199 OBJECT_EYECATCHER + 6, dump_command_data, search_cmd, { 1, 1, 0 } } 106 OBJECT_EYECATCHER + 6, dump_command_data, search_cmd, { 1, 1, 0 } }
200 107
201 ,{ DICT_RULE, "RULE", sizeof(struct dict_rule_data), 2, -1 /* special case: grouped avp or command */, 108 ,{ DICT_RULE, "RULE", sizeof(struct dict_rule_data), 2, -1 /* special case: grouped avp or command */,
202 OBJECT_EYECATCHER + 7, dump_rule_data, search_rule, { 1, 0, 0 } } 109 OBJECT_EYECATCHER + 7, dump_rule_data, search_rule, { 1, 0, 0 } }
203 110
204 }; 111 };
205 112
206 /* Macro to verify a "type" value */ 113 /* Macro to verify a "type" value */
207 #define CHECK_TYPE( type ) ( ((type) > 0) && ((type) <= DICT_TYPE_MAX) ) 114 #define CHECK_TYPE( type ) ( ((type) > 0) && ((type) <= DICT_TYPE_MAX) )
208 115
209 /* Cast macro */ 116 /* Cast macro */
210 #define _O( object ) ((struct dict_object *) (object)) 117 #define _O( object ) ((struct dict_object *) (object))
228 /* Duplicate a string inplace, save its length */ 135 /* Duplicate a string inplace, save its length */
229 #define DUP_string_len( str, plen ) { \ 136 #define DUP_string_len( str, plen ) { \
230 *(plen) = strlen((str)); \ 137 *(plen) = strlen((str)); \
231 str = os0dup( str, *(plen)); \ 138 str = os0dup( str, *(plen)); \
232 } 139 }
233 140
234 /* Initialize an object */ 141 /* Initialize an object */
235 static void init_object( struct dict_object * obj, enum dict_object_type type ) 142 static void init_object( struct dict_object * obj, enum dict_object_type type )
236 { 143 {
237 int i; 144 int i;
238 145
239 TRACE_ENTRY("%p %d", obj, type); 146 TRACE_ENTRY("%p %d", obj, type);
240 147
241 /* Clean the object first */ 148 /* Clean the object first */
242 memset ( obj, 0, sizeof(struct dict_object)); 149 memset ( obj, 0, sizeof(struct dict_object));
243 150
244 CHECK_PARAMS_DO( CHECK_TYPE(type), return ); 151 CHECK_PARAMS_DO( CHECK_TYPE(type), return );
245 152
246 obj->type = type; 153 obj->type = type;
247 obj->objeyec = OBJECT_EYECATCHER; 154 obj->objeyec = OBJECT_EYECATCHER;
248 obj->typeyec = _OBINFO(obj).eyecatcher; 155 obj->typeyec = _OBINFO(obj).eyecatcher;
249 156
250 /* We don't initialize the data nor the parent here */ 157 /* We don't initialize the data nor the parent here */
251 158
252 /* Now init the lists */ 159 /* Now init the lists */
253 for (i=0; i<NB_LISTS_PER_OBJ; i++) { 160 for (i=0; i<NB_LISTS_PER_OBJ; i++) {
254 if (_OBINFO(obj).haslist[i] != 0) 161 if (_OBINFO(obj).haslist[i] != 0)
255 fd_list_init(&obj->list[i], obj); 162 fd_list_init(&obj->list[i], obj);
256 else 163 else
257 fd_list_init(&obj->list[i], NULL); 164 fd_list_init(&obj->list[i], NULL);
258 } 165 }
259 166
260 fd_list_init(&obj->disp_cbs, NULL); 167 fd_list_init(&obj->disp_cbs, NULL);
261 } 168 }
262 169
263 /* Initialize the "data" part of an object */ 170 /* Initialize the "data" part of an object */
264 static int init_object_data(struct dict_object * dest, void * source, enum dict_object_type type, int dupos) 171 static int init_object_data(struct dict_object * dest, void * source, enum dict_object_type type, int dupos)
265 { 172 {
266 TRACE_ENTRY("%p %p %d", dest, source, type); 173 TRACE_ENTRY("%p %p %d", dest, source, type);
267 CHECK_PARAMS( dest && source && CHECK_TYPE(type) ); 174 CHECK_PARAMS( dest && source && CHECK_TYPE(type) );
268 175
269 /* Generic: copy the full data structure */ 176 /* Generic: copy the full data structure */
270 memcpy( &dest->data, source, dict_obj_info[type].datasize ); 177 memcpy( &dest->data, source, dict_obj_info[type].datasize );
271 178
272 /* Then strings must be duplicated, not copied */ 179 /* Then strings must be duplicated, not copied */
273 /* This function might be simplified by always defining the "name" field as the first field of the structures, but... it's error-prone */ 180 /* This function might be simplified by always defining the "name" field as the first field of the structures, but... it's error-prone */
274 switch (type) { 181 switch (type) {
275 case DICT_VENDOR: 182 case DICT_VENDOR:
276 DUP_string_len( dest->data.vendor.vendor_name, &dest->datastr_len ); 183 DUP_string_len( dest->data.vendor.vendor_name, &dest->datastr_len );
277 break; 184 break;
278 185
279 case DICT_APPLICATION: 186 case DICT_APPLICATION:
280 DUP_string_len( dest->data.application.application_name, &dest->datastr_len ); 187 DUP_string_len( dest->data.application.application_name, &dest->datastr_len );
281 break; 188 break;
282 189
283 case DICT_TYPE: 190 case DICT_TYPE:
284 DUP_string_len( dest->data.type.type_name, &dest->datastr_len ); 191 DUP_string_len( dest->data.type.type_name, &dest->datastr_len );
285 break; 192 break;
286 193
287 case DICT_ENUMVAL: 194 case DICT_ENUMVAL:
288 DUP_string_len( dest->data.enumval.enum_name, &dest->datastr_len ); 195 DUP_string_len( dest->data.enumval.enum_name, &dest->datastr_len );
289 if (dupos) { 196 if (dupos) {
290 // we also need to duplicate the octetstring constant value since it is a pointer. 197 // we also need to duplicate the octetstring constant value since it is a pointer.
291 dest->data.enumval.enum_value.os.data = os0dup( 198 dest->data.enumval.enum_value.os.data = os0dup(
292 ((struct dict_enumval_data *)source)->enum_value.os.data, 199 ((struct dict_enumval_data *)source)->enum_value.os.data,
293 ((struct dict_enumval_data *)source)->enum_value.os.len 200 ((struct dict_enumval_data *)source)->enum_value.os.len
294 ); 201 );
295 } 202 }
296 break; 203 break;
297 204
298 case DICT_AVP: 205 case DICT_AVP:
299 DUP_string_len( dest->data.avp.avp_name, &dest->datastr_len ); 206 DUP_string_len( dest->data.avp.avp_name, &dest->datastr_len );
300 break; 207 break;
301 208
302 case DICT_COMMAND: 209 case DICT_COMMAND:
303 DUP_string_len( dest->data.cmd.cmd_name, &dest->datastr_len ); 210 DUP_string_len( dest->data.cmd.cmd_name, &dest->datastr_len );
304 break; 211 break;
305 212
306 default: 213 default:
307 /* Nothing to do for RULES */ 214 /* Nothing to do for RULES */
308 ; 215 ;
309 } 216 }
310 217
311 return 0; 218 return 0;
312 } 219 }
313 220
314 /* Check that an object is valid (1: OK, 0: error) */ 221 /* Check that an object is valid (1: OK, 0: error) */
315 static int verify_object( struct dict_object * obj ) 222 static int verify_object( struct dict_object * obj )
316 { 223 {
317 TRACE_ENTRY("%p", obj); 224 TRACE_ENTRY("%p", obj);
318 225
319 CHECK_PARAMS_DO( obj 226 CHECK_PARAMS_DO( obj
320 && (obj->objeyec == OBJECT_EYECATCHER) 227 && (obj->objeyec == OBJECT_EYECATCHER)
321 && CHECK_TYPE(obj->type) 228 && CHECK_TYPE(obj->type)
322 && (obj->typeyec == dict_obj_info[obj->type].eyecatcher), 229 && (obj->typeyec == dict_obj_info[obj->type].eyecatcher),
323 { 230 {
331 } else { 238 } else {
332 TRACE_DEBUG(FULL, "Invalid object : NULL pointer"); 239 TRACE_DEBUG(FULL, "Invalid object : NULL pointer");
333 } 240 }
334 return 0; 241 return 0;
335 } ); 242 } );
336 243
337 /* The object is probably valid. */ 244 /* The object is probably valid. */
338 return 1; 245 return 1;
339 } 246 }
340 247
341 /* Free the data associated to an object */ 248 /* Free the data associated to an object */
342 static void destroy_object_data(struct dict_object * obj) 249 static void destroy_object_data(struct dict_object * obj)
343 { 250 {
344 /* TRACE_ENTRY("%p", obj); */ 251 /* TRACE_ENTRY("%p", obj); */
345 252
346 switch (obj->type) { 253 switch (obj->type) {
347 case DICT_VENDOR: 254 case DICT_VENDOR:
348 free( obj->data.vendor.vendor_name ); 255 free( obj->data.vendor.vendor_name );
349 break; 256 break;
350 257
351 case DICT_APPLICATION: 258 case DICT_APPLICATION:
352 free( obj->data.application.application_name ); 259 free( obj->data.application.application_name );
353 break; 260 break;
354 261
355 case DICT_TYPE: 262 case DICT_TYPE:
356 free( obj->data.type.type_name ); 263 free( obj->data.type.type_name );
357 break; 264 break;
358 265
359 case DICT_ENUMVAL: 266 case DICT_ENUMVAL:
360 free( obj->data.enumval.enum_name ); 267 free( obj->data.enumval.enum_name );
361 break; 268 break;
362 269
363 case DICT_AVP: 270 case DICT_AVP:
364 free( obj->data.avp.avp_name ); 271 free( obj->data.avp.avp_name );
365 break; 272 break;
366 273
367 case DICT_COMMAND: 274 case DICT_COMMAND:
368 free( obj->data.cmd.cmd_name ); 275 free( obj->data.cmd.cmd_name );
369 break; 276 break;
370 277
371 default: 278 default:
372 /* nothing to do */ 279 /* nothing to do */
373 ; 280 ;
374 } 281 }
375 } 282 }
376 283
377 /* Forward declaration */ 284 /* Forward declaration */
378 static void destroy_object(struct dict_object * obj); 285 static void destroy_object(struct dict_object * obj);
379 286
380 /* Destroy all objects in a list - the lock must be held */ 287 /* Destroy all objects in a list - the lock must be held */
381 static void destroy_list(struct fd_list * head) 288 static void destroy_list(struct fd_list * head)
382 { 289 {
383 /* TRACE_ENTRY("%p", head); */ 290 /* TRACE_ENTRY("%p", head); */
384 291
385 /* loop in the list */ 292 /* loop in the list */
386 while (!FD_IS_LIST_EMPTY(head)) 293 while (!FD_IS_LIST_EMPTY(head))
387 { 294 {
388 /* When destroying the object, it is unlinked from the list */ 295 /* When destroying the object, it is unlinked from the list */
389 destroy_object(_O(head->next->o)); 296 destroy_object(_O(head->next->o));
390 } 297 }
391 } 298 }
392 299
393 /* Free an object and its sublists */ 300 /* Free an object and its sublists */
394 static void destroy_object(struct dict_object * obj) 301 static void destroy_object(struct dict_object * obj)
395 { 302 {
396 int i; 303 int i;
397 304
398 /* TRACE_ENTRY("%p", obj); */ 305 /* TRACE_ENTRY("%p", obj); */
399 306
400 /* Update global count */ 307 /* Update global count */
401 if (obj->dico) 308 if (obj->dico)
402 obj->dico->dict_count[obj->type]--; 309 obj->dico->dict_count[obj->type]--;
403 310
404 /* Mark the object as invalid */ 311 /* Mark the object as invalid */
405 obj->objeyec = 0xdead; 312 obj->objeyec = 0xdead;
406 313
407 /* First, destroy the data associated to the object */ 314 /* First, destroy the data associated to the object */
408 destroy_object_data(obj); 315 destroy_object_data(obj);
409 316
410 for (i=0; i<NB_LISTS_PER_OBJ; i++) { 317 for (i=0; i<NB_LISTS_PER_OBJ; i++) {
411 if (_OBINFO(obj).haslist[i]) 318 if (_OBINFO(obj).haslist[i])
412 /* unlink the element from the list */ 319 /* unlink the element from the list */
413 fd_list_unlink( &obj->list[i] ); 320 fd_list_unlink( &obj->list[i] );
414 else 321 else
415 /* This is either a sentinel or unused (=emtpy) list, let's destroy it */ 322 /* This is either a sentinel or unused (=emtpy) list, let's destroy it */
416 destroy_list( &obj->list[i] ); 323 destroy_list( &obj->list[i] );
417 } 324 }
418 325
419 /* Unlink all elements from the dispatch list; they will be freed when callback is unregistered */ 326 /* Unlink all elements from the dispatch list; they will be freed when callback is unregistered */
420 CHECK_POSIX_DO( pthread_rwlock_wrlock(&fd_disp_lock), /* continue */ ); 327 CHECK_POSIX_DO( pthread_rwlock_wrlock(&fd_disp_lock), /* continue */ );
421 while (!FD_IS_LIST_EMPTY(&obj->disp_cbs)) { 328 while (!FD_IS_LIST_EMPTY(&obj->disp_cbs)) {
422 fd_list_unlink( obj->disp_cbs.next ); 329 fd_list_unlink( obj->disp_cbs.next );
423 } 330 }
424 CHECK_POSIX_DO( pthread_rwlock_unlock(&fd_disp_lock), /* continue */ ); 331 CHECK_POSIX_DO( pthread_rwlock_unlock(&fd_disp_lock), /* continue */ );
425 332
426 /* Last, destroy the object */ 333 /* Last, destroy the object */
427 free(obj); 334 free(obj);
428 } 335 }
429 336
430 /*******************************************************************************************************/ 337 /*******************************************************************************************************/
435 /*******************************************************************************************************/ 342 /*******************************************************************************************************/
436 /*******************************************************************************************************/ 343 /*******************************************************************************************************/
437 344
438 /* Compare two values */ 345 /* Compare two values */
439 #define ORDER_scalar( i1, i2 ) \ 346 #define ORDER_scalar( i1, i2 ) \
440 ((i1 < i2 ) ? -1 : ( i1 > i2 ? 1 : 0 )) 347 ((i1 < i2 ) ? -1 : ( i1 > i2 ? 1 : 0 ))
441 348
442 349
443 /* Compare two vendor objects by their id (checks already performed) */ 350 /* Compare two vendor objects by their id (checks already performed) */
444 static int order_vendor_by_id ( struct dict_object *o1, struct dict_object *o2 ) 351 static int order_vendor_by_id ( struct dict_object *o1, struct dict_object *o2 )
445 { 352 {
446 TRACE_ENTRY("%p %p", o1, o2); 353 TRACE_ENTRY("%p %p", o1, o2);
447 354
448 return ORDER_scalar( o1->data.vendor.vendor_id, o2->data.vendor.vendor_id ); 355 return ORDER_scalar( o1->data.vendor.vendor_id, o2->data.vendor.vendor_id );
449 } 356 }
450 357
451 /* Compare two application objects by their id (checks already performed) */ 358 /* Compare two application objects by their id (checks already performed) */
452 static int order_appli_by_id ( struct dict_object *o1, struct dict_object *o2 ) 359 static int order_appli_by_id ( struct dict_object *o1, struct dict_object *o2 )
453 { 360 {
454 TRACE_ENTRY("%p %p", o1, o2); 361 TRACE_ENTRY("%p %p", o1, o2);
455 362
456 return ORDER_scalar( o1->data.application.application_id, o2->data.application.application_id ); 363 return ORDER_scalar( o1->data.application.application_id, o2->data.application.application_id );
457 } 364 }
458 365
459 /* Compare two type objects by their name (checks already performed) */ 366 /* Compare two type objects by their name (checks already performed) */
460 static int order_type_by_name ( struct dict_object *o1, struct dict_object *o2 ) 367 static int order_type_by_name ( struct dict_object *o1, struct dict_object *o2 )
461 { 368 {
462 TRACE_ENTRY("%p %p", o1, o2); 369 TRACE_ENTRY("%p %p", o1, o2);
463 370
464 return fd_os_cmp( o1->data.type.type_name, o1->datastr_len, o2->data.type.type_name, o2->datastr_len ); 371 return fd_os_cmp( o1->data.type.type_name, o1->datastr_len, o2->data.type.type_name, o2->datastr_len );
465 } 372 }
466 373
467 /* Compare two type_enum objects by their names (checks already performed) */ 374 /* Compare two type_enum objects by their names (checks already performed) */
468 static int order_enum_by_name ( struct dict_object *o1, struct dict_object *o2 ) 375 static int order_enum_by_name ( struct dict_object *o1, struct dict_object *o2 )
469 { 376 {
470 TRACE_ENTRY("%p %p", o1, o2); 377 TRACE_ENTRY("%p %p", o1, o2);
471 378
472 return fd_os_cmp( o1->data.enumval.enum_name, o1->datastr_len, o2->data.enumval.enum_name, o2->datastr_len ); 379 return fd_os_cmp( o1->data.enumval.enum_name, o1->datastr_len, o2->data.enumval.enum_name, o2->datastr_len );
473 } 380 }
474 381
475 /* Compare two type_enum objects by their values (checks already performed) */ 382 /* Compare two type_enum objects by their values (checks already performed) */
476 static int order_enum_by_val ( struct dict_object *o1, struct dict_object *o2 ) 383 static int order_enum_by_val ( struct dict_object *o1, struct dict_object *o2 )
477 { 384 {
478 TRACE_ENTRY("%p %p", o1, o2); 385 TRACE_ENTRY("%p %p", o1, o2);
479 386
480 /* The comparison function depends on the type of data */ 387 /* The comparison function depends on the type of data */
481 switch ( o1->parent->data.type.type_base ) { 388 switch ( o1->parent->data.type.type_base ) {
482 case AVP_TYPE_OCTETSTRING: 389 case AVP_TYPE_OCTETSTRING:
483 return fd_os_cmp( o1->data.enumval.enum_value.os.data, o1->data.enumval.enum_value.os.len, 390 return fd_os_cmp( o1->data.enumval.enum_value.os.data, o1->data.enumval.enum_value.os.len,
484 o2->data.enumval.enum_value.os.data, o2->data.enumval.enum_value.os.len); 391 o2->data.enumval.enum_value.os.data, o2->data.enumval.enum_value.os.len);
485 392
486 case AVP_TYPE_INTEGER32: 393 case AVP_TYPE_INTEGER32:
487 return ORDER_scalar( o1->data.enumval.enum_value.i32, o2->data.enumval.enum_value.i32 ); 394 return ORDER_scalar( o1->data.enumval.enum_value.i32, o2->data.enumval.enum_value.i32 );
488 395
489 case AVP_TYPE_INTEGER64: 396 case AVP_TYPE_INTEGER64:
490 return ORDER_scalar( o1->data.enumval.enum_value.i64, o2->data.enumval.enum_value.i64 ); 397 return ORDER_scalar( o1->data.enumval.enum_value.i64, o2->data.enumval.enum_value.i64 );
510 417
511 /* Compare two avp objects by their codes (checks already performed) */ 418 /* Compare two avp objects by their codes (checks already performed) */
512 static int order_avp_by_code ( struct dict_object *o1, struct dict_object *o2 ) 419 static int order_avp_by_code ( struct dict_object *o1, struct dict_object *o2 )
513 { 420 {
514 TRACE_ENTRY("%p %p", o1, o2); 421 TRACE_ENTRY("%p %p", o1, o2);
515 422
516 return ORDER_scalar( o1->data.avp.avp_code, o2->data.avp.avp_code ); 423 return ORDER_scalar( o1->data.avp.avp_code, o2->data.avp.avp_code );
517 } 424 }
518 425
519 /* Compare two avp objects by their names (checks already performed) */ 426 /* Compare two avp objects by their names (checks already performed) */
520 static int order_avp_by_name ( struct dict_object *o1, struct dict_object *o2 ) 427 static int order_avp_by_name ( struct dict_object *o1, struct dict_object *o2 )
521 { 428 {
522 TRACE_ENTRY("%p %p", o1, o2); 429 TRACE_ENTRY("%p %p", o1, o2);
523 430
524 return fd_os_cmp( o1->data.avp.avp_name, o1->datastr_len, o2->data.avp.avp_name, o2->datastr_len ); 431 return fd_os_cmp( o1->data.avp.avp_name, o1->datastr_len, o2->data.avp.avp_name, o2->datastr_len );
525 } 432 }
526 433
527 /* Compare two command objects by their names (checks already performed) */ 434 /* Compare two command objects by their names (checks already performed) */
528 static int order_cmd_by_name ( struct dict_object *o1, struct dict_object *o2 ) 435 static int order_cmd_by_name ( struct dict_object *o1, struct dict_object *o2 )
529 { 436 {
530 TRACE_ENTRY("%p %p", o1, o2); 437 TRACE_ENTRY("%p %p", o1, o2);
531 438
532 return fd_os_cmp( o1->data.cmd.cmd_name, o1->datastr_len, o2->data.cmd.cmd_name, o2->datastr_len ); 439 return fd_os_cmp( o1->data.cmd.cmd_name, o1->datastr_len, o2->data.cmd.cmd_name, o2->datastr_len );
533 } 440 }
534 441
535 /* Compare two command objects by their codes and flags (request or answer) (checks already performed) */ 442 /* Compare two command objects by their codes and flags (request or answer) (checks already performed) */
536 static int order_cmd_by_codefl( struct dict_object *o1, struct dict_object *o2 ) 443 static int order_cmd_by_codefl( struct dict_object *o1, struct dict_object *o2 )
537 { 444 {
538 uint8_t fl1, fl2; 445 uint8_t fl1, fl2;
539 int cmp = 0; 446 int cmp = 0;
540 447
541 TRACE_ENTRY("%p %p", o1, o2); 448 TRACE_ENTRY("%p %p", o1, o2);
542 449
543 cmp = ORDER_scalar( o1->data.cmd.cmd_code, o2->data.cmd.cmd_code ); 450 cmp = ORDER_scalar( o1->data.cmd.cmd_code, o2->data.cmd.cmd_code );
544 if (cmp) 451 if (cmp)
545 return cmp; 452 return cmp;
546 453
547 /* Same command code, we must compare the value of the 'R' flag */ 454 /* Same command code, we must compare the value of the 'R' flag */
548 fl1 = o1->data.cmd.cmd_flag_val & CMD_FLAG_REQUEST; 455 fl1 = o1->data.cmd.cmd_flag_val & CMD_FLAG_REQUEST;
549 fl2 = o2->data.cmd.cmd_flag_val & CMD_FLAG_REQUEST; 456 fl2 = o2->data.cmd.cmd_flag_val & CMD_FLAG_REQUEST;
550 457
551 /* We want requests first, so we reverse the operators here */ 458 /* We want requests first, so we reverse the operators here */
552 return ORDER_scalar(fl2, fl1); 459 return ORDER_scalar(fl2, fl1);
553 460
554 } 461 }
555 462
556 /* Compare two rule object by the AVP vendor & code that they refer (checks already performed) */ 463 /* Compare two rule object by the AVP vendor & code that they refer (checks already performed) */
557 static int order_rule_by_avpvc ( struct dict_object *o1, struct dict_object *o2 ) 464 static int order_rule_by_avpvc ( struct dict_object *o1, struct dict_object *o2 )
558 { 465 {
559 TRACE_ENTRY("%p %p", o1, o2); 466 TRACE_ENTRY("%p %p", o1, o2);
560 467
561 return ORDER_scalar(o1->data.rule.rule_avp->data.avp.avp_vendor, o2->data.rule.rule_avp->data.avp.avp_vendor) 468 return ORDER_scalar(o1->data.rule.rule_avp->data.avp.avp_vendor, o2->data.rule.rule_avp->data.avp.avp_vendor)
562 ?: ORDER_scalar(o1->data.rule.rule_avp->data.avp.avp_code, o2->data.rule.rule_avp->data.avp.avp_code) ; 469 ?: ORDER_scalar(o1->data.rule.rule_avp->data.avp.avp_code, o2->data.rule.rule_avp->data.avp.avp_code) ;
563 } 470 }
564 471
565 /*******************************************************************************************************/ 472 /*******************************************************************************************************/
566 /*******************************************************************************************************/ 473 /*******************************************************************************************************/
742 649
743 static int search_vendor ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result ) 650 static int search_vendor ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result )
744 { 651 {
745 int ret = 0; 652 int ret = 0;
746 vendor_id_t id; 653 vendor_id_t id;
747 654
748 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 655 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result);
749 656
750 switch (criteria) { 657 switch (criteria) {
751 case VENDOR_BY_ID: 658 case VENDOR_BY_ID:
752 id = *(vendor_id_t *) what; 659 id = *(vendor_id_t *) what;
753 SEARCH_scalar( id, &dict->dict_vendors.list[0], vendor.vendor_id, 1, &dict->dict_vendors ); 660 SEARCH_scalar( id, &dict->dict_vendors.list[0], vendor.vendor_id, 1, &dict->dict_vendors );
754 break; 661 break;
755 662
756 case VENDOR_BY_NAME: 663 case VENDOR_BY_NAME:
757 /* "what" is a vendor name */ 664 /* "what" is a vendor name */
758 SEARCH_os0( what, &dict->dict_vendors.list[0], vendor.vendor_name, 0); 665 SEARCH_os0( what, &dict->dict_vendors.list[0], vendor.vendor_name, 0);
759 break; 666 break;
760 667
761 case VENDOR_OF_APPLICATION: 668 case VENDOR_OF_APPLICATION:
762 /* "what" should be an application object */ 669 /* "what" should be an application object */
763 SEARCH_childs_parent( DICT_APPLICATION, &dict->dict_vendors ); 670 SEARCH_childs_parent( DICT_APPLICATION, &dict->dict_vendors );
764 break; 671 break;
765 672
766 case VENDOR_OF_AVP: 673 case VENDOR_OF_AVP:
767 /* "what" should be an avp object */ 674 /* "what" should be an avp object */
768 SEARCH_sentinel( DICT_AVP, 0, 1 ); 675 SEARCH_sentinel( DICT_AVP, 0, 1 );
769 break; 676 break;
770 677
771 default: 678 default:
772 /* Invalid criteria */ 679 /* Invalid criteria */
773 CHECK_PARAMS( criteria = 0 ); 680 CHECK_PARAMS( criteria = 0 );
774 } 681 }
775 end: 682 end:
778 685
779 static int search_application ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result ) 686 static int search_application ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result )
780 { 687 {
781 int ret = 0; 688 int ret = 0;
782 application_id_t id; 689 application_id_t id;
783 690
784 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 691 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result);
785 692
786 switch (criteria) { 693 switch (criteria) {
787 case APPLICATION_BY_ID: 694 case APPLICATION_BY_ID:
788 id = *(application_id_t *) what; 695 id = *(application_id_t *) what;
789 696
790 SEARCH_scalar( id, &dict->dict_applications.list[0], application.application_id, 1, &dict->dict_applications ); 697 SEARCH_scalar( id, &dict->dict_applications.list[0], application.application_id, 1, &dict->dict_applications );
791 break; 698 break;
792 699
793 case APPLICATION_BY_NAME: 700 case APPLICATION_BY_NAME:
794 /* "what" is an application name */ 701 /* "what" is an application name */
795 SEARCH_os0( what, &dict->dict_applications.list[0], application.application_name, 0); 702 SEARCH_os0( what, &dict->dict_applications.list[0], application.application_name, 0);
796 break; 703 break;
797 704
798 case APPLICATION_OF_TYPE: 705 case APPLICATION_OF_TYPE:
799 /* "what" should be a type object */ 706 /* "what" should be a type object */
800 SEARCH_childs_parent( DICT_TYPE, &dict->dict_applications ); 707 SEARCH_childs_parent( DICT_TYPE, &dict->dict_applications );
801 break; 708 break;
802 709
803 case APPLICATION_OF_COMMAND: 710 case APPLICATION_OF_COMMAND:
804 /* "what" should be a command object */ 711 /* "what" should be a command object */
805 SEARCH_childs_parent( DICT_COMMAND, &dict->dict_applications ); 712 SEARCH_childs_parent( DICT_COMMAND, &dict->dict_applications );
806 break; 713 break;
807 714
808 default: 715 default:
809 /* Invalid criteria */ 716 /* Invalid criteria */
810 CHECK_PARAMS( criteria = 0 ); 717 CHECK_PARAMS( criteria = 0 );
811 } 718 }
812 end: 719 end:
814 } 721 }
815 722
816 static int search_type ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result ) 723 static int search_type ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result )
817 { 724 {
818 int ret = 0; 725 int ret = 0;
819 726
820 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 727 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result);
821 728
822 switch (criteria) { 729 switch (criteria) {
823 case TYPE_BY_NAME: 730 case TYPE_BY_NAME:
824 /* "what" is a type name */ 731 /* "what" is a type name */
825 SEARCH_os0( what, &dict->dict_types, type.type_name, 1); 732 SEARCH_os0( what, &dict->dict_types, type.type_name, 1);
826 break; 733 break;
827 734
828 case TYPE_OF_ENUMVAL: 735 case TYPE_OF_ENUMVAL:
829 /* "what" should be a type_enum object */ 736 /* "what" should be a type_enum object */
830 SEARCH_childs_parent( DICT_ENUMVAL, NULL ); 737 SEARCH_childs_parent( DICT_ENUMVAL, NULL );
831 break; 738 break;
832 739
833 case TYPE_OF_AVP: 740 case TYPE_OF_AVP:
834 /* "what" should be an avp object */ 741 /* "what" should be an avp object */
835 SEARCH_childs_parent( DICT_AVP, NULL ); 742 SEARCH_childs_parent( DICT_AVP, NULL );
836 break; 743 break;
837 744
838 745
839 default: 746 default:
840 /* Invalid criteria */ 747 /* Invalid criteria */
841 CHECK_PARAMS( criteria = 0 ); 748 CHECK_PARAMS( criteria = 0 );
842 } 749 }
843 end: 750 end:
845 } 752 }
846 753
847 static int search_enumval ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result ) 754 static int search_enumval ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result )
848 { 755 {
849 int ret = 0; 756 int ret = 0;
850 757
851 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 758 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result);
852 759
853 switch (criteria) { 760 switch (criteria) {
854 case ENUMVAL_BY_STRUCT: 761 case ENUMVAL_BY_STRUCT:
855 { 762 {
856 struct dict_object * parent = NULL; 763 struct dict_object * parent = NULL;
857 struct dict_enumval_request * _what = (struct dict_enumval_request *) what; 764 struct dict_enumval_request * _what = (struct dict_enumval_request *) what;
858 765
859 CHECK_PARAMS( _what && ( _what->type_obj || _what->type_name ) ); 766 CHECK_PARAMS( _what && ( _what->type_obj || _what->type_name ) );
860 767
861 if (_what->type_obj != NULL) { 768 if (_what->type_obj != NULL) {
862 parent = _what->type_obj; 769 parent = _what->type_obj;
863 CHECK_PARAMS( verify_object(parent) && (parent->type == DICT_TYPE) ); 770 CHECK_PARAMS( verify_object(parent) && (parent->type == DICT_TYPE) );
864 } else { 771 } else {
865 /* We received only the type name, we must find it first */ 772 /* We received only the type name, we must find it first */
866 CHECK_FCT_DO( search_type( dict, TYPE_BY_NAME, _what->type_name, &parent ), 773 CHECK_FCT_DO( search_type( dict, TYPE_BY_NAME, _what->type_name, &parent ),
867 CHECK_PARAMS( 0 ) ); 774 CHECK_PARAMS( 0 ) );
868 } 775 }
869 776
870 /* From here the "parent" object is valid */ 777 /* From here the "parent" object is valid */
871 778
872 if ( _what->search.enum_name != NULL ) { 779 if ( _what->search.enum_name != NULL ) {
873 /* We are looking for this string */ 780 /* We are looking for this string */
874 SEARCH_os0( _what->search.enum_name, &parent->list[1], enumval.enum_name, 1 ); 781 SEARCH_os0( _what->search.enum_name, &parent->list[1], enumval.enum_name, 1 );
875 } else { 782 } else {
876 /* We are looking for the value in enum_value */ 783 /* We are looking for the value in enum_value */
877 switch (parent->data.type.type_base) { 784 switch (parent->data.type.type_base) {
878 case AVP_TYPE_OCTETSTRING: 785 case AVP_TYPE_OCTETSTRING:
879 SEARCH_os( _what->search.enum_value.os.data, 786 SEARCH_os( _what->search.enum_value.os.data,
880 _what->search.enum_value.os.len, 787 _what->search.enum_value.os.len,
881 &parent->list[2], 788 &parent->list[2],
882 enumval.enum_value.os , 789 enumval.enum_value.os ,
883 1 ); 790 1 );
884 break; 791 break;
885 792
886 case AVP_TYPE_INTEGER32: 793 case AVP_TYPE_INTEGER32:
887 SEARCH_scalar( _what->search.enum_value.i32, 794 SEARCH_scalar( _what->search.enum_value.i32,
888 &parent->list[2], 795 &parent->list[2],
889 enumval.enum_value.i32, 796 enumval.enum_value.i32,
890 1, 797 1,
891 (struct dict_object *)NULL); 798 (struct dict_object *)NULL);
892 break; 799 break;
893 800
894 case AVP_TYPE_INTEGER64: 801 case AVP_TYPE_INTEGER64:
895 SEARCH_scalar( _what->search.enum_value.i64, 802 SEARCH_scalar( _what->search.enum_value.i64,
896 &parent->list[2], 803 &parent->list[2],
897 enumval.enum_value.i64, 804 enumval.enum_value.i64,
898 1, 805 1,
899 (struct dict_object *)NULL); 806 (struct dict_object *)NULL);
900 break; 807 break;
901 808
902 case AVP_TYPE_UNSIGNED32: 809 case AVP_TYPE_UNSIGNED32:
903 SEARCH_scalar( _what->search.enum_value.u32, 810 SEARCH_scalar( _what->search.enum_value.u32,
904 &parent->list[2], 811 &parent->list[2],
905 enumval.enum_value.u32, 812 enumval.enum_value.u32,
906 1, 813 1,
907 (struct dict_object *)NULL); 814 (struct dict_object *)NULL);
908 break; 815 break;
909 816
910 case AVP_TYPE_UNSIGNED64: 817 case AVP_TYPE_UNSIGNED64:
911 SEARCH_scalar( _what->search.enum_value.u64, 818 SEARCH_scalar( _what->search.enum_value.u64,
912 &parent->list[2], 819 &parent->list[2],
913 enumval.enum_value.u64, 820 enumval.enum_value.u64,
914 1, 821 1,
915 (struct dict_object *)NULL); 822 (struct dict_object *)NULL);
916 break; 823 break;
917 824
918 case AVP_TYPE_FLOAT32: 825 case AVP_TYPE_FLOAT32:
919 SEARCH_scalar( _what->search.enum_value.f32, 826 SEARCH_scalar( _what->search.enum_value.f32,
920 &parent->list[2], 827 &parent->list[2],
921 enumval.enum_value.f32, 828 enumval.enum_value.f32,
922 1, 829 1,
923 (struct dict_object *)NULL); 830 (struct dict_object *)NULL);
924 break; 831 break;
925 832
926 case AVP_TYPE_FLOAT64: 833 case AVP_TYPE_FLOAT64:
927 SEARCH_scalar( _what->search.enum_value.f64, 834 SEARCH_scalar( _what->search.enum_value.f64,
928 &parent->list[2], 835 &parent->list[2],
929 enumval.enum_value.f64, 836 enumval.enum_value.f64,
930 1, 837 1,
931 (struct dict_object *)NULL); 838 (struct dict_object *)NULL);
932 break; 839 break;
933 840
934 default: 841 default:
935 /* Invalid parent type basetype */ 842 /* Invalid parent type basetype */
936 CHECK_PARAMS( parent = NULL ); 843 CHECK_PARAMS( parent = NULL );
937 } 844 }
938 } 845 }
939 846
940 } 847 }
941 break; 848 break;
942 849
943 850
944 default: 851 default:
945 /* Invalid criteria */ 852 /* Invalid criteria */
946 CHECK_PARAMS( criteria = 0 ); 853 CHECK_PARAMS( criteria = 0 );
947 } 854 }
948 end: 855 end:
950 } 857 }
951 858
952 static int search_avp ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result ) 859 static int search_avp ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result )
953 { 860 {
954 int ret = 0; 861 int ret = 0;
955 862
956 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 863 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result);
957 864
958 switch (criteria) { 865 switch (criteria) {
959 case AVP_BY_CODE: 866 case AVP_BY_CODE:
960 { 867 {
961 avp_code_t code; 868 avp_code_t code;
962 code = *(avp_code_t *) what; 869 code = *(avp_code_t *) what;
963 870
964 SEARCH_scalar( code, &dict->dict_vendors.list[1], avp.avp_code, 1, (struct dict_object *)NULL ); 871 SEARCH_scalar( code, &dict->dict_vendors.list[1], avp.avp_code, 1, (struct dict_object *)NULL );
965 } 872 }
966 break; 873 break;
967 874
968 case AVP_BY_NAME: 875 case AVP_BY_NAME:
969 /* "what" is the AVP name, vendor 0 */ 876 /* "what" is the AVP name, vendor 0 */
970 SEARCH_os0( what, &dict->dict_vendors.list[2], avp.avp_name, 1); 877 SEARCH_os0( what, &dict->dict_vendors.list[2], avp.avp_name, 1);
971 break; 878 break;
972 879
973 case AVP_BY_CODE_AND_VENDOR: 880 case AVP_BY_CODE_AND_VENDOR:
974 case AVP_BY_NAME_AND_VENDOR: 881 case AVP_BY_NAME_AND_VENDOR:
975 { 882 {
976 struct dict_avp_request * _what = (struct dict_avp_request *) what; 883 struct dict_avp_request * _what = (struct dict_avp_request *) what;
977 struct dict_object * vendor = NULL; 884 struct dict_object * vendor = NULL;
978 885
979 CHECK_PARAMS( (criteria != AVP_BY_NAME_AND_VENDOR) || _what->avp_name ); 886 CHECK_PARAMS( (criteria != AVP_BY_NAME_AND_VENDOR) || _what->avp_name );
980 887
981 /* Now look for the vendor first */ 888 /* Now look for the vendor first */
982 CHECK_FCT( search_vendor( dict, VENDOR_BY_ID, &_what->avp_vendor, &vendor ) ); 889 CHECK_FCT( search_vendor( dict, VENDOR_BY_ID, &_what->avp_vendor, &vendor ) );
983 if (vendor == NULL) { 890 if (vendor == NULL) {
984 if (result) 891 if (result)
985 *result = NULL; 892 *result = NULL;
986 else 893 else
987 ret = ENOENT; 894 ret = ENOENT;
988 goto end; 895 goto end;
989 } 896 }
990 897
991 /* We now have our vendor = head of the appropriate avp list */ 898 /* We now have our vendor = head of the appropriate avp list */
992 if (criteria == AVP_BY_NAME_AND_VENDOR) { 899 if (criteria == AVP_BY_NAME_AND_VENDOR) {
993 SEARCH_os0( _what->avp_name, &vendor->list[2], avp.avp_name, 1); 900 SEARCH_os0( _what->avp_name, &vendor->list[2], avp.avp_name, 1);
994 } else { 901 } else {
995 /* AVP_BY_CODE_AND_VENDOR */ 902 /* AVP_BY_CODE_AND_VENDOR */
996 SEARCH_scalar( _what->avp_code, &vendor->list[1], avp.avp_code, 1, (struct dict_object *)NULL ); 903 SEARCH_scalar( _what->avp_code, &vendor->list[1], avp.avp_code, 1, (struct dict_object *)NULL );
997 } 904 }
998 } 905 }
999 break; 906 break;
1000 907
1001 case AVP_BY_STRUCT: 908 case AVP_BY_STRUCT:
1002 { 909 {
1003 struct dict_avp_request_ex * _what = (struct dict_avp_request_ex *) what; 910 struct dict_avp_request_ex * _what = (struct dict_avp_request_ex *) what;
1004 struct dict_object * vendor = NULL; 911 struct dict_object * vendor = NULL;
1005 912
1006 CHECK_PARAMS( _what->avp_vendor.vendor || _what->avp_vendor.vendor_id || _what->avp_vendor.vendor_name ); 913 CHECK_PARAMS( _what->avp_vendor.vendor || _what->avp_vendor.vendor_id || _what->avp_vendor.vendor_name );
1007 CHECK_PARAMS( _what->avp_data.avp_code || _what->avp_data.avp_name ); 914 CHECK_PARAMS( _what->avp_data.avp_code || _what->avp_data.avp_name );
1008 915
1009 /* Now look for the vendor first */ 916 /* Now look for the vendor first */
1010 if (_what->avp_vendor.vendor) { 917 if (_what->avp_vendor.vendor) {
1011 CHECK_PARAMS( ! _what->avp_vendor.vendor_id && ! _what->avp_vendor.vendor_name ); 918 CHECK_PARAMS( ! _what->avp_vendor.vendor_id && ! _what->avp_vendor.vendor_name );
1012 vendor = _what->avp_vendor.vendor; 919 vendor = _what->avp_vendor.vendor;
1013 } else if (_what->avp_vendor.vendor_id) { 920 } else if (_what->avp_vendor.vendor_id) {
1014 CHECK_PARAMS( ! _what->avp_vendor.vendor_name ); 921 CHECK_PARAMS( ! _what->avp_vendor.vendor_name );
1015 CHECK_FCT( search_vendor( dict, VENDOR_BY_ID, &_what->avp_vendor.vendor_id, &vendor ) ); 922 CHECK_FCT( search_vendor( dict, VENDOR_BY_ID, &_what->avp_vendor.vendor_id, &vendor ) );
1016 } else { 923 } else {
1017 CHECK_FCT( search_vendor( dict, VENDOR_BY_NAME, _what->avp_vendor.vendor_name, &vendor ) ); 924 CHECK_FCT( search_vendor( dict, VENDOR_BY_NAME, _what->avp_vendor.vendor_name, &vendor ) );
1018 } 925 }
1019 926
1020 if (vendor == NULL) { 927 if (vendor == NULL) {
1021 if (result) 928 if (result)
1022 *result = NULL; 929 *result = NULL;
1023 else 930 else
1024 ret = ENOENT; 931 ret = ENOENT;
1025 goto end; 932 goto end;
1026 } 933 }
1027 934
1028 /* We now have our vendor = head of the appropriate avp list */ 935 /* We now have our vendor = head of the appropriate avp list */
1029 if (_what->avp_data.avp_code) { 936 if (_what->avp_data.avp_code) {
1030 CHECK_PARAMS( ! _what->avp_data.avp_name ); 937 CHECK_PARAMS( ! _what->avp_data.avp_name );
1031 SEARCH_scalar( _what->avp_data.avp_code, &vendor->list[1], avp.avp_code, 1, (struct dict_object *)NULL ); 938 SEARCH_scalar( _what->avp_data.avp_code, &vendor->list[1], avp.avp_code, 1, (struct dict_object *)NULL );
1032 } else { 939 } else {
1033 SEARCH_os0( _what->avp_data.avp_name, &vendor->list[2], avp.avp_name, 1); 940 SEARCH_os0( _what->avp_data.avp_name, &vendor->list[2], avp.avp_name, 1);
1034 } 941 }
1035 } 942 }
1036 break; 943 break;
1037 944
1038 case AVP_BY_NAME_ALL_VENDORS: 945 case AVP_BY_NAME_ALL_VENDORS:
1039 { 946 {
1040 struct fd_list * li; 947 struct fd_list * li;
1041 size_t wl = strlen((char *)what); 948 size_t wl = strlen((char *)what);
1042 949
1043 /* First, search for vendor 0 */ 950 /* First, search for vendor 0 */
1044 SEARCH_os0_l( what, wl, &dict->dict_vendors.list[2], avp.avp_name, 1); 951 SEARCH_os0_l( what, wl, &dict->dict_vendors.list[2], avp.avp_name, 1);
1045 952
1046 /* If not found, loop for all vendors, until found */ 953 /* If not found, loop for all vendors, until found */
1047 for (li = dict->dict_vendors.list[0].next; li != &dict->dict_vendors.list[0]; li = li->next) { 954 for (li = dict->dict_vendors.list[0].next; li != &dict->dict_vendors.list[0]; li = li->next) {
1048 SEARCH_os0_l( what, wl, &_O(li->o)->list[2], avp.avp_name, 1); 955 SEARCH_os0_l( what, wl, &_O(li->o)->list[2], avp.avp_name, 1);
1049 } 956 }
1050 } 957 }
1051 break; 958 break;
1052 959
1053 default: 960 default:
1054 /* Invalid criteria */ 961 /* Invalid criteria */
1055 CHECK_PARAMS( criteria = 0 ); 962 CHECK_PARAMS( criteria = 0 );
1056 } 963 }
1057 end: 964 end:
1059 } 966 }
1060 967
1061 static int search_cmd ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result ) 968 static int search_cmd ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result )
1062 { 969 {
1063 int ret = 0; 970 int ret = 0;
1064 971
1065 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 972 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result);
1066 973
1067 switch (criteria) { 974 switch (criteria) {
1068 case CMD_BY_NAME: 975 case CMD_BY_NAME:
1069 /* "what" is a command name */ 976 /* "what" is a command name */
1070 SEARCH_os0( what, &dict->dict_cmd_name, cmd.cmd_name, 1); 977 SEARCH_os0( what, &dict->dict_cmd_name, cmd.cmd_name, 1);
1071 break; 978 break;
1072 979
1073 case CMD_BY_CODE_R: 980 case CMD_BY_CODE_R:
1074 case CMD_BY_CODE_A: 981 case CMD_BY_CODE_A:
1075 { 982 {
1076 command_code_t code; 983 command_code_t code;
1077 uint8_t searchfl = 0; 984 uint8_t searchfl = 0;
1078 985
1079 /* The command code that we are searching */ 986 /* The command code that we are searching */
1080 code = *(command_code_t *) what; 987 code = *(command_code_t *) what;
1081 988
1082 /* The flag (request or answer) of the command we are searching */ 989 /* The flag (request or answer) of the command we are searching */
1083 if (criteria == CMD_BY_CODE_R) { 990 if (criteria == CMD_BY_CODE_R) {
1084 searchfl = CMD_FLAG_REQUEST; 991 searchfl = CMD_FLAG_REQUEST;
1085 } 992 }
1086 993
1087 /* perform the search */ 994 /* perform the search */
1088 SEARCH_codefl( code, searchfl, &dict->dict_cmd_code ); 995 SEARCH_codefl( code, searchfl, &dict->dict_cmd_code );
1089 } 996 }
1090 break; 997 break;
1091 998
1092 case CMD_ANSWER: 999 case CMD_ANSWER:
1093 { 1000 {
1094 /* "what" is a command object of type "request" */ 1001 /* "what" is a command object of type "request" */
1095 struct dict_object * req = (struct dict_object *) what; 1002 struct dict_object * req = (struct dict_object *) what;
1096 struct dict_object * ans = NULL; 1003 struct dict_object * ans = NULL;
1097 1004
1098 CHECK_PARAMS( verify_object(req) 1005 CHECK_PARAMS( verify_object(req)
1099 && (req->type == DICT_COMMAND) 1006 && (req->type == DICT_COMMAND)
1100 && (req->data.cmd.cmd_flag_mask & CMD_FLAG_REQUEST) 1007 && (req->data.cmd.cmd_flag_mask & CMD_FLAG_REQUEST)
1101 && (req->data.cmd.cmd_flag_val & CMD_FLAG_REQUEST) ); 1008 && (req->data.cmd.cmd_flag_val & CMD_FLAG_REQUEST) );
1102 1009
1103 /* The answer is supposed to be the next element in the list, if it exists */ 1010 /* The answer is supposed to be the next element in the list, if it exists */
1104 ans = req->list[1].next->o; 1011 ans = req->list[1].next->o;
1105 if ( ans == NULL ) { 1012 if ( ans == NULL ) {
1106 TRACE_DEBUG( FULL, "the request was the last element in the list" ); 1013 TRACE_DEBUG( FULL, "the request was the last element in the list" );
1107 ret = ENOENT; 1014 ret = ENOENT;
1108 goto end; 1015 goto end;
1109 } 1016 }
1110 1017
1111 /* Now check that the ans element is really the correct one */ 1018 /* Now check that the ans element is really the correct one */
1112 if ( (ans->data.cmd.cmd_code != req->data.cmd.cmd_code) 1019 if ( (ans->data.cmd.cmd_code != req->data.cmd.cmd_code)
1113 || (!(ans->data.cmd.cmd_flag_mask & CMD_FLAG_REQUEST)) 1020 || (!(ans->data.cmd.cmd_flag_mask & CMD_FLAG_REQUEST))
1114 || ( ans->data.cmd.cmd_flag_val & CMD_FLAG_REQUEST ) ) { 1021 || ( ans->data.cmd.cmd_flag_val & CMD_FLAG_REQUEST ) ) {
1115 TRACE_DEBUG( FULL, "the answer does not follow the request in the list" ); 1022 TRACE_DEBUG( FULL, "the answer does not follow the request in the list" );
1116 ret = ENOENT; 1023 ret = ENOENT;
1117 goto end; 1024 goto end;
1118 } 1025 }
1119 1026
1120 if (result) 1027 if (result)
1121 *result = ans; 1028 *result = ans;
1122 ret = 0; 1029 ret = 0;
1123 } 1030 }
1124 break; 1031 break;
1125 1032
1126 default: 1033 default:
1127 /* Invalid criteria */ 1034 /* Invalid criteria */
1128 CHECK_PARAMS( criteria = 0 ); 1035 CHECK_PARAMS( criteria = 0 );
1129 } 1036 }
1130 end: 1037 end:
1132 } 1039 }
1133 1040
1134 static int search_rule ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result ) 1041 static int search_rule ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result )
1135 { 1042 {
1136 int ret = 0; 1043 int ret = 0;
1137 1044
1138 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 1045 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result);
1139 1046
1140 switch (criteria) { 1047 switch (criteria) {
1141 case RULE_BY_AVP_AND_PARENT: 1048 case RULE_BY_AVP_AND_PARENT:
1142 { 1049 {
1143 struct dict_object * parent = NULL; 1050 struct dict_object * parent = NULL;
1144 struct dict_object * avp = NULL; 1051 struct dict_object * avp = NULL;
1145 struct dict_rule_request * _what = (struct dict_rule_request *) what; 1052 struct dict_rule_request * _what = (struct dict_rule_request *) what;
1146 1053
1147 CHECK_PARAMS( _what 1054 CHECK_PARAMS( _what
1148 && (parent = _what->rule_parent) 1055 && (parent = _what->rule_parent)
1149 && (avp = _what->rule_avp ) ); 1056 && (avp = _what->rule_avp ) );
1150 1057
1151 CHECK_PARAMS( verify_object(parent) 1058 CHECK_PARAMS( verify_object(parent)
1152 && ((parent->type == DICT_COMMAND) 1059 && ((parent->type == DICT_COMMAND)
1153 || ((parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED))) ); 1060 || ((parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED))) );
1154 1061
1155 CHECK_PARAMS( verify_object(avp) && (avp->type == DICT_AVP) ); 1062 CHECK_PARAMS( verify_object(avp) && (avp->type == DICT_AVP) );
1156 1063
1157 /* Perform the search */ 1064 /* Perform the search */
1158 SEARCH_ruleavpname( avp->data.avp.avp_name, avp->datastr_len, &parent->list[2]); 1065 SEARCH_ruleavpname( avp->data.avp.avp_name, avp->datastr_len, &parent->list[2]);
1159 1066
1160 } 1067 }
1161 break; 1068 break;
1162 1069
1163 default: 1070 default:
1164 /* Invalid criteria */ 1071 /* Invalid criteria */
1165 CHECK_PARAMS( criteria = 0 ); 1072 CHECK_PARAMS( criteria = 0 );
1166 } 1073 }
1167 end: 1074 end:
1177 /*******************************************************************************************************/ 1084 /*******************************************************************************************************/
1178 /* The following functions are used to debug the module, and allow to print out the content of the dictionary */ 1085 /* The following functions are used to debug the module, and allow to print out the content of the dictionary */
1179 static DECLARE_FD_DUMP_PROTOTYPE(dump_vendor_data, void * data ) 1086 static DECLARE_FD_DUMP_PROTOTYPE(dump_vendor_data, void * data )
1180 { 1087 {
1181 struct dict_vendor_data * vendor = (struct dict_vendor_data *)data; 1088 struct dict_vendor_data * vendor = (struct dict_vendor_data *)data;
1182 1089
1183 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-6u \"%s\"", vendor->vendor_id, vendor->vendor_name); 1090 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-6u \"%s\"", vendor->vendor_id, vendor->vendor_name);
1184 } 1091 }
1185 static DECLARE_FD_DUMP_PROTOTYPE(dump_application_data, void * data ) 1092 static DECLARE_FD_DUMP_PROTOTYPE(dump_application_data, void * data )
1186 { 1093 {
1187 struct dict_application_data * appli = (struct dict_application_data *) data; 1094 struct dict_application_data * appli = (struct dict_application_data *) data;
1188 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-6u \"%s\"", appli->application_id, appli->application_name); 1095 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-6u \"%s\"", appli->application_id, appli->application_name);
1189 } 1096 }
1190 static DECLARE_FD_DUMP_PROTOTYPE(dump_type_data, void * data ) 1097 static DECLARE_FD_DUMP_PROTOTYPE(dump_type_data, void * data )
1191 { 1098 {
1192 struct dict_type_data * type = ( struct dict_type_data * ) data; 1099 struct dict_type_data * type = ( struct dict_type_data * ) data;
1193 1100
1194 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-12s \"%s\"", 1101 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-12s \"%s\"",
1195 type_base_name[type->type_base], 1102 type_base_name[type->type_base],
1196 type->type_name); 1103 type->type_name);
1197 } 1104 }
1198 static DECLARE_FD_DUMP_PROTOTYPE(dump_enumval_data, struct dict_enumval_data * enumval, enum dict_avp_basetype type ) 1105 static DECLARE_FD_DUMP_PROTOTYPE(dump_enumval_data, struct dict_enumval_data * enumval, enum dict_avp_basetype type )
1199 { 1106 {
1200 const int LEN_MAX = 20; 1107 const int LEN_MAX = 20;
1209 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "0x%2hhX/'%c' ", enumval->enum_value.os.data[i], ASCII(enumval->enum_value.os.data[i])), return NULL); 1116 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "0x%2hhX/'%c' ", enumval->enum_value.os.data[i], ASCII(enumval->enum_value.os.data[i])), return NULL);
1210 if (n == LEN_MAX) 1117 if (n == LEN_MAX)
1211 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "..."), return NULL); 1118 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "..."), return NULL);
1212 } 1119 }
1213 break; 1120 break;
1214 1121
1215 case AVP_TYPE_INTEGER32: 1122 case AVP_TYPE_INTEGER32:
1216 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%i", enumval->enum_value.i32), return NULL); 1123 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%i", enumval->enum_value.i32), return NULL);
1217 break; 1124 break;
1218 1125
1219 case AVP_TYPE_INTEGER64: 1126 case AVP_TYPE_INTEGER64:
1233 break; 1140 break;
1234 1141
1235 case AVP_TYPE_FLOAT64: 1142 case AVP_TYPE_FLOAT64:
1236 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%g", enumval->enum_value.f64), return NULL); 1143 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%g", enumval->enum_value.f64), return NULL);
1237 break; 1144 break;
1238 1145
1239 default: 1146 default:
1240 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "??? (ERROR unknown type %d)", type), return NULL); 1147 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "??? (ERROR unknown type %d)", type), return NULL);
1241 } 1148 }
1242 return *buf; 1149 return *buf;
1243 } 1150 }
1244 static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_data, void * data ) 1151 static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_data, void * data )
1245 { 1152 {
1246 struct dict_avp_data * avp = (struct dict_avp_data * ) data; 1153 struct dict_avp_data * avp = (struct dict_avp_data * ) data;
1247 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %-6u \"%s\"", 1154 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %-6u \"%s\"",
1248 DUMP_AVPFL_val(avp->avp_flag_val), 1155 DUMP_AVPFL_val(avp->avp_flag_val),
1249 DUMP_AVPFL_val(avp->avp_flag_mask), 1156 DUMP_AVPFL_val(avp->avp_flag_mask),
1250 type_base_name[avp->avp_basetype], 1157 type_base_name[avp->avp_basetype],
1251 avp->avp_code, 1158 avp->avp_code,
1252 avp->avp_name ); 1159 avp->avp_name );
1253 } 1160 }
1254 static DECLARE_FD_DUMP_PROTOTYPE(dump_command_data, void * data ) 1161 static DECLARE_FD_DUMP_PROTOTYPE(dump_command_data, void * data )
1255 { 1162 {
1256 struct dict_cmd_data * cmd = (struct dict_cmd_data *) data; 1163 struct dict_cmd_data * cmd = (struct dict_cmd_data *) data;
1257 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %-6u \"%s\"", 1164 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %-6u \"%s\"",
1258 DUMP_CMDFL_val(cmd->cmd_flag_val), DUMP_CMDFL_val(cmd->cmd_flag_mask), cmd->cmd_code, cmd->cmd_name); 1165 DUMP_CMDFL_val(cmd->cmd_flag_val), DUMP_CMDFL_val(cmd->cmd_flag_mask), cmd->cmd_code, cmd->cmd_name);
1259 } 1166 }
1260 static DECLARE_FD_DUMP_PROTOTYPE(dump_rule_data, void * data ) 1167 static DECLARE_FD_DUMP_PROTOTYPE(dump_rule_data, void * data )
1261 { 1168 {
1262 struct dict_rule_data * rule = (struct dict_rule_data * )data; 1169 struct dict_rule_data * rule = (struct dict_rule_data * )data;
1263 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: pos:%d ord:%d m/M:%2d/%2d avp:\"%s\"", 1170 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: pos:%d ord:%d m/M:%2d/%2d avp:\"%s\"",
1264 rule->rule_position, 1171 rule->rule_position,
1265 rule->rule_order, 1172 rule->rule_order,
1266 rule->rule_min, 1173 rule->rule_min,
1267 rule->rule_max, 1174 rule->rule_max,
1268 rule->rule_avp->data.avp.avp_name); 1175 rule->rule_avp->data.avp.avp_name);
1269 } 1176 }
1270 1177
1271 static DECLARE_FD_DUMP_PROTOTYPE(dump_object, struct dict_object * obj, int parents, int depth, int indent ); 1178 static DECLARE_FD_DUMP_PROTOTYPE(dump_object, struct dict_object * obj, int parents, int depth, int indent );
1288 } 1195 }
1289 1196
1290 static DECLARE_FD_DUMP_PROTOTYPE(dump_object, struct dict_object * obj, int parents, int depth, int indent ) 1197 static DECLARE_FD_DUMP_PROTOTYPE(dump_object, struct dict_object * obj, int parents, int depth, int indent )
1291 { 1198 {
1292 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*s{dictobj}(@%p): ", indent, "", obj), return NULL); 1199 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*s{dictobj}(@%p): ", indent, "", obj), return NULL);
1293 1200
1294 if (!verify_object(obj)) { 1201 if (!verify_object(obj)) {
1295 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL); 1202 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL);
1296 return *buf; 1203 return *buf;
1297 } 1204 }
1298 1205
1299 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s p:%p ", 1206 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s p:%p ",
1300 _OBINFO(obj).name, 1207 _OBINFO(obj).name,
1301 obj->parent), return NULL); 1208 obj->parent), return NULL);
1302 1209
1303 if (obj->type == DICT_ENUMVAL) { 1210 if (obj->type == DICT_ENUMVAL) {
1304 CHECK_MALLOC_DO( dump_enumval_data ( FD_DUMP_STD_PARAMS, &obj->data.enumval, obj->parent->data.type.type_base ), return NULL); 1211 CHECK_MALLOC_DO( dump_enumval_data ( FD_DUMP_STD_PARAMS, &obj->data.enumval, obj->parent->data.type.type_base ), return NULL);
1305 } else { 1212 } else {
1306 CHECK_MALLOC_DO( _OBINFO(obj).dump_data(FD_DUMP_STD_PARAMS, &obj->data), return NULL); 1213 CHECK_MALLOC_DO( _OBINFO(obj).dump_data(FD_DUMP_STD_PARAMS, &obj->data), return NULL);
1307 } 1214 }
1308 1215
1309 if (parents) { 1216 if (parents) {
1310 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n%*sparent:", indent + 1, ""), return NULL); 1217 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n%*sparent:", indent + 1, ""), return NULL);
1311 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, obj->parent, parents-1, 0, 0 ), return NULL); 1218 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, obj->parent, parents-1, 0, 0 ), return NULL);
1312 } 1219 }
1313 1220
1314 if (depth) { 1221 if (depth) {
1315 int i; 1222 int i;
1316 for (i=0; i<NB_LISTS_PER_OBJ; i++) { 1223 for (i=0; i<NB_LISTS_PER_OBJ; i++) {
1317 if ((obj->list[i].o == NULL) && (obj->list[i].next != &obj->list[i])) { 1224 if ((obj->list[i].o == NULL) && (obj->list[i].next != &obj->list[i])) {
1318 CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &obj->list[i], 0, depth - 1, indent + 2), return NULL); 1225 CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &obj->list[i], 0, depth - 1, indent + 2), return NULL);
1319 break; /* we get duplicate information sorted by another criteria otherwise, which is not very useful */ 1226 break; /* we get duplicate information sorted by another criteria otherwise, which is not very useful */
1320 } 1227 }
1321 } 1228 }
1322 } 1229 }
1323 1230
1324 return *buf; 1231 return *buf;
1325 } 1232 }
1326 1233
1327 DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_object, struct dict_object * obj) 1234 DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_object, struct dict_object * obj)
1328 { 1235 {
1329 FD_DUMP_HANDLE_OFFSET(); 1236 FD_DUMP_HANDLE_OFFSET();
1330 1237
1331 CHECK_MALLOC_DO( dump_object(FD_DUMP_STD_PARAMS, obj, 1, 2, 0), return NULL); 1238 CHECK_MALLOC_DO( dump_object(FD_DUMP_STD_PARAMS, obj, 1, 2, 0), return NULL);
1332 1239
1333 return *buf; 1240 return *buf;
1334 } 1241 }
1335 1242
1336 DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump, struct dictionary * dict) 1243 DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump, struct dictionary * dict)
1337 { 1244 {
1338 int i; 1245 int i;
1339 struct fd_list * li; 1246 struct fd_list * li;
1340 1247
1341 FD_DUMP_HANDLE_OFFSET(); 1248 FD_DUMP_HANDLE_OFFSET();
1342 1249
1343 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{dictionary}(@%p): ", dict), return NULL); 1250 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{dictionary}(@%p): ", dict), return NULL);
1344 1251
1345 if ((dict == NULL) || (dict->dict_eyec != DICT_EYECATCHER)) { 1252 if ((dict == NULL) || (dict->dict_eyec != DICT_EYECATCHER)) {
1346 return fd_dump_extend(FD_DUMP_STD_PARAMS, "INVALID/NULL"); 1253 return fd_dump_extend(FD_DUMP_STD_PARAMS, "INVALID/NULL");
1347 } 1254 }
1348 1255
1349 CHECK_POSIX_DO( pthread_rwlock_rdlock( &dict->dict_lock ), /* ignore */ ); 1256 CHECK_POSIX_DO( pthread_rwlock_rdlock( &dict->dict_lock ), /* ignore */ );
1350 1257
1351 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): VENDORS / AVP / RULES\n", dict), goto error); 1258 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): VENDORS / AVP / RULES\n", dict), goto error);
1352 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_vendors, 0, 3, 3 ), goto error); 1259 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_vendors, 0, 3, 3 ), goto error);
1353 for (li = dict->dict_vendors.list[0].next; li != &dict->dict_vendors.list[0]; li = li->next) { 1260 for (li = dict->dict_vendors.list[0].next; li != &dict->dict_vendors.list[0]; li = li->next) {
1354 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL); 1261 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL);
1355 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 3, 3 ), goto error); 1262 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 3, 3 ), goto error);
1356 } 1263 }
1357 1264
1358 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): APPLICATIONS\n", dict), goto error); 1265 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): APPLICATIONS\n", dict), goto error);
1359 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_applications, 0, 1, 3 ), goto error); 1266 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_applications, 0, 1, 3 ), goto error);
1360 for (li = dict->dict_applications.list[0].next; li != &dict->dict_applications.list[0]; li = li->next) { 1267 for (li = dict->dict_applications.list[0].next; li != &dict->dict_applications.list[0]; li = li->next) {
1361 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL); 1268 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL);
1362 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 1, 3 ), goto error); 1269 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 1, 3 ), goto error);
1363 } 1270 }
1364 1271
1365 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): TYPES / ENUMVAL", dict), goto error); 1272 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): TYPES / ENUMVAL", dict), goto error);
1366 CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_types, 0, 2, 3 ), goto error); 1273 CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_types, 0, 2, 3 ), goto error);
1367 1274
1368 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): COMMANDS / RULES", dict), goto error); 1275 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): COMMANDS / RULES", dict), goto error);
1369 CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_cmd_code, 0, 0, 3 ), goto error); 1276 CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_cmd_code, 0, 0, 3 ), goto error);
1370 1277
1371 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): statistics", dict), goto error); 1278 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): statistics", dict), goto error);
1372 for (i=1; i<=DICT_TYPE_MAX; i++) 1279 for (i=1; i<=DICT_TYPE_MAX; i++)
1373 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n %5d: %s", dict->dict_count[i], dict_obj_info[i].name), goto error); 1280 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n %5d: %s", dict->dict_count[i], dict_obj_info[i].name), goto error);
1374 1281
1375 CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ ); 1282 CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ );
1376 return *buf; 1283 return *buf;
1377 error: 1284 error:
1378 /* Free the rwlock */ 1285 /* Free the rwlock */
1379 CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ ); 1286 CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ );
1380 return NULL; 1287 return NULL;
1381 } 1288 }
1382 1289
1384 1291
1385 /* Default dump functions */ 1292 /* Default dump functions */
1386 static DECLARE_FD_DUMP_PROTOTYPE(dump_val_os, union avp_value * value) 1293 static DECLARE_FD_DUMP_PROTOTYPE(dump_val_os, union avp_value * value)
1387 { 1294 {
1388 int i; 1295 int i;
1389 1296
1390 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "<"), return NULL); 1297 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "<"), return NULL);
1391 for (i = 0; i < value->os.len; i++) { 1298 for (i = 0; i < value->os.len; i++) {
1392 if (i == 1024) { /* Dump only up to 1024 bytes of the buffer */ 1299 if (i == 1024) { /* Dump only up to 1024 bytes of the buffer */
1393 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "[...] (len=%zd)", value->os.len), return NULL); 1300 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "[...] (len=%zd)", value->os.len), return NULL);
1394 break; 1301 break;
1433 static DECLARE_FD_DUMP_PROTOTYPE((*get_default_dump_val_cb(enum dict_avp_basetype datatype)), union avp_value *) 1340 static DECLARE_FD_DUMP_PROTOTYPE((*get_default_dump_val_cb(enum dict_avp_basetype datatype)), union avp_value *)
1434 { 1341 {
1435 switch (datatype) { 1342 switch (datatype) {
1436 case AVP_TYPE_OCTETSTRING: 1343 case AVP_TYPE_OCTETSTRING:
1437 return &dump_val_os; 1344 return &dump_val_os;
1438 1345
1439 case AVP_TYPE_INTEGER32: 1346 case AVP_TYPE_INTEGER32:
1440 return &dump_val_i32; 1347 return &dump_val_i32;
1441 1348
1442 case AVP_TYPE_INTEGER64: 1349 case AVP_TYPE_INTEGER64:
1443 return &dump_val_i64; 1350 return &dump_val_i64;
1451 case AVP_TYPE_FLOAT32: 1358 case AVP_TYPE_FLOAT32:
1452 return &dump_val_f32; 1359 return &dump_val_f32;
1453 1360
1454 case AVP_TYPE_FLOAT64: 1361 case AVP_TYPE_FLOAT64:
1455 return &dump_val_f64; 1362 return &dump_val_f64;
1456 1363
1457 case AVP_TYPE_GROUPED: 1364 case AVP_TYPE_GROUPED:
1458 TRACE_DEBUG(FULL, "error: grouped AVP with a value!"); 1365 TRACE_DEBUG(FULL, "error: grouped AVP with a value!");
1459 } 1366 }
1460 return NULL; 1367 return NULL;
1461 } 1368 }
1465 #define INOBJHDRVAL indent<0 ? 1 : indent, indent<0 ? "-" : "|" 1372 #define INOBJHDRVAL indent<0 ? 1 : indent, indent<0 ? "-" : "|"
1466 1373
1467 typedef DECLARE_FD_DUMP_PROTOTYPE((*dump_val_cb_t), union avp_value *); 1374 typedef DECLARE_FD_DUMP_PROTOTYPE((*dump_val_cb_t), union avp_value *);
1468 1375
1469 /* Formatter for the AVP value dump line */ 1376 /* Formatter for the AVP value dump line */
1470 static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_val, union avp_value *avp_value, 1377 static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_val, union avp_value *avp_value,
1471 dump_val_cb_t def_dump_val_cb, 1378 dump_val_cb_t def_dump_val_cb,
1472 dump_val_cb_t dump_val_cb, 1379 dump_val_cb_t dump_val_cb,
1473 enum dict_avp_basetype datatype, 1380 enum dict_avp_basetype datatype,
1474 char * type_name, 1381 char * type_name,
1475 char * const_name, 1382 char * const_name,
1476 int indent, 1383 int indent,
1477 int header) 1384 int header)
1478 { 1385 {
1479 if (header) { 1386 if (header) {
1480 /* Header for all AVP values dumps: */ 1387 /* Header for all AVP values dumps: */
1481 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, INOBJHDR "value ", INOBJHDRVAL), return NULL); 1388 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, INOBJHDR "value ", INOBJHDRVAL), return NULL);
1482 1389
1483 /* If the type is provided, write it */ 1390 /* If the type is provided, write it */
1484 if (type_name) { 1391 if (type_name) {
1485 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "t: '%s' ", type_name), return NULL); 1392 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "t: '%s' ", type_name), return NULL);
1486 } 1393 }
1487 1394
1488 /* Always give the base datatype anyway */ 1395 /* Always give the base datatype anyway */
1489 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(%s) ", type_base_name[datatype]), return NULL); 1396 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(%s) ", type_base_name[datatype]), return NULL);
1490 1397
1491 /* Now, the value */ 1398 /* Now, the value */
1492 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "v: "), return NULL); 1399 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "v: "), return NULL);
1500 CHECK_MALLOC_DO( (*def_dump_val_cb)( FD_DUMP_STD_PARAMS, avp_value), return NULL); 1407 CHECK_MALLOC_DO( (*def_dump_val_cb)( FD_DUMP_STD_PARAMS, avp_value), return NULL);
1501 } 1408 }
1502 if (const_name) { 1409 if (const_name) {
1503 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ")"), return NULL); 1410 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ")"), return NULL);
1504 } 1411 }
1505 1412
1506 /* Done! */ 1413 /* Done! */
1507 return *buf; 1414 return *buf;
1508 } 1415 }
1509 1416
1510 /* Dump the value of an AVP of known type into the returned str */ 1417 /* Dump the value of an AVP of known type into the returned str */
1512 { 1419 {
1513 DECLARE_FD_DUMP_PROTOTYPE((*dump_val_cb), union avp_value *avp_value) = NULL; 1420 DECLARE_FD_DUMP_PROTOTYPE((*dump_val_cb), union avp_value *avp_value) = NULL;
1514 struct dict_object * type = NULL; 1421 struct dict_object * type = NULL;
1515 char * type_name = NULL; 1422 char * type_name = NULL;
1516 char * const_name = NULL; 1423 char * const_name = NULL;
1517 1424
1518 FD_DUMP_HANDLE_OFFSET(); 1425 FD_DUMP_HANDLE_OFFSET();
1519 1426
1520 /* Handle invalid parameters */ 1427 /* Handle invalid parameters */
1521 if (!avp_value) { 1428 if (!avp_value) {
1522 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(avp value not set)"), return NULL); 1429 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(avp value not set)"), return NULL);
1523 return *buf; 1430 return *buf;
1524 } 1431 }
1525 1432
1526 if (!model) { 1433 if (!model) {
1527 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(model not set)"), return NULL); 1434 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(model not set)"), return NULL);
1528 return *buf; 1435 return *buf;
1529 } 1436 }
1530 1437
1531 if (! ( verify_object(model) && (model->type == DICT_AVP) )) { 1438 if (! ( verify_object(model) && (model->type == DICT_AVP) )) {
1532 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(invalid model)"), return NULL); 1439 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(invalid model)"), return NULL);
1533 return *buf; 1440 return *buf;
1534 } 1441 }
1535 1442
1536 /* Get the type definition of this AVP */ 1443 /* Get the type definition of this AVP */
1537 type = model->parent; 1444 type = model->parent;
1538 if (type) { 1445 if (type) {
1539 struct dict_enumval_request request; 1446 struct dict_enumval_request request;
1540 struct dict_object * enumval = NULL; 1447 struct dict_object * enumval = NULL;
1541 1448
1542 type_name = type->data.type.type_name; 1449 type_name = type->data.type.type_name;
1543 1450
1544 /* overwrite the dump function ? */ 1451 /* overwrite the dump function ? */
1545 if (type->data.type.type_dump) 1452 if (type->data.type.type_dump)
1546 dump_val_cb = type->data.type.type_dump; 1453 dump_val_cb = type->data.type.type_dump;
1547 1454
1548 /* Now check if the AVP value matches a constant */ 1455 /* Now check if the AVP value matches a constant */
1549 memset(&request, 0, sizeof(request)); 1456 memset(&request, 0, sizeof(request));
1550 request.type_obj = type; 1457 request.type_obj = type;
1551 memcpy(&request.search.enum_value, avp_value, sizeof(union avp_value)); 1458 memcpy(&request.search.enum_value, avp_value, sizeof(union avp_value));
1552 /* bypass checks */ 1459 /* bypass checks */
1553 if ((search_enumval( type->dico, ENUMVAL_BY_STRUCT, &request, &enumval ) == 0) && (enumval)) { 1460 if ((search_enumval( type->dico, ENUMVAL_BY_STRUCT, &request, &enumval ) == 0) && (enumval)) {
1554 /* We found a constant, get its name */ 1461 /* We found a constant, get its name */
1555 const_name = enumval->data.enumval.enum_name; 1462 const_name = enumval->data.enumval.enum_name;
1556 } 1463 }
1557 } 1464 }
1558 1465
1559 /* And finally, dump the value */ 1466 /* And finally, dump the value */
1560 CHECK_MALLOC_DO( dump_avp_val(FD_DUMP_STD_PARAMS, avp_value, get_default_dump_val_cb(model->data.avp.avp_basetype), dump_val_cb, model->data.avp.avp_basetype, type_name, const_name, indent, header), return NULL ); 1467 CHECK_MALLOC_DO( dump_avp_val(FD_DUMP_STD_PARAMS, avp_value, get_default_dump_val_cb(model->data.avp.avp_basetype), dump_val_cb, model->data.avp.avp_basetype, type_name, const_name, indent, header), return NULL );
1561 return *buf; 1468 return *buf;
1562 } 1469 }
1563 1470
1573 1480
1574 /* Get the data associated to an object */ 1481 /* Get the data associated to an object */
1575 int fd_dict_gettype ( struct dict_object * object, enum dict_object_type * type) 1482 int fd_dict_gettype ( struct dict_object * object, enum dict_object_type * type)
1576 { 1483 {
1577 TRACE_ENTRY("%p %p", object, type); 1484 TRACE_ENTRY("%p %p", object, type);
1578 1485
1579 CHECK_PARAMS( type && verify_object(object) ); 1486 CHECK_PARAMS( type && verify_object(object) );
1580 1487
1581 /* Copy the value and return */ 1488 /* Copy the value and return */
1582 *type = object->type; 1489 *type = object->type;
1583 return 0; 1490 return 0;
1584 } 1491 }
1585 1492
1586 int fd_dict_getdict ( struct dict_object * object, struct dictionary ** dict) 1493 int fd_dict_getdict ( struct dict_object * object, struct dictionary ** dict)
1587 { 1494 {
1588 TRACE_ENTRY("%p %p", object, dict); 1495 TRACE_ENTRY("%p %p", object, dict);
1589 1496
1590 CHECK_PARAMS( dict && verify_object(object) ); 1497 CHECK_PARAMS( dict && verify_object(object) );
1591 1498
1592 /* Copy the value and return */ 1499 /* Copy the value and return */
1593 *dict = object->dico; 1500 *dict = object->dico;
1594 return 0; 1501 return 0;
1595 } 1502 }
1596 1503
1597 1504
1598 /* Get the data associated to an object */ 1505 /* Get the data associated to an object */
1599 int fd_dict_getval ( struct dict_object * object, void * val) 1506 int fd_dict_getval ( struct dict_object * object, void * val)
1600 { 1507 {
1601 TRACE_ENTRY("%p %p", object, val); 1508 TRACE_ENTRY("%p %p", object, val);
1602 1509
1603 CHECK_PARAMS( val && verify_object(object) ); 1510 CHECK_PARAMS( val && verify_object(object) );
1604 1511
1605 /* Copy the value and return */ 1512 /* Copy the value and return */
1606 memcpy(val, &object->data, _OBINFO(object).datasize);; 1513 memcpy(val, &object->data, _OBINFO(object).datasize);;
1607 return 0; 1514 return 0;
1608 } 1515 }
1609 1516
1613 int ret = 0; 1520 int ret = 0;
1614 int dupos = 0; 1521 int dupos = 0;
1615 struct dict_object * new = NULL; 1522 struct dict_object * new = NULL;
1616 struct dict_object * vendor = NULL; 1523 struct dict_object * vendor = NULL;
1617 struct dict_object * locref = NULL; 1524 struct dict_object * locref = NULL;
1618 1525
1619 TRACE_ENTRY("%p %d(%s) %p %p %p", dict, type, dict_obj_info[CHECK_TYPE(type) ? type : 0].name, data, parent, ref); 1526 TRACE_ENTRY("%p %d(%s) %p %p %p", dict, type, dict_obj_info[CHECK_TYPE(type) ? type : 0].name, data, parent, ref);
1620 1527
1621 /* Check parameters */ 1528 /* Check parameters */
1622 CHECK_PARAMS( dict && (dict->dict_eyec == DICT_EYECATCHER) && CHECK_TYPE(type) && data ); 1529 CHECK_PARAMS( dict && (dict->dict_eyec == DICT_EYECATCHER) && CHECK_TYPE(type) && data );
1623 1530
1624 /* Check the "parent" parameter */ 1531 /* Check the "parent" parameter */
1625 switch (dict_obj_info[type].parent) { 1532 switch (dict_obj_info[type].parent) {
1626 case 0: /* parent is forbidden */ 1533 case 0: /* parent is forbidden */
1627 CHECK_PARAMS_DO( parent == NULL, goto error_param ); 1534 CHECK_PARAMS_DO( parent == NULL, goto error_param );
1628 1535
1629 case 1: /* parent is optional */ 1536 case 1: /* parent is optional */
1630 if (parent == NULL) 1537 if (parent == NULL)
1631 break; 1538 break;
1632 1539
1633 case 2: /* parent is mandatory */ 1540 case 2: /* parent is mandatory */
1634 CHECK_PARAMS_DO( verify_object(parent), goto error_param ); 1541 CHECK_PARAMS_DO( verify_object(parent), goto error_param );
1635 1542
1636 if (type == DICT_RULE ) { /* Special case : grouped AVP or Command parents are allowed */ 1543 if (type == DICT_RULE ) { /* Special case : grouped AVP or Command parents are allowed */
1637 CHECK_PARAMS_DO( (parent->type == DICT_COMMAND ) 1544 CHECK_PARAMS_DO( (parent->type == DICT_COMMAND )
1638 || ( (parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED ) ), goto error_param ); 1545 || ( (parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED ) ), goto error_param );
1639 } else { 1546 } else {
1640 CHECK_PARAMS_DO( parent->type == dict_obj_info[type].parenttype, goto error_param ); 1547 CHECK_PARAMS_DO( parent->type == dict_obj_info[type].parenttype, goto error_param );
1641 } 1548 }
1642 } 1549 }
1643 1550
1644 /* For AVP object, we must also check that the "vendor" referenced exists */ 1551 /* For AVP object, we must also check that the "vendor" referenced exists */
1645 if (type == DICT_AVP) { 1552 if (type == DICT_AVP) {
1646 CHECK_FCT_DO( fd_dict_search( dict, DICT_VENDOR, VENDOR_BY_ID, &(((struct dict_avp_data *)data)->avp_vendor), (void*)&vendor, ENOENT ), 1553 CHECK_FCT_DO( fd_dict_search( dict, DICT_VENDOR, VENDOR_BY_ID, &(((struct dict_avp_data *)data)->avp_vendor), (void*)&vendor, ENOENT ),
1647 { TRACE_DEBUG(INFO, "Unable to find vendor '%d' referenced in the AVP data", ((struct dict_avp_data *)data)->avp_vendor); goto error_param; } ); 1554 { TRACE_DEBUG(INFO, "Unable to find vendor '%d' referenced in the AVP data", ((struct dict_avp_data *)data)->avp_vendor); goto error_param; } );
1648 1555
1649 /* Also check if a parent is provided, that the type are the same */ 1556 /* Also check if a parent is provided, that the type are the same */
1650 if (parent) { 1557 if (parent) {
1651 CHECK_PARAMS_DO( parent->data.type.type_base == ((struct dict_avp_data *)data)->avp_basetype, goto error_param ); 1558 CHECK_PARAMS_DO( parent->data.type.type_base == ((struct dict_avp_data *)data)->avp_basetype, goto error_param );
1652 } 1559 }
1653 } 1560 }
1654 1561
1655 /* For RULE object, we must also check that the "avp" referenced exists */ 1562 /* For RULE object, we must also check that the "avp" referenced exists */
1656 if (type == DICT_RULE) { 1563 if (type == DICT_RULE) {
1657 CHECK_PARAMS_DO( verify_object(((struct dict_rule_data *)data)->rule_avp), goto error_param ); 1564 CHECK_PARAMS_DO( verify_object(((struct dict_rule_data *)data)->rule_avp), goto error_param );
1658 CHECK_PARAMS_DO( ((struct dict_rule_data *)data)->rule_avp->type == DICT_AVP, goto error_param ); 1565 CHECK_PARAMS_DO( ((struct dict_rule_data *)data)->rule_avp->type == DICT_AVP, goto error_param );
1659 } 1566 }
1660 1567
1661 /* For COMMAND object, check that the 'R' flag is fixed */ 1568 /* For COMMAND object, check that the 'R' flag is fixed */
1662 if (type == DICT_COMMAND) { 1569 if (type == DICT_COMMAND) {
1663 CHECK_PARAMS_DO( ((struct dict_cmd_data *)data)->cmd_flag_mask & CMD_FLAG_REQUEST, goto error_param ); 1570 CHECK_PARAMS_DO( ((struct dict_cmd_data *)data)->cmd_flag_mask & CMD_FLAG_REQUEST, goto error_param );
1664 } 1571 }
1665 1572
1666 /* For ENUMVAL object, check if the parent type is an OctetString */ 1573 /* For ENUMVAL object, check if the parent type is an OctetString */
1667 if (type == DICT_ENUMVAL) { 1574 if (type == DICT_ENUMVAL) {
1668 if (parent->data.type.type_base == AVP_TYPE_OCTETSTRING) 1575 if (parent->data.type.type_base == AVP_TYPE_OCTETSTRING)
1669 dupos = 1; 1576 dupos = 1;
1670 } 1577 }
1671 1578
1672 /* We have to check that the new values are not equal to the sentinels */ 1579 /* We have to check that the new values are not equal to the sentinels */
1673 if (type == DICT_VENDOR) { 1580 if (type == DICT_VENDOR) {
1674 CHECK_PARAMS_DO( ((struct dict_vendor_data *)data)->vendor_id != 0, goto error_param ); 1581 CHECK_PARAMS_DO( ((struct dict_vendor_data *)data)->vendor_id != 0, goto error_param );
1675 } 1582 }
1676 if (type == DICT_APPLICATION) { 1583 if (type == DICT_APPLICATION) {
1677 CHECK_PARAMS_DO( ((struct dict_application_data *)data)->application_id != 0, goto error_param ); 1584 CHECK_PARAMS_DO( ((struct dict_application_data *)data)->application_id != 0, goto error_param );
1678 } 1585 }
1679 1586
1680 /* Parameters are valid, create the new object */ 1587 /* Parameters are valid, create the new object */
1681 CHECK_MALLOC( new = malloc(sizeof(struct dict_object)) ); 1588 CHECK_MALLOC( new = malloc(sizeof(struct dict_object)) );
1682 1589
1683 /* Initialize the data of the new object */ 1590 /* Initialize the data of the new object */
1684 init_object(new, type); 1591 init_object(new, type);
1685 init_object_data(new, data, type, dupos); 1592 init_object_data(new, data, type, dupos);
1686 new->dico = dict; 1593 new->dico = dict;
1687 new->parent = parent; 1594 new->parent = parent;
1688 1595
1689 /* We will change the dictionary => acquire the write lock */ 1596 /* We will change the dictionary => acquire the write lock */
1690 CHECK_POSIX_DO( ret = pthread_rwlock_wrlock(&dict->dict_lock), goto error_free ); 1597 CHECK_POSIX_DO( ret = pthread_rwlock_wrlock(&dict->dict_lock), goto error_free );
1691 1598
1692 /* Now link the object -- this also checks that no object with same keys already exists */ 1599 /* Now link the object -- this also checks that no object with same keys already exists */
1693 switch (type) { 1600 switch (type) {
1694 case DICT_VENDOR: 1601 case DICT_VENDOR:
1695 /* A vendor object is linked in the g_dict_vendors.list[0], by their id */ 1602 /* A vendor object is linked in the g_dict_vendors.list[0], by their id */
1696 ret = fd_list_insert_ordered ( &dict->dict_vendors.list[0], &new->list[0], (int (*)(void*, void *))order_vendor_by_id, (void **)&locref ); 1603 ret = fd_list_insert_ordered ( &dict->dict_vendors.list[0], &new->list[0], (int (*)(void*, void *))order_vendor_by_id, (void **)&locref );
1697 if (ret) 1604 if (ret)
1698 goto error_unlock; 1605 goto error_unlock;
1699 break; 1606 break;
1700 1607
1701 case DICT_APPLICATION: 1608 case DICT_APPLICATION:
1702 /* An application object is linked in the g_dict_applciations.list[0], by their id */ 1609 /* An application object is linked in the g_dict_applciations.list[0], by their id */
1703 ret = fd_list_insert_ordered ( &dict->dict_applications.list[0], &new->list[0], (int (*)(void*, void *))order_appli_by_id, (void **)&locref ); 1610 ret = fd_list_insert_ordered ( &dict->dict_applications.list[0], &new->list[0], (int (*)(void*, void *))order_appli_by_id, (void **)&locref );
1704 if (ret) 1611 if (ret)
1705 goto error_unlock; 1612 goto error_unlock;
1706 break; 1613 break;
1707 1614
1708 case DICT_TYPE: 1615 case DICT_TYPE:
1709 /* A type object is linked in g_list_types by its name */ 1616 /* A type object is linked in g_list_types by its name */
1710 ret = fd_list_insert_ordered ( &dict->dict_types, &new->list[0], (int (*)(void*, void *))order_type_by_name, (void **)&locref ); 1617 ret = fd_list_insert_ordered ( &dict->dict_types, &new->list[0], (int (*)(void*, void *))order_type_by_name, (void **)&locref );
1711 if (ret) 1618 if (ret)
1712 goto error_unlock; 1619 goto error_unlock;
1713 break; 1620 break;
1714 1621
1715 case DICT_ENUMVAL: 1622 case DICT_ENUMVAL:
1716 /* A type_enum object is linked in it's parent 'type' object lists 1 and 2 by its name and values */ 1623 /* A type_enum object is linked in it's parent 'type' object lists 1 and 2 by its name and values */
1717 ret = fd_list_insert_ordered ( &parent->list[1], &new->list[0], (int (*)(void*, void *))order_enum_by_name, (void **)&locref ); 1624 ret = fd_list_insert_ordered ( &parent->list[1], &new->list[0], (int (*)(void*, void *))order_enum_by_name, (void **)&locref );
1718 if (ret) 1625 if (ret)
1719 goto error_unlock; 1626 goto error_unlock;
1720 1627
1721 ret = fd_list_insert_ordered ( &parent->list[2], &new->list[1], (int (*)(void*, void *))order_enum_by_val, (void **)&locref ); 1628 ret = fd_list_insert_ordered ( &parent->list[2], &new->list[1], (int (*)(void*, void *))order_enum_by_val, (void **)&locref );
1722 if (ret) { 1629 if (ret) {
1723 fd_list_unlink(&new->list[0]); 1630 fd_list_unlink(&new->list[0]);
1724 goto error_unlock; 1631 goto error_unlock;
1725 } 1632 }
1726 break; 1633 break;
1727 1634
1728 case DICT_AVP: 1635 case DICT_AVP:
1729 /* An avp object is linked in lists 1 and 2 of its vendor, by code and name */ 1636 /* An avp object is linked in lists 1 and 2 of its vendor, by code and name */
1730 ret = fd_list_insert_ordered ( &vendor->list[1], &new->list[0], (int (*)(void*, void *))order_avp_by_code, (void **)&locref ); 1637 ret = fd_list_insert_ordered ( &vendor->list[1], &new->list[0], (int (*)(void*, void *))order_avp_by_code, (void **)&locref );
1731 if (ret) 1638 if (ret)
1732 goto error_unlock; 1639 goto error_unlock;
1733 1640
1734 ret = fd_list_insert_ordered ( &vendor->list[2], &new->list[1], (int (*)(void*, void *))order_avp_by_name, (void **)&locref ); 1641 ret = fd_list_insert_ordered ( &vendor->list[2], &new->list[1], (int (*)(void*, void *))order_avp_by_name, (void **)&locref );
1735 if (ret) { 1642 if (ret) {
1736 fd_list_unlink(&new->list[0]); 1643 fd_list_unlink(&new->list[0]);
1737 goto error_unlock; 1644 goto error_unlock;
1738 } 1645 }
1739 break; 1646 break;
1740 1647
1741 case DICT_COMMAND: 1648 case DICT_COMMAND:
1742 /* A command object is linked in g_list_cmd_name and g_list_cmd_code by its name and code */ 1649 /* A command object is linked in g_list_cmd_name and g_list_cmd_code by its name and code */
1743 ret = fd_list_insert_ordered ( &dict->dict_cmd_code, &new->list[1], (int (*)(void*, void *))order_cmd_by_codefl, (void **)&locref ); 1650 ret = fd_list_insert_ordered ( &dict->dict_cmd_code, &new->list[1], (int (*)(void*, void *))order_cmd_by_codefl, (void **)&locref );
1744 if (ret) 1651 if (ret)
1745 goto error_unlock; 1652 goto error_unlock;
1746 1653
1747 ret = fd_list_insert_ordered ( &dict->dict_cmd_name, &new->list[0], (int (*)(void*, void *))order_cmd_by_name, (void **)&locref ); 1654 ret = fd_list_insert_ordered ( &dict->dict_cmd_name, &new->list[0], (int (*)(void*, void *))order_cmd_by_name, (void **)&locref );
1748 if (ret) { 1655 if (ret) {
1749 fd_list_unlink(&new->list[1]); 1656 fd_list_unlink(&new->list[1]);
1750 goto error_unlock; 1657 goto error_unlock;
1751 } 1658 }
1752 break; 1659 break;
1753 1660
1754 case DICT_RULE: 1661 case DICT_RULE:
1755 /* A rule object is linked in list[2] of its parent command or AVP by the name of the AVP it refers */ 1662 /* A rule object is linked in list[2] of its parent command or AVP by the name of the AVP it refers */
1756 ret = fd_list_insert_ordered ( &parent->list[2], &new->list[0], (int (*)(void*, void *))order_rule_by_avpvc, (void **)&locref ); 1663 ret = fd_list_insert_ordered ( &parent->list[2], &new->list[0], (int (*)(void*, void *))order_rule_by_avpvc, (void **)&locref );
1757 if (ret) 1664 if (ret)
1758 goto error_unlock; 1665 goto error_unlock;
1759 break; 1666 break;
1760 1667
1761 default: 1668 default:
1762 ASSERT(0); 1669 ASSERT(0);
1763 } 1670 }
1764 1671
1765 /* A new object has been created, increment the global counter */ 1672 /* A new object has been created, increment the global counter */
1766 dict->dict_count[type]++; 1673 dict->dict_count[type]++;
1767 1674
1768 /* Unlock the dictionary */ 1675 /* Unlock the dictionary */
1769 CHECK_POSIX_DO( ret = pthread_rwlock_unlock(&dict->dict_lock), goto error_free ); 1676 CHECK_POSIX_DO( ret = pthread_rwlock_unlock(&dict->dict_lock), goto error_free );
1770 1677
1771 /* Save the pointer to the new object */ 1678 /* Save the pointer to the new object */
1772 if (ref) 1679 if (ref)
1773 *ref = new; 1680 *ref = new;
1774 1681
1775 return 0; 1682 return 0;
1776 1683
1777 error_param: 1684 error_param:
1778 ret = EINVAL; 1685 ret = EINVAL;
1779 goto all_errors; 1686 goto all_errors;
1780 1687
1781 error_unlock: 1688 error_unlock:
1784 /* We have a duplicate key in locref. Check if the pointed object is the same or not */ 1691 /* We have a duplicate key in locref. Check if the pointed object is the same or not */
1785 switch (type) { 1692 switch (type) {
1786 case DICT_VENDOR: 1693 case DICT_VENDOR:
1787 TRACE_DEBUG(FULL, "Vendor %s already in dictionary", new->data.vendor.vendor_name); 1694 TRACE_DEBUG(FULL, "Vendor %s already in dictionary", new->data.vendor.vendor_name);
1788 /* if we are here, it means the two vendors id are identical */ 1695 /* if we are here, it means the two vendors id are identical */
1789 if (fd_os_cmp(locref->data.vendor.vendor_name, locref->datastr_len, 1696 if (fd_os_cmp(locref->data.vendor.vendor_name, locref->datastr_len,
1790 new->data.vendor.vendor_name, new->datastr_len)) { 1697 new->data.vendor.vendor_name, new->datastr_len)) {
1791 TRACE_DEBUG(INFO, "Conflicting vendor name: %s", new->data.vendor.vendor_name); 1698 TRACE_DEBUG(INFO, "Conflicting vendor name: %s", new->data.vendor.vendor_name);
1792 break; 1699 break;
1793 } 1700 }
1794 /* Otherwise (same name), we consider the function succeeded, since the (same) object is in the dictionary */ 1701 /* Otherwise (same name), we consider the function succeeded, since the (same) object is in the dictionary */
1795 ret = 0; 1702 ret = 0;
1796 break; 1703 break;
1797 1704
1798 case DICT_APPLICATION: 1705 case DICT_APPLICATION:
1799 TRACE_DEBUG(FULL, "Application %s already in dictionary", new->data.application.application_name); 1706 TRACE_DEBUG(FULL, "Application %s already in dictionary", new->data.application.application_name);
1800 /* got same id */ 1707 /* got same id */
1801 if (fd_os_cmp(locref->data.application.application_name, locref->datastr_len, 1708 if (fd_os_cmp(locref->data.application.application_name, locref->datastr_len,
1802 new->data.application.application_name, new->datastr_len)) { 1709 new->data.application.application_name, new->datastr_len)) {
1803 TRACE_DEBUG(FULL, "Conflicting application name"); 1710 TRACE_DEBUG(FULL, "Conflicting application name");
1804 break; 1711 break;
1805 } 1712 }
1806 ret = 0; 1713 ret = 0;
1934 } 1841 }
1935 all_errors: 1842 all_errors:
1936 if (ret != 0) { 1843 if (ret != 0) {
1937 char * buf = NULL; 1844 char * buf = NULL;
1938 size_t len = 0, offset=0; 1845 size_t len = 0, offset=0;
1939 1846
1940 if (type == DICT_ENUMVAL) { 1847 if (type == DICT_ENUMVAL) {
1941 CHECK_MALLOC( dump_enumval_data ( &buf, &len, &offset, data, parent->data.type.type_base )); 1848 CHECK_MALLOC( dump_enumval_data ( &buf, &len, &offset, data, parent->data.type.type_base ));
1942 } else { 1849 } else {
1943 CHECK_MALLOC( dict_obj_info[CHECK_TYPE(type) ? type : 0].dump_data(&buf, &len, &offset, data) ); 1850 CHECK_MALLOC( dict_obj_info[CHECK_TYPE(type) ? type : 0].dump_data(&buf, &len, &offset, data) );
1944 } 1851 }
1945 1852
1946 TRACE_DEBUG(INFO, "An error occurred while adding the following data in the dictionary: %s", buf); 1853 TRACE_DEBUG(INFO, "An error occurred while adding the following data in the dictionary: %s", buf);
1947 1854
1948 if (ret == EEXIST) { 1855 if (ret == EEXIST) {
1949 offset=0; 1856 offset=0;
1950 CHECK_MALLOC( dump_object(&buf, &len, &offset, locref, 0, 0, 0) ); 1857 CHECK_MALLOC( dump_object(&buf, &len, &offset, locref, 0, 0, 0) );
1951 TRACE_DEBUG(INFO, "Conflicting entry in the dictionary: %s", buf); 1858 TRACE_DEBUG(INFO, "Conflicting entry in the dictionary: %s", buf);
1952 } 1859 }
1961 int fd_dict_delete(struct dict_object * obj) 1868 int fd_dict_delete(struct dict_object * obj)
1962 { 1869 {
1963 int i; 1870 int i;
1964 struct dictionary * dict; 1871 struct dictionary * dict;
1965 int ret=0; 1872 int ret=0;
1966 1873
1967 /* check params */ 1874 /* check params */
1968 CHECK_PARAMS( verify_object(obj) && obj->dico); 1875 CHECK_PARAMS( verify_object(obj) && obj->dico);
1969 dict = obj->dico; 1876 dict = obj->dico;
1970 1877
1971 /* Lock the dictionary for change */ 1878 /* Lock the dictionary for change */
1972 CHECK_POSIX( pthread_rwlock_wrlock(&dict->dict_lock) ); 1879 CHECK_POSIX( pthread_rwlock_wrlock(&dict->dict_lock) );
1973 1880
1974 /* check the object is not sentinel for another list */ 1881 /* check the object is not sentinel for another list */
1975 for (i=0; i<NB_LISTS_PER_OBJ; i++) { 1882 for (i=0; i<NB_LISTS_PER_OBJ; i++) {
1976 if (!_OBINFO(obj).haslist[i] && !(FD_IS_LIST_EMPTY(&obj->list[i]))) { 1883 if (!_OBINFO(obj).haslist[i] && !(FD_IS_LIST_EMPTY(&obj->list[i]))) {
1977 /* There are children, this is not good */ 1884 /* There are children, this is not good */
1978 ret = EINVAL; 1885 ret = EINVAL;
1981 dump_list(&obj->list[i], 0,0,0); 1888 dump_list(&obj->list[i], 0,0,0);
1982 #endif 1889 #endif
1983 break; 1890 break;
1984 } 1891 }
1985 } 1892 }
1986 1893
1987 /* ok, now destroy the object */ 1894 /* ok, now destroy the object */
1988 if (!ret) 1895 if (!ret)
1989 destroy_object(obj); 1896 destroy_object(obj);
1990 1897
1991 /* Unlock */ 1898 /* Unlock */
1992 CHECK_POSIX( pthread_rwlock_unlock(&dict->dict_lock) ); 1899 CHECK_POSIX( pthread_rwlock_unlock(&dict->dict_lock) );
1993 1900
1994 return ret; 1901 return ret;
1995 } 1902 }
1996 1903
1997 1904
1998 int fd_dict_search ( struct dictionary * dict, enum dict_object_type type, int criteria, const void * what, struct dict_object **result, int retval ) 1905 int fd_dict_search ( struct dictionary * dict, enum dict_object_type type, int criteria, const void * what, struct dict_object **result, int retval )
1999 { 1906 {
2000 int ret = 0; 1907 int ret = 0;
2001 1908
2002 TRACE_ENTRY("%p %d(%s) %d %p %p %d", dict, type, dict_obj_info[CHECK_TYPE(type) ? type : 0].name, criteria, what, result, retval); 1909 TRACE_ENTRY("%p %d(%s) %d %p %p %d", dict, type, dict_obj_info[CHECK_TYPE(type) ? type : 0].name, criteria, what, result, retval);
2003 1910
2004 /* Check param */ 1911 /* Check param */
2005 CHECK_PARAMS( dict && (dict->dict_eyec == DICT_EYECATCHER) && CHECK_TYPE(type) ); 1912 CHECK_PARAMS( dict && (dict->dict_eyec == DICT_EYECATCHER) && CHECK_TYPE(type) );
2006 1913
2007 /* Lock the dictionary for reading */ 1914 /* Lock the dictionary for reading */
2008 CHECK_POSIX( pthread_rwlock_rdlock(&dict->dict_lock) ); 1915 CHECK_POSIX( pthread_rwlock_rdlock(&dict->dict_lock) );
2009 1916
2010 /* Now call the type-specific search function */ 1917 /* Now call the type-specific search function */
2011 ret = dict_obj_info[type].search_fct (dict, criteria, what, result); 1918 ret = dict_obj_info[type].search_fct (dict, criteria, what, result);
2012 1919
2013 /* Unlock */ 1920 /* Unlock */
2014 CHECK_POSIX( pthread_rwlock_unlock(&dict->dict_lock) ); 1921 CHECK_POSIX( pthread_rwlock_unlock(&dict->dict_lock) );
2015 1922
2016 /* Update the return value as needed */ 1923 /* Update the return value as needed */
2017 if ((result != NULL) && (*result == NULL)) 1924 if ((result != NULL) && (*result == NULL))
2018 ret = retval; 1925 ret = retval;
2019 1926
2020 return ret; 1927 return ret;
2021 } 1928 }
2022 1929
2023 /* Function to retrieve list of objects in the dictionary. Use with care (read only). 1930 /* Function to retrieve list of objects in the dictionary. Use with care (read only).
2024 1931
2027 for (li = sentinel->next; li != sentinel; li=li->next) { 1934 for (li = sentinel->next; li != sentinel; li=li->next) {
2028 struct dict_object * obj = li->o; 1935 struct dict_object * obj = li->o;
2029 ... 1936 ...
2030 } 1937 }
2031 1938
2032 The following criteria are allowed, with corresponding parent. 1939 The following criteria are allowed, with corresponding parent.
2033 The parent is either struct dictionary * or struct dict_object * 1940 The parent is either struct dictionary * or struct dict_object *
2034 1941
2035 VENDOR_BY_ID : (parent = dictionary) returns list of vendors ordered by ID 1942 VENDOR_BY_ID : (parent = dictionary) returns list of vendors ordered by ID
2036 APPLICATION_BY_ID : (parent = dictionary) returns list of applications ordered by ID 1943 APPLICATION_BY_ID : (parent = dictionary) returns list of applications ordered by ID
2037 ** for these two lists, the Vendor with id 0 and applciation with id 0 are excluded. 1944 ** for these two lists, the Vendor with id 0 and applciation with id 0 are excluded.
2038 You must resolve them separatly with dict_search. 1945 You must resolve them separatly with dict_search.
2039 1946
2040 TYPE_BY_NAME : (parent = dictionary) returns list of types ordered by name (osstring order) 1947 TYPE_BY_NAME : (parent = dictionary) returns list of types ordered by name (osstring order)
2041 ENUMVAL_BY_NAME : (parent = type object) return list of constants for this type ordered by name (osstring order) 1948 ENUMVAL_BY_NAME : (parent = type object) return list of constants for this type ordered by name (osstring order)
2042 ENUMVAL_BY_VALUE : (parent = type object) return list of constants for this type ordered by values 1949 ENUMVAL_BY_VALUE : (parent = type object) return list of constants for this type ordered by values
2043 AVP_BY_NAME : (parent = vendor object) return list of AVP for this vendor ordered by name (osstring order) 1950 AVP_BY_NAME : (parent = vendor object) return list of AVP for this vendor ordered by name (osstring order)
2044 AVP_BY_CODE : (parent = vendor object) return list of AVP for this vendor ordered by code 1951 AVP_BY_CODE : (parent = vendor object) return list of AVP for this vendor ordered by code
2050 */ 1957 */
2051 int fd_dict_getlistof(int criteria, void * parent, struct fd_list ** sentinel) 1958 int fd_dict_getlistof(int criteria, void * parent, struct fd_list ** sentinel)
2052 { 1959 {
2053 struct dictionary * dict = parent; 1960 struct dictionary * dict = parent;
2054 struct dict_object * obj_parent = parent; 1961 struct dict_object * obj_parent = parent;
2055 1962
2056 TRACE_ENTRY("%i %p %p", criteria, parent, sentinel); 1963 TRACE_ENTRY("%i %p %p", criteria, parent, sentinel);
2057 1964
2058 CHECK_PARAMS(sentinel && parent); 1965 CHECK_PARAMS(sentinel && parent);
2059 1966
2060 switch(criteria) { 1967 switch(criteria) {
2061 case VENDOR_BY_ID: /* parent must be the dictionary */ 1968 case VENDOR_BY_ID: /* parent must be the dictionary */
2062 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER); 1969 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER);
2063 *sentinel = &dict->dict_vendors.list[0]; 1970 *sentinel = &dict->dict_vendors.list[0];
2064 break; 1971 break;
2065 1972
2066 case APPLICATION_BY_ID: /* parent must be the dictionary */ 1973 case APPLICATION_BY_ID: /* parent must be the dictionary */
2067 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER); 1974 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER);
2068 *sentinel = &dict->dict_applications.list[0]; 1975 *sentinel = &dict->dict_applications.list[0];
2069 break; 1976 break;
2070 1977
2071 case TYPE_BY_NAME: /* parent must be the dictionary */ 1978 case TYPE_BY_NAME: /* parent must be the dictionary */
2072 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER); 1979 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER);
2073 *sentinel = &dict->dict_types; 1980 *sentinel = &dict->dict_types;
2074 break; 1981 break;
2075 1982
2076 case ENUMVAL_BY_NAME: /* parent must be a type object */ 1983 case ENUMVAL_BY_NAME: /* parent must be a type object */
2077 CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_TYPE)); 1984 CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_TYPE));
2078 *sentinel = &obj_parent->list[1]; 1985 *sentinel = &obj_parent->list[1];
2079 break; 1986 break;
2080 1987
2081 case ENUMVAL_BY_VALUE: /* parent must be a type object */ 1988 case ENUMVAL_BY_VALUE: /* parent must be a type object */
2082 CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_TYPE)); 1989 CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_TYPE));
2083 *sentinel = &obj_parent->list[2]; 1990 *sentinel = &obj_parent->list[2];
2084 break; 1991 break;
2085 1992
2086 case AVP_BY_NAME: /* parent must be a VENDOR object */ 1993 case AVP_BY_NAME: /* parent must be a VENDOR object */
2087 CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_VENDOR)); 1994 CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_VENDOR));
2088 *sentinel = &obj_parent->list[2]; 1995 *sentinel = &obj_parent->list[2];
2089 break; 1996 break;
2090 1997
2091 case AVP_BY_CODE: /* parent must be a VENDOR object */ 1998 case AVP_BY_CODE: /* parent must be a VENDOR object */
2092 CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_VENDOR)); 1999 CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_VENDOR));
2093 *sentinel = &obj_parent->list[1]; 2000 *sentinel = &obj_parent->list[1];
2094 break; 2001 break;
2095 2002
2096 case CMD_BY_NAME: /* parent must be the dictionary */ 2003 case CMD_BY_NAME: /* parent must be the dictionary */
2097 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER); 2004 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER);
2098 *sentinel = &dict->dict_cmd_name; 2005 *sentinel = &dict->dict_cmd_name;
2099 break; 2006 break;
2100 2007
2101 case CMD_BY_CODE_R: /* parent must be the dictionary */ 2008 case CMD_BY_CODE_R: /* parent must be the dictionary */
2102 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER); 2009 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER);
2103 *sentinel = &dict->dict_cmd_code; 2010 *sentinel = &dict->dict_cmd_code;
2104 break; 2011 break;
2105 2012
2106 case RULE_BY_AVP_AND_PARENT: /* parent must be command or grouped AVP */ 2013 case RULE_BY_AVP_AND_PARENT: /* parent must be command or grouped AVP */
2107 CHECK_PARAMS(verify_object(obj_parent)); 2014 CHECK_PARAMS(verify_object(obj_parent));
2108 CHECK_PARAMS( (obj_parent->type == DICT_COMMAND) || 2015 CHECK_PARAMS( (obj_parent->type == DICT_COMMAND) ||
2109 ((obj_parent->type == DICT_AVP) 2016 ((obj_parent->type == DICT_AVP)
2110 && (obj_parent->data.avp.avp_basetype == AVP_TYPE_GROUPED)) ); 2017 && (obj_parent->data.avp.avp_basetype == AVP_TYPE_GROUPED)) );
2111 *sentinel = &obj_parent->list[2]; 2018 *sentinel = &obj_parent->list[2];
2112 break; 2019 break;
2113 2020
2114 default: 2021 default:
2115 CHECK_PARAMS(0); 2022 CHECK_PARAMS(0);
2116 } 2023 }
2117 2024
2118 return 0; 2025 return 0;
2119 } 2026 }
2120 2027
2121 /*******************************************************************************************************/ 2028 /*******************************************************************************************************/
2122 /*******************************************************************************************************/ 2029 /*******************************************************************************************************/
2128 2035
2129 /* Initialize the dictionary */ 2036 /* Initialize the dictionary */
2130 int fd_dict_init ( struct dictionary ** dict) 2037 int fd_dict_init ( struct dictionary ** dict)
2131 { 2038 {
2132 struct dictionary * new = NULL; 2039 struct dictionary * new = NULL;
2133 2040
2134 TRACE_ENTRY("%p", dict); 2041 TRACE_ENTRY("%p", dict);
2135 2042
2136 /* Sanity checks */ 2043 /* Sanity checks */
2137 ASSERT( (sizeof(type_base_name) / sizeof(type_base_name[0])) == (AVP_TYPE_MAX + 1) ); 2044 ASSERT( (sizeof(type_base_name) / sizeof(type_base_name[0])) == (AVP_TYPE_MAX + 1) );
2138 ASSERT( (sizeof(dict_obj_info) / sizeof(dict_obj_info[0])) == (DICT_TYPE_MAX + 1) ); 2045 ASSERT( (sizeof(dict_obj_info) / sizeof(dict_obj_info[0])) == (DICT_TYPE_MAX + 1) );
2139 CHECK_PARAMS(dict); 2046 CHECK_PARAMS(dict);
2140 2047
2141 /* Allocate the memory for the dictionary */ 2048 /* Allocate the memory for the dictionary */
2142 CHECK_MALLOC( new = malloc(sizeof(struct dictionary)) ); 2049 CHECK_MALLOC( new = malloc(sizeof(struct dictionary)) );
2143 memset(new, 0, sizeof(struct dictionary)); 2050 memset(new, 0, sizeof(struct dictionary));
2144 2051
2145 new->dict_eyec = DICT_EYECATCHER; 2052 new->dict_eyec = DICT_EYECATCHER;
2146 2053
2147 /* Initialize the lock for the dictionary */ 2054 /* Initialize the lock for the dictionary */
2148 CHECK_POSIX( pthread_rwlock_init(&new->dict_lock, NULL) ); 2055 CHECK_POSIX( pthread_rwlock_init(&new->dict_lock, NULL) );
2149 2056
2150 /* Initialize the sentinel for vendors and AVP lists */ 2057 /* Initialize the sentinel for vendors and AVP lists */
2151 init_object( &new->dict_vendors, DICT_VENDOR ); 2058 init_object( &new->dict_vendors, DICT_VENDOR );
2152 #define NO_VENDOR_NAME "(no vendor)" 2059 #define NO_VENDOR_NAME "(no vendor)"
2153 new->dict_vendors.data.vendor.vendor_name = NO_VENDOR_NAME; 2060 new->dict_vendors.data.vendor.vendor_name = NO_VENDOR_NAME;
2154 new->dict_vendors.datastr_len = CONSTSTRLEN(NO_VENDOR_NAME); 2061 new->dict_vendors.datastr_len = CONSTSTRLEN(NO_VENDOR_NAME);
2155 /* new->dict_vendors.list[0].o = NULL; *//* overwrite since element is also sentinel for this list. */ 2062 /* new->dict_vendors.list[0].o = NULL; *//* overwrite since element is also sentinel for this list. */
2156 new->dict_vendors.dico = new; 2063 new->dict_vendors.dico = new;
2157 2064
2158 /* Initialize the sentinel for applications */ 2065 /* Initialize the sentinel for applications */
2159 init_object( &new->dict_applications, DICT_APPLICATION ); 2066 init_object( &new->dict_applications, DICT_APPLICATION );
2160 #define APPLICATION_0_NAME "Diameter Common Messages" 2067 #define APPLICATION_0_NAME "Diameter Common Messages"
2161 new->dict_applications.data.application.application_name = APPLICATION_0_NAME; 2068 new->dict_applications.data.application.application_name = APPLICATION_0_NAME;
2162 new->dict_applications.datastr_len = CONSTSTRLEN(APPLICATION_0_NAME); 2069 new->dict_applications.datastr_len = CONSTSTRLEN(APPLICATION_0_NAME);
2163 /* new->dict_applications.list[0].o = NULL; *//* overwrite since since element is also sentinel for this list. */ 2070 /* new->dict_applications.list[0].o = NULL; *//* overwrite since since element is also sentinel for this list. */
2164 new->dict_applications.dico = new; 2071 new->dict_applications.dico = new;
2165 2072
2166 /* Initialize the sentinel for types */ 2073 /* Initialize the sentinel for types */
2167 fd_list_init ( &new->dict_types, NULL ); 2074 fd_list_init ( &new->dict_types, NULL );
2168 2075
2169 /* Initialize the sentinels for commands */ 2076 /* Initialize the sentinels for commands */
2170 fd_list_init ( &new->dict_cmd_name, NULL ); 2077 fd_list_init ( &new->dict_cmd_name, NULL );
2171 fd_list_init ( &new->dict_cmd_code, NULL ); 2078 fd_list_init ( &new->dict_cmd_code, NULL );
2172 2079
2173 /* Initialize the error command object */ 2080 /* Initialize the error command object */
2174 init_object( &new->dict_cmd_error, DICT_COMMAND ); 2081 init_object( &new->dict_cmd_error, DICT_COMMAND );
2175 #define GENERIC_ERROR_NAME "(generic error format)" 2082 #define GENERIC_ERROR_NAME "(generic error format)"
2176 new->dict_cmd_error.data.cmd.cmd_name = GENERIC_ERROR_NAME; 2083 new->dict_cmd_error.data.cmd.cmd_name = GENERIC_ERROR_NAME;
2177 new->dict_cmd_error.datastr_len = CONSTSTRLEN(GENERIC_ERROR_NAME); 2084 new->dict_cmd_error.datastr_len = CONSTSTRLEN(GENERIC_ERROR_NAME);
2178 new->dict_cmd_error.data.cmd.cmd_flag_mask=CMD_FLAG_ERROR | CMD_FLAG_REQUEST | CMD_FLAG_RETRANSMIT; 2085 new->dict_cmd_error.data.cmd.cmd_flag_mask=CMD_FLAG_ERROR | CMD_FLAG_REQUEST | CMD_FLAG_RETRANSMIT;
2179 new->dict_cmd_error.data.cmd.cmd_flag_val =CMD_FLAG_ERROR; 2086 new->dict_cmd_error.data.cmd.cmd_flag_val =CMD_FLAG_ERROR;
2180 new->dict_cmd_error.dico = new; 2087 new->dict_cmd_error.dico = new;
2181 2088
2182 *dict = new; 2089 *dict = new;
2183 2090
2184 /* Done */ 2091 /* Done */
2185 return 0; 2092 return 0;
2186 } 2093 }
2187 2094
2188 /* Destroy a dictionary */ 2095 /* Destroy a dictionary */
2189 int fd_dict_fini ( struct dictionary ** dict) 2096 int fd_dict_fini ( struct dictionary ** dict)
2190 { 2097 {
2191 int i; 2098 int i;
2192 2099
2193 TRACE_ENTRY(""); 2100 TRACE_ENTRY("");
2194 CHECK_PARAMS( dict && *dict && ((*dict)->dict_eyec == DICT_EYECATCHER) ); 2101 CHECK_PARAMS( dict && *dict && ((*dict)->dict_eyec == DICT_EYECATCHER) );
2195 2102
2196 /* Acquire the write lock to make sure no other operation is ongoing */ 2103 /* Acquire the write lock to make sure no other operation is ongoing */
2197 CHECK_POSIX( pthread_rwlock_wrlock(&(*dict)->dict_lock) ); 2104 CHECK_POSIX( pthread_rwlock_wrlock(&(*dict)->dict_lock) );
2198 2105
2199 /* Empty all the lists, free the elements */ 2106 /* Empty all the lists, free the elements */
2200 destroy_list ( &(*dict)->dict_cmd_error.list[2] ); 2107 destroy_list ( &(*dict)->dict_cmd_error.list[2] );
2201 destroy_list ( &(*dict)->dict_cmd_code ); 2108 destroy_list ( &(*dict)->dict_cmd_code );
2202 destroy_list ( &(*dict)->dict_cmd_name ); 2109 destroy_list ( &(*dict)->dict_cmd_name );
2203 destroy_list ( &(*dict)->dict_types ); 2110 destroy_list ( &(*dict)->dict_types );
2204 for (i=0; i< NB_LISTS_PER_OBJ; i++) { 2111 for (i=0; i< NB_LISTS_PER_OBJ; i++) {
2205 destroy_list ( &(*dict)->dict_applications.list[i] ); 2112 destroy_list ( &(*dict)->dict_applications.list[i] );
2206 destroy_list ( &(*dict)->dict_vendors.list[i] ); 2113 destroy_list ( &(*dict)->dict_vendors.list[i] );
2207 } 2114 }
2208 2115
2209 /* Dictionary is empty, now destroy the lock */ 2116 /* Dictionary is empty, now destroy the lock */
2210 CHECK_POSIX( pthread_rwlock_unlock(&(*dict)->dict_lock) ); 2117 CHECK_POSIX( pthread_rwlock_unlock(&(*dict)->dict_lock) );
2211 CHECK_POSIX( pthread_rwlock_destroy(&(*dict)->dict_lock) ); 2118 CHECK_POSIX( pthread_rwlock_destroy(&(*dict)->dict_lock) );
2212 2119
2213 free(*dict); 2120 free(*dict);
2214 *dict = NULL; 2121 *dict = NULL;
2215 2122
2216 return 0; 2123 return 0;
2217 } 2124 }
2218 2125
2219 /*******************************************************************************************************/ 2126 /*******************************************************************************************************/
2220 /*******************************************************************************************************/ 2127 /*******************************************************************************************************/
2227 /* Iterate a callback on the rules for an object */ 2134 /* Iterate a callback on the rules for an object */
2228 int fd_dict_iterate_rules ( struct dict_object *parent, void * data, int (*cb)(void *, struct dict_rule_data *) ) 2135 int fd_dict_iterate_rules ( struct dict_object *parent, void * data, int (*cb)(void *, struct dict_rule_data *) )
2229 { 2136 {
2230 int ret = 0; 2137 int ret = 0;
2231 struct fd_list * li; 2138 struct fd_list * li;
2232 2139
2233 TRACE_ENTRY("%p %p %p", parent, data, cb); 2140 TRACE_ENTRY("%p %p %p", parent, data, cb);
2234 2141
2235 /* Check parameters */ 2142 /* Check parameters */
2236 CHECK_PARAMS( verify_object(parent) ); 2143 CHECK_PARAMS( verify_object(parent) );
2237 CHECK_PARAMS( (parent->type == DICT_COMMAND) 2144 CHECK_PARAMS( (parent->type == DICT_COMMAND)
2238 || ((parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED)) ); 2145 || ((parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED)) );
2239 TRACE_DEBUG (FULL, "Iterating on rules of %s: '%s'.", 2146 TRACE_DEBUG (FULL, "Iterating on rules of %s: '%s'.",
2240 _OBINFO(parent).name, 2147 _OBINFO(parent).name,
2241 parent->type == DICT_COMMAND ? 2148 parent->type == DICT_COMMAND ?
2242 parent->data.cmd.cmd_name 2149 parent->data.cmd.cmd_name
2243 : parent->data.avp.avp_name); 2150 : parent->data.avp.avp_name);
2244 2151
2245 /* Acquire the read lock */ 2152 /* Acquire the read lock */
2246 CHECK_POSIX( pthread_rwlock_rdlock(&parent->dico->dict_lock) ); 2153 CHECK_POSIX( pthread_rwlock_rdlock(&parent->dico->dict_lock) );
2247 2154
2248 /* go through the list and call the cb on each rule data */ 2155 /* go through the list and call the cb on each rule data */
2249 for (li = &(parent->list[2]); li->next != &(parent->list[2]); li = li->next) { 2156 for (li = &(parent->list[2]); li->next != &(parent->list[2]); li = li->next) {
2250 ret = (*cb)(data, &(_O(li->next->o)->data.rule)); 2157 ret = (*cb)(data, &(_O(li->next->o)->data.rule));
2251 if (ret != 0) 2158 if (ret != 0)
2252 break; 2159 break;
2253 } 2160 }
2254 2161
2255 /* Release the lock */ 2162 /* Release the lock */
2256 CHECK_POSIX( pthread_rwlock_unlock(&parent->dico->dict_lock) ); 2163 CHECK_POSIX( pthread_rwlock_unlock(&parent->dico->dict_lock) );
2257 2164
2258 return ret; 2165 return ret;
2259 } 2166 }
2260 2167
2261 /* Create the list of vendors. Returns a 0-terminated array, that must be freed after use. Returns NULL on error. */ 2168 /* Create the list of vendors. Returns a 0-terminated array, that must be freed after use. Returns NULL on error. */
2262 uint32_t * fd_dict_get_vendorid_list(struct dictionary * dict) 2169 uint32_t * fd_dict_get_vendorid_list(struct dictionary * dict)
2263 { 2170 {
2264 uint32_t * ret = NULL; 2171 uint32_t * ret = NULL;
2265 int i = 0; 2172 int i = 0;
2266 struct fd_list * li; 2173 struct fd_list * li;
2267 2174
2268 TRACE_ENTRY(); 2175 TRACE_ENTRY();
2269 2176
2270 /* Acquire the read lock */ 2177 /* Acquire the read lock */
2271 CHECK_POSIX_DO( pthread_rwlock_rdlock(&dict->dict_lock), return NULL ); 2178 CHECK_POSIX_DO( pthread_rwlock_rdlock(&dict->dict_lock), return NULL );
2272 2179
2273 /* Allocate an array to contain all the elements */ 2180 /* Allocate an array to contain all the elements */
2274 CHECK_MALLOC_DO( ret = calloc( dict->dict_count[DICT_VENDOR] + 1, sizeof(uint32_t) ), goto out ); 2181 CHECK_MALLOC_DO( ret = calloc( dict->dict_count[DICT_VENDOR] + 1, sizeof(uint32_t) ), goto out );
2275 2182
2276 /* Copy the vendors IDs */ 2183 /* Copy the vendors IDs */
2277 for (li = dict->dict_vendors.list[0].next; li != &(dict->dict_vendors.list[0]); li = li->next) { 2184 for (li = dict->dict_vendors.list[0].next; li != &(dict->dict_vendors.list[0]); li = li->next) {
2278 ret[i] = _O(li->o)->data.vendor.vendor_id; 2185 ret[i] = _O(li->o)->data.vendor.vendor_id;
2279 i++; 2186 i++;
2280 ASSERT( i <= dict->dict_count[DICT_VENDOR] ); 2187 ASSERT( i <= dict->dict_count[DICT_VENDOR] );
2281 } 2188 }
2282 out: 2189 out:
2283 /* Release the lock */ 2190 /* Release the lock */
2284 CHECK_POSIX_DO( pthread_rwlock_unlock(&dict->dict_lock), return NULL ); 2191 CHECK_POSIX_DO( pthread_rwlock_unlock(&dict->dict_lock), return NULL );
2285 2192
2286 return ret; 2193 return ret;
2287 } 2194 }
2288 2195
2289 /* Return the location of the cb list for an object, after checking its type */ 2196 /* Return the location of the cb list for an object, after checking its type */
2290 int fd_dict_disp_cb(enum dict_object_type type, struct dict_object *obj, struct fd_list ** cb_list) 2197 int fd_dict_disp_cb(enum dict_object_type type, struct dict_object *obj, struct fd_list ** cb_list)
"Welcome to our mercurial repository"