Changes in / [1453:05185ab84cf8:1449:ffe2f27e00e5] in freeDiameter
- Files:
-
- 3 deleted
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
extensions/CMakeLists.txt
r1452 r1436 90 90 91 91 FD_EXTENSION_SUBDIR(dbg_dict_dump "Log dictionary dump" ON) 92 FD_EXTENSION_SUBDIR(dbg_dict_dump_json "Dump dictionary as JSON" ON)93 92 FD_EXTENSION_SUBDIR(dbg_loglevel "Read loglevel from file -- allows runtime change" ON) 94 93 FD_EXTENSION_SUBDIR(dbg_monitor "Outputs periodical status information" ON) -
freeDiameterd/main.c
r1450 r1412 91 91 } 92 92 93 /* Clea nup pidfile on exit */93 /* Cleaup pidfile on exit */ 94 94 if (atexit(pidfile_cleanup) != 0) { 95 95 LOG_F("Unable to setup pidfile cleanup"); -
libfdproto/dictionary.c
r1451 r1444 35 35 36 36 #include "fdproto-internal.h" 37 #include "dictionary-internal.h"38 37 #include <inttypes.h> 39 38 … … 50 49 }; 51 50 51 /* The number of lists in an object */ 52 #define NB_LISTS_PER_OBJ 3 53 52 54 /* Some eye catchers definitions */ 53 55 #define OBJECT_EYECATCHER (0x0b13c7) 54 56 #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 }; 55 148 56 149 /* Forward declarations of dump functions */ … … 85 178 } dict_obj_info[] = { { 0, "(error)", 0, 0, 0, 0, NULL, NULL, {0, 0, 0} } 86 179 87 /* type name datasize parent parenttype 180 /* type name datasize parent parenttype 88 181 eyecatcher dump_data search_fct, haslist[] */ 89 182 90 183 ,{ DICT_VENDOR, "VENDOR", sizeof(struct dict_vendor_data), 0, 0, 91 184 OBJECT_EYECATCHER + 1, dump_vendor_data, search_vendor, { 1, 0, 0 } } 92 185 93 186 ,{ DICT_APPLICATION, "APPLICATION", sizeof(struct dict_application_data), 1, DICT_VENDOR, 94 187 OBJECT_EYECATCHER + 2, dump_application_data, search_application, { 1, 0, 0 } } 95 188 96 189 ,{ DICT_TYPE, "TYPE", sizeof(struct dict_type_data), 1, DICT_APPLICATION, 97 190 OBJECT_EYECATCHER + 3, dump_type_data, search_type, { 1, 0, 0 } } 98 191 99 192 ,{ DICT_ENUMVAL, "ENUMVAL", sizeof(struct dict_enumval_data), 2, DICT_TYPE, 100 193 OBJECT_EYECATCHER + 4, NULL, search_enumval, { 1, 1, 0 } } 101 194 102 195 ,{ DICT_AVP, "AVP", sizeof(struct dict_avp_data), 1, DICT_TYPE, 103 196 OBJECT_EYECATCHER + 5, dump_avp_data, search_avp, { 1, 1, 0 } } 104 197 105 198 ,{ DICT_COMMAND, "COMMAND", sizeof(struct dict_cmd_data), 1, DICT_APPLICATION, 106 199 OBJECT_EYECATCHER + 6, dump_command_data, search_cmd, { 1, 1, 0 } } 107 200 108 201 ,{ DICT_RULE, "RULE", sizeof(struct dict_rule_data), 2, -1 /* special case: grouped avp or command */, 109 202 OBJECT_EYECATCHER + 7, dump_rule_data, search_rule, { 1, 0, 0 } } 110 203 111 204 }; 112 205 113 206 /* Macro to verify a "type" value */ 114 207 #define CHECK_TYPE( type ) ( ((type) > 0) && ((type) <= DICT_TYPE_MAX) ) … … 138 231 str = os0dup( str, *(plen)); \ 139 232 } 140 233 141 234 /* Initialize an object */ 142 235 static void init_object( struct dict_object * obj, enum dict_object_type type ) 143 236 { 144 237 int i; 145 238 146 239 TRACE_ENTRY("%p %d", obj, type); 147 240 148 241 /* Clean the object first */ 149 242 memset ( obj, 0, sizeof(struct dict_object)); 150 243 151 244 CHECK_PARAMS_DO( CHECK_TYPE(type), return ); 152 245 … … 156 249 157 250 /* We don't initialize the data nor the parent here */ 158 251 159 252 /* Now init the lists */ 160 253 for (i=0; i<NB_LISTS_PER_OBJ; i++) { 161 if (_OBINFO(obj).haslist[i] != 0) 254 if (_OBINFO(obj).haslist[i] != 0) 162 255 fd_list_init(&obj->list[i], obj); 163 256 else 164 257 fd_list_init(&obj->list[i], NULL); 165 258 } 166 259 167 260 fd_list_init(&obj->disp_cbs, NULL); 168 261 } … … 173 266 TRACE_ENTRY("%p %p %d", dest, source, type); 174 267 CHECK_PARAMS( dest && source && CHECK_TYPE(type) ); 175 176 /* Generic: copy the full data structure */ 268 269 /* Generic: copy the full data structure */ 177 270 memcpy( &dest->data, source, dict_obj_info[type].datasize ); 178 271 179 272 /* Then strings must be duplicated, not copied */ 180 273 /* This function might be simplified by always defining the "name" field as the first field of the structures, but... it's error-prone */ … … 183 276 DUP_string_len( dest->data.vendor.vendor_name, &dest->datastr_len ); 184 277 break; 185 278 186 279 case DICT_APPLICATION: 187 280 DUP_string_len( dest->data.application.application_name, &dest->datastr_len ); 188 281 break; 189 282 190 283 case DICT_TYPE: 191 284 DUP_string_len( dest->data.type.type_name, &dest->datastr_len ); 192 285 break; 193 286 194 287 case DICT_ENUMVAL: 195 288 DUP_string_len( dest->data.enumval.enum_name, &dest->datastr_len ); 196 289 if (dupos) { 197 290 // we also need to duplicate the octetstring constant value since it is a pointer. 198 dest->data.enumval.enum_value.os.data = os0dup( 199 ((struct dict_enumval_data *)source)->enum_value.os.data, 291 dest->data.enumval.enum_value.os.data = os0dup( 292 ((struct dict_enumval_data *)source)->enum_value.os.data, 200 293 ((struct dict_enumval_data *)source)->enum_value.os.len 201 294 ); … … 206 299 DUP_string_len( dest->data.avp.avp_name, &dest->datastr_len ); 207 300 break; 208 301 209 302 case DICT_COMMAND: 210 303 DUP_string_len( dest->data.cmd.cmd_name, &dest->datastr_len ); 211 304 break; 212 305 213 306 default: 214 307 /* Nothing to do for RULES */ 215 308 ; 216 309 } 217 310 218 311 return 0; 219 312 } … … 223 316 { 224 317 TRACE_ENTRY("%p", obj); 225 318 226 319 CHECK_PARAMS_DO( obj 227 320 && (obj->objeyec == OBJECT_EYECATCHER) … … 241 334 return 0; 242 335 } ); 243 336 244 337 /* The object is probably valid. */ 245 338 return 1; … … 250 343 { 251 344 /* TRACE_ENTRY("%p", obj); */ 252 345 253 346 switch (obj->type) { 254 347 case DICT_VENDOR: 255 348 free( obj->data.vendor.vendor_name ); 256 349 break; 257 350 258 351 case DICT_APPLICATION: 259 352 free( obj->data.application.application_name ); 260 353 break; 261 354 262 355 case DICT_TYPE: 263 356 free( obj->data.type.type_name ); 264 357 break; 265 358 266 359 case DICT_ENUMVAL: 267 360 free( obj->data.enumval.enum_name ); … … 271 364 free( obj->data.avp.avp_name ); 272 365 break; 273 366 274 367 case DICT_COMMAND: 275 368 free( obj->data.cmd.cmd_name ); 276 369 break; 277 370 278 371 default: 279 372 /* nothing to do */ … … 286 379 287 380 /* Destroy all objects in a list - the lock must be held */ 288 static void destroy_list(struct fd_list * head) 381 static void destroy_list(struct fd_list * head) 289 382 { 290 383 /* TRACE_ENTRY("%p", head); */ 291 384 292 385 /* loop in the list */ 293 386 while (!FD_IS_LIST_EMPTY(head)) … … 297 390 } 298 391 } 299 392 300 393 /* Free an object and its sublists */ 301 394 static void destroy_object(struct dict_object * obj) 302 395 { 303 396 int i; 304 397 305 398 /* TRACE_ENTRY("%p", obj); */ 306 399 307 400 /* Update global count */ 308 if (obj->dico) 401 if (obj->dico) 309 402 obj->dico->dict_count[obj->type]--; 310 403 311 404 /* Mark the object as invalid */ 312 405 obj->objeyec = 0xdead; 313 406 314 407 /* First, destroy the data associated to the object */ 315 408 destroy_object_data(obj); 316 409 317 410 for (i=0; i<NB_LISTS_PER_OBJ; i++) { 318 411 if (_OBINFO(obj).haslist[i]) … … 323 416 destroy_list( &obj->list[i] ); 324 417 } 325 418 326 419 /* Unlink all elements from the dispatch list; they will be freed when callback is unregistered */ 327 420 CHECK_POSIX_DO( pthread_rwlock_wrlock(&fd_disp_lock), /* continue */ ); … … 330 423 } 331 424 CHECK_POSIX_DO( pthread_rwlock_unlock(&fd_disp_lock), /* continue */ ); 332 425 333 426 /* Last, destroy the object */ 334 427 free(obj); … … 345 438 /* Compare two values */ 346 439 #define ORDER_scalar( i1, i2 ) \ 347 ((i1 < i2 ) ? -1 : ( i1 > i2 ? 1 : 0 )) 440 ((i1 < i2 ) ? -1 : ( i1 > i2 ? 1 : 0 )) 348 441 349 442 … … 352 445 { 353 446 TRACE_ENTRY("%p %p", o1, o2); 354 447 355 448 return ORDER_scalar( o1->data.vendor.vendor_id, o2->data.vendor.vendor_id ); 356 449 } … … 360 453 { 361 454 TRACE_ENTRY("%p %p", o1, o2); 362 455 363 456 return ORDER_scalar( o1->data.application.application_id, o2->data.application.application_id ); 364 457 } … … 368 461 { 369 462 TRACE_ENTRY("%p %p", o1, o2); 370 463 371 464 return fd_os_cmp( o1->data.type.type_name, o1->datastr_len, o2->data.type.type_name, o2->datastr_len ); 372 465 } … … 376 469 { 377 470 TRACE_ENTRY("%p %p", o1, o2); 378 471 379 472 return fd_os_cmp( o1->data.enumval.enum_name, o1->datastr_len, o2->data.enumval.enum_name, o2->datastr_len ); 380 473 } … … 384 477 { 385 478 TRACE_ENTRY("%p %p", o1, o2); 386 479 387 480 /* The comparison function depends on the type of data */ 388 481 switch ( o1->parent->data.type.type_base ) { 389 482 case AVP_TYPE_OCTETSTRING: 390 return fd_os_cmp( o1->data.enumval.enum_value.os.data, o1->data.enumval.enum_value.os.len, 483 return fd_os_cmp( o1->data.enumval.enum_value.os.data, o1->data.enumval.enum_value.os.len, 391 484 o2->data.enumval.enum_value.os.data, o2->data.enumval.enum_value.os.len); 392 485 393 486 case AVP_TYPE_INTEGER32: 394 487 return ORDER_scalar( o1->data.enumval.enum_value.i32, o2->data.enumval.enum_value.i32 ); … … 420 513 { 421 514 TRACE_ENTRY("%p %p", o1, o2); 422 515 423 516 return ORDER_scalar( o1->data.avp.avp_code, o2->data.avp.avp_code ); 424 517 } … … 428 521 { 429 522 TRACE_ENTRY("%p %p", o1, o2); 430 523 431 524 return fd_os_cmp( o1->data.avp.avp_name, o1->datastr_len, o2->data.avp.avp_name, o2->datastr_len ); 432 525 } … … 436 529 { 437 530 TRACE_ENTRY("%p %p", o1, o2); 438 531 439 532 return fd_os_cmp( o1->data.cmd.cmd_name, o1->datastr_len, o2->data.cmd.cmd_name, o2->datastr_len ); 440 533 } … … 445 538 uint8_t fl1, fl2; 446 539 int cmp = 0; 447 540 448 541 TRACE_ENTRY("%p %p", o1, o2); 449 542 450 543 cmp = ORDER_scalar( o1->data.cmd.cmd_code, o2->data.cmd.cmd_code ); 451 if (cmp) 544 if (cmp) 452 545 return cmp; 453 546 454 547 /* Same command code, we must compare the value of the 'R' flag */ 455 548 fl1 = o1->data.cmd.cmd_flag_val & CMD_FLAG_REQUEST; 456 549 fl2 = o2->data.cmd.cmd_flag_val & CMD_FLAG_REQUEST; 457 550 458 551 /* We want requests first, so we reverse the operators here */ 459 552 return ORDER_scalar(fl2, fl1); 460 553 461 554 } 462 555 … … 465 558 { 466 559 TRACE_ENTRY("%p %p", o1, o2); 467 468 return ORDER_scalar(o1->data.rule.rule_avp->data.avp.avp_vendor, o2->data.rule.rule_avp->data.avp.avp_vendor) 560 561 return ORDER_scalar(o1->data.rule.rule_avp->data.avp.avp_vendor, o2->data.rule.rule_avp->data.avp.avp_vendor) 469 562 ?: ORDER_scalar(o1->data.rule.rule_avp->data.avp.avp_code, o2->data.rule.rule_avp->data.avp.avp_code) ; 470 563 } … … 652 745 int ret = 0; 653 746 vendor_id_t id; 654 747 655 748 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 656 749 657 750 switch (criteria) { 658 751 case VENDOR_BY_ID: … … 660 753 SEARCH_scalar( id, &dict->dict_vendors.list[0], vendor.vendor_id, 1, &dict->dict_vendors ); 661 754 break; 662 755 663 756 case VENDOR_BY_NAME: 664 757 /* "what" is a vendor name */ 665 758 SEARCH_os0( what, &dict->dict_vendors.list[0], vendor.vendor_name, 0); 666 759 break; 667 760 668 761 case VENDOR_OF_APPLICATION: 669 762 /* "what" should be an application object */ 670 763 SEARCH_childs_parent( DICT_APPLICATION, &dict->dict_vendors ); 671 764 break; 672 765 673 766 case VENDOR_OF_AVP: 674 767 /* "what" should be an avp object */ 675 768 SEARCH_sentinel( DICT_AVP, 0, 1 ); 676 769 break; 677 770 678 771 default: 679 772 /* Invalid criteria */ … … 688 781 int ret = 0; 689 782 application_id_t id; 690 783 691 784 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 692 785 693 786 switch (criteria) { 694 787 case APPLICATION_BY_ID: … … 697 790 SEARCH_scalar( id, &dict->dict_applications.list[0], application.application_id, 1, &dict->dict_applications ); 698 791 break; 699 792 700 793 case APPLICATION_BY_NAME: 701 794 /* "what" is an application name */ 702 795 SEARCH_os0( what, &dict->dict_applications.list[0], application.application_name, 0); 703 796 break; 704 797 705 798 case APPLICATION_OF_TYPE: 706 799 /* "what" should be a type object */ 707 800 SEARCH_childs_parent( DICT_TYPE, &dict->dict_applications ); 708 801 break; 709 802 710 803 case APPLICATION_OF_COMMAND: 711 804 /* "what" should be a command object */ 712 805 SEARCH_childs_parent( DICT_COMMAND, &dict->dict_applications ); 713 806 break; 714 807 715 808 default: 716 809 /* Invalid criteria */ … … 724 817 { 725 818 int ret = 0; 726 819 727 820 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 728 821 729 822 switch (criteria) { 730 823 case TYPE_BY_NAME: … … 732 825 SEARCH_os0( what, &dict->dict_types, type.type_name, 1); 733 826 break; 734 827 735 828 case TYPE_OF_ENUMVAL: 736 829 /* "what" should be a type_enum object */ 737 830 SEARCH_childs_parent( DICT_ENUMVAL, NULL ); 738 831 break; 739 832 740 833 case TYPE_OF_AVP: 741 834 /* "what" should be an avp object */ 742 835 SEARCH_childs_parent( DICT_AVP, NULL ); 743 836 break; 744 745 837 838 746 839 default: 747 840 /* Invalid criteria */ … … 755 848 { 756 849 int ret = 0; 757 850 758 851 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 759 852 760 853 switch (criteria) { 761 854 case ENUMVAL_BY_STRUCT: … … 763 856 struct dict_object * parent = NULL; 764 857 struct dict_enumval_request * _what = (struct dict_enumval_request *) what; 765 858 766 859 CHECK_PARAMS( _what && ( _what->type_obj || _what->type_name ) ); 767 860 768 861 if (_what->type_obj != NULL) { 769 862 parent = _what->type_obj; … … 774 867 CHECK_PARAMS( 0 ) ); 775 868 } 776 869 777 870 /* From here the "parent" object is valid */ 778 871 779 872 if ( _what->search.enum_name != NULL ) { 780 873 /* We are looking for this string */ … … 784 877 switch (parent->data.type.type_base) { 785 878 case AVP_TYPE_OCTETSTRING: 786 SEARCH_os( _what->search.enum_value.os.data, 787 _what->search.enum_value.os.len, 788 &parent->list[2], 789 enumval.enum_value.os , 879 SEARCH_os( _what->search.enum_value.os.data, 880 _what->search.enum_value.os.len, 881 &parent->list[2], 882 enumval.enum_value.os , 790 883 1 ); 791 884 break; … … 798 891 (struct dict_object *)NULL); 799 892 break; 800 893 801 894 case AVP_TYPE_INTEGER64: 802 895 SEARCH_scalar( _what->search.enum_value.i64, … … 806 899 (struct dict_object *)NULL); 807 900 break; 808 901 809 902 case AVP_TYPE_UNSIGNED32: 810 903 SEARCH_scalar( _what->search.enum_value.u32, … … 814 907 (struct dict_object *)NULL); 815 908 break; 816 909 817 910 case AVP_TYPE_UNSIGNED64: 818 911 SEARCH_scalar( _what->search.enum_value.u64, … … 822 915 (struct dict_object *)NULL); 823 916 break; 824 917 825 918 case AVP_TYPE_FLOAT32: 826 919 SEARCH_scalar( _what->search.enum_value.f32, … … 830 923 (struct dict_object *)NULL); 831 924 break; 832 925 833 926 case AVP_TYPE_FLOAT64: 834 927 SEARCH_scalar( _what->search.enum_value.f64, … … 838 931 (struct dict_object *)NULL); 839 932 break; 840 933 841 934 default: 842 935 /* Invalid parent type basetype */ … … 844 937 } 845 938 } 846 939 847 940 } 848 941 break; 849 850 942 943 851 944 default: 852 945 /* Invalid criteria */ … … 860 953 { 861 954 int ret = 0; 862 955 863 956 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 864 957 865 958 switch (criteria) { 866 959 case AVP_BY_CODE: … … 872 965 } 873 966 break; 874 967 875 968 case AVP_BY_NAME: 876 969 /* "what" is the AVP name, vendor 0 */ 877 970 SEARCH_os0( what, &dict->dict_vendors.list[2], avp.avp_name, 1); 878 971 break; 879 972 880 973 case AVP_BY_CODE_AND_VENDOR: 881 974 case AVP_BY_NAME_AND_VENDOR: … … 883 976 struct dict_avp_request * _what = (struct dict_avp_request *) what; 884 977 struct dict_object * vendor = NULL; 885 978 886 979 CHECK_PARAMS( (criteria != AVP_BY_NAME_AND_VENDOR) || _what->avp_name ); 887 980 888 981 /* Now look for the vendor first */ 889 982 CHECK_FCT( search_vendor( dict, VENDOR_BY_ID, &_what->avp_vendor, &vendor ) ); … … 895 988 goto end; 896 989 } 897 990 898 991 /* We now have our vendor = head of the appropriate avp list */ 899 992 if (criteria == AVP_BY_NAME_AND_VENDOR) { … … 905 998 } 906 999 break; 907 1000 908 1001 case AVP_BY_STRUCT: 909 1002 { 910 1003 struct dict_avp_request_ex * _what = (struct dict_avp_request_ex *) what; 911 1004 struct dict_object * vendor = NULL; 912 1005 913 1006 CHECK_PARAMS( _what->avp_vendor.vendor || _what->avp_vendor.vendor_id || _what->avp_vendor.vendor_name ); 914 1007 CHECK_PARAMS( _what->avp_data.avp_code || _what->avp_data.avp_name ); 915 1008 916 1009 /* Now look for the vendor first */ 917 1010 if (_what->avp_vendor.vendor) { … … 924 1017 CHECK_FCT( search_vendor( dict, VENDOR_BY_NAME, _what->avp_vendor.vendor_name, &vendor ) ); 925 1018 } 926 1019 927 1020 if (vendor == NULL) { 928 1021 if (result) … … 932 1025 goto end; 933 1026 } 934 1027 935 1028 /* We now have our vendor = head of the appropriate avp list */ 936 1029 if (_what->avp_data.avp_code) { … … 942 1035 } 943 1036 break; 944 1037 945 1038 case AVP_BY_NAME_ALL_VENDORS: 946 1039 { 947 1040 struct fd_list * li; 948 1041 size_t wl = strlen((char *)what); 949 1042 950 1043 /* First, search for vendor 0 */ 951 1044 SEARCH_os0_l( what, wl, &dict->dict_vendors.list[2], avp.avp_name, 1); 952 1045 953 1046 /* If not found, loop for all vendors, until found */ 954 1047 for (li = dict->dict_vendors.list[0].next; li != &dict->dict_vendors.list[0]; li = li->next) { … … 957 1050 } 958 1051 break; 959 1052 960 1053 default: 961 1054 /* Invalid criteria */ … … 969 1062 { 970 1063 int ret = 0; 971 1064 972 1065 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 973 1066 974 1067 switch (criteria) { 975 1068 case CMD_BY_NAME: … … 977 1070 SEARCH_os0( what, &dict->dict_cmd_name, cmd.cmd_name, 1); 978 1071 break; 979 1072 980 1073 case CMD_BY_CODE_R: 981 1074 case CMD_BY_CODE_A: … … 983 1076 command_code_t code; 984 1077 uint8_t searchfl = 0; 985 1078 986 1079 /* The command code that we are searching */ 987 1080 code = *(command_code_t *) what; 988 1081 989 1082 /* The flag (request or answer) of the command we are searching */ 990 1083 if (criteria == CMD_BY_CODE_R) { 991 1084 searchfl = CMD_FLAG_REQUEST; 992 1085 } 993 1086 994 1087 /* perform the search */ 995 1088 SEARCH_codefl( code, searchfl, &dict->dict_cmd_code ); 996 1089 } 997 1090 break; 998 1091 999 1092 case CMD_ANSWER: 1000 1093 { … … 1002 1095 struct dict_object * req = (struct dict_object *) what; 1003 1096 struct dict_object * ans = NULL; 1004 1005 CHECK_PARAMS( verify_object(req) 1097 1098 CHECK_PARAMS( verify_object(req) 1006 1099 && (req->type == DICT_COMMAND) 1007 1100 && (req->data.cmd.cmd_flag_mask & CMD_FLAG_REQUEST) 1008 1101 && (req->data.cmd.cmd_flag_val & CMD_FLAG_REQUEST) ); 1009 1102 1010 1103 /* The answer is supposed to be the next element in the list, if it exists */ 1011 1104 ans = req->list[1].next->o; … … 1015 1108 goto end; 1016 1109 } 1017 1110 1018 1111 /* Now check that the ans element is really the correct one */ 1019 1112 if ( (ans->data.cmd.cmd_code != req->data.cmd.cmd_code) … … 1024 1117 goto end; 1025 1118 } 1026 1119 1027 1120 if (result) 1028 1121 *result = ans; 1029 1122 ret = 0; 1030 } 1031 break; 1032 1123 } 1124 break; 1125 1033 1126 default: 1034 1127 /* Invalid criteria */ … … 1042 1135 { 1043 1136 int ret = 0; 1044 1137 1045 1138 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 1046 1139 1047 1140 switch (criteria) { 1048 1141 case RULE_BY_AVP_AND_PARENT: … … 1051 1144 struct dict_object * avp = NULL; 1052 1145 struct dict_rule_request * _what = (struct dict_rule_request *) what; 1053 1054 CHECK_PARAMS( _what 1146 1147 CHECK_PARAMS( _what 1055 1148 && (parent = _what->rule_parent) 1056 1149 && (avp = _what->rule_avp ) ); 1057 1058 CHECK_PARAMS( verify_object(parent) 1059 && ((parent->type == DICT_COMMAND) 1150 1151 CHECK_PARAMS( verify_object(parent) 1152 && ((parent->type == DICT_COMMAND) 1060 1153 || ((parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED))) ); 1061 1154 1062 1155 CHECK_PARAMS( verify_object(avp) && (avp->type == DICT_AVP) ); 1063 1156 1064 1157 /* Perform the search */ 1065 1158 SEARCH_ruleavpname( avp->data.avp.avp_name, avp->datastr_len, &parent->list[2]); 1066 1159 1067 1160 } 1068 1161 break; 1069 1162 1070 1163 default: 1071 1164 /* Invalid criteria */ … … 1087 1180 { 1088 1181 struct dict_vendor_data * vendor = (struct dict_vendor_data *)data; 1089 1182 1090 1183 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-6u \"%s\"", vendor->vendor_id, vendor->vendor_name); 1091 1184 } … … 1098 1191 { 1099 1192 struct dict_type_data * type = ( struct dict_type_data * ) data; 1100 1101 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-12s \"%s\"", 1102 type_base_name[type->type_base], 1193 1194 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-12s \"%s\"", 1195 type_base_name[type->type_base], 1103 1196 type->type_name); 1104 1197 } … … 1119 1212 } 1120 1213 break; 1121 1214 1122 1215 case AVP_TYPE_INTEGER32: 1123 1216 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%i", enumval->enum_value.i32), return NULL); … … 1143 1236 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%g", enumval->enum_value.f64), return NULL); 1144 1237 break; 1145 1238 1146 1239 default: 1147 1240 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "??? (ERROR unknown type %d)", type), return NULL); … … 1152 1245 { 1153 1246 struct dict_avp_data * avp = (struct dict_avp_data * ) data; 1154 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %-6u \"%s\"", 1155 DUMP_AVPFL_val(avp->avp_flag_val), 1156 DUMP_AVPFL_val(avp->avp_flag_mask), 1157 type_base_name[avp->avp_basetype], 1158 avp->avp_code, 1247 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), 1249 DUMP_AVPFL_val(avp->avp_flag_mask), 1250 type_base_name[avp->avp_basetype], 1251 avp->avp_code, 1159 1252 avp->avp_name ); 1160 1253 } … … 1162 1255 { 1163 1256 struct dict_cmd_data * cmd = (struct dict_cmd_data *) data; 1164 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %-6u \"%s\"", 1257 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %-6u \"%s\"", 1165 1258 DUMP_CMDFL_val(cmd->cmd_flag_val), DUMP_CMDFL_val(cmd->cmd_flag_mask), cmd->cmd_code, cmd->cmd_name); 1166 1259 } … … 1169 1262 struct dict_rule_data * rule = (struct dict_rule_data * )data; 1170 1263 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: pos:%d ord:%d m/M:%2d/%2d avp:\"%s\"", 1171 rule->rule_position, 1172 rule->rule_order, 1173 rule->rule_min, 1264 rule->rule_position, 1265 rule->rule_order, 1266 rule->rule_min, 1174 1267 rule->rule_max, 1175 1268 rule->rule_avp->data.avp.avp_name); … … 1198 1291 { 1199 1292 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*s{dictobj}(@%p): ", indent, "", obj), return NULL); 1200 1293 1201 1294 if (!verify_object(obj)) { 1202 1295 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL); 1203 1296 return *buf; 1204 1297 } 1205 1206 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s p:%p ", 1207 _OBINFO(obj).name, 1298 1299 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s p:%p ", 1300 _OBINFO(obj).name, 1208 1301 obj->parent), return NULL); 1209 1302 1210 1303 if (obj->type == DICT_ENUMVAL) { 1211 1304 CHECK_MALLOC_DO( dump_enumval_data ( FD_DUMP_STD_PARAMS, &obj->data.enumval, obj->parent->data.type.type_base ), return NULL); … … 1213 1306 CHECK_MALLOC_DO( _OBINFO(obj).dump_data(FD_DUMP_STD_PARAMS, &obj->data), return NULL); 1214 1307 } 1215 1308 1216 1309 if (parents) { 1217 1310 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n%*sparent:", indent + 1, ""), return NULL); 1218 1311 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, obj->parent, parents-1, 0, 0 ), return NULL); 1219 1312 } 1220 1313 1221 1314 if (depth) { 1222 1315 int i; … … 1228 1321 } 1229 1322 } 1230 1323 1231 1324 return *buf; 1232 1325 } … … 1235 1328 { 1236 1329 FD_DUMP_HANDLE_OFFSET(); 1237 1330 1238 1331 CHECK_MALLOC_DO( dump_object(FD_DUMP_STD_PARAMS, obj, 1, 2, 0), return NULL); 1239 1332 1240 1333 return *buf; 1241 1334 } … … 1245 1338 int i; 1246 1339 struct fd_list * li; 1247 1340 1248 1341 FD_DUMP_HANDLE_OFFSET(); 1249 1342 1250 1343 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{dictionary}(@%p): ", dict), return NULL); 1251 1344 1252 1345 if ((dict == NULL) || (dict->dict_eyec != DICT_EYECATCHER)) { 1253 1346 return fd_dump_extend(FD_DUMP_STD_PARAMS, "INVALID/NULL"); 1254 1347 } 1255 1348 1256 1349 CHECK_POSIX_DO( pthread_rwlock_rdlock( &dict->dict_lock ), /* ignore */ ); 1257 1350 1258 1351 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): VENDORS / AVP / RULES\n", dict), goto error); 1259 1352 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_vendors, 0, 3, 3 ), goto error); … … 1262 1355 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 3, 3 ), goto error); 1263 1356 } 1264 1357 1265 1358 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): APPLICATIONS\n", dict), goto error); 1266 1359 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_applications, 0, 1, 3 ), goto error); … … 1269 1362 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 1, 3 ), goto error); 1270 1363 } 1271 1364 1272 1365 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): TYPES / ENUMVAL", dict), goto error); 1273 1366 CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_types, 0, 2, 3 ), goto error); 1274 1367 1275 1368 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): COMMANDS / RULES", dict), goto error); 1276 1369 CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_cmd_code, 0, 0, 3 ), goto error); 1277 1370 1278 1371 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): statistics", dict), goto error); 1279 1372 for (i=1; i<=DICT_TYPE_MAX; i++) 1280 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); 1281 1374 1282 1375 CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ ); 1283 1376 return *buf; 1284 error: 1377 error: 1285 1378 /* Free the rwlock */ 1286 1379 CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ ); … … 1294 1387 { 1295 1388 int i; 1296 1389 1297 1390 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "<"), return NULL); 1298 1391 for (i = 0; i < value->os.len; i++) { … … 1343 1436 case AVP_TYPE_OCTETSTRING: 1344 1437 return &dump_val_os; 1345 1438 1346 1439 case AVP_TYPE_INTEGER32: 1347 1440 return &dump_val_i32; … … 1361 1454 case AVP_TYPE_FLOAT64: 1362 1455 return &dump_val_f64; 1363 1456 1364 1457 case AVP_TYPE_GROUPED: 1365 1458 TRACE_DEBUG(FULL, "error: grouped AVP with a value!"); … … 1375 1468 1376 1469 /* Formatter for the AVP value dump line */ 1377 static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_val, union avp_value *avp_value, 1378 dump_val_cb_t def_dump_val_cb, 1379 dump_val_cb_t dump_val_cb, 1380 enum dict_avp_basetype datatype, 1381 char * type_name, 1382 char * const_name, 1383 int indent, 1470 static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_val, union avp_value *avp_value, 1471 dump_val_cb_t def_dump_val_cb, 1472 dump_val_cb_t dump_val_cb, 1473 enum dict_avp_basetype datatype, 1474 char * type_name, 1475 char * const_name, 1476 int indent, 1384 1477 int header) 1385 1478 { … … 1387 1480 /* Header for all AVP values dumps: */ 1388 1481 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, INOBJHDR "value ", INOBJHDRVAL), return NULL); 1389 1482 1390 1483 /* If the type is provided, write it */ 1391 1484 if (type_name) { 1392 1485 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "t: '%s' ", type_name), return NULL); 1393 1486 } 1394 1487 1395 1488 /* Always give the base datatype anyway */ 1396 1489 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(%s) ", type_base_name[datatype]), return NULL); … … 1410 1503 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ")"), return NULL); 1411 1504 } 1412 1505 1413 1506 /* Done! */ 1414 1507 return *buf; … … 1422 1515 char * type_name = NULL; 1423 1516 char * const_name = NULL; 1424 1517 1425 1518 FD_DUMP_HANDLE_OFFSET(); 1426 1519 1427 1520 /* Handle invalid parameters */ 1428 1521 if (!avp_value) { … … 1435 1528 return *buf; 1436 1529 } 1437 1530 1438 1531 if (! ( verify_object(model) && (model->type == DICT_AVP) )) { 1439 1532 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(invalid model)"), return NULL); 1440 1533 return *buf; 1441 1534 } 1442 1535 1443 1536 /* Get the type definition of this AVP */ 1444 1537 type = model->parent; … … 1446 1539 struct dict_enumval_request request; 1447 1540 struct dict_object * enumval = NULL; 1448 1541 1449 1542 type_name = type->data.type.type_name; 1450 1543 1451 1544 /* overwrite the dump function ? */ 1452 1545 if (type->data.type.type_dump) 1453 1546 dump_val_cb = type->data.type.type_dump; 1454 1547 1455 1548 /* Now check if the AVP value matches a constant */ 1456 1549 memset(&request, 0, sizeof(request)); … … 1463 1556 } 1464 1557 } 1465 1558 1466 1559 /* And finally, dump the value */ 1467 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 ); … … 1483 1576 { 1484 1577 TRACE_ENTRY("%p %p", object, type); 1485 1578 1486 1579 CHECK_PARAMS( type && verify_object(object) ); 1487 1580 1488 1581 /* Copy the value and return */ 1489 1582 *type = object->type; … … 1494 1587 { 1495 1588 TRACE_ENTRY("%p %p", object, dict); 1496 1589 1497 1590 CHECK_PARAMS( dict && verify_object(object) ); 1498 1591 1499 1592 /* Copy the value and return */ 1500 1593 *dict = object->dico; … … 1507 1600 { 1508 1601 TRACE_ENTRY("%p %p", object, val); 1509 1602 1510 1603 CHECK_PARAMS( val && verify_object(object) ); 1511 1604 1512 1605 /* Copy the value and return */ 1513 1606 memcpy(val, &object->data, _OBINFO(object).datasize);; … … 1523 1616 struct dict_object * vendor = NULL; 1524 1617 struct dict_object * locref = NULL; 1525 1618 1526 1619 TRACE_ENTRY("%p %d(%s) %p %p %p", dict, type, dict_obj_info[CHECK_TYPE(type) ? type : 0].name, data, parent, ref); 1527 1620 1528 1621 /* Check parameters */ 1529 1622 CHECK_PARAMS( dict && (dict->dict_eyec == DICT_EYECATCHER) && CHECK_TYPE(type) && data ); 1530 1623 1531 1624 /* Check the "parent" parameter */ 1532 1625 switch (dict_obj_info[type].parent) { 1533 1626 case 0: /* parent is forbidden */ 1534 1627 CHECK_PARAMS_DO( parent == NULL, goto error_param ); 1535 1628 1536 1629 case 1: /* parent is optional */ 1537 1630 if (parent == NULL) 1538 1631 break; 1539 1632 1540 1633 case 2: /* parent is mandatory */ 1541 1634 CHECK_PARAMS_DO( verify_object(parent), goto error_param ); 1542 1635 1543 1636 if (type == DICT_RULE ) { /* Special case : grouped AVP or Command parents are allowed */ 1544 CHECK_PARAMS_DO( (parent->type == DICT_COMMAND ) 1637 CHECK_PARAMS_DO( (parent->type == DICT_COMMAND ) 1545 1638 || ( (parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED ) ), goto error_param ); 1546 1639 } else { … … 1548 1641 } 1549 1642 } 1550 1643 1551 1644 /* For AVP object, we must also check that the "vendor" referenced exists */ 1552 1645 if (type == DICT_AVP) { 1553 1646 CHECK_FCT_DO( fd_dict_search( dict, DICT_VENDOR, VENDOR_BY_ID, &(((struct dict_avp_data *)data)->avp_vendor), (void*)&vendor, ENOENT ), 1554 1647 { TRACE_DEBUG(INFO, "Unable to find vendor '%d' referenced in the AVP data", ((struct dict_avp_data *)data)->avp_vendor); goto error_param; } ); 1555 1648 1556 1649 /* Also check if a parent is provided, that the type are the same */ 1557 1650 if (parent) { … … 1559 1652 } 1560 1653 } 1561 1654 1562 1655 /* For RULE object, we must also check that the "avp" referenced exists */ 1563 1656 if (type == DICT_RULE) { … … 1565 1658 CHECK_PARAMS_DO( ((struct dict_rule_data *)data)->rule_avp->type == DICT_AVP, goto error_param ); 1566 1659 } 1567 1660 1568 1661 /* For COMMAND object, check that the 'R' flag is fixed */ 1569 1662 if (type == DICT_COMMAND) { … … 1576 1669 dupos = 1; 1577 1670 } 1578 1671 1579 1672 /* We have to check that the new values are not equal to the sentinels */ 1580 1673 if (type == DICT_VENDOR) { … … 1584 1677 CHECK_PARAMS_DO( ((struct dict_application_data *)data)->application_id != 0, goto error_param ); 1585 1678 } 1586 1679 1587 1680 /* Parameters are valid, create the new object */ 1588 1681 CHECK_MALLOC( new = malloc(sizeof(struct dict_object)) ); 1589 1682 1590 1683 /* Initialize the data of the new object */ 1591 1684 init_object(new, type); … … 1593 1686 new->dico = dict; 1594 1687 new->parent = parent; 1595 1688 1596 1689 /* We will change the dictionary => acquire the write lock */ 1597 1690 CHECK_POSIX_DO( ret = pthread_rwlock_wrlock(&dict->dict_lock), goto error_free ); 1598 1691 1599 1692 /* Now link the object -- this also checks that no object with same keys already exists */ 1600 1693 switch (type) { … … 1605 1698 goto error_unlock; 1606 1699 break; 1607 1700 1608 1701 case DICT_APPLICATION: 1609 1702 /* An application object is linked in the g_dict_applciations.list[0], by their id */ … … 1612 1705 goto error_unlock; 1613 1706 break; 1614 1707 1615 1708 case DICT_TYPE: 1616 1709 /* A type object is linked in g_list_types by its name */ … … 1619 1712 goto error_unlock; 1620 1713 break; 1621 1714 1622 1715 case DICT_ENUMVAL: 1623 1716 /* A type_enum object is linked in it's parent 'type' object lists 1 and 2 by its name and values */ … … 1625 1718 if (ret) 1626 1719 goto error_unlock; 1627 1720 1628 1721 ret = fd_list_insert_ordered ( &parent->list[2], &new->list[1], (int (*)(void*, void *))order_enum_by_val, (void **)&locref ); 1629 if (ret) { 1630 fd_list_unlink(&new->list[0]); 1631 goto error_unlock; 1722 if (ret) { 1723 fd_list_unlink(&new->list[0]); 1724 goto error_unlock; 1632 1725 } 1633 1726 break; 1634 1727 1635 1728 case DICT_AVP: 1636 1729 /* An avp object is linked in lists 1 and 2 of its vendor, by code and name */ … … 1638 1731 if (ret) 1639 1732 goto error_unlock; 1640 1733 1641 1734 ret = fd_list_insert_ordered ( &vendor->list[2], &new->list[1], (int (*)(void*, void *))order_avp_by_name, (void **)&locref ); 1642 1735 if (ret) { … … 1645 1738 } 1646 1739 break; 1647 1740 1648 1741 case DICT_COMMAND: 1649 1742 /* A command object is linked in g_list_cmd_name and g_list_cmd_code by its name and code */ … … 1651 1744 if (ret) 1652 1745 goto error_unlock; 1653 1746 1654 1747 ret = fd_list_insert_ordered ( &dict->dict_cmd_name, &new->list[0], (int (*)(void*, void *))order_cmd_by_name, (void **)&locref ); 1655 1748 if (ret) { … … 1658 1751 } 1659 1752 break; 1660 1753 1661 1754 case DICT_RULE: 1662 1755 /* A rule object is linked in list[2] of its parent command or AVP by the name of the AVP it refers */ … … 1665 1758 goto error_unlock; 1666 1759 break; 1667 1760 1668 1761 default: 1669 1762 ASSERT(0); 1670 1763 } 1671 1764 1672 1765 /* A new object has been created, increment the global counter */ 1673 1766 dict->dict_count[type]++; 1674 1767 1675 1768 /* Unlock the dictionary */ 1676 1769 CHECK_POSIX_DO( ret = pthread_rwlock_unlock(&dict->dict_lock), goto error_free ); 1677 1770 1678 1771 /* Save the pointer to the new object */ 1679 1772 if (ref) 1680 1773 *ref = new; 1681 1774 1682 1775 return 0; 1683 1776 1684 1777 error_param: 1685 1778 ret = EINVAL; … … 1694 1787 TRACE_DEBUG(FULL, "Vendor %s already in dictionary", new->data.vendor.vendor_name); 1695 1788 /* if we are here, it means the two vendors id are identical */ 1696 if (fd_os_cmp(locref->data.vendor.vendor_name, locref->datastr_len, 1789 if (fd_os_cmp(locref->data.vendor.vendor_name, locref->datastr_len, 1697 1790 new->data.vendor.vendor_name, new->datastr_len)) { 1698 1791 TRACE_DEBUG(INFO, "Conflicting vendor name: %s", new->data.vendor.vendor_name); … … 1700 1793 } 1701 1794 /* Otherwise (same name), we consider the function succeeded, since the (same) object is in the dictionary */ 1702 ret = 0; 1795 ret = 0; 1703 1796 break; 1704 1797 … … 1706 1799 TRACE_DEBUG(FULL, "Application %s already in dictionary", new->data.application.application_name); 1707 1800 /* got same id */ 1708 if (fd_os_cmp(locref->data.application.application_name, locref->datastr_len, 1801 if (fd_os_cmp(locref->data.application.application_name, locref->datastr_len, 1709 1802 new->data.application.application_name, new->datastr_len)) { 1710 1803 TRACE_DEBUG(FULL, "Conflicting application name"); … … 1844 1937 char * buf = NULL; 1845 1938 size_t len = 0, offset=0; 1846 1939 1847 1940 if (type == DICT_ENUMVAL) { 1848 1941 CHECK_MALLOC( dump_enumval_data ( &buf, &len, &offset, data, parent->data.type.type_base )); … … 1850 1943 CHECK_MALLOC( dict_obj_info[CHECK_TYPE(type) ? type : 0].dump_data(&buf, &len, &offset, data) ); 1851 1944 } 1852 1945 1853 1946 TRACE_DEBUG(INFO, "An error occurred while adding the following data in the dictionary: %s", buf); 1854 1947 1855 1948 if (ret == EEXIST) { 1856 1949 offset=0; … … 1871 1964 struct dictionary * dict; 1872 1965 int ret=0; 1873 1966 1874 1967 /* check params */ 1875 1968 CHECK_PARAMS( verify_object(obj) && obj->dico); … … 1878 1971 /* Lock the dictionary for change */ 1879 1972 CHECK_POSIX( pthread_rwlock_wrlock(&dict->dict_lock) ); 1880 1973 1881 1974 /* check the object is not sentinel for another list */ 1882 1975 for (i=0; i<NB_LISTS_PER_OBJ; i++) { … … 1891 1984 } 1892 1985 } 1893 1986 1894 1987 /* ok, now destroy the object */ 1895 1988 if (!ret) 1896 1989 destroy_object(obj); 1897 1990 1898 1991 /* Unlock */ 1899 1992 CHECK_POSIX( pthread_rwlock_unlock(&dict->dict_lock) ); 1900 1993 1901 1994 return ret; 1902 1995 } … … 1906 1999 { 1907 2000 int ret = 0; 1908 2001 1909 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); 1910 2003 1911 2004 /* Check param */ 1912 2005 CHECK_PARAMS( dict && (dict->dict_eyec == DICT_EYECATCHER) && CHECK_TYPE(type) ); 1913 2006 1914 2007 /* Lock the dictionary for reading */ 1915 2008 CHECK_POSIX( pthread_rwlock_rdlock(&dict->dict_lock) ); 1916 2009 1917 2010 /* Now call the type-specific search function */ 1918 2011 ret = dict_obj_info[type].search_fct (dict, criteria, what, result); 1919 2012 1920 2013 /* Unlock */ 1921 2014 CHECK_POSIX( pthread_rwlock_unlock(&dict->dict_lock) ); 1922 2015 1923 2016 /* Update the return value as needed */ 1924 2017 if ((result != NULL) && (*result == NULL)) 1925 2018 ret = retval; 1926 2019 1927 2020 return ret; 1928 2021 } … … 1937 2030 } 1938 2031 1939 The following criteria are allowed, with corresponding parent. 2032 The following criteria are allowed, with corresponding parent. 1940 2033 The parent is either struct dictionary * or struct dict_object * 1941 2034 1942 2035 VENDOR_BY_ID : (parent = dictionary) returns list of vendors ordered by ID 1943 2036 APPLICATION_BY_ID : (parent = dictionary) returns list of applications ordered by ID 1944 ** for these two lists, the Vendor with id 0 and applciation with id 0 are excluded. 2037 ** for these two lists, the Vendor with id 0 and applciation with id 0 are excluded. 1945 2038 You must resolve them separatly with dict_search. 1946 2039 1947 2040 TYPE_BY_NAME : (parent = dictionary) returns list of types ordered by name (osstring order) 1948 2041 ENUMVAL_BY_NAME : (parent = type object) return list of constants for this type ordered by name (osstring order) … … 1960 2053 struct dictionary * dict = parent; 1961 2054 struct dict_object * obj_parent = parent; 1962 2055 1963 2056 TRACE_ENTRY("%i %p %p", criteria, parent, sentinel); 1964 2057 1965 2058 CHECK_PARAMS(sentinel && parent); 1966 2059 1967 2060 switch(criteria) { 1968 2061 case VENDOR_BY_ID: /* parent must be the dictionary */ … … 1970 2063 *sentinel = &dict->dict_vendors.list[0]; 1971 2064 break; 1972 2065 1973 2066 case APPLICATION_BY_ID: /* parent must be the dictionary */ 1974 2067 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER); 1975 2068 *sentinel = &dict->dict_applications.list[0]; 1976 2069 break; 1977 2070 1978 2071 case TYPE_BY_NAME: /* parent must be the dictionary */ 1979 2072 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER); 1980 2073 *sentinel = &dict->dict_types; 1981 2074 break; 1982 2075 1983 2076 case ENUMVAL_BY_NAME: /* parent must be a type object */ 1984 2077 CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_TYPE)); 1985 2078 *sentinel = &obj_parent->list[1]; 1986 2079 break; 1987 2080 1988 2081 case ENUMVAL_BY_VALUE: /* parent must be a type object */ 1989 2082 CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_TYPE)); 1990 2083 *sentinel = &obj_parent->list[2]; 1991 2084 break; 1992 2085 1993 2086 case AVP_BY_NAME: /* parent must be a VENDOR object */ 1994 2087 CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_VENDOR)); 1995 2088 *sentinel = &obj_parent->list[2]; 1996 2089 break; 1997 2090 1998 2091 case AVP_BY_CODE: /* parent must be a VENDOR object */ 1999 2092 CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_VENDOR)); 2000 2093 *sentinel = &obj_parent->list[1]; 2001 2094 break; 2002 2095 2003 2096 case CMD_BY_NAME: /* parent must be the dictionary */ 2004 2097 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER); 2005 2098 *sentinel = &dict->dict_cmd_name; 2006 2099 break; 2007 2100 2008 2101 case CMD_BY_CODE_R: /* parent must be the dictionary */ 2009 2102 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER); 2010 2103 *sentinel = &dict->dict_cmd_code; 2011 2104 break; 2012 2105 2013 2106 case RULE_BY_AVP_AND_PARENT: /* parent must be command or grouped AVP */ 2014 2107 CHECK_PARAMS(verify_object(obj_parent)); 2015 2108 CHECK_PARAMS( (obj_parent->type == DICT_COMMAND) || 2016 ((obj_parent->type == DICT_AVP) 2109 ((obj_parent->type == DICT_AVP) 2017 2110 && (obj_parent->data.avp.avp_basetype == AVP_TYPE_GROUPED)) ); 2018 2111 *sentinel = &obj_parent->list[2]; 2019 2112 break; 2020 2113 2021 2114 default: 2022 2115 CHECK_PARAMS(0); 2023 2116 } 2024 2117 2025 2118 return 0; 2026 2119 } … … 2038 2131 { 2039 2132 struct dictionary * new = NULL; 2040 2133 2041 2134 TRACE_ENTRY("%p", dict); 2042 2135 2043 2136 /* Sanity checks */ 2044 2137 ASSERT( (sizeof(type_base_name) / sizeof(type_base_name[0])) == (AVP_TYPE_MAX + 1) ); 2045 2138 ASSERT( (sizeof(dict_obj_info) / sizeof(dict_obj_info[0])) == (DICT_TYPE_MAX + 1) ); 2046 2139 CHECK_PARAMS(dict); 2047 2140 2048 2141 /* Allocate the memory for the dictionary */ 2049 2142 CHECK_MALLOC( new = malloc(sizeof(struct dictionary)) ); 2050 2143 memset(new, 0, sizeof(struct dictionary)); 2051 2144 2052 2145 new->dict_eyec = DICT_EYECATCHER; 2053 2146 2054 2147 /* Initialize the lock for the dictionary */ 2055 2148 CHECK_POSIX( pthread_rwlock_init(&new->dict_lock, NULL) ); 2056 2149 2057 2150 /* Initialize the sentinel for vendors and AVP lists */ 2058 2151 init_object( &new->dict_vendors, DICT_VENDOR ); … … 2062 2155 /* new->dict_vendors.list[0].o = NULL; *//* overwrite since element is also sentinel for this list. */ 2063 2156 new->dict_vendors.dico = new; 2064 2157 2065 2158 /* Initialize the sentinel for applications */ 2066 2159 init_object( &new->dict_applications, DICT_APPLICATION ); … … 2070 2163 /* new->dict_applications.list[0].o = NULL; *//* overwrite since since element is also sentinel for this list. */ 2071 2164 new->dict_applications.dico = new; 2072 2165 2073 2166 /* Initialize the sentinel for types */ 2074 2167 fd_list_init ( &new->dict_types, NULL ); 2075 2168 2076 2169 /* Initialize the sentinels for commands */ 2077 2170 fd_list_init ( &new->dict_cmd_name, NULL ); 2078 2171 fd_list_init ( &new->dict_cmd_code, NULL ); 2079 2172 2080 2173 /* Initialize the error command object */ 2081 2174 init_object( &new->dict_cmd_error, DICT_COMMAND ); … … 2086 2179 new->dict_cmd_error.data.cmd.cmd_flag_val =CMD_FLAG_ERROR; 2087 2180 new->dict_cmd_error.dico = new; 2088 2181 2089 2182 *dict = new; 2090 2183 2091 2184 /* Done */ 2092 2185 return 0; … … 2097 2190 { 2098 2191 int i; 2099 2192 2100 2193 TRACE_ENTRY(""); 2101 2194 CHECK_PARAMS( dict && *dict && ((*dict)->dict_eyec == DICT_EYECATCHER) ); 2102 2195 2103 2196 /* Acquire the write lock to make sure no other operation is ongoing */ 2104 2197 CHECK_POSIX( pthread_rwlock_wrlock(&(*dict)->dict_lock) ); 2105 2198 2106 2199 /* Empty all the lists, free the elements */ 2107 2200 destroy_list ( &(*dict)->dict_cmd_error.list[2] ); … … 2113 2206 destroy_list ( &(*dict)->dict_vendors.list[i] ); 2114 2207 } 2115 2208 2116 2209 /* Dictionary is empty, now destroy the lock */ 2117 2210 CHECK_POSIX( pthread_rwlock_unlock(&(*dict)->dict_lock) ); 2118 2211 CHECK_POSIX( pthread_rwlock_destroy(&(*dict)->dict_lock) ); 2119 2212 2120 2213 free(*dict); 2121 2214 *dict = NULL; 2122 2215 2123 2216 return 0; 2124 2217 } … … 2137 2230 int ret = 0; 2138 2231 struct fd_list * li; 2139 2232 2140 2233 TRACE_ENTRY("%p %p %p", parent, data, cb); 2141 2234 2142 2235 /* Check parameters */ 2143 2236 CHECK_PARAMS( verify_object(parent) ); 2144 CHECK_PARAMS( (parent->type == DICT_COMMAND) 2237 CHECK_PARAMS( (parent->type == DICT_COMMAND) 2145 2238 || ((parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED)) ); 2146 TRACE_DEBUG (FULL, "Iterating on rules of %s: '%s'.", 2147 _OBINFO(parent).name, 2148 parent->type == DICT_COMMAND ? 2239 TRACE_DEBUG (FULL, "Iterating on rules of %s: '%s'.", 2240 _OBINFO(parent).name, 2241 parent->type == DICT_COMMAND ? 2149 2242 parent->data.cmd.cmd_name 2150 2243 : parent->data.avp.avp_name); 2151 2244 2152 2245 /* Acquire the read lock */ 2153 2246 CHECK_POSIX( pthread_rwlock_rdlock(&parent->dico->dict_lock) ); 2154 2247 2155 2248 /* go through the list and call the cb on each rule data */ 2156 2249 for (li = &(parent->list[2]); li->next != &(parent->list[2]); li = li->next) { … … 2159 2252 break; 2160 2253 } 2161 2254 2162 2255 /* Release the lock */ 2163 2256 CHECK_POSIX( pthread_rwlock_unlock(&parent->dico->dict_lock) ); 2164 2257 2165 2258 return ret; 2166 2259 } … … 2172 2265 int i = 0; 2173 2266 struct fd_list * li; 2174 2267 2175 2268 TRACE_ENTRY(); 2176 2269 2177 2270 /* Acquire the read lock */ 2178 2271 CHECK_POSIX_DO( pthread_rwlock_rdlock(&dict->dict_lock), return NULL ); 2179 2272 2180 2273 /* Allocate an array to contain all the elements */ 2181 2274 CHECK_MALLOC_DO( ret = calloc( dict->dict_count[DICT_VENDOR] + 1, sizeof(uint32_t) ), goto out ); 2182 2275 2183 2276 /* Copy the vendors IDs */ 2184 2277 for (li = dict->dict_vendors.list[0].next; li != &(dict->dict_vendors.list[0]); li = li->next) { … … 2187 2280 ASSERT( i <= dict->dict_count[DICT_VENDOR] ); 2188 2281 } 2189 out: 2282 out: 2190 2283 /* Release the lock */ 2191 2284 CHECK_POSIX_DO( pthread_rwlock_unlock(&dict->dict_lock), return NULL ); 2192 2285 2193 2286 return ret; 2194 2287 }
Note: See TracChangeset
for help on using the changeset viewer.