Mercurial > hg > freeDiameter
changeset 1104:757df62cadb6
Merge
author | Sebastien Decugis <sdecugis@freediameter.net> |
---|---|
date | Fri, 10 May 2013 18:49:19 +0800 |
parents | d8591b1c56cd (diff) a1d6e1980132 (current diff) |
children | 8401adfb58f5 |
files | libfdcore/p_psm.c libfdproto/fifo.c |
diffstat | 82 files changed, 7925 insertions(+), 2234 deletions(-) [+] |
line wrap: on
line diff
--- a/CMakeLists.txt Fri May 10 09:50:09 2013 +0800 +++ b/CMakeLists.txt Fri May 10 18:49:19 2013 +0800 @@ -6,15 +6,15 @@ # Informations to display in daemon's help SET(FD_PROJECT_NAME freeDiameter) SET(FD_PROJECT_BINARY freeDiameterd) -SET(FD_PROJECT_COPYRIGHT "Copyright (c) 2008-2011, WIDE Project (www.wide.ad.jp) and NICT (www.nict.go.jp)") +SET(FD_PROJECT_COPYRIGHT "Copyright (c) 2008-2013, WIDE Project (www.wide.ad.jp) and NICT (www.nict.go.jp)") # Version of the source code SET(FD_PROJECT_VERSION_MAJOR 1) -SET(FD_PROJECT_VERSION_MINOR 1) -SET(FD_PROJECT_VERSION_REV 6) +SET(FD_PROJECT_VERSION_MINOR 2) +SET(FD_PROJECT_VERSION_REV 0) # Version of the API with the library -SET(FD_PROJECT_VERSION_API 5) +SET(FD_PROJECT_VERSION_API 6) # The test framework, using CTest and CDash. INCLUDE(CTest)
--- a/contrib/debian/changelog Fri May 10 09:50:09 2013 +0800 +++ b/contrib/debian/changelog Fri May 10 18:49:19 2013 +0800 @@ -1,4 +1,4 @@ -freediameter (1.1.7) UNRELEASED; urgency=low +freediameter (1.2.0) UNRELEASED; urgency=low * Major changes in the logging system to be more syslog and user friendly * New extension: dict_dcca_3gpp @@ -6,6 +6,10 @@ * New extension: rt_ignore_dh (hide network topology by proxying Destination-Host). * New extension: rt_load_balance (load balancer based on pending queue size). * New extension: rt_busypeers. See doc/rt_busypeers.conf.sample. + * New API (fd_hook_*) for extensions to control messages logging & profiling + * New API (fd_stats_*) for extensions to monitor framework state (e.g. SNMP implem) + * API changes: all the fd_*_dump functions now return strings instead of logging directly. + * Updated dbg_monitoring extension to use the new API * New script to generate dictionary extensions from org file (see contrib/tools) * New compilation option: WORKAROUND_ACCEPT_INVALID_VSAI to improve interoperability. * New compilation option: DISABLE_PEER_EXPIRY for use in test environments. @@ -13,9 +17,10 @@ * Copy Proxy-Info AVP automatically in new answers. * Port value 0 allowed in configuration to disable local server (e.g. disable non-secure port). * API change: fd_msg_send_timeout now takes a separate callback for timeout situation. - * New function: fd_msg_dump_full + * Function changes: fd_msg_dump_* now split in three different type of output. + * New test testmesg_stress to measure message parser performance - -- Sebastien Decugis <sdecugis@freediameter.net> Tue, 23 Apr 2013 16:30:28 +0800 + -- Sebastien Decugis <sdecugis@freediameter.net> Mon, 06 May 2013 10:45:26 +0800 freediameter (1.1.6) UNRELEASED; urgency=low
--- a/doc/dbg_interactive.py.sample Fri May 10 09:50:09 2013 +0800 +++ b/doc/dbg_interactive.py.sample Fri May 10 18:49:19 2013 +0800 @@ -363,7 +363,6 @@ # Create empt (as for avps, pass None or a dictionary object as 1st param, and flags as optional 2nd param)y a_msg = msg() a_msg.dump() -a_msg.log(FD_MSG_LOG_DROPPED, "Check libfdproto for more details. Configure with fd_msg_log_config.") del a_msg # It is also possible to pass MSGFL_* flags in second parameter (ALLOC_ETEID is default)
--- a/extensions/CMakeLists.txt Fri May 10 09:50:09 2013 +0800 +++ b/extensions/CMakeLists.txt Fri May 10 18:49:19 2013 +0800 @@ -85,6 +85,7 @@ # Debug & test extensions FD_EXTENSION_SUBDIR(dbg_monitor "Outputs periodical status information" OFF) +FD_EXTENSION_SUBDIR(dbg_msg_timings "Show some timing information for messages" OFF) FD_EXTENSION_SUBDIR(dbg_rt "Routing extension for debugging the routing module" OFF) FD_EXTENSION_SUBDIR(test_app "Testing application to send dummy message to another peer, like a Diameter 'ping'" OFF) FD_EXTENSION_SUBDIR(test_sip "Testing application to simulate Diameter-SIP client (RFC4740)" OFF)
--- a/extensions/_sample/sample.c Fri May 10 09:50:09 2013 +0800 +++ b/extensions/_sample/sample.c Fri May 10 18:49:19 2013 +0800 @@ -84,7 +84,6 @@ rule_data.rule_max = -1; CHECK_FCT( fd_dict_new ( fd_g_config->cnf_dict, DICT_RULE, &rule_data, example_avp_avp, NULL )); - fd_dict_dump_object(example_avp_avp); } TRACE_DEBUG(INFO, "'Example-AVP' created without error");
--- a/extensions/app_diameap/diameap_eap.c Fri May 10 09:50:09 2013 +0800 +++ b/extensions/app_diameap/diameap_eap.c Fri May 10 18:49:19 2013 +0800 @@ -372,7 +372,7 @@ case EAP_INTEGRITY_CHECK: if ((*eap_sm->selectedMethod->eap_method_check)(eap_sm, - eap_i->aaaEapRespData) == FALSE) + &eap_i->aaaEapRespData) == FALSE) { TRACE_DEBUG(INFO,"%s[EAP Protocol] Invalid EAP packet received {Type=%d, Vendor=%d}. Integrity check failed (non fatal error).",DIAMEAP_EXTENSION,eap_sm->currentMethod,eap_sm->currentVendor); //non_fata_error @@ -433,7 +433,7 @@ } } if ((*eap_sm->selectedMethod->eap_method_process)(eap_sm, - eap_i->aaaEapRespData)) + &eap_i->aaaEapRespData)) { TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] Authentication process failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname); *non_fatal_error = TRUE;
--- a/extensions/app_diameap/diameap_plugins.c Fri May 10 09:50:09 2013 +0800 +++ b/extensions/app_diameap/diameap_plugins.c Fri May 10 18:49:19 2013 +0800 @@ -262,7 +262,7 @@ if (registerplugin->check) { plugin->eap_method_check = (boolean(*)(struct eap_state_machine *, - struct eap_packet)) dlsym(plugin->handler, + struct eap_packet*)) dlsym(plugin->handler, registerplugin->check); if (plugin->eap_method_check == NULL) { @@ -284,7 +284,7 @@ if (registerplugin->process) { plugin->eap_method_process = (int(*)(struct eap_state_machine *, - struct eap_packet)) dlsym(plugin->handler, + struct eap_packet*)) dlsym(plugin->handler, registerplugin->process); if (plugin->eap_method_process == NULL) {
--- a/extensions/app_diameap/diameap_server.c Fri May 10 09:50:09 2013 +0800 +++ b/extensions/app_diameap/diameap_server.c Fri May 10 18:49:19 2013 +0800 @@ -84,11 +84,9 @@ -void diameap_cli_sess_cleanup(void * arg, char * sid, void * opaque) +void diameap_cli_sess_cleanup(struct sess_state * diameap_sess_data, os0_t sid, void * opaque) { - struct diameap_sess_data_sm * diameap_sess_data = - (struct diameap_sess_data_sm *) arg; CHECK_PARAMS_DO( diameap_sess_data, return ); if (diameap_sess_data != NULL) @@ -140,7 +138,7 @@ static int diameap_initialize_diameap_sm( struct diameap_state_machine * diameap_sm, - struct diameap_sess_data_sm * diameap_sess_data) + struct sess_state * diameap_sess_data) { TRACE_ENTRY("%p %p", diameap_sm, diameap_sess_data); @@ -1016,7 +1014,7 @@ static int diameap_sess_data_new( - struct diameap_sess_data_sm *diameap_sess_data, + struct sess_state *diameap_sess_data, struct diameap_state_machine *diameap_sm) { if (!diameap_sm) @@ -3063,7 +3061,7 @@ { TRACE_ENTRY("%p %p %p %p", rmsg, ravp, sess, action); - struct diameap_sess_data_sm * diameap_sess_data = NULL; + struct sess_state * diameap_sess_data = NULL; struct diameap_state_machine * diameap_sm = NULL; struct diameap_eap_interface eap_i; struct msg *req, *ans; @@ -3257,9 +3255,9 @@ ; TRACE_DEBUG(FULL+1,"%sStoring DiamEAP session data.",DIAMEAP_EXTENSION) ; - CHECK_MALLOC(diameap_sess_data = malloc(sizeof(struct diameap_sess_data_sm))) + CHECK_MALLOC(diameap_sess_data = malloc(sizeof(struct sess_state))) ; - memset(diameap_sess_data, 0, sizeof(struct diameap_sess_data_sm)); + memset(diameap_sess_data, 0, sizeof(struct sess_state)); diameap_sess_data_new(diameap_sess_data, diameap_sm); CHECK_FCT_DO(fd_sess_state_store(diameap_server_reg, sess, &diameap_sess_data), @@ -3388,7 +3386,7 @@ struct disp_when when; /*create handler for sessions */ - CHECK_FCT(fd_sess_handler_create(&diameap_server_reg, diameap_cli_sess_cleanup, NULL)); + CHECK_FCT(fd_sess_handler_create(&diameap_server_reg, diameap_cli_sess_cleanup, NULL, NULL)); /* Register the callback */ memset(&when, 0, sizeof(when));
--- a/extensions/app_diameap/diameap_server.h Fri May 10 09:50:09 2013 +0800 +++ b/extensions/app_diameap/diameap_server.h Fri May 10 18:49:19 2013 +0800 @@ -39,9 +39,9 @@ #ifndef DIAMEAP_SERVER_H_ #define DIAMEAP_SERVER_H_ - + /* session data structure to store */ -struct diameap_sess_data_sm +struct sess_state { int invalid_eappackets; /* Number of invalid EAP Packet received*/
--- a/extensions/app_diameap/libdiameap.h Fri May 10 09:50:09 2013 +0800 +++ b/extensions/app_diameap/libdiameap.h Fri May 10 18:49:19 2013 +0800 @@ -109,9 +109,9 @@ u8 identifier,struct eap_packet * eapPacket); /* address of the eap_method_buildReq method */ int (*eap_method_getTimeout)(struct eap_state_machine *smd, int * timeout); /* address of the eap_method_getTimeout method */ boolean (*eap_method_check)(struct eap_state_machine *smd, - struct eap_packet eapRespData); /* address of the eap_method_check method */ + struct eap_packet * eapRespData); /* address of the eap_method_check method */ int (*eap_method_process)(struct eap_state_machine *smd, - struct eap_packet eapRespData); /* address of the eap_method_process method */ + struct eap_packet * eapRespData); /* address of the eap_method_process method */ boolean (*eap_method_isDone)(struct eap_state_machine *smd); /* address of the eap_method_isDone method */ int (*eap_method_getKey)(struct eap_state_machine *smd, u8 ** msk,int *msklength, u8 ** emsk,int *emsklength); /* address of the eap_method_getKey method */
--- a/extensions/app_radgw/rgwx_acct.c Fri May 10 09:50:09 2013 +0800 +++ b/extensions/app_radgw/rgwx_acct.c Fri May 10 18:49:19 2013 +0800 @@ -159,6 +159,11 @@ uint32_t term_cause; /* If not 0, the Termination-Cause to put in the STR. */ }; +static DECLARE_FD_DUMP_PROTOTYPE(acct_conf_session_state_dump, struct sess_state * st) +{ + return fd_dump_extend( FD_DUMP_STD_PARAMS, "[rgwx sess_state](@%p): aai:%x str:%d TC:%u", st, st->auth_appl, st->send_str, st->term_cause); +} + /* Initialize the plugin */ static int acct_conf_parse(char * conffile, struct rgwp_config ** state) { @@ -171,7 +176,7 @@ CHECK_MALLOC( new = malloc(sizeof(struct rgwp_config)) ); memset(new, 0, sizeof(struct rgwp_config)); - CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, free, NULL ) ); + CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, (void *)free, acct_conf_session_state_dump, NULL ) ); new->confstr = conffile; if (conffile && strstr(conffile, "nonai"))
--- a/extensions/app_radgw/rgwx_auth.c Fri May 10 09:50:09 2013 +0800 +++ b/extensions/app_radgw/rgwx_auth.c Fri May 10 18:49:19 2013 +0800 @@ -124,6 +124,11 @@ int ignore_nai; }; +struct sess_state { + char req_auth[16]; +}; + + /* Initialize the plugin */ static int auth_conf_parse(char * confstr, struct rgwp_config ** state) { @@ -136,7 +141,7 @@ CHECK_MALLOC( new = malloc(sizeof(struct rgwp_config)) ); memset(new, 0, sizeof(struct rgwp_config)); - CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, free, NULL ) ); + CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, (void *)free, NULL, NULL ) ); new->confstr = confstr; if (confstr && strstr(confstr, "nonai")) @@ -1056,11 +1061,11 @@ /* Store the request identifier in the session (if provided) */ { - unsigned char * req_auth; - CHECK_MALLOC(req_auth = malloc(16)); - memcpy(req_auth, &rad_req->hdr->authenticator[0], 16); + struct sess_state *st; + CHECK_MALLOC(st = malloc(sizeof(struct sess_state))); + memcpy(st->req_auth, &rad_req->hdr->authenticator[0], 16); - CHECK_FCT( fd_sess_state_store( cs->sess_hdl, sess, &req_auth ) ); + CHECK_FCT( fd_sess_state_store( cs->sess_hdl, sess, &st ) ); } return 0; @@ -1076,7 +1081,7 @@ int ta_set = 0; int no_str = 0; /* indicate if an STR is required for this server */ uint8_t tuntag = 0; - unsigned char * req_auth = NULL; + struct sess_state *st; int error_cause = 0; struct session * sess; os0_t sid = NULL; @@ -1088,7 +1093,7 @@ /* Retrieve the request identified which was stored in the session */ CHECK_FCT( fd_msg_sess_get(fd_g_config->cnf_dict, *diam_ans, &sess, NULL) ); if (sess) { - CHECK_FCT( fd_sess_state_retrieve( cs->sess_hdl, sess, &req_auth ) ); + CHECK_FCT( fd_sess_state_retrieve( cs->sess_hdl, sess, &st ) ); CHECK_FCT( fd_sess_getsid(sess, &sid, &sidlen) ); } /* else ? */ @@ -1758,7 +1763,7 @@ size_t len[3]; /* We need the request authenticator */ - CHECK_PARAMS(req_auth); + CHECK_PARAMS(st); /* Retrieve the shared secret */ CHECK_FCT(rgw_clients_getkey(cli, &secret, &secret_len)); @@ -1777,7 +1782,7 @@ /* Initial b1 = MD5(S + R + A) */ addr[0] = secret; len[0] = secret_len; - addr[1] = req_auth; + addr[1] = st->req_auth; len[1] = 16; addr[2] = &buf[1]; len[2] = 2; @@ -1852,7 +1857,7 @@ size_t recv_len, send_len; /* We need the request authenticator */ - CHECK_PARAMS(req_auth); + CHECK_PARAMS(st); /* Retrieve the shared secret */ CHECK_FCT(rgw_clients_getkey(cli, &secret, &secret_len)); @@ -1865,7 +1870,7 @@ recv_len = ahdr->avp_value->os.len >= 32 ? 32 : ahdr->avp_value->os.len; send_len = ahdr->avp_value->os.len - recv_len; - if ( ! radius_msg_add_mppe_keys(*rad_fw, req_auth, secret, secret_len, + if ( ! radius_msg_add_mppe_keys(*rad_fw, st->req_auth, secret, secret_len, ahdr->avp_value->os.data + recv_len, send_len, ahdr->avp_value->os.data, recv_len) ) { TRACE_DEBUG(INFO, "Error while converting EAP-Master-Session-Key to RADIUS message"); @@ -1924,7 +1929,7 @@ } CHECK_FCT( fd_msg_free( aoh ) ); - free(req_auth); + free(st); if (error_cause) { if ( ! radius_msg_add_attr_int32(*rad_fw, RADIUS_ATTR_ERROR_CAUSE, error_cause) ) {
--- a/extensions/app_radgw/rgwx_echodrop.c Fri May 10 09:50:09 2013 +0800 +++ b/extensions/app_radgw/rgwx_echodrop.c Fri May 10 18:49:19 2013 +0800 @@ -37,20 +37,31 @@ #include "rgwx_echodrop.h" +struct sess_state { + struct fd_list sentinel; +}; + /* If a session is destroyed, empty the list of ed_saved_attribute */ -static void state_delete(void * arg, char * sid, void * opaque) { - struct fd_list * list = (struct fd_list *)arg; - - CHECK_PARAMS_DO( list, return ); - - while (!FD_IS_LIST_EMPTY(list)) { - struct ed_saved_attribute * esa = (struct ed_saved_attribute *)(list->next); +static void state_delete(struct sess_state * arg, os0_t sid, void * opaque) { + while (!FD_IS_LIST_EMPTY(&arg->sentinel)) { + struct ed_saved_attribute * esa = (struct ed_saved_attribute *)(arg->sentinel.next); fd_list_unlink(&esa->chain); free(esa); } - free(list); + free(arg); } +static DECLARE_FD_DUMP_PROTOTYPE(ed_session_state_dump, struct sess_state * st) +{ + struct fd_list * li; + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "[rgwx sess_state](@%p):\n", st), return NULL); + for (li = st->sentinel.next; li != &st->sentinel; li = li->next) { + struct ed_saved_attribute * esa = (struct ed_saved_attribute *)(li); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "[rgwx sess_state {esa}] t:%2hhx l:%2hhx d:", esa->attr.type, esa->attr.length), return NULL); + CHECK_MALLOC_DO( fd_dump_extend_hexdump(FD_DUMP_STD_PARAMS, (&esa->attr.length) + 1, esa->attr.length - 2, 0,0), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL); + } +} /* Initialize the plugin and parse the configuration. */ static int ed_conf_parse(char * conffile, struct rgwp_config ** state) @@ -68,7 +79,7 @@ fd_list_init(&new->attributes, NULL); /* Create the session handler */ - CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, state_delete, NULL ) ); + CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, state_delete, ed_session_state_dump, NULL ) ); /* Parse the configuration file */ CHECK_FCT( ed_conffile_parse(conffile, new) ); @@ -216,6 +227,7 @@ /* Save the echoed values in the session, if any */ if (!FD_IS_LIST_EMPTY(&echo_list)) { struct session * sess; + struct sess_state * st; CHECK_FCT( fd_msg_sess_get(fd_g_config->cnf_dict, *diam_fw, &sess, NULL) ); @@ -228,12 +240,12 @@ } ); /* Move the values in a dynamically allocated list */ - CHECK_MALLOC( li = malloc(sizeof(struct fd_list)) ); - fd_list_init(li, NULL); - fd_list_move_end(li, &echo_list); + CHECK_MALLOC( st = malloc(sizeof(struct sess_state)) ); + fd_list_init(&st->sentinel, NULL); + fd_list_move_end(&st->sentinel, &echo_list); /* Save the list in the session */ - CHECK_FCT( fd_sess_state_store( cs->sess_hdl, sess, &li ) ); + CHECK_FCT( fd_sess_state_store( cs->sess_hdl, sess, &st ) ); } return 0; @@ -242,8 +254,8 @@ /* Process an answer: add the ECHO attributes back, if any */ static int ed_diam_ans( struct rgwp_config * cs, struct msg ** diam_ans, struct radius_msg ** rad_fw, struct rgw_client * cli ) { - struct fd_list * list = NULL; struct session * sess; + struct sess_state * st; TRACE_ENTRY("%p %p %p %p", cs, diam_ans, rad_fw, cli); CHECK_PARAMS(cs); @@ -257,8 +269,8 @@ } /* Now try and retrieve any data from the session */ - CHECK_FCT( fd_sess_state_retrieve( cs->sess_hdl, sess, &list ) ); - if (list == NULL) { + CHECK_FCT( fd_sess_state_retrieve( cs->sess_hdl, sess, &st ) ); + if (st == NULL) { /* No attribute saved in the session, just return */ return 0; } @@ -267,8 +279,8 @@ CHECK_PARAMS( rad_fw && *rad_fw); - while (! FD_IS_LIST_EMPTY(list) ) { - struct ed_saved_attribute * esa = (struct ed_saved_attribute *)(list->next); + while (! FD_IS_LIST_EMPTY(&st->sentinel) ) { + struct ed_saved_attribute * esa = (struct ed_saved_attribute *)(st->sentinel.next); fd_list_unlink(&esa->chain); @@ -279,7 +291,7 @@ free(esa); } - free(list); + free(st); return 0; }
--- a/extensions/app_radgw/rgwx_sip.c Fri May 10 09:50:09 2013 +0800 +++ b/extensions/app_radgw/rgwx_sip.c Fri May 10 18:49:19 2013 +0800 @@ -133,7 +133,6 @@ } dict; /* cache of the dictionary objects we use */ - struct session_handler * sess_hdl; /* We store RADIUS request authenticator information in the session */ char * confstr; //Chained list of nonce struct fd_list listnonce; @@ -257,7 +256,6 @@ CHECK_MALLOC( new = malloc(sizeof(struct rgwp_config)) ); memset(new, 0, sizeof(struct rgwp_config)); - CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, free, NULL ) ); new->confstr = conffile; /* Resolve all dictionary objects we use */ @@ -311,8 +309,6 @@ TRACE_ENTRY("%p", state); CHECK_PARAMS_DO( state, return ); - CHECK_FCT_DO( fd_sess_handler_destroy( &state->sess_hdl, NULL ), ); - nonce_deletelistnonce(state); CHECK_POSIX_DO(pthread_mutex_destroy(&state->nonce_mutex), /*continue*/); @@ -320,7 +316,6 @@ return; } - /* Handle an incoming RADIUS request */ static int sip_rad_req( struct rgwp_config * cs, struct radius_msg * rad_req, struct radius_msg ** rad_ans, struct msg ** diam_fw, struct rgw_client * cli ) { @@ -716,15 +711,6 @@ //fd_msg_dump_walk(1,*diam_fw); - /* Store the request identifier in the session */ - { - unsigned char * req_sip; - CHECK_MALLOC(req_sip = malloc(16)); - memcpy(req_sip, &rad_req->hdr->authenticator[0], 16); - - CHECK_FCT( fd_sess_state_store( cs->sess_hdl, sess, &req_sip ) ); - } - return 0; } @@ -856,9 +842,6 @@ } } - CHECK_FCT( fd_sess_state_retrieve( cs->sess_hdl, sess, &req_sip ) ); - free(req_sip); - return 0; }
--- a/extensions/app_sip/app_sip.c Fri May 10 09:50:09 2013 +0800 +++ b/extensions/app_sip/app_sip.c Fri May 10 18:49:19 2013 +0800 @@ -212,7 +212,7 @@ if(start_mysql_connection()) return EINVAL; - CHECK_FCT(fd_sess_handler_create(&ds_sess_hdl, free, NULL)); + CHECK_FCT(fd_sess_handler_create(&ds_sess_hdl, (void *)free, NULL, NULL)); //Creation of thread for Registration Termination if(pthread_create(&rtr_thread, NULL,rtr_socket, NULL))
--- a/extensions/app_sip/app_sip.h Fri May 10 09:50:09 2013 +0800 +++ b/extensions/app_sip/app_sip.h Fri May 10 18:49:19 2013 +0800 @@ -212,11 +212,6 @@ #define CODE_SIP_USER_DATA_TYPE 388 #define CODE_SIP_AOR 122 -struct ds_nonce -{ - char *nonce; -}; - //Storage for some useful AVPs struct app_sip_dict{ struct dict_object * Auth_Session_State;
--- a/extensions/app_sip/multimediaauth.c Fri May 10 09:50:09 2013 +0800 +++ b/extensions/app_sip/multimediaauth.c Fri May 10 18:49:19 2013 +0800 @@ -35,6 +35,11 @@ *********************************************************************************************************/ #include "app_sip.h" +struct sess_state +{ + char *nonce; +}; + int app_sip_MAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act) { @@ -55,7 +60,7 @@ unsigned char *username=NULL; //The nonce we will store and retrieve in session - struct ds_nonce *storednonce=NULL; + struct sess_state *storednonce=NULL; TRACE_ENTRY("%p %p %p %p", msg, paramavp, sess, act); @@ -361,8 +366,8 @@ //We store the nonce (storednonce structure) inside the session - storednonce=malloc(sizeof(struct ds_nonce)); - memset(storednonce,0,sizeof(struct ds_nonce)); + storednonce=malloc(sizeof(struct sess_state)); + memset(storednonce,0,sizeof(struct sess_state)); CHECK_MALLOC(storednonce->nonce=malloc(NONCE_SIZE*2+1)); memcpy(storednonce->nonce,(char *)nonce,NONCE_SIZE*2+1); CHECK_FCT( fd_sess_state_store ( ds_sess_hdl, sess, &storednonce ));
--- a/extensions/dbg_interactive/dictionary.i Fri May 10 09:50:09 2013 +0800 +++ b/extensions/dbg_interactive/dictionary.i Fri May 10 18:49:19 2013 +0800 @@ -59,7 +59,10 @@ return; } void dump() { - fd_dict_dump($self); + char * buf = NULL; + size_t len; + printf("%s", fd_dict_dump(&buf, &len, NULL, $self)); + free(buf); } PyObject * vendors_list() { uint32_t *list = NULL, *li; @@ -127,7 +130,10 @@ %extend dict_object { void dump() { - fd_dict_dump_object($self); + char * buf = NULL; + size_t len; + printf("%s", fd_dict_dump_object(&buf, &len, NULL, $self)); + free(buf); } enum dict_object_type gettype() { enum dict_object_type t;
--- a/extensions/dbg_interactive/endpoints.i Fri May 10 09:50:09 2013 +0800 +++ b/extensions/dbg_interactive/endpoints.i Fri May 10 18:49:19 2013 +0800 @@ -125,6 +125,9 @@ } void dump() { - fd_ep_dump_one( "", $self ); + char * buf = NULL; + size_t len; + printf("%s", fd_ep_dump_one(&buf, &len, NULL, $self)); + free(buf); } }
--- a/extensions/dbg_interactive/messages.i Fri May 10 09:50:09 2013 +0800 +++ b/extensions/dbg_interactive/messages.i Fri May 10 18:49:19 2013 +0800 @@ -290,15 +290,10 @@ /* Dump */ void dump (int tree = 1) { - if (tree) - fd_msg_dump_walk(0, $self); - else - fd_msg_dump_one(0, $self); - } - - /* Log to file (depending on config) */ - void log ( enum fd_msg_log_cause cause, char * message ) { - fd_msg_log( cause, $self, message ); + char * buf = NULL; + size_t len; + printf("%s", fd_msg_dump_treeview(&buf, &len, NULL, $self, NULL, 0, tree)); + free(buf); } /* Model */ @@ -574,10 +569,10 @@ /* Dump */ void dump (int tree = 1) { - if (tree) - fd_msg_dump_walk(0, $self); - else - fd_msg_dump_one(0, $self); + char * buf = NULL; + size_t len; + printf("%s", fd_msg_dump_treeview(&buf, &len, NULL, $self, NULL, 0, tree)); + free(buf); } /* Model */
--- a/extensions/dbg_interactive/queues.i Fri May 10 09:50:09 2013 +0800 +++ b/extensions/dbg_interactive/queues.i Fri May 10 18:49:19 2013 +0800 @@ -65,12 +65,7 @@ /* Get the length of the queue (nb elements) */ int length() { - int l; - int ret = fd_fifo_length ( $self, &l ); - if (ret != 0) { - DI_ERROR(ret, NULL, NULL); - } - return l; + return fd_fifo_length ( $self ) ; } /* Is the threashold function useful here? TODO... */
--- a/extensions/dbg_interactive/sessions.i Fri May 10 09:50:09 2013 +0800 +++ b/extensions/dbg_interactive/sessions.i Fri May 10 18:49:19 2013 +0800 @@ -38,8 +38,12 @@ /****** SESSIONS *********/ %{ +struct sess_state { + PyObject * pystate; +}; + /* call it (might be called from a different thread than the interpreter, when session times out) */ -static void call_the_python_cleanup_callback(session_state * state, os0_t sid, void * cb) { +static void call_the_python_cleanup_callback(struct sess_state * state, os0_t sid, void * cb) { PyObject *result; if (!cb) { fd_log_debug("Internal error: missing callback object!"); @@ -66,7 +70,7 @@ Py_XINCREF(PyCb); - ret = fd_sess_handler_create_internal ( &hdl, call_the_python_cleanup_callback, PyCb ); + ret = fd_sess_handler_create ( &hdl, call_the_python_cleanup_callback, NULL, PyCb ); if (ret != 0) { DI_ERROR(ret, NULL, NULL); return NULL; @@ -86,7 +90,10 @@ return; } void dump() { - fd_sess_dump_hdl(0, $self); + char * buf = NULL; + size_t len; + printf("%s", fd_sess_dump_hdl(&buf, &len, NULL, $self)); + free(buf); } } @@ -165,13 +172,18 @@ } } void dump() { - fd_sess_dump(0, $self); + char * buf = NULL; + size_t len = 0; + printf("%s", fd_sess_dump(&buf, &len, NULL, $self, 1) ); + free(buf); } void store(struct session_handler * handler, PyObject * DISOWN) { int ret; - void * store = DISOWN; + struct sess_state * st = NULL; + st = malloc(sizeof(struct sess_state)); + st->pystate = DISOWN; Py_XINCREF(DISOWN); - ret = fd_sess_state_store_internal(handler, $self, (void *) &store); + ret = fd_sess_state_store(handler, $self, (void *) &st); if (ret != 0) { DI_ERROR(ret, NULL, NULL); } @@ -179,16 +191,19 @@ %newobject retrieve; PyObject * retrieve(struct session_handler * handler) { int ret; + struct sess_state * st = NULL; PyObject * state = NULL; - ret = fd_sess_state_retrieve_internal(handler, $self, (void *) &state); + ret = fd_sess_state_retrieve(handler, $self, (void *) &st); if (ret != 0) { DI_ERROR(ret, NULL, NULL); return NULL; } - if (state == NULL) { + if (st == NULL) { Py_INCREF(Py_None); return Py_None; } + state = st->pystate; + free(st); return state; } }
--- a/extensions/dbg_monitor/dbg_monitor.c Fri May 10 09:50:09 2013 +0800 +++ b/extensions/dbg_monitor/dbg_monitor.c Fri May 10 18:49:19 2013 +0800 @@ -49,40 +49,103 @@ EXTENSION_ENTRY("dbg_monitor", monitor_main); + + +/* Display information about a queue */ +static void display_info(char * queue_desc, char * peer, int current_count, int limit_count, int highest_count, long long total_count, + struct timespec * total, struct timespec * blocking, struct timespec * last) +{ + long long us = (total->tv_sec * 1000000) + (total->tv_nsec / 1000); + long double throughput = (long double)total_count * 1000000; + throughput /= us; + if (peer) { + TRACE_DEBUG(INFO, "'%s'@'%s': cur:%d/%d, h:%d, T:%lld in %ld.%06lds (%.2LFitems/s), blocked:%ld.%06lds, last processing:%ld.%06lds", + queue_desc, peer, current_count, limit_count, highest_count, + total_count, total->tv_sec, total->tv_nsec/1000, throughput, + blocking->tv_sec, blocking->tv_nsec/1000, last->tv_sec, last->tv_nsec/1000); + } else { + TRACE_DEBUG(INFO, "Global '%s': cur:%d/%d, h:%d, T:%lld in %ld.%06lds (%.2LFitems/s), blocked:%ld.%06lds, last processing:%ld.%06lds", + queue_desc, current_count, limit_count, highest_count, + total_count, total->tv_sec, total->tv_nsec/1000, throughput, + blocking->tv_sec, blocking->tv_nsec/1000, last->tv_sec, last->tv_nsec/1000); + } +} + /* Thread to display periodical debug information */ static pthread_t thr; static void * mn_thr(void * arg) { int i = 0; fd_log_threadname("Monitor thread"); + char * buf = NULL; + size_t len; /* Loop */ while (1) { + int current_count, limit_count, highest_count; + long long total_count; + struct timespec total, blocking, last; + struct fd_list * li; + #ifdef DEBUG for (i++; i % 30; i++) { fd_log_debug("[dbg_monitor] %ih%*im%*is", i/3600, 2, (i/60) % 60 , 2, i%60); /* This makes it easier to detect inactivity periods in the log file */ sleep(1); } #else /* DEBUG */ - sleep(3600); /* 1 hour */ + sleep(3599); /* 1 hour */ #endif /* DEBUG */ - fd_log_debug("[dbg_monitor] Dumping current information"); - CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_QUEUES, 0, NULL), /* continue */); - CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_SERV, 0, NULL), /* continue */); - CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_PEERS, 0, NULL), /* continue */); + TRACE_DEBUG(INFO, "[dbg_monitor] Dumping queues statistics"); + + CHECK_FCT_DO( fd_stat_getstats(STAT_G_LOCAL, NULL, ¤t_count, &limit_count, &highest_count, &total_count, &total, &blocking, &last), ); + display_info("Local delivery", NULL, current_count, limit_count, highest_count, total_count, &total, &blocking, &last); + + CHECK_FCT_DO( fd_stat_getstats(STAT_G_INCOMING, NULL, ¤t_count, &limit_count, &highest_count, &total_count, &total, &blocking, &last), ); + display_info("Total received", NULL, current_count, limit_count, highest_count, total_count, &total, &blocking, &last); + + CHECK_FCT_DO( fd_stat_getstats(STAT_G_OUTGOING, NULL, ¤t_count, &limit_count, &highest_count, &total_count, &total, &blocking, &last), ); + display_info("Total sending", NULL, current_count, limit_count, highest_count, total_count, &total, &blocking, &last); + + + CHECK_FCT_DO( pthread_rwlock_rdlock(&fd_g_peers_rw), /* continue */ ); + + for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) { + struct peer_hdr * p = (struct peer_hdr *)li->o; + + TRACE_DEBUG(INFO, "%s", fd_peer_dump(&buf, &len, NULL, p, 1)); + + CHECK_FCT_DO( fd_stat_getstats(STAT_P_PSM, p, ¤t_count, &limit_count, &highest_count, &total_count, &total, &blocking, &last), ); + display_info("Events, incl. recept", p->info.pi_diamid, current_count, limit_count, highest_count, total_count, &total, &blocking, &last); + + CHECK_FCT_DO( fd_stat_getstats(STAT_P_TOSEND, p, ¤t_count, &limit_count, &highest_count, &total_count, &total, &blocking, &last), ); + display_info("Outgoing", p->info.pi_diamid, current_count, limit_count, highest_count, total_count, &total, &blocking, &last); + + } + + CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ ); + + TRACE_DEBUG(INFO, "[dbg_monitor] Dumping servers information"); + TRACE_DEBUG(INFO, "%s", fd_servers_dump(&buf, &len, NULL)); + sleep(1); } + free(buf); return NULL; } /* Function called on receipt of MONITOR_SIGNAL */ static void got_sig() { - fd_log_debug("[dbg_monitor] Dumping extra information"); - CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_DICT, 0, NULL), /* continue */); - CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_CONFIG, 0, NULL), /* continue */); - CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_EXT, 0, NULL), /* continue */); + char * buf = NULL; + size_t len; + TRACE_DEBUG(INFO, "[dbg_monitor] Dumping config information"); + TRACE_DEBUG(INFO, "%s", fd_conf_dump(&buf, &len, NULL)); + TRACE_DEBUG(INFO, "[dbg_monitor] Dumping extensions information"); + TRACE_DEBUG(INFO, "%s", fd_ext_dump(&buf, &len, NULL)); + TRACE_DEBUG(INFO, "[dbg_monitor] Dumping dictionary information"); + TRACE_DEBUG(INFO, "%s", fd_dict_dump(&buf, &len, NULL, fd_g_config->cnf_dict)); + free(buf); } /* Entry point */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/dbg_msg_timings/CMakeLists.txt Fri May 10 18:49:19 2013 +0800 @@ -0,0 +1,12 @@ +# Messages timing extension +PROJECT("Messages timing extension" C) +FD_ADD_EXTENSION(dbg_msg_timings dbg_msg_timings.c) + + +#### +## INSTALL section ## + +INSTALL(TARGETS dbg_msg_timings + LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX} + COMPONENT freeDiameter-debug-tools) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/dbg_msg_timings/dbg_msg_timings.c Fri May 10 18:49:19 2013 +0800 @@ -0,0 +1,134 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis <sdecugis@freediameter.net> * +* * +* Copyright (c) 2013, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +/* This extension uses the hooks mechanism to compute some timing information related to messages */ + +#include <freeDiameter/extension.h> + +struct fd_hook_permsgdata { + struct timespec received_on; + struct timespec sent_on; +}; + +static struct fd_hook_data_hdl *mt_data_hdl = NULL; +static struct fd_hook_hdl *mt_hdl = NULL; + +/* The callback called when messages are received and sent */ +static void mt_hook_cb(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata) +{ + struct msg_hdr * hdr; + char * buf = NULL; + size_t len; + + ASSERT(pmd); + + if (type == HOOK_DATA_RECEIVED) { + /* We just store the timestamp it was received on */ + (void)clock_gettime(CLOCK_REALTIME, &pmd->received_on); + return; + } + + ASSERT(msg); + + /* Check if this message is request or answer */ + CHECK_FCT_DO( fd_msg_hdr(msg, &hdr), return); + + if (type == HOOK_MESSAGE_RECEIVED) { + ASSERT(pmd->received_on.tv_sec); /* otherwise it means the HOOK_DATA_RECEIVED hook was not trigged for this message */ + if (hdr->msg_flags & CMD_FLAG_REQUEST) { + /* We have received a new request, nothing special to do */ + } else { + /* This is an answer, check how long it took to get it */ + struct fd_hook_permsgdata *qpmd = fd_hook_get_request_pmd(mt_data_hdl, msg); + struct timespec delay; + ASSERT(qpmd); /* If we do not have it, we must find out why */ + ASSERT(qpmd->sent_on.tv_sec); /* same, would mean the HOOK_MESSAGE_SENT hook was not trigged */ + TS_DIFFERENCE( &delay, &qpmd->sent_on, &pmd->received_on ); + CHECK_MALLOC_DO( fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), return ); + LOG_N("[TIMING] RCV ANS %ld.%06ld sec: %s", (long)delay.tv_sec, delay.tv_nsec / 1000, buf); + } + } else if (type == HOOK_MESSAGE_SENT) { + DiamId_t source = NULL; + size_t slen = 0; + + (void)clock_gettime(CLOCK_REALTIME, &pmd->sent_on); + + /* Is this a forwarded message ? */ + CHECK_FCT_DO( fd_msg_source_get(msg, &source, &slen), return ); + if (source) { + struct timespec delay; + ASSERT(pmd->received_on.tv_sec); + TS_DIFFERENCE( &delay, &pmd->received_on, &pmd->sent_on ); + CHECK_MALLOC_DO( fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), return ); + LOG_N("[TIMING] FWD %ld.%06ld sec: %s", (long)delay.tv_sec, delay.tv_nsec / 1000, buf); + } else if (hdr->msg_flags & CMD_FLAG_REQUEST) { + /* We are sending a request issued locally, nothing special to log */ + } else { + /* We have generated an anwer, log the time it took since the corresponding request was received */ + struct fd_hook_permsgdata *qpmd = fd_hook_get_request_pmd(mt_data_hdl, msg); + if (qpmd->received_on.tv_sec) { + struct timespec delay; + TS_DIFFERENCE( &delay, &qpmd->received_on, &pmd->sent_on ); + CHECK_MALLOC_DO( fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), return ); + LOG_N("[TIMING] ANS %ld.%06ld sec: %s", (long)delay.tv_sec, delay.tv_nsec / 1000, buf); + } + } + } + + free(buf); +} + +/* Entry point */ +static int mt_main(char * conffile) +{ + TRACE_ENTRY("%p", conffile); + + CHECK_FCT( fd_hook_data_register( sizeof(struct fd_hook_permsgdata), NULL, NULL, &mt_data_hdl ) ); + + CHECK_FCT( fd_hook_register( ((1 << HOOK_MESSAGE_RECEIVED) | (1 << HOOK_MESSAGE_SENT) | (1 << HOOK_DATA_RECEIVED)), + mt_hook_cb, NULL, mt_data_hdl, &mt_hdl) ); + + return 0; +} + +/* Cleanup */ +void fd_ext_fini(void) +{ + TRACE_ENTRY(); + CHECK_FCT_DO( fd_hook_unregister( mt_hdl ), ); + return ; +} + +EXTENSION_ENTRY("dbg_msg_timing", mt_main);
--- a/extensions/dict_dcca_3gpp/dict_dcca_3gpp.c Fri May 10 09:50:09 2013 +0800 +++ b/extensions/dict_dcca_3gpp/dict_dcca_3gpp.c Fri May 10 18:49:19 2013 +0800 @@ -1,6 +1,91 @@ +/********************************************************************************************************* + * Software License Agreement (BSD License) * + * Author: Thomas Klausner <tk@giga.or.at> * + * * + * Copyright (c) 2013, Thomas Klausner * + * All rights reserved. * + * * + * Written under contract by nfotex IT GmbH, http://nfotex.com/ * + * * + * Redistribution and use of this software in source and binary forms, with or without modification, are * + * permitted provided that the following conditions are met: * + * * + * * Redistributions of source code must retain the above * + * copyright notice, this list of conditions and the * + * following disclaimer. * + * * + * * Redistributions in binary form must reproduce the above * + * copyright notice, this list of conditions and the * + * following disclaimer in the documentation and/or other * + * materials provided with the distribution. * + * * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + *********************************************************************************************************/ + /* - * Dictionary definitions of objects specified in DCCA (Nokia, 3GPP). + * Dictionary definitions for objects specified for DCCA by 3GPP. + * + * This extensions contains a lot of AVPs from various 3GPP standards + * documents, and some rules for the grouped AVPs described therein. + * + * This extension does not contain ALL AVPs described by 3GPP, but + * quite a big number of them. + * + * When extending the AVPs, please edit dict_dcca_3gpp.org instead and + * create pastable code with contrib/tools/org_to_fd.pl. + * + * Some points of consideration: + * 1. This dictionary could be split up per document. + * + * + pro: you can only load the AVPs/Rules you're interested in -> + * smaller memory size + * + * - con: the documents use AVPs from each other A LOT, so setting the + * dependencies correctly will be annoying + * + * - con: you need to load all of them as extensions + * + * 2. This dictionary contains ONE AVP in the "3GPP2" vendor space, + * since I found it wasteful to write a separate dictionary just for + * one AVP. Also, it is defined in a 3GPP document. + * + * 3. While there are quite a number of rules here already, many more + * are missing. I've only added rules for those grouped AVPs or + * commands in which I was concretely interested so far; many more + * will need to be added to make this complete. + * + * That being said, I hope this will be useful for you. + * */ + + +/* + * Some comments on the 3GPP Standards documents themselves: + * + * 1. It would be good if 29.061 was reviewed to check for each AVP if + * it is Mandatory or not. The data currently in the document does not + * match what was in the previous version of the freeDiameter + * extension (the one that existedbefore I rewrote it) or what I saw + * so far. IIRC, even the table and the document contradict each + * other. The AVP table is also missing an entry for + * "External-Identifier", 28. + * + * 2. 29.140 has conflicting AVP names with other documents: + * - Sequence-Number is also in 32.329 + * - Recipient-Address is also in 32.299 + * - Status is also in 32.299 + * + * 3. 29.229 has name conflict with 29.329 about User-Data (different + * AVP code 702, instead of 606) -- the weird thing is, the latter + * uses some AVPs from the former, but not this one. +*/ #include <freeDiameter/extension.h> @@ -13,7 +98,7 @@ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) ); struct local_rules_definition { - char *avp_name; + struct dict_avp_request avp_vendor_plus_name; enum rule_position position; int min; int max; @@ -21,6 +106,7 @@ #define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 ) +/* Attention! This version of the macro uses AVP_BY_NAME_AND_VENDOR, in contrast to most other copies! */ #define PARSE_loc_rules( _rulearray, _parent) { \ int __ar; \ for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) { \ @@ -33,17 +119,17 @@ CHECK_FCT( fd_dict_search( \ fd_g_config->cnf_dict, \ DICT_AVP, \ - AVP_BY_NAME, \ - (_rulearray)[__ar].avp_name, \ + AVP_BY_NAME_AND_VENDOR, \ + &(_rulearray)[__ar].avp_vendor_plus_name, \ &__data.rule_avp, 0 ) ); \ if ( !__data.rule_avp ) { \ - TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name ); \ + TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_vendor_plus_name.avp_name); \ return ENOENT; \ } \ CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL), \ { \ TRACE_DEBUG(INFO, "Error on rule with AVP '%s'", \ - (_rulearray)[__ar].avp_name ); \ + (_rulearray)[__ar].avp_vendor_plus_name.avp_name); \ return EINVAL; \ } ); \ } \ @@ -64,8 +150,12 @@ { struct dict_vendor_data vendor_data = { 10415, "3GPP" }; CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &vendor_data, NULL, NULL)); - } - + } + { + struct dict_vendor_data vendor_data = { 5535, "3GPP2" }; + CHECK_FCT(fd_dict_new(fd_g_config->cnf_dict, DICT_VENDOR, &vendor_data, NULL, NULL)); + } + } @@ -80,9 +170,10 @@ CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type); CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type); CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "IPFilterRule", &IPFilterRule_type); - CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type); + CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type); CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type); + /* The following is created automatically. Do not modify. */ /* Changes will be lost during the next update. Modify the source org file instead. */ @@ -786,7 +877,436 @@ CHECK_dict_new(DICT_AVP, &data, type, NULL); }; - /* 3GPP 29.212-b70 (11.7.0 2012.12.20) */ + /* 3GPP 29.140-700 (7.0.0 2007.07.05) */ + /* Served-User-Identity */ + { + struct dict_avp_data data = { + 1100, /* Code */ + 10415, /* Vendor */ + "Served-User-Identity", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* reuses: MSISDN */ + /* VASP-ID */ + { + struct dict_avp_data data = { + 1101, /* Code */ + 10415, /* Vendor */ + "VASP-ID", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* VAS-ID */ + { + struct dict_avp_data data = { + 1102, /* Code */ + 10415, /* Vendor */ + "VAS-ID", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* Trigger-Event */ + { + struct dict_avp_data data = { + 1103, /* Code */ + 10415, /* Vendor */ + "Trigger-Event", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Trigger-Event)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* reuses: 3GPP-IMSI */ + /* Sender-Address */ + { + struct dict_avp_data data = { + 1104, /* Code */ + 10415, /* Vendor */ + "Sender-Address", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* Initial-Recipient-Address */ + { + struct dict_avp_data data = { + 1105, /* Code */ + 10415, /* Vendor */ + "Initial-Recipient-Address", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Result-Recipient-Address */ + { + struct dict_avp_data data = { + 1106, /* Code */ + 10415, /* Vendor */ + "Result-Recipient-Address", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* conflicts with one in (more common) 32.329 */ + /* Sequence-Number-29.140 */ + { + struct dict_avp_data data = { + 1107, /* Code */ + 10415, /* Vendor */ + "Sequence-Number-29.140", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* conflicts with one in (more common) 32.299 */ + /* Recipient-Address-29.140 */ + { + struct dict_avp_data data = { + 1108, /* Code */ + 10415, /* Vendor */ + "Recipient-Address-29.140", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* Routeing-Address */ + { + struct dict_avp_data data = { + 1109, /* Code */ + 10415, /* Vendor */ + "Routeing-Address", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* Originating-Interface */ + { + struct dict_avp_data data = { + 1110, /* Code */ + 10415, /* Vendor */ + "Originating-Interface", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Originating-Interface)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Delivery-Report */ + { + struct dict_avp_data data = { + 1111, /* Code */ + 10415, /* Vendor */ + "Delivery-Report", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Delivery-Report)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Read-Reply */ + { + struct dict_avp_data data = { + 1112, /* Code */ + 10415, /* Vendor */ + "Read-Reply", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Read-Reply)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Sender-Visibility */ + { + struct dict_avp_data data = { + 1113, /* Code */ + 10415, /* Vendor */ + "Sender-Visibility", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Sender-Visibility)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Service-Key */ + { + struct dict_avp_data data = { + 1114, /* Code */ + 10415, /* Vendor */ + "Service-Key", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* Billing-Information */ + { + struct dict_avp_data data = { + 1115, /* Code */ + 10415, /* Vendor */ + "Billing-Information", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* conflicts with one in (more common) 32.299 */ + /* Status-29.140 */ + { + struct dict_avp_data data = { + 1116, /* Code */ + 10415, /* Vendor */ + "Status-29.140", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Status-Code */ + { + struct dict_avp_data data = { + 1117, /* Code */ + 10415, /* Vendor */ + "Status-Code", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* Status-Text */ + { + struct dict_avp_data data = { + 1118, /* Code */ + 10415, /* Vendor */ + "Status-Text", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* Routeing-Address-Resolution */ + { + struct dict_avp_data data = { + 1119, /* Code */ + 10415, /* Vendor */ + "Routeing-Address-Resolution", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Routeing-Address-Resolution)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* 3GPP 29.173-c00 (12.0.0 2013.03.13) */ + /* LMSI */ + { + struct dict_avp_data data = { + 2400, /* Code */ + 10415, /* Vendor */ + "LMSI", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Serving-Node */ + { + struct dict_avp_data data = { + 2401, /* Code */ + 10415, /* Vendor */ + "Serving-Node", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* MME-Name */ + { + struct dict_avp_data data = { + 2402, /* Code */ + 10415, /* Vendor */ + "MME-Name", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, DiameterIdentity_type, NULL); + }; + + /* MSC-Number */ + { + struct dict_avp_data data = { + 2403, /* Code */ + 10415, /* Vendor */ + "MSC-Number", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* LCS-Capabilities-Sets */ + { + struct dict_avp_data data = { + 2404, /* Code */ + 10415, /* Vendor */ + "LCS-Capabilities-Sets", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* GMLC-Address */ + { + struct dict_avp_data data = { + 2405, /* Code */ + 10415, /* Vendor */ + "GMLC-Address", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, Address_type, NULL); + }; + + /* Additional-Serving-Node */ + { + struct dict_avp_data data = { + 2406, /* Code */ + 10415, /* Vendor */ + "Additional-Serving-Node", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* PPR-Address */ + { + struct dict_avp_data data = { + 2407, /* Code */ + 10415, /* Vendor */ + "PPR-Address", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, Address_type, NULL); + }; + + /* MME-Realm */ + { + struct dict_avp_data data = { + 2408, /* Code */ + 10415, /* Vendor */ + "MME-Realm", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, DiameterIdentity_type, NULL); + }; + + /* SGSN-Name */ + { + struct dict_avp_data data = { + 2409, /* Code */ + 10415, /* Vendor */ + "SGSN-Name", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, DiameterIdentity_type, NULL); + }; + + /* SGSN-Realm */ + { + struct dict_avp_data data = { + 2410, /* Code */ + 10415, /* Vendor */ + "SGSN-Realm", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, DiameterIdentity_type, NULL); + }; + + /* 3GPP 29.212-c00 (12.0.0 2013.03.15) */ + /* Gx-specific */ /* ADC-Revalidation-Time */ { struct dict_avp_data data = { @@ -1279,19 +1799,6 @@ CHECK_dict_new(DICT_AVP, &data, NULL, NULL); }; - /* HeNB-BBF-FQDN */ - { - struct dict_avp_data data = { - 2803, /* Code */ - 10415, /* Vendor */ - "HeNB-BBF-FQDN", /* Name */ - AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ - AVP_FLAG_VENDOR, /* Fixed flag values */ - AVP_TYPE_OCTETSTRING /* base type of data */ - }; - CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); - }; - /* HeNB-Local-IP-Address */ { struct dict_avp_data data = { @@ -1773,12 +2280,12 @@ CHECK_dict_new(DICT_AVP, &data, DiameterIdentity_type, NULL); }; - /* TDF-IP-address */ + /* TDF-IP-Address */ { struct dict_avp_data data = { 1091, /* Code */ 10415, /* Vendor */ - "TDF-IP-address", /* Name */ + "TDF-IP-Address", /* Name */ AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ AVP_FLAG_VENDOR, /* Fixed flag values */ AVP_TYPE_OCTETSTRING /* base type of data */ @@ -1831,18 +2338,18 @@ CHECK_dict_new(DICT_AVP, &data, type, NULL); }; - /* Qos-Upgrade */ + /* QoS-Upgrade */ { struct dict_avp_data data = { 1030, /* Code */ 10415, /* Vendor */ - "Qos-Upgrade", /* Name */ - AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ - AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ - AVP_TYPE_INTEGER32 /* base type of data */ - }; - struct dict_object *type; - struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Qos-Upgrade)", NULL, NULL, NULL }; + "QoS-Upgrade", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(QoS-Upgrade)", NULL, NULL, NULL }; CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); CHECK_dict_new(DICT_AVP, &data, type, NULL); }; @@ -2067,12 +2574,12 @@ CHECK_dict_new(DICT_AVP, &data, NULL, NULL); }; - /* Rule-DeActivation-Time */ + /* Rule-Deactivation-Time */ { struct dict_avp_data data = { 1044, /* Code */ 10415, /* Vendor */ - "Rule-DeActivation-Time", /* Name */ + "Rule-Deactivation-Time", /* Name */ AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ AVP_TYPE_OCTETSTRING /* base type of data */ @@ -2128,6 +2635,7 @@ CHECK_dict_new(DICT_AVP, &data, type, NULL); }; + /* Gxx-specific */ /* QoS-Rule-Install */ { struct dict_avp_data data = { @@ -2222,6 +2730,7 @@ CHECK_dict_new(DICT_AVP, &data, type, NULL); }; + /* S15-specific */ /* CS-Service-Qos-Request-Identifier */ { struct dict_avp_data data = { @@ -2251,6 +2760,492 @@ CHECK_dict_new(DICT_AVP, &data, type, NULL); }; + /* 3GPP 29.214-b80 (11.8.0 2013.03.15) */ + /* Abort-Cause */ + { + struct dict_avp_data data = { + 500, /* Code */ + 10415, /* Vendor */ + "Abort-Cause", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Abort-Cause)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Access-Network-Charging-Address */ + { + struct dict_avp_data data = { + 501, /* Code */ + 10415, /* Vendor */ + "Access-Network-Charging-Address", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, Address_type, NULL); + }; + + /* Access-Network-Charging-Identifier */ + { + struct dict_avp_data data = { + 502, /* Code */ + 10415, /* Vendor */ + "Access-Network-Charging-Identifier", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Access-Network-Charging-Identifier-Value */ + { + struct dict_avp_data data = { + 503, /* Code */ + 10415, /* Vendor */ + "Access-Network-Charging-Identifier-Value", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Acceptable-Service-Info */ + { + struct dict_avp_data data = { + 526, /* Code */ + 10415, /* Vendor */ + "Acceptable-Service-Info", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* AF-Application-Identifier */ + { + struct dict_avp_data data = { + 504, /* Code */ + 10415, /* Vendor */ + "AF-Application-Identifier", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* AF-Charging-Identifier */ + { + struct dict_avp_data data = { + 505, /* Code */ + 10415, /* Vendor */ + "AF-Charging-Identifier", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Application-Service-Provider-Identity */ + { + struct dict_avp_data data = { + 532, /* Code */ + 10415, /* Vendor */ + "Application-Service-Provider-Identity", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* Codec-Data */ + { + struct dict_avp_data data = { + 524, /* Code */ + 10415, /* Vendor */ + "Codec-Data", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Flow-Description */ + { + struct dict_avp_data data = { + 507, /* Code */ + 10415, /* Vendor */ + "Flow-Description", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, IPFilterRule_type, NULL); + }; + + /* Flow-Number */ + { + struct dict_avp_data data = { + 509, /* Code */ + 10415, /* Vendor */ + "Flow-Number", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Flows */ + { + struct dict_avp_data data = { + 510, /* Code */ + 10415, /* Vendor */ + "Flows", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Flow-Status */ + { + struct dict_avp_data data = { + 511, /* Code */ + 10415, /* Vendor */ + "Flow-Status", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Flow-Status)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Flow-Usage */ + { + struct dict_avp_data data = { + 512, /* Code */ + 10415, /* Vendor */ + "Flow-Usage", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Flow-Usage)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Service-URN */ + { + struct dict_avp_data data = { + 525, /* Code */ + 10415, /* Vendor */ + "Service-URN", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Specific-Action */ + { + struct dict_avp_data data = { + 513, /* Code */ + 10415, /* Vendor */ + "Specific-Action", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Specific-Action)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Max-Requested-Bandwidth-DL */ + { + struct dict_avp_data data = { + 515, /* Code */ + 10415, /* Vendor */ + "Max-Requested-Bandwidth-DL", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Max-Requested-Bandwidth-UL */ + { + struct dict_avp_data data = { + 516, /* Code */ + 10415, /* Vendor */ + "Max-Requested-Bandwidth-UL", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Media-Component-Description */ + { + struct dict_avp_data data = { + 517, /* Code */ + 10415, /* Vendor */ + "Media-Component-Description", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Media-Component-Number */ + { + struct dict_avp_data data = { + 518, /* Code */ + 10415, /* Vendor */ + "Media-Component-Number", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Media-Sub-Component */ + { + struct dict_avp_data data = { + 519, /* Code */ + 10415, /* Vendor */ + "Media-Sub-Component", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Media-Type */ + { + struct dict_avp_data data = { + 520, /* Code */ + 10415, /* Vendor */ + "Media-Type", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Media-Type)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* MPS-Identifier */ + { + struct dict_avp_data data = { + 528, /* Code */ + 10415, /* Vendor */ + "MPS-Identifier", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Min-Requested-Bandwidth-DL */ + { + struct dict_avp_data data = { + 534, /* Code */ + 10415, /* Vendor */ + "Min-Requested-Bandwidth-DL", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Min-Requested-Bandwidth-UL */ + { + struct dict_avp_data data = { + 535, /* Code */ + 10415, /* Vendor */ + "Min-Requested-Bandwidth-UL", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* RR-Bandwidth */ + { + struct dict_avp_data data = { + 521, /* Code */ + 10415, /* Vendor */ + "RR-Bandwidth", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* RS-Bandwidth */ + { + struct dict_avp_data data = { + 522, /* Code */ + 10415, /* Vendor */ + "RS-Bandwidth", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Service-Info-Status */ + { + struct dict_avp_data data = { + 527, /* Code */ + 10415, /* Vendor */ + "Service-Info-Status", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Service-Info-Status)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* SIP-Forking-Indication */ + { + struct dict_avp_data data = { + 523, /* Code */ + 10415, /* Vendor */ + "SIP-Forking-Indication", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SIP-Forking-Indication)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Sponsor-Identity */ + { + struct dict_avp_data data = { + 531, /* Code */ + 10415, /* Vendor */ + "Sponsor-Identity", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* Sponsored-Connectivity-Data */ + { + struct dict_avp_data data = { + 530, /* Code */ + 10415, /* Vendor */ + "Sponsored-Connectivity-Data", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* AF-Signalling-Protocol */ + { + struct dict_avp_data data = { + 529, /* Code */ + 10415, /* Vendor */ + "AF-Signalling-Protocol", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(AF-Signalling-Protocol)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Required-Access-Info */ + { + struct dict_avp_data data = { + 536, /* Code */ + 10415, /* Vendor */ + "Required-Access-Info", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Required-Access-Info)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Rx-Request-Type */ + { + struct dict_avp_data data = { + 533, /* Code */ + 10415, /* Vendor */ + "Rx-Request-Type", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Rx-Request-Type)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* IP-Domain-Id */ + { + struct dict_avp_data data = { + 537, /* Code */ + 10415, /* Vendor */ + "IP-Domain-Id", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + /* 3GPP 29.229-b20 (11.2.0 2012.12.21) */ /* Associated-Identities */ { @@ -3357,12 +4352,12 @@ CHECK_dict_new(DICT_AVP, &data, NULL, NULL); }; - /* Application-provided-called-party-address */ + /* Application-Provided-Called-Party-Address */ { struct dict_avp_data data = { 837, /* Code */ 10415, /* Vendor */ - "Application-provided-called-party-address", /* Name */ + "Application-Provided-Called-Party-Address", /* Name */ AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ AVP_TYPE_OCTETSTRING /* base type of data */ @@ -6722,6 +7717,2113 @@ CHECK_dict_new(DICT_AVP, &data, Address_type, NULL); }; + /* 3GPP 29.272-c00 (12.0.0 2013.03.13) */ + /* Subscription-Data */ + { + struct dict_avp_data data = { + 1400, /* Code */ + 10415, /* Vendor */ + "Subscription-Data", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Terminal-Information */ + { + struct dict_avp_data data = { + 1401, /* Code */ + 10415, /* Vendor */ + "Terminal-Information", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* IMEI */ + { + struct dict_avp_data data = { + 1402, /* Code */ + 10415, /* Vendor */ + "IMEI", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* Software-Version */ + { + struct dict_avp_data data = { + 1403, /* Code */ + 10415, /* Vendor */ + "Software-Version", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* QoS-Subscribed */ + { + struct dict_avp_data data = { + 1404, /* Code */ + 10415, /* Vendor */ + "QoS-Subscribed", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* ULR-Flags */ + { + struct dict_avp_data data = { + 1405, /* Code */ + 10415, /* Vendor */ + "ULR-Flags", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* ULA-Flags */ + { + struct dict_avp_data data = { + 1406, /* Code */ + 10415, /* Vendor */ + "ULA-Flags", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Visited-PLMN-Id */ + { + struct dict_avp_data data = { + 1407, /* Code */ + 10415, /* Vendor */ + "Visited-PLMN-Id", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Requested-EUTRAN-Authentication-Info */ + { + struct dict_avp_data data = { + 1408, /* Code */ + 10415, /* Vendor */ + "Requested-EUTRAN-Authentication-Info", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Requested-UTRAN-GERAN-Authentication-Info */ + { + struct dict_avp_data data = { + 1409, /* Code */ + 10415, /* Vendor */ + "Requested-UTRAN-GERAN-Authentication-Info", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Number-Of-Requested-Vectors */ + { + struct dict_avp_data data = { + 1410, /* Code */ + 10415, /* Vendor */ + "Number-Of-Requested-Vectors", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Re-Synchronization-Info */ + { + struct dict_avp_data data = { + 1411, /* Code */ + 10415, /* Vendor */ + "Re-Synchronization-Info", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Immediate-Response-Preferred */ + { + struct dict_avp_data data = { + 1412, /* Code */ + 10415, /* Vendor */ + "Immediate-Response-Preferred", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Authentication-Info */ + { + struct dict_avp_data data = { + 1413, /* Code */ + 10415, /* Vendor */ + "Authentication-Info", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* E-UTRAN-Vector */ + { + struct dict_avp_data data = { + 1414, /* Code */ + 10415, /* Vendor */ + "E-UTRAN-Vector", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* UTRAN-Vector */ + { + struct dict_avp_data data = { + 1415, /* Code */ + 10415, /* Vendor */ + "UTRAN-Vector", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* GERAN-Vector */ + { + struct dict_avp_data data = { + 1416, /* Code */ + 10415, /* Vendor */ + "GERAN-Vector", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Network-Access-Mode */ + { + struct dict_avp_data data = { + 1417, /* Code */ + 10415, /* Vendor */ + "Network-Access-Mode", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Network-Access-Mode)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* HPLMN-ODB */ + { + struct dict_avp_data data = { + 1418, /* Code */ + 10415, /* Vendor */ + "HPLMN-ODB", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Item-Number */ + { + struct dict_avp_data data = { + 1419, /* Code */ + 10415, /* Vendor */ + "Item-Number", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Cancellation-Type */ + { + struct dict_avp_data data = { + 1420, /* Code */ + 10415, /* Vendor */ + "Cancellation-Type", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Cancellation-Type)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* DSR-Flags */ + { + struct dict_avp_data data = { + 1421, /* Code */ + 10415, /* Vendor */ + "DSR-Flags", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* DSA-Flags */ + { + struct dict_avp_data data = { + 1422, /* Code */ + 10415, /* Vendor */ + "DSA-Flags", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Context-Identifier */ + { + struct dict_avp_data data = { + 1423, /* Code */ + 10415, /* Vendor */ + "Context-Identifier", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Subscriber-Status */ + { + struct dict_avp_data data = { + 1424, /* Code */ + 10415, /* Vendor */ + "Subscriber-Status", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Subscriber-Status)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Operator-Determined-Barring */ + { + struct dict_avp_data data = { + 1425, /* Code */ + 10415, /* Vendor */ + "Operator-Determined-Barring", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Access-Restriction-Data */ + { + struct dict_avp_data data = { + 1426, /* Code */ + 10415, /* Vendor */ + "Access-Restriction-Data", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* APN-OI-Replacement */ + { + struct dict_avp_data data = { + 1427, /* Code */ + 10415, /* Vendor */ + "APN-OI-Replacement", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* All-APN-Configurations-Included-Indicator */ + { + struct dict_avp_data data = { + 1428, /* Code */ + 10415, /* Vendor */ + "All-APN-Configurations-Included-Indicator", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(All-APN-Configurations-Included-Indicator)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* APN-Configuration-Profile */ + { + struct dict_avp_data data = { + 1429, /* Code */ + 10415, /* Vendor */ + "APN-Configuration-Profile", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* APN-Configuration */ + { + struct dict_avp_data data = { + 1430, /* Code */ + 10415, /* Vendor */ + "APN-Configuration", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* EPS-Subscribed-QoS-Profile */ + { + struct dict_avp_data data = { + 1431, /* Code */ + 10415, /* Vendor */ + "EPS-Subscribed-QoS-Profile", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* VPLMN-Dynamic-Address-Allowed */ + { + struct dict_avp_data data = { + 1432, /* Code */ + 10415, /* Vendor */ + "VPLMN-Dynamic-Address-Allowed", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(VPLMN-Dynamic-Address-Allowed)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* STN-SR */ + { + struct dict_avp_data data = { + 1433, /* Code */ + 10415, /* Vendor */ + "STN-SR", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Alert-Reason */ + { + struct dict_avp_data data = { + 1434, /* Code */ + 10415, /* Vendor */ + "Alert-Reason", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Alert-Reason)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* AMBR */ + { + struct dict_avp_data data = { + 1435, /* Code */ + 10415, /* Vendor */ + "AMBR", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* CSG-Subscription-Data */ + { + struct dict_avp_data data = { + 1436, /* Code */ + 10415, /* Vendor */ + "CSG-Subscription-Data", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* CSG-Id */ + { + struct dict_avp_data data = { + 1437, /* Code */ + 10415, /* Vendor */ + "CSG-Id", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* PDN-GW-Allocation-Type */ + { + struct dict_avp_data data = { + 1438, /* Code */ + 10415, /* Vendor */ + "PDN-GW-Allocation-Type", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PDN-GW-Allocation-Type)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Expiration-Date */ + { + struct dict_avp_data data = { + 1439, /* Code */ + 10415, /* Vendor */ + "Expiration-Date", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, Time_type, NULL); + }; + + /* RAT-Frequency-Selection-Priority-ID */ + { + struct dict_avp_data data = { + 1440, /* Code */ + 10415, /* Vendor */ + "RAT-Frequency-Selection-Priority-ID", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* IDA-Flags */ + { + struct dict_avp_data data = { + 1441, /* Code */ + 10415, /* Vendor */ + "IDA-Flags", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* PUA-Flags */ + { + struct dict_avp_data data = { + 1442, /* Code */ + 10415, /* Vendor */ + "PUA-Flags", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* NOR-Flags */ + { + struct dict_avp_data data = { + 1443, /* Code */ + 10415, /* Vendor */ + "NOR-Flags", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* User-Id */ + { + struct dict_avp_data data = { + 1444, /* Code */ + 10415, /* Vendor */ + "User-Id", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* Equipment-Status */ + { + struct dict_avp_data data = { + 1445, /* Code */ + 10415, /* Vendor */ + "Equipment-Status", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Equipment-Status)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Regional-Subscription-Zone-Code */ + { + struct dict_avp_data data = { + 1446, /* Code */ + 10415, /* Vendor */ + "Regional-Subscription-Zone-Code", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* RAND */ + { + struct dict_avp_data data = { + 1447, /* Code */ + 10415, /* Vendor */ + "RAND", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* XRES */ + { + struct dict_avp_data data = { + 1448, /* Code */ + 10415, /* Vendor */ + "XRES", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* AUTN */ + { + struct dict_avp_data data = { + 1449, /* Code */ + 10415, /* Vendor */ + "AUTN", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* KASME */ + { + struct dict_avp_data data = { + 1450, /* Code */ + 10415, /* Vendor */ + "KASME", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Trace-Collection-Entity */ + { + struct dict_avp_data data = { + 1452, /* Code */ + 10415, /* Vendor */ + "Trace-Collection-Entity", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, Address_type, NULL); + }; + + /* Kc */ + { + struct dict_avp_data data = { + 1453, /* Code */ + 10415, /* Vendor */ + "Kc", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* SRES */ + { + struct dict_avp_data data = { + 1454, /* Code */ + 10415, /* Vendor */ + "SRES", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* PDN-Type */ + { + struct dict_avp_data data = { + 1456, /* Code */ + 10415, /* Vendor */ + "PDN-Type", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PDN-Type)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Roaming-Restricted-Due-To-Unsupported-Feature */ + { + struct dict_avp_data data = { + 1457, /* Code */ + 10415, /* Vendor */ + "Roaming-Restricted-Due-To-Unsupported-Feature", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Roaming-Restricted-Due-To-Unsupported-Feature)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Trace-Data */ + { + struct dict_avp_data data = { + 1458, /* Code */ + 10415, /* Vendor */ + "Trace-Data", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Trace-Reference */ + { + struct dict_avp_data data = { + 1459, /* Code */ + 10415, /* Vendor */ + "Trace-Reference", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Trace-Depth */ + { + struct dict_avp_data data = { + 1462, /* Code */ + 10415, /* Vendor */ + "Trace-Depth", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Trace-Depth)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Trace-NE-Type-List */ + { + struct dict_avp_data data = { + 1463, /* Code */ + 10415, /* Vendor */ + "Trace-NE-Type-List", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Trace-Interface-List */ + { + struct dict_avp_data data = { + 1464, /* Code */ + 10415, /* Vendor */ + "Trace-Interface-List", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Trace-Event-List */ + { + struct dict_avp_data data = { + 1465, /* Code */ + 10415, /* Vendor */ + "Trace-Event-List", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* OMC-Id */ + { + struct dict_avp_data data = { + 1466, /* Code */ + 10415, /* Vendor */ + "OMC-Id", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* GPRS-Subscription-Data */ + { + struct dict_avp_data data = { + 1467, /* Code */ + 10415, /* Vendor */ + "GPRS-Subscription-Data", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Complete-Data-List-Included-Indicator */ + { + struct dict_avp_data data = { + 1468, /* Code */ + 10415, /* Vendor */ + "Complete-Data-List-Included-Indicator", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Complete-Data-List-Included-Indicator)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* PDP-Context */ + { + struct dict_avp_data data = { + 1469, /* Code */ + 10415, /* Vendor */ + "PDP-Context", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* PDP-Type */ + { + struct dict_avp_data data = { + 1470, /* Code */ + 10415, /* Vendor */ + "PDP-Type", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* 3GPP2-MEID */ + { + struct dict_avp_data data = { + 1471, /* Code */ + 10415, /* Vendor */ + "3GPP2-MEID", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Specific-APN-Info */ + { + struct dict_avp_data data = { + 1472, /* Code */ + 10415, /* Vendor */ + "Specific-APN-Info", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* LCS-Info */ + { + struct dict_avp_data data = { + 1473, /* Code */ + 10415, /* Vendor */ + "LCS-Info", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* GMLC-Number */ + { + struct dict_avp_data data = { + 1474, /* Code */ + 10415, /* Vendor */ + "GMLC-Number", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* LCS-PrivacyException */ + { + struct dict_avp_data data = { + 1475, /* Code */ + 10415, /* Vendor */ + "LCS-PrivacyException", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* SS-Code */ + { + struct dict_avp_data data = { + 1476, /* Code */ + 10415, /* Vendor */ + "SS-Code", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* SS-Status */ + { + struct dict_avp_data data = { + 1477, /* Code */ + 10415, /* Vendor */ + "SS-Status", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Notification-To-UE-User */ + { + struct dict_avp_data data = { + 1478, /* Code */ + 10415, /* Vendor */ + "Notification-To-UE-User", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Notification-To-UE-User)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* External-Client */ + { + struct dict_avp_data data = { + 1479, /* Code */ + 10415, /* Vendor */ + "External-Client", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Client-Identity */ + { + struct dict_avp_data data = { + 1480, /* Code */ + 10415, /* Vendor */ + "Client-Identity", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* GMLC-Restriction */ + { + struct dict_avp_data data = { + 1481, /* Code */ + 10415, /* Vendor */ + "GMLC-Restriction", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(GMLC-Restriction)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* PLMN-Client */ + { + struct dict_avp_data data = { + 1482, /* Code */ + 10415, /* Vendor */ + "PLMN-Client", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(PLMN-Client)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Service-Type */ + { + struct dict_avp_data data = { + 1483, /* Code */ + 10415, /* Vendor */ + "Service-Type", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* ServiceTypeIdentity */ + { + struct dict_avp_data data = { + 1484, /* Code */ + 10415, /* Vendor */ + "ServiceTypeIdentity", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* MO-LR */ + { + struct dict_avp_data data = { + 1485, /* Code */ + 10415, /* Vendor */ + "MO-LR", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Teleservice-List */ + { + struct dict_avp_data data = { + 1486, /* Code */ + 10415, /* Vendor */ + "Teleservice-List", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* TS-Code */ + { + struct dict_avp_data data = { + 1487, /* Code */ + 10415, /* Vendor */ + "TS-Code", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Call-Barring-Infor-List */ + { + struct dict_avp_data data = { + 1488, /* Code */ + 10415, /* Vendor */ + "Call-Barring-Infor-List", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* SGSN-Number */ + { + struct dict_avp_data data = { + 1489, /* Code */ + 10415, /* Vendor */ + "SGSN-Number", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* IDR-Flags */ + { + struct dict_avp_data data = { + 1490, /* Code */ + 10415, /* Vendor */ + "IDR-Flags", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* ICS-Indicator */ + { + struct dict_avp_data data = { + 1491, /* Code */ + 10415, /* Vendor */ + "ICS-Indicator", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(ICS-Indicator)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* IMS-Voice-Over-PS-Sessions-Supported */ + { + struct dict_avp_data data = { + 1492, /* Code */ + 10415, /* Vendor */ + "IMS-Voice-Over-PS-Sessions-Supported", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(IMS-Voice-Over-PS-Sessions-Supported)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Homogeneous-Support-of-IMS-Voice-Over-PS-Sessions */ + { + struct dict_avp_data data = { + 1493, /* Code */ + 10415, /* Vendor */ + "Homogeneous-Support-of-IMS-Voice-Over-PS-Sessions", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Homogeneous-Support-of-IMS-Voice-Over-PS-Sessions)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Last-UE-Activity-Time */ + { + struct dict_avp_data data = { + 1494, /* Code */ + 10415, /* Vendor */ + "Last-UE-Activity-Time", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, Time_type, NULL); + }; + + /* EPS-User-State */ + { + struct dict_avp_data data = { + 1495, /* Code */ + 10415, /* Vendor */ + "EPS-User-State", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* EPS-Location-Information */ + { + struct dict_avp_data data = { + 1496, /* Code */ + 10415, /* Vendor */ + "EPS-Location-Information", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* MME-User-State */ + { + struct dict_avp_data data = { + 1497, /* Code */ + 10415, /* Vendor */ + "MME-User-State", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* SGSN-User-State */ + { + struct dict_avp_data data = { + 1498, /* Code */ + 10415, /* Vendor */ + "SGSN-User-State", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* User-State */ + { + struct dict_avp_data data = { + 1499, /* Code */ + 10415, /* Vendor */ + "User-State", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(User-State)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* MME-LocationInformation */ + { + struct dict_avp_data data = { + 1600, /* Code */ + 10415, /* Vendor */ + "MME-LocationInformation", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* SGSN-Location-Information */ + { + struct dict_avp_data data = { + 1601, /* Code */ + 10415, /* Vendor */ + "SGSN-Location-Information", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* E-UTRAN-Cell-Global-Identity */ + { + struct dict_avp_data data = { + 1602, /* Code */ + 10415, /* Vendor */ + "E-UTRAN-Cell-Global-Identity", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Tracking-Area-Identity */ + { + struct dict_avp_data data = { + 1603, /* Code */ + 10415, /* Vendor */ + "Tracking-Area-Identity", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Cell-Global-Identity */ + { + struct dict_avp_data data = { + 1604, /* Code */ + 10415, /* Vendor */ + "Cell-Global-Identity", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Routing-Area-Identity */ + { + struct dict_avp_data data = { + 1605, /* Code */ + 10415, /* Vendor */ + "Routing-Area-Identity", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Location-Area-Identity */ + { + struct dict_avp_data data = { + 1606, /* Code */ + 10415, /* Vendor */ + "Location-Area-Identity", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Service-Area-Identity */ + { + struct dict_avp_data data = { + 1607, /* Code */ + 10415, /* Vendor */ + "Service-Area-Identity", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Geographical-Information */ + { + struct dict_avp_data data = { + 1608, /* Code */ + 10415, /* Vendor */ + "Geographical-Information", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Geodetic-Information */ + { + struct dict_avp_data data = { + 1609, /* Code */ + 10415, /* Vendor */ + "Geodetic-Information", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Current-Location-Retrieved */ + { + struct dict_avp_data data = { + 1610, /* Code */ + 10415, /* Vendor */ + "Current-Location-Retrieved", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Current-Location-Retrieved)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Age-Of-Location-Information */ + { + struct dict_avp_data data = { + 1611, /* Code */ + 10415, /* Vendor */ + "Age-Of-Location-Information", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Active-APN */ + { + struct dict_avp_data data = { + 1612, /* Code */ + 10415, /* Vendor */ + "Active-APN", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Error-Diagnostic */ + { + struct dict_avp_data data = { + 1614, /* Code */ + 10415, /* Vendor */ + "Error-Diagnostic", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Error-Diagnostic)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Ext-PDP-Address */ + { + struct dict_avp_data data = { + 1621, /* Code */ + 10415, /* Vendor */ + "Ext-PDP-Address", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, Address_type, NULL); + }; + + /* UE-SRVCC-Capability */ + { + struct dict_avp_data data = { + 1615, /* Code */ + 10415, /* Vendor */ + "UE-SRVCC-Capability", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(UE-SRVCC-Capability)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* MPS-Priority */ + { + struct dict_avp_data data = { + 1616, /* Code */ + 10415, /* Vendor */ + "MPS-Priority", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* VPLMN-LIPA-Allowed */ + { + struct dict_avp_data data = { + 1617, /* Code */ + 10415, /* Vendor */ + "VPLMN-LIPA-Allowed", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(VPLMN-LIPA-Allowed)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* LIPA-Permission */ + { + struct dict_avp_data data = { + 1618, /* Code */ + 10415, /* Vendor */ + "LIPA-Permission", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(LIPA-Permission)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Subscribed-Periodic-RAU-TAU-Timer */ + { + struct dict_avp_data data = { + 1619, /* Code */ + 10415, /* Vendor */ + "Subscribed-Periodic-RAU-TAU-Timer", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Ext-PDP-Type */ + { + struct dict_avp_data data = { + 1620, /* Code */ + 10415, /* Vendor */ + "Ext-PDP-Type", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* SIPTO-Permission */ + { + struct dict_avp_data data = { + 1613, /* Code */ + 10415, /* Vendor */ + "SIPTO-Permission", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SIPTO-Permission)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* MDT-Configuration */ + { + struct dict_avp_data data = { + 1622, /* Code */ + 10415, /* Vendor */ + "MDT-Configuration", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Job-Type */ + { + struct dict_avp_data data = { + 1623, /* Code */ + 10415, /* Vendor */ + "Job-Type", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Job-Type)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Area-Scope */ + { + struct dict_avp_data data = { + 1624, /* Code */ + 10415, /* Vendor */ + "Area-Scope", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* List-Of-Measurements */ + { + struct dict_avp_data data = { + 1625, /* Code */ + 10415, /* Vendor */ + "List-Of-Measurements", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Reporting-Trigger */ + { + struct dict_avp_data data = { + 1626, /* Code */ + 10415, /* Vendor */ + "Reporting-Trigger", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Report-Interval */ + { + struct dict_avp_data data = { + 1627, /* Code */ + 10415, /* Vendor */ + "Report-Interval", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Report-Interval)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Report-Amount */ + { + struct dict_avp_data data = { + 1628, /* Code */ + 10415, /* Vendor */ + "Report-Amount", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Report-Amount)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Event-Threshold-RSRP */ + { + struct dict_avp_data data = { + 1629, /* Code */ + 10415, /* Vendor */ + "Event-Threshold-RSRP", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Event-Threshold-RSRQ */ + { + struct dict_avp_data data = { + 1630, /* Code */ + 10415, /* Vendor */ + "Event-Threshold-RSRQ", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Logging-Interval */ + { + struct dict_avp_data data = { + 1631, /* Code */ + 10415, /* Vendor */ + "Logging-Interval", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Logging-Interval)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Logging-Duration */ + { + struct dict_avp_data data = { + 1632, /* Code */ + 10415, /* Vendor */ + "Logging-Duration", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Logging-Duration)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Relay-Node-Indicator */ + { + struct dict_avp_data data = { + 1633, /* Code */ + 10415, /* Vendor */ + "Relay-Node-Indicator", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Relay-Node-Indicator)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* MDT-User-Consent */ + { + struct dict_avp_data data = { + 1634, /* Code */ + 10415, /* Vendor */ + "MDT-User-Consent", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(MDT-User-Consent)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* PUR-Flags */ + { + struct dict_avp_data data = { + 1635, /* Code */ + 10415, /* Vendor */ + "PUR-Flags", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Subscribed-VSRVCC */ + { + struct dict_avp_data data = { + 1636, /* Code */ + 10415, /* Vendor */ + "Subscribed-VSRVCC", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Subscribed-VSRVCC)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Equivalent-PLMN-List */ + { + struct dict_avp_data data = { + 1637, /* Code */ + 10415, /* Vendor */ + "Equivalent-PLMN-List", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* CLR-Flags */ + { + struct dict_avp_data data = { + 1638, /* Code */ + 10415, /* Vendor */ + "CLR-Flags", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* UVR-Flags */ + { + struct dict_avp_data data = { + 1639, /* Code */ + 10415, /* Vendor */ + "UVR-Flags", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* UVA-Flags */ + { + struct dict_avp_data data = { + 1640, /* Code */ + 10415, /* Vendor */ + "UVA-Flags", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* VPLMN-CSG-Subscription-Data */ + { + struct dict_avp_data data = { + 1641, /* Code */ + 10415, /* Vendor */ + "VPLMN-CSG-Subscription-Data", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Time-Zone */ + { + struct dict_avp_data data = { + 1642, /* Code */ + 10415, /* Vendor */ + "Time-Zone", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* A-MSISDN */ + { + struct dict_avp_data data = { + 1643, /* Code */ + 10415, /* Vendor */ + "A-MSISDN", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* MME-Number-for-MT-SMS */ + { + struct dict_avp_data data = { + 1645, /* Code */ + 10415, /* Vendor */ + "MME-Number-for-MT-SMS", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* SMS-Register-Request */ + { + struct dict_avp_data data = { + 1648, /* Code */ + 10415, /* Vendor */ + "SMS-Register-Request", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(SMS-Register-Request)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Local-Time-Zone */ + { + struct dict_avp_data data = { + 1649, /* Code */ + 10415, /* Vendor */ + "Local-Time-Zone", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Daylight-Saving-Time */ + { + struct dict_avp_data data = { + 1650, /* Code */ + 10415, /* Vendor */ + "Daylight-Saving-Time", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Daylight-Saving-Time)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Subscription-Data-Flags */ + { + struct dict_avp_data data = { + 1654, /* Code */ + 10415, /* Vendor */ + "Subscription-Data-Flags", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Measurement-Period-UMTS */ + { + struct dict_avp_data data = { + 1655, /* Code */ + 10415, /* Vendor */ + "Measurement-Period-UMTS", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Measurement-Period-UMTS)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Measurement-Period-LTE */ + { + struct dict_avp_data data = { + 1656, /* Code */ + 10415, /* Vendor */ + "Measurement-Period-LTE", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Measurement-Period-LTE)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Collection-Period-RRM-LTE */ + { + struct dict_avp_data data = { + 1657, /* Code */ + 10415, /* Vendor */ + "Collection-Period-RRM-LTE", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Collection-Period-RRM-LTE)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Collection-Period-RRM-UMTS */ + { + struct dict_avp_data data = { + 1658, /* Code */ + 10415, /* Vendor */ + "Collection-Period-RRM-UMTS", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + struct dict_object *type; + struct dict_type_data tdata = { AVP_TYPE_INTEGER32, "3GPP/Enumerated(Collection-Period-RRM-UMTS)", NULL, NULL, NULL }; + CHECK_dict_new(DICT_TYPE, &tdata, NULL, &type); + CHECK_dict_new(DICT_AVP, &data, type, NULL); + }; + + /* Positioning-Method */ + { + struct dict_avp_data data = { + 1659, /* Code */ + 10415, /* Vendor */ + "Positioning-Method", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Measurement-Quantity */ + { + struct dict_avp_data data = { + 1660, /* Code */ + 10415, /* Vendor */ + "Measurement-Quantity", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Event-Threshold-Event-1F */ + { + struct dict_avp_data data = { + 1661, /* Code */ + 10415, /* Vendor */ + "Event-Threshold-Event-1F", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Event-Threshold-Event-1I */ + { + struct dict_avp_data data = { + 1662, /* Code */ + 10415, /* Vendor */ + "Event-Threshold-Event-1I", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_INTEGER32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + /* 3GPP 29.329-b50 (11.5.0 2012.12.21) */ /* User-Identity */ { @@ -6750,12 +9852,12 @@ }; /* Name conflict with 29.229 User-Data (606), renamed */ - /* User-Data-Sh */ + /* User-Data-29.329 */ { struct dict_avp_data data = { 702, /* Code */ 10415, /* Vendor */ - "User-Data-Sh", /* Name */ + "User-Data-29.329", /* Name */ AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ AVP_TYPE_OCTETSTRING /* base type of data */ @@ -7006,6 +10108,653 @@ CHECK_dict_new(DICT_AVP, &data, NULL, NULL); }; + /* OMA DDS Charging_Data V1.0 20110201-A */ + /* Application-Server-Id */ + { + struct dict_avp_data data = { + 2101, /* Code */ + 10415, /* Vendor */ + "Application-Server-Id", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* Application-Service-Type */ + { + struct dict_avp_data data = { + 2102, /* Code */ + 10415, /* Vendor */ + "Application-Service-Type", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* Application-Session-Id */ + { + struct dict_avp_data data = { + 2103, /* Code */ + 10415, /* Vendor */ + "Application-Session-Id", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* Content-ID */ + { + struct dict_avp_data data = { + 2116, /* Code */ + 10415, /* Vendor */ + "Content-ID", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* Content-provider-ID */ + { + struct dict_avp_data data = { + 2117, /* Code */ + 10415, /* Vendor */ + "Content-provider-ID", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* DCD-Information */ + { + struct dict_avp_data data = { + 2115, /* Code */ + 10415, /* Vendor */ + "DCD-Information", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Delivery-Status */ + { + struct dict_avp_data data = { + 2104, /* Code */ + 10415, /* Vendor */ + "Delivery-Status", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL); + }; + + /* IM-Information */ + { + struct dict_avp_data data = { + 2110, /* Code */ + 10415, /* Vendor */ + "IM-Information", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Number-Of-Messages-Successfully-Exploded */ + { + struct dict_avp_data data = { + 2111, /* Code */ + 10415, /* Vendor */ + "Number-Of-Messages-Successfully-Exploded", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Number-Of-Messages-Successfully-Sent */ + { + struct dict_avp_data data = { + 2112, /* Code */ + 10415, /* Vendor */ + "Number-Of-Messages-Successfully-Sent", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Service-Generic-Information */ + { + struct dict_avp_data data = { + 1256, /* Code */ + 10415, /* Vendor */ + "Service-Generic-Information", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_GROUPED /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Total-Number-Of-Messages-Exploded */ + { + struct dict_avp_data data = { + 2113, /* Code */ + 10415, /* Vendor */ + "Total-Number-Of-Messages-Exploded", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* Total-Number-Of-Messages-Sent */ + { + struct dict_avp_data data = { + 2114, /* Code */ + 10415, /* Vendor */ + "Total-Number-Of-Messages-Sent", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flag values */ + AVP_TYPE_UNSIGNED32 /* base type of data */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + + + /*****************************************************/ + /* end of generated data, rules below added manually */ + /*****************************************************/ + + + + /* 3GPP2-BSID */ + { + struct dict_avp_data data = { + 9010, /* Code */ + 5535, /* Vendor */ + "3GPP2-BSID", /* Name */ + AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY, /* Fixed flags */ + AVP_FLAG_VENDOR, /* Fixed flag values */ + AVP_TYPE_OCTETSTRING /* base type of data */ /* XXX: guessed */ + }; + CHECK_dict_new(DICT_AVP, &data, NULL, NULL); + }; + + /* 29.212 */ + + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "Allocation-Retention-Priority"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "Priority-Level" }, RULE_REQUIRED, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Pre-emption-Capability" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Pre-emption-Vulnerability" }, RULE_OPTIONAL, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "QoS-Information"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "QoS-Class-Identifier" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Max-Requested-Bandwidth-UL" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Max-Requested-Bandwidth-DL" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Guaranteed-Bitrate-UL" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Guaranteed-Bitrate-DL" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Bearer-Identifier" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Allocation-Retention-Priority" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "APN-Aggregate-Max-Bitrate-UL" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "APN-Aggregate-Max-Bitrate-DL" }, RULE_OPTIONAL, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + /* 32.299 */ + + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "Application-Server-Information"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "Application-Server" }, RULE_REQUIRED, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Application-Provided-Called-Party-Address" }, RULE_OPTIONAL, -1, -1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "Envelope"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "Envelope-Start-Time" }, RULE_REQUIRED, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Envelope-End-Time" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 0, .avp_name = "CC-Total-Octets" }, RULE_REQUIRED, -1, 1 }, + { { .avp_vendor = 0, .avp_name = "CC-Input-Octets" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 0, .avp_name = "CC-Output-Octets" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 0, .avp_name = "CC-Service-Specific-Units" }, RULE_OPTIONAL, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "IMS-Information"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "Event-Type" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Role-Of-Node" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Node-Functionality" }, RULE_REQUIRED, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "User-Session-Id" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Outgoing-Session-Id" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Session-Priority" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Calling-Party-Address" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Called-Party-Address" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Called-Asserted-Identity" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Number-Portability-Routing-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Carrier-Select-Routing-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Alternate-Charged-Party-Address" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Requested-Party-Address" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Associated-URI" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Time-Stamps" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Application-Server-Information" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Inter-Operator-Identifier" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Transit-IOI-List" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "IMS-Charging-Identifier" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "SDP-Session-Description" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "SDP-Media-Component" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Served-Party-IP-Address" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Server-Capabilities" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Trunk-Group-Id" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Bearer-Service" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Service-Id" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Service-Specific-Info" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Message-Body" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Cause-Code" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Access-Network-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Early-Media-Description" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "IMS-Communication-Service-Identifier" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "IMS-Application-Reference-Identifier" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Online-Charging-Flag" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Real-Time-Tariff-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Account-Expiration" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Initial-IMS-Charging-Identifier" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "NNI-Information" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "From-Address" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "IMS-Emergency-Indicator" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Access-Transfer-Information" }, RULE_OPTIONAL, -1, -1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "MMS-Information"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "Originator-Address" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Recipient-Address" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Submission-Time" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "MM-Content-Type" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Priority" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Message-ID" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Message-Type" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Message-Size" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Message-Class" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Delivery-Report-Requested" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Read-Reply-Report-Requested" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "MMBox-Storage-Requested" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Applic-ID" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Reply-Applic-ID" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Aux-Applic-Info" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Content-Class" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "DRM-Content" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Adaptations" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "VASP-ID" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "VAS-ID" }, RULE_OPTIONAL, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + { + /* Multiple-Services-Credit-Control */ + /* additional allowed AVPs */ + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 0; + vpa.avp_name = "Multiple-Services-Credit-Control"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "Time-Quota-Threshold" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Volume-Quota-Threshold" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Unit-Quota-Threshold" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Quota-Holding-Time" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Quota-Consumption-Time" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Reporting-Reason" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Trigger" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "PS-Furnish-Charging-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Refund-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "AF-Correlation-Information" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Envelope" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Envelope-Reporting" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Time-Quota-Mechanism" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Service-Specific-Info" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "QoS-Information" }, RULE_OPTIONAL, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "Offline-Charging"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "Quota-Consumption-Time" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Time-Quota-Mechanism" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Envelope-Reporting" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 0, .avp_name = "Multiple-Services-Credit-Control" }, RULE_OPTIONAL, -1, -1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "Originator-Address"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "Address-Type" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Address-Data" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Address-Domain" }, RULE_OPTIONAL, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "PS-Furnish-Charging-Information"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Id" }, RULE_REQUIRED, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "PS-Free-Format-Data" }, RULE_REQUIRED, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "PS-Append-Free-Format-Data" }, RULE_OPTIONAL, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "PS-Information"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Id" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "PDN-Connection-Charging-ID" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Node-Id" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "3GPP-PDP-Type" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "PDP-Address" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "PDP-Address-Prefix-Length" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Dynamic-Address-Flag" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Dynamic-Address-Flag-Extension" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "QoS-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "SGSN-Address" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "GGSN-Address" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "SGW-Address" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "CG-Address" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Serving-Node-Type" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "SGW-Change" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "3GPP-IMSI-MCC-MNC" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "IMSI-Unauthenticated-Flag" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "3GPP-GGSN-MCC-MNC" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "3GPP-NSAPI" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 0, .avp_name = "Called-Station-Id" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "3GPP-Session-Stop-Indicator" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "3GPP-Selection-Mode" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Characteristics" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Charging-Characteristics-Selection-Mode" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "3GPP-SGSN-MCC-MNC" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "3GPP-MS-TimeZone" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Charging-Rule-Base-Name" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "3GPP-User-Location-Info" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "User-CSG-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 5535, .avp_name = "3GPP2-BSID" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "3GPP-RAT-Type" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "PS-Furnish-Charging-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "PDP-Context-Type" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Offline-Charging" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Traffic-Data-Volumes" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Service-Data-Container" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 0, .avp_name = "User-Equipment-Info" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Terminal-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Start-Time" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Stop-Time" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Change-Condition" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Diagnostics" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Low-Priority-Indicator" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "MME-Number-for-MT-SMS" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "MME-Name" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "MME-Realm" }, RULE_OPTIONAL, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "Recipient-Address"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "Address-Type" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Address-Data" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Address-Domain" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Addressee-Type" }, RULE_OPTIONAL, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "SDP-Media-Component"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "SDP-Media-Name" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "SDP-Media-Description" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Local-GW-Inserted-Indication" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "IP-Realm-Default-Indication" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Transcoder-Inserted-Indication" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Media-Initiator-Flag" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Media-Initiator-Party" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "3GPP-Charging-Id" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Access-Network-Charging-Identifier-Value" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "SDP-Type" }, RULE_OPTIONAL, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "Service-Information"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 0, .avp_name = "Subscription-Id" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "AoC-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "PS-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "WLAN-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "IMS-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "MMS-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "LCS-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "PoC-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "MBMS-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "SMS-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "MMTel-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Service-Generic-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "IM-Information" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "DCD-Information" }, RULE_OPTIONAL, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "SMS-Information"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "SMS-Node" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Client-Address" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Originator-SCCP-Address" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "SMSC-Address" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Data-Coding-Scheme" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "SM-Discharge-Time" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "SM-Message-Type" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Originator-Interface" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "SM-Protocol-ID" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Reply-Path-Requested" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "SM-Status" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "SM-User-Data-Header" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Number-Of-Messages-Sent" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Recipient-Info" }, RULE_OPTIONAL, -1, -1 }, + { { .avp_vendor = 10415, .avp_name = "Originator-Received-Address" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "SM-Service-Type" }, RULE_OPTIONAL, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "Time-Quota-Mechanism"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "Time-Quota-Type" }, RULE_REQUIRED, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Base-Time-Interval" }, RULE_REQUIRED, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "Time-Stamps"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "SIP-Request-Timestamp" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "SIP-Response-Timestamp" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "SIP-Request-Timestamp-Fraction" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "SIP-Response-Timestamp-Fraction" }, RULE_OPTIONAL, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + + /* OMA */ + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "DCD-Information"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "Content-ID" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Content-provider-ID" }, RULE_OPTIONAL, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "IM-Information"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "Total-Number-Of-Messages-Sent" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Total-Number-Of-Messages-Exploded" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Number-Of-Messages-Successfully-Sent" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Number-Of-Messages-Successfully-Exploded" }, RULE_OPTIONAL, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } + { + struct dict_object *rule_avp; + struct dict_avp_request vpa; + vpa.avp_vendor = 10415; + vpa.avp_name = "Service-Generic-Information"; + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp); + struct local_rules_definition rules[] = + { + { { .avp_vendor = 10415, .avp_name = "Application-Server-Id" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Application-Service-Type" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Application-Session-Id" }, RULE_OPTIONAL, -1, 1 }, + { { .avp_vendor = 10415, .avp_name = "Delivery-Status" }, RULE_OPTIONAL, -1, 1 }, + }; + PARSE_loc_rules(rules, rule_avp); + } TRACE_DEBUG(INFO, "Extension 'Dictionary definitions for DCCA 3GPP' initialized"); return 0;
--- a/extensions/dict_dcca_3gpp/dict_dcca_3gpp.org Fri May 10 09:50:09 2013 +0800 +++ b/extensions/dict_dcca_3gpp/dict_dcca_3gpp.org Fri May 10 18:49:19 2013 +0800 @@ -75,7 +75,46 @@ | MBMS-Flow-Identifier | 920 | 17.7.23 | OctetString | M,V | P | | | | | CN-IP-Multicast-Distribution | 921 | 17.7.24 | Enumerated | M,V | P | | | | | MBMS-HC-Indicator | 922 | 17.7.25 | Enumerated | M,V | P | | | | -| # 3GPP 29.212-b70 (11.7.0 2012.12.20) | | | | | | | | | +| # 3GPP 29.140-700 (7.0.0 2007.07.05) | | | | | | | | | +| Served-User-Identity | 1100 | 6.3.1 | Grouped | M,V | | | | N | +| # reuses: MSISDN | 701 | 6.3.2 | OctetString | M,V | | | | N | +| VASP-ID | 1101 | 6.3.3 | UTF8String | M,V | | | | N | +| VAS-ID | 1102 | 6.3.4 | UTF8String | M,V | | | | N | +| Trigger-Event | 1103 | 6.3.5 | Enumerated | M,V | | | | N | +| # reuses: 3GPP-IMSI | 1 | 6.3.6 | UTF8String | M,V | | | | N | +| Sender-Address | 1104 | 6.3.7 | UTF8String | M,V | | | | N | +| Initial-Recipient-Address | 1105 | 6.3.8 | Grouped | M,V | | | | N | +| Result-Recipient-Address | 1106 | 6.3.9 | Grouped | M,V | | | | N | +| # conflicts with one in (more common) 32.329 | | | | | | | | | +| Sequence-Number-29.140 | 1107 | 6.3.10 | Unsigned32 | M,V | | | | N | +| # conflicts with one in (more common) 32.299 | | | | | | | | | +| Recipient-Address-29.140 | 1108 | 6.3.11 | UTF8String | M,V | | | | N | +| Routeing-Address | 1109 | 6.3.12 | UTF8String | M,V | | | | N | +| Originating-Interface | 1110 | 6.3.13 | Enumerated | M,V | | | | N | +| Delivery-Report | 1111 | 6.3.14 | Enumerated | M,V | | | | N | +| Read-Reply | 1112 | 6.3.15 | Enumerated | M,V | | | | N | +| Sender-Visibility | 1113 | 6.3.16 | Enumerated | M,V | | | | N | +| Service-Key | 1114 | 6.3.17 | UTF8String | M,V | | | | N | +| Billing-Information | 1115 | 6.3.18 | UTF8String | M,V | | | | N | +| # conflicts with one in (more common) 32.299 | | | | | | | | | +| Status-29.140 | 1116 | 6.3.19 | Grouped | M,V | | | | N | +| Status-Code | 1117 | 6.3.20 | UTF8String | M,V | | | | N | +| Status-Text | 1118 | 6.3.21 | UTF8String | M,V | | | | N | +| Routeing-Address-Resolution | 1119 | 6.3.22 | Enumerated | M,V | | | | N | +| # 3GPP 29.173-c00 (12.0.0 2013.03.13) | | | | | | | | | +| LMSI | 2400 | 6.4.2 | OctetString | M,V | | | | N | +| Serving-Node | 2401 | 6.4.3 | Grouped | M,V | | | | N | +| MME-Name | 2402 | 6.4.4 | DiameterIdentity | M,V | | | | N | +| MSC-Number | 2403 | 6.4.5 | OctetString | M,V | | | | N | +| LCS-Capabilities-Sets | 2404 | 6.4.6 | Unsigned32 | M,V | | | | N | +| GMLC-Address | 2405 | 6.4.7 | Address | M,V | | | | N | +| Additional-Serving-Node | 2406 | 6.4.8 | Grouped | M,V | | | | N | +| PPR-Address | 2407 | 6.4.9 | Address | M,V | | | | N | +| MME-Realm | 2408 | 6.4.12 | DiameterIdentity | V | | | M | N | +| SGSN-Name | 2409 | 6.4.13 | DiameterIdentity | V | | | M | N | +| SGSN-Realm | 2410 | 6.4.14 | DiameterIdentity | V | | | M | N | +| # 3GPP 29.212-c00 (12.0.0 2013.03.15) | | | | | | | | | +| # Gx-specific | | | | | | | | | | ADC-Revalidation-Time | 2801 | 5.3.93 | Time | V | P | | M | Y | | ADC-Rule-Install | 1092 | 5.3.85 | Grouped | V | P | | M | Y | | ADC-Rule-Remove | 1093 | 5.3.86 | Grouped | V | P | | M | Y | @@ -112,7 +151,6 @@ | IP-CAN-Type | 1027 | 5.3.27 | Enumerated | M,V | P | | | Y | | Guaranteed-Bitrate-DL | 1025 | 5.3.25 | Unsigned32 | M,V | P | | | Y | | Guaranteed-Bitrate-UL | 1026 | 5.3.26 | Unsigned32 | M,V | P | | | Y | -| HeNB-BBF-FQDN | 2803 | 5.3.94 | UTF8String | V | P | | M | Y | | HeNB-Local-IP-Address | 2804 | 5.3.95 | Address | V | P | | M | Y | | Metering-Method | 1007 | 5.3.8 | Enumerated | M,V | P | | | Y | | Monitoring-Key | 1066 | 5.3.59 | OctetString | V | P | | M | Y | @@ -132,7 +170,7 @@ | Pre-emption-Vulnerability | 1048 | 5.3.47 | Enumerated | V | P | | M | Y | | Priority-Level | 1046 | 5.3.45 | Unsigned32 | V | P | | M | Y | | Redirect-Information | 1085 | 5.3.82 | Grouped | V | P | | M | Y | -| Redirect- Support | 1086 | 5.3.83 | Enumerated | V | P | | M | Y | +| Redirect-Support | 1086 | 5.3.83 | Enumerated | V | P | | M | Y | | Reporting-Level | 1011 | 5.3.12 | Enumerated | M,V | P | | | Y | | Routing-Filter | 1078 | 5.3.72 | Grouped | V | P | | M | Y | | Routing-IP-Address | 1079 | 5.3.73 | Address | V | P | | M | Y | @@ -147,11 +185,11 @@ | TDF-Application-Instance-Identifier | 2802 | 5.3.92 | OctetString | V | P | | M | Y | | TDF-Destination-Host | 1089 | 5.3.80 | DiameterIdentity | V | P | | M | Y | | TDF-Destination-Realm | 1090 | 5.3.79 | DiameterIdentity | V | P | | M | Y | -| TDF-IP-address | 1091 | 5.3.81 | Address | V | P | | M | Y | +| TDF-IP-Address | 1091 | 5.3.81 | Address | V | P | | M | Y | | QoS-Class-Identifier | 1028 | 5.3.17 | Enumerated | M,V | P | | | Y | | QoS-Information | 1016 | 5.3.16 | Grouped | M.V | P | | | Y | | QoS-Negotiation | 1029 | 5.3.28 | Enumerated | M,V | P | | | Y | -| Qos-Upgrade | 1030 | 5.3.29 | Enumerated | M.V | P | | | Y | +| QoS-Upgrade | 1030 | 5.3.29 | Enumerated | M.V | P | | | Y | | PS-to-CS-Session-Continuity | 1099 | 5.3.84 | Enumerated | V | P | | | Y | | Resource-Allocation-Notification | 1063 | 5.3.50 | Enumerated | V | P | | M | Y | | Rule-Failure-Code | 1031 | 5.3.38 | Enumerated | M.V | P | | | Y | @@ -168,10 +206,11 @@ | UDP-Source-Port | 2806 | 5.3.97 | Unsigned32 | V | P | | M | Y | | UE-Local-IP-Address | 2805 | 5.3.96 | Address | V | P | | M | Y | | Usage-Monitoring-Information | 1067 | 5.3.60 | Grouped | V | P | | M | Y | -| Rule-DeActivation-Time | 1044 | 5.3.43 | Time | M,V | P | | | Y | +| Rule-Deactivation-Time | 1044 | 5.3.43 | Time | M,V | P | | | Y | | Usage-Monitoring-Level | 1068 | 5.3.61 | Enumerated | V | P | | M | Y | | Usage-Monitoring-Report | 1069 | 5.3.62 | Enumerated | V | P | | M | Y | | Usage-Monitoring-Support | 1070 | 5.3.63 | Enumerated | V | P | | M | Y | +| # Gxx-specific | | | | | | | | | | QoS-Rule-Install | 1051 | 5a.3.1 | Grouped | M,V | P | | | Y | | QoS-Rule-Remove | 1052 | 5a.3.2 | Grouped | M,V | P | | | Y | | QoS-Rule-Definition | 1053 | 5a.3.3 | Grouped | M,V | P | | | Y | @@ -179,8 +218,45 @@ | QoS-Rule-Base-Name | 1074 | 5a.3.7 | UTF8String | V | P | | M | Y | | QoS-Rule-Report | 1055 | 5a.3.5 | Grouped | M,V | P | | | Y | | Session-Linking-Indicator | 1064 | 5a.3.6 | Enumerated | M,V | P | | | Y | +| # S15-specific | | | | | | | | | | CS-Service-Qos-Request-Identifier | 2807 | E.6.3.2 | OctetString | M,V | P | | | Y | | CS-Service-QoS-Request-Operation | 2808 | E.6.3.3 | Enumerated | M.V | P | | | Y | +| # 3GPP 29.214-b80 (11.8.0 2013.03.15) | | | | | | | | | +| Abort-Cause | 500 | 5.3.1 | Enumerated | M,V | P | | | Y | +| Access-Network-Charging-Address | 501 | 5.3.2 | Address | M,V | P | | | Y | +| Access-Network-Charging-Identifier | 502 | 5.3.3 | Grouped | M,V | P | | | Y | +| Access-Network-Charging-Identifier-Value | 503 | 5.3.4 | OctetString | M,V | P | | | Y | +| Acceptable-Service-Info | 526 | 5.3.24 | Grouped | M,V | P | | | Y | +| AF-Application-Identifier | 504 | 5.3.5 | OctetString | M,V | P | | | Y | +| AF-Charging-Identifier | 505 | 5.3.6 | OctetString | M,V | P | | | Y | +| Application-Service-Provider-Identity | 532 | 5.3.29 | UTF8String | V | P | | M | Y | +| Codec-Data | 524 | 5.3.7 | OctetString | M,V | P | | | Y | +| Flow-Description | 507 | 5.3.8 | IPFilterRule | M,V | P | | | Y | +| Flow-Number | 509 | 5.3.9 | Unsigned32 | M,V | P | | | Y | +| Flows | 510 | 5.3.10 | Grouped | M,V | P | | | Y | +| Flow-Status | 511 | 5.3.11 | Enumerated | M,V | P | | | Y | +| Flow-Usage | 512 | 5.3.12 | Enumerated | M,V | P | | | Y | +| Service-URN | 525 | 5.3.23 | OctetString | M,V | P | | | Y | +| Specific-Action | 513 | 5.3.13 | Enumerated | M,V | P | | | Y | +| Max-Requested-Bandwidth-DL | 515 | 5.3.14 | Unsigned32 | M,V | P | | | Y | +| Max-Requested-Bandwidth-UL | 516 | 5.3.15 | Unsigned32 | M,V | P | | | Y | +| Media-Component-Description | 517 | 5.3.16 | Grouped | M,V | P | | | Y | +| Media-Component-Number | 518 | 5.3.17 | Unsigned32 | M,V | P | | | Y | +| Media-Sub-Component | 519 | 5.3.18 | Grouped | M,V | P | | | Y | +| Media-Type | 520 | 5.3.19 | Enumerated | M,V | P | | | Y | +| MPS-Identifier | 528 | 5.3.30 | OctetString | V | P | | M | Y | +| Min-Requested-Bandwidth-DL | 534 | 5.3.32 | Unsigned32 | V | P | | M | Y | +| Min-Requested-Bandwidth-UL | 535 | 5.3.33 | Unsigned32 | V | P | | M | Y | +| RR-Bandwidth | 521 | 5.3.20 | Unsigned32 | M,V | P | | | Y | +| RS-Bandwidth | 522 | 5.3.21 | Unsigned32 | M,V | P | | | Y | +| Service-Info-Status | 527 | 5.3.25 | Enumerated | M,V | P | | | Y | +| SIP-Forking-Indication | 523 | 5.3.22 | Enumerated | M,V | P | | | Y | +| Sponsor-Identity | 531 | 5.3.28 | UTF8String | V | P | | M | Y | +| Sponsored-Connectivity-Data | 530 | 5.3.27 | Grouped | V | P | | M | Y | +| AF-Signalling-Protocol | 529 | 5.3.26 | Enumerated | V | P | | M | Y | +| Required-Access-Info | 536 | 5.3.34 | Enumerated | V | P | | M | Y | +| Rx-Request-Type | 533 | 5.3.31 | Enumerated | V | P | | M | Y | +| IP-Domain-Id | 537 | 5.3.35 | OctetString | V | P | | M | Y | | # 3GPP 29.229-b20 (11.2.0 2012.12.21) | | | | | | | | | | Associated-Identities | 632 | 6.3.33 | Grouped | V | | | M | N | | Associated-Registered-Identities | 647 | 6.3.50 | Grouped | V | | | M | N | @@ -264,7 +340,7 @@ | Applic-ID | 1218 | | UTF8String | M,V | P | | | N | | Application-Server | 836 | | UTF8String | M,V | P | | | N | | Application-Server-Information | 850 | | Grouped | M,V | P | | | N | -| Application-provided-called-party-address | 837 | | UTF8String | M,V | P | | | N | +| Application-Provided-Called-Party-Address | 837 | | UTF8String | M,V | P | | | N | | Associated-Party-Address | 2035 | | UTF8String | M,V | P | | | N | | Associated-URI | 856 | | UTF8String | M,V | P | | | N | | Aux-Applic-Info | 1219 | | UTF8String | M,V | P | | | N | @@ -509,11 +585,165 @@ | WLAN-Session-Id | 1246 | | UTF8String | M,V | P | | | N | | WLAN-Technology | 893 | | Unsigned32 | M,V | P | | | N | | WLAN-UE-Local-IPAddress | 894 | | Address | M,V | P | | | N | +| # 3GPP 29.272-c00 (12.0.0 2013.03.13) | | | | | | | | | +| Subscription-Data | 1400 | 7.3.2 | Grouped | M,V | | | | N | +| Terminal-Information | 1401 | 7.3.3 | Grouped | M,V | | | | N | +| IMEI | 1402 | 7.3.4 | UTF8String | M,V | | | | N | +| Software-Version | 1403 | 7.3.5 | UTF8String | M,V | | | | N | +| QoS-Subscribed | 1404 | 7.3.77 | OctetString | M,V | | | | N | +| ULR-Flags | 1405 | 7.3.7 | Unsigned32 | M,V | | | | N | +| ULA-Flags | 1406 | 7.3.8 | Unsigned32 | M,V | | | | N | +| Visited-PLMN-Id | 1407 | 7.3.9 | OctetString | M,V | | | | N | +| Requested-EUTRAN-Authentication-Info | 1408 | 7.3.11 | Grouped | M,V | | | | N | +| Requested-UTRAN- GERAN-Authentication-Info | 1409 | 7.3.12 | Grouped | M,V | | | | N | +| Number-Of-Requested-Vectors | 1410 | 7.3.14 | Unsigned32 | M,V | | | | N | +| Re-Synchronization-Info | 1411 | 7.3.15 | OctetString | M,V | | | | N | +| Immediate-Response-Preferred | 1412 | 7.3.16 | Unsigned32 | M,V | | | | N | +| Authentication-Info | 1413 | 7.3.17 | Grouped | M,V | | | | N | +| E-UTRAN-Vector | 1414 | 7.3.18 | Grouped | M,V | | | | N | +| UTRAN-Vector | 1415 | 7.3.19 | Grouped | M,V | | | | N | +| GERAN-Vector | 1416 | 7.3.20 | Grouped | M,V | | | | N | +| Network-Access-Mode | 1417 | 7.3.21 | Enumerated | M,V | | | | N | +| HPLMN-ODB | 1418 | 7.3.22 | Unsigned32 | M,V | | | | N | +| Item-Number | 1419 | 7.3.23 | Unsigned32 | M,V | | | | N | +| Cancellation-Type | 1420 | 7.3.24 | Enumerated | M,V | | | | N | +| DSR-Flags | 1421 | 7.3.25 | Unsigned32 | M,V | | | | N | +| DSA-Flags | 1422 | 7.3.26 | Unsigned32 | M,V | | | | N | +| Context-Identifier | 1423 | 7.3.27 | Unsigned32 | M,V | | | | N | +| Subscriber-Status | 1424 | 7.3.29 | Enumerated | M,V | | | | N | +| Operator-Determined-Barring | 1425 | 7.3.30 | Unsigned32 | M,V | | | | N | +| Access-Restriction-Data | 1426 | 7.3.31 | Unsigned32 | M,V | | | | N | +| APN-OI-Replacement | 1427 | 7.3.32 | UTF8String | M,V | | | | N | +| All-APN-Configurations-Included-Indicator | 1428 | 7.3.33 | Enumerated | M,V | | | | N | +| APN-Configuration-Profile | 1429 | 7.3.34 | Grouped | M,V | | | | N | +| APN-Configuration | 1430 | 7.3.35 | Grouped | M,V | | | | N | +| EPS-Subscribed-QoS-Profile | 1431 | 7.3.37 | Grouped | M,V | | | | N | +| VPLMN-Dynamic-Address-Allowed | 1432 | 7.3.38 | Enumerated | M,V | | | | N | +| STN-SR | 1433 | 7.3.39 | OctetString | M,V | | | | N | +| Alert-Reason | 1434 | 7.3.83 | Enumerated | M,V | | | | N | +| AMBR | 1435 | 7.3.41 | Grouped | M,V | | | | N | +| CSG-Subscription-Data | 1436 | 7.3.78 | Grouped | M. V | | | | N | +| CSG-Id | 1437 | 7.3.79 | Unsigned32 | M,V | | | | N | +| PDN-GW-Allocation-Type | 1438 | 7.3.44 | Enumerated | M,V | | | | N | +| Expiration-Date | 1439 | 7.3.80 | Time | M,V | | | | N | +| RAT-Frequency-Selection-Priority-ID | 1440 | 7.3.46 | Unsigned32 | M,V | | | | N | +| IDA-Flags | 1441 | 7.3.47 | Unsigned32 | M,V | | | | N | +| PUA-Flags | 1442 | 7.3.48 | Unsigned32 | M,V | | | | N | +| NOR-Flags | 1443 | 7.3.49 | Unsigned32 | M,V | | | | N | +| User-Id | 1444 | 7.3.50 | UTF8String | V | | | M | N | +| Equipment-Status | 1445 | 7.3.51 | Enumerated | M,V | | | | N | +| Regional-Subscription-Zone-Code | 1446 | 7.3.52 | OctetString | M,V | | | | N | +| RAND | 1447 | 7.3.53 | OctetString | M,V | | | | N | +| XRES | 1448 | 7.3.54 | OctetString | M,V | | | | N | +| AUTN | 1449 | 7.3.55 | OctetString | M,V | | | | N | +| KASME | 1450 | 7.3.56 | OctetString | M,V | | | | N | +| Trace-Collection-Entity | 1452 | 7.3.98 | Address | M,V | | | | N | +| Kc | 1453 | 7.3.59 | OctetString | M,V | | | | N | +| SRES | 1454 | 7.3.60 | OctetString | M,V | | | | N | +| PDN-Type | 1456 | 7.3.62 | Enumerated | M,V | | | | N | +| Roaming-Restricted-Due-To-Unsupported-Feature | 1457 | 7.3.81 | Enumerated | M,V | | | | N | +| Trace-Data | 1458 | 7.3.63 | Grouped | M,V | | | | N | +| Trace-Reference | 1459 | 7.3.64 | OctetString | M,V | | | | N | +| Trace-Depth | 1462 | 7.3.67 | Enumerated | M,V | | | | N | +| Trace-NE-Type-List | 1463 | 7.3.68 | OctetString | M,V | | | | N | +| Trace-Interface-List | 1464 | 7.3.69 | OctetString | M,V | | | | N | +| Trace-Event-List | 1465 | 7.3.70 | OctetString | M,V | | | | N | +| OMC-Id | 1466 | 7.3.71 | OctetString | M,V | | | | N | +| GPRS-Subscription-Data | 1467 | 7.3.72 | Grouped | M,V | | | | N | +| Complete-Data-List-Included-Indicator | 1468 | 7.3.73 | Enumerated | M,V | | | | N | +| PDP-Context | 1469 | 7.3.74 | Grouped | M,V | | | | N | +| PDP-Type | 1470 | 7.3.75 | OctetString | M,V | | | | N | +| 3GPP2-MEID | 1471 | 7.3.6 | OctetString | M,V | | | | N | +| Specific-APN-Info | 1472 | 7.3.82 | Grouped | M,V | | | | N | +| LCS-Info | 1473 | 7.3.84 | Grouped | M,V | | | | N | +| GMLC-Number | 1474 | 7.3.85 | OctetString | M,V | | | | N | +| LCS-PrivacyException | 1475 | 7.3.86 | Grouped | M,V | | | | N | +| SS-Code | 1476 | 7.3.87 | OctetString | M,V | | | | N | +| SS-Status | 1477 | 7.3.88 | Grouped | M,V | | | | N | +| Notification-To-UE-User | 1478 | 7.3.89 | Enumerated | M,V | | | | N | +| External-Client | 1479 | 7.3.90 | Grouped | M,V | | | | N | +| Client-Identity | 1480 | 7.3.91 | OctetString | M,V | | | | N | +| GMLC-Restriction | 1481 | 7.3.92 | Enumerated | M,V | | | | N | +| PLMN-Client | 1482 | 7.3.93 | Enumerated | M,V | | | | N | +| Service-Type | 1483 | 7.3.94 | Grouped | M,V | | | | N | +| ServiceTypeIdentity | 1484 | 7.3.95 | Unsigned32 | M,V | | | | N | +| MO-LR | 1485 | 7.3.96 | Grouped | M,V | | | | N | +| Teleservice-List | 1486 | 7.3.99 | Grouped | M,V | | | | N | +| TS-Code | 1487 | 7.3.100 | OctetString | M,V | | | | N | +| Call-Barring-Infor-List | 1488 | 7.3.101 | Grouped | M,V | | | | N | +| SGSN-Number | 1489 | 7.3.102 | OctetString | M,V | | | | N | +| IDR-Flags | 1490 | 7.3.103 | Unsigned32 | M,V | | | | N | +| ICS-Indicator | 1491 | 7.3.104 | Enumerated | V | | | M | N | +| IMS-Voice-Over-PS-Sessions-Supported | 1492 | 7.3.106 | Enumerated | V | | | M | N | +| Homogeneous-Support-of-IMS-Voice-Over-PS-Sessions | 1493 | 7.3.107 | Enumerated | V | | | M | N | +| Last-UE-Activity-Time | 1494 | 7.3.108 | Time | V | | | M | N | +| EPS-User-State | 1495 | 7.3.110 | Grouped | V | | | M | N | +| EPS-Location-Information | 1496 | 7.3.111 | Grouped | V | | | M | N | +| MME-User-State | 1497 | 7.3.112 | Grouped | V | | | M | N | +| SGSN-User-State | 1498 | 7.3.113 | Grouped | V | | | M | N | +| User-State | 1499 | 7.3.114 | Enumerated | V | | | M | N | +| MME-Location Information | 1600 | 7.3.115 | Grouped | V | | | M | N | +| SGSN-Location-Information | 1601 | 7.3.116 | Grouped | V | | | M | N | +| E-UTRAN-Cell-Global-Identity | 1602 | 7.3.117 | OctetString | V | | | M | N | +| Tracking-Area-Identity | 1603 | 7.3.118 | OctetString | V | | | M | N | +| Cell-Global-Identity | 1604 | 7.3.119 | OctetString | V | | | M | N | +| Routing-Area-Identity | 1605 | 7.3.120 | OctetString | V | | | M | N | +| Location-Area-Identity | 1606 | 7.3.121 | OctetString | V | | | M | N | +| Service-Area-Identity | 1607 | 7.3.122 | OctetString | V | | | M | N | +| Geographical-Information | 1608 | 7.3.123 | OctetString | V | | | M | N | +| Geodetic-Information | 1609 | 7.3.124 | OctetString | V | | | M | N | +| Current-Location-Retrieved | 1610 | 7.3.125 | Enumerated | V | | | M | N | +| Age-Of-Location-Information | 1611 | 7.3.126 | Unsigned32 | V | | | M | N | +| Active-APN | 1612 | 7.3.127 | Grouped | V | | | M | N | +| Error-Diagnostic | 1614 | 7.3.128 | Enumerated | V | | | M | N | +| Ext-PDP-Address | 1621 | 7.3.129 | Address | V | | | M | N | +| UE-SRVCC-Capability | 1615 | 7.3.130 | Enumerated | V | | | M | N | +| MPS-Priority | 1616 | 7.3.131 | Unsigned32 | V | | | M | N | +| VPLMN-LIPA-Allowed | 1617 | 7.3.132 | Enumerated | V | | | M | N | +| LIPA-Permission | 1618 | 7.3.133 | Enumerated | V | | | M | N | +| Subscribed-Periodic-RAU-TAU-Timer | 1619 | 7.3.134 | Unsigned32 | V | | | M | N | +| Ext-PDP-Type | 1620 | 7.3.75A | OctetString | V | | | M | N | +| SIPTO-Permission | 1613 | 7.3.135 | Enumerated | V | | | M | N | +| MDT-Configuration | 1622 | 7.3.136 | Grouped | V | | | M | N | +| Job-Type | 1623 | 7.3.137 | Enumerated | V | | | M | N | +| Area-Scope | 1624 | 7.3.138 | Grouped | V | | | M | N | +| List-Of-Measurements | 1625 | 7.3.139 | Unsigned32 | V | | | M | N | +| Reporting-Trigger | 1626 | 7.3.140 | Unsigned32 | V | | | M | N | +| Report-Interval | 1627 | 7.3.141 | Enumerated | V | | | M | N | +| Report-Amount | 1628 | 7.3.142 | Enumerated | V | | | M | N | +| Event-Threshold-RSRP | 1629 | 7.3.143 | Unsigned32 | V | | | M | N | +| Event-Threshold-RSRQ | 1630 | 7.3.144 | Unsigned32 | V | | | M | N | +| Logging-Interval | 1631 | 7.3.145 | Enumerated | V | | | M | N | +| Logging-Duration | 1632 | 7.3.146 | Enumerated | V | | | M | N | +| Relay-Node-Indicator | 1633 | 7.3.147 | Enumerated | V | | | M | N | +| MDT-User-Consent | 1634 | 7.3.148 | Enumerated | V | | | M | N | +| PUR-Flags | 1635 | 7.3.149 | Unsigned32 | V | | | M | N | +| Subscribed-VSRVCC | 1636 | 7.3.150 | Enumerated | V | | | M | N | +| Equivalent-PLMN-List | 1637 | 7.3.151 | Grouped | V | | | M | N | +| CLR-Flags | 1638 | 7.3.152 | Unsigned32 | V | | | M | N | +| UVR-Flags | 1639 | 7.3.153 | Unsigned32 | M,V | | | | N | +| UVA-Flags | 1640 | 7.3.154 | Unsigned32 | M,V | | | | N | +| VPLMN-CSG-Subscription-Data | 1641 | 7.3.155 | Grouped | M,V | | | | N | +| Time-Zone | 1642 | 7.3.163 | UTF8String | V | | | M | N | +| A-MSISDN | 1643 | 7.3.157 | OctetString | V | | | M | N | +| MME-Number-for-MT-SMS | 1645 | 7.3.159 | OctetString | V | | | M | N | +| SMS-Register-Request | 1648 | 7.3.162 | Enumerated | V | | | M | N | +| Local-Time-Zone | 1649 | 7.3.156 | Grouped | V | | | M | N | +| Daylight-Saving-Time | 1650 | 7.3.164 | Enumerated | V | | | M | N | +| Subscription-Data-Flags | 1654 | 7.3.165 | Unsigned32 | V | | | M | N | +| Measurement-Period-UMTS | 1655 | 7.3.166 | Enumerated | V | | | M | N | +| Measurement-Period-LTE | 1656 | 7.3.167 | Enumerated | V | | | M | N | +| Collection-Period-RRM-LTE | 1657 | 7.3.168 | Enumerated | V | | | M | N | +| Collection-Period-RRM-UMTS | 1658 | 7.3.169 | Enumerated | V | | | M | N | +| Positioning-Method | 1659 | 7.3.170 | OctetString | V | | | M | N | +| Measurement-Quantity | 1660 | 7.3.171 | OctetString | V | | | M | N | +| Event-Threshold-Event-1F | 1661 | 7.3.172 | Integer32 | V | | | M | N | +| Event-Threshold-Event-1I | 1662 | 7.3.173 | Integer32 | V | | | M | N | | # 3GPP 29.329-b50 (11.5.0 2012.12.21) | | | | | | | | | | User-Identity | 700 | 6.3.1 | Grouped | M,V | | | | N | | MSISDN | 701 | 6.3.2 | OctetString | M,V | | | | N | | # Name conflict with 29.229 User-Data (606), renamed | | | | | | | | | -| User-Data-Sh | 702 | 6.3.3 | OctetString | M,V | | | | N | +| User-Data-29.329 | 702 | 6.3.3 | OctetString | M,V | | | | N | | Data-Reference | 703 | 6.3.4 | Enumerated | M,V | | | | N | | Service-Indication | 704 | 6.3.5 | OctetString | M,V | | | | N | | Subs-Req-Type | 705 | 6.3.6 | Enumerated | M,V | | | | N | @@ -541,3 +771,17 @@ | Repository-Data-ID | 715 | 6.3.24 | Grouped | V | | | M | N | | Sequence-Number | 716 | 6.3.25 | Unsigned32 | V | | | M | N | | UDR-Flags | 719 | 6.3.28 | Unsigned32 | V | | | M | N | +| # OMA DDS Charging_Data V1.0 20110201-A | | | | | | | | | +| Application-Server-Id | 2101 | 8.4 | UTF8String | M,V | | | | Y | +| Application-Service-Type | 2102 | 8.4 | UTF8String | M,V | | | | Y | +| Application-Session-Id | 2103 | 8.4 | UTF8String | M,V | | | | Y | +| Content-ID | 2116 | 8.4 | UTF8String | M,V | | | | Y | +| Content-provider-ID | 2117 | 8.4 | UTF8String | M,V | | | | Y | +| DCD-Information | 2115 | 8.5.5 | Grouped | M,V | | | | Y | +| Delivery-Status | 2104 | 8.4 | UTF8String | M,V | | | | Y | +| IM-Information | 2110 | 8.5.6 | Grouped | M,V | | | | Y | +| Number-Of-Messages-Successfully-Exploded | 2111 | 8.4 | Unsigned32 | M,V | | | | Y | +| Number-Of-Messages-Successfully-Sent | 2112 | 8.4 | Unsigned32 | M,V | | | | Y | +| Service-Generic-Information | 1256 | 8.5.10 | Grouped | M,V | | | | Y | +| Total-Number-Of-Messages-Exploded | 2113 | 8.4 | Unsigned32 | M,V | | | | Y | +| Total-Number-Of-Messages-Sent | 2114 | 8.4 | Unsigned32 | M,V | | | | Y |
--- a/extensions/dict_legacy_xml/dict_lxml_xml.c Fri May 10 09:50:09 2013 +0800 +++ b/extensions/dict_legacy_xml/dict_lxml_xml.c Fri May 10 18:49:19 2013 +0800 @@ -1808,9 +1808,6 @@ } ); TRACE_DEBUG(FULL, "Conversion from '%s' to freeDiameter internal format complete.", xmlfilename); - if (TRACE_BOOL(ANNOYING)) { - fd_dict_dump(fd_g_config->cnf_dict); - } /* Done */ del_dict_contents(&data.dict);
--- a/extensions/test_app/ta_cli.c Fri May 10 09:50:09 2013 +0800 +++ b/extensions/test_app/ta_cli.c Fri May 10 18:49:19 2013 +0800 @@ -45,7 +45,7 @@ static struct session_handler * ta_cli_reg = NULL; -struct ta_mess_info { +struct sess_state { int32_t randval; /* a random value to store in Test-AVP */ struct timespec ts; /* Time of sending the message */ } ; @@ -53,7 +53,7 @@ /* Cb called when an answer is received */ static void ta_cb_ans(void * data, struct msg ** msg) { - struct ta_mess_info * mi = NULL; + struct sess_state * mi = NULL; struct timespec ts; struct session * sess; struct avp * avp; @@ -176,7 +176,7 @@ struct msg * req = NULL; struct avp * avp; union avp_value val; - struct ta_mess_info * mi = NULL, *svg; + struct sess_state * mi = NULL, *svg; struct session *sess = NULL; TRACE_DEBUG(FULL, "Creating a new message for sending."); @@ -190,7 +190,7 @@ CHECK_FCT_DO( fd_msg_sess_get(fd_g_config->cnf_dict, req, &sess, NULL), goto out ); /* Create the random value to store with the session */ - mi = malloc(sizeof(struct ta_mess_info)); + mi = malloc(sizeof(struct sess_state)); if (mi == NULL) { fd_log_debug("malloc failed: %s", strerror(errno)); goto out; @@ -264,7 +264,7 @@ int ta_cli_init(void) { - CHECK_FCT( fd_sess_handler_create(&ta_cli_reg, free, NULL) ); + CHECK_FCT( fd_sess_handler_create(&ta_cli_reg, (void *)free, NULL, NULL) ); CHECK_FCT( fd_event_trig_regcb(ta_conf->signal, "test_app.cli", ta_cli_test_message ) );
--- a/extensions/test_sip/test_sip.c Fri May 10 09:50:09 2013 +0800 +++ b/extensions/test_sip/test_sip.c Fri May 10 18:49:19 2013 +0800 @@ -53,7 +53,6 @@ struct disp_hdl * test_sip_default_hdl=NULL; -struct session_handler * ts_sess_hdl; //configuration stucture struct ts_conf * ts_conf=NULL; @@ -213,7 +212,6 @@ return 1; */ - CHECK_FCT(fd_sess_handler_create(&ts_sess_hdl, free, NULL)); //CHECK_FCT( fd_event_trig_regcb(30, "test_sip", (void *)test_sipSL_LIR_cb ) ); CHECK_FCT( fd_event_trig_regcb(30, "test_sip", (void *)test_sip_SAR_cb ) ); CHECK_FCT( fd_event_trig_regcb(31, "test_sip", (void *)test_sip_LIR_cb ) );
--- a/freeDiameterd/main.c Fri May 10 09:50:09 2013 +0800 +++ b/freeDiameterd/main.c Fri May 10 18:49:19 2013 +0800 @@ -48,7 +48,6 @@ static char *conffile = NULL; static int gnutls_debug = 0; -static int fd_msg_log_enabled = 0; /* all logs disabled by default, this field is a bitfield of enabled FD_MSG_LOG_* */ /* gnutls debug */ static void fd_gnutls_debug(int level, const char * str) { @@ -87,25 +86,6 @@ TRACE_DEBUG(INFO, "Enabled GNUTLS debug at level %d", gnutls_debug); } - /* set messages logging */ - if (fd_msg_log_enabled) { - if (fd_msg_log_enabled & (1 << FD_MSG_LOG_DROPPED)) { - CHECK_FCT( fd_msg_log_config(FD_MSG_LOG_DROPPED, FD_MSG_LOGTO_DEBUGONLY, NULL) ); - } - if (fd_msg_log_enabled & (1 << FD_MSG_LOG_RECEIVED)) { - CHECK_FCT( fd_msg_log_config(FD_MSG_LOG_RECEIVED, FD_MSG_LOGTO_DEBUGONLY, NULL) ); - } - if (fd_msg_log_enabled & (1 << FD_MSG_LOG_SENT)) { - CHECK_FCT( fd_msg_log_config(FD_MSG_LOG_SENT, FD_MSG_LOGTO_DEBUGONLY, NULL) ); - } - if (fd_msg_log_enabled & (1 << FD_MSG_LOG_NODELIVER)) { - CHECK_FCT( fd_msg_log_config(FD_MSG_LOG_NODELIVER, FD_MSG_LOGTO_DEBUGONLY, NULL) ); - } - if (fd_msg_log_enabled & (1 << FD_MSG_LOG_TIMING)) { - CHECK_FCT( fd_msg_log_config(FD_MSG_LOG_TIMING, FD_MSG_LOGTO_DEBUGONLY, NULL) ); - } - } - /* Allow SIGINT and SIGTERM from this point to terminate the application */ CHECK_POSIX( pthread_create(&signals_thr, NULL, catch_signals, NULL) ); @@ -168,14 +148,12 @@ printf( " -h, --help Print help and exit\n" " -V, --version Print version and exit\n" " -c, --config=filename Read configuration from this file instead of the \n" - " default location (" DEFAULT_CONF_PATH "/" FD_DEFAULT_CONF_FILENAME ").\n" - " -M, --enable_msg_log=( DROPPED | RECEIVED | SENT | NODELIVER | TIMING )\n" - " Enable logging of these messages in the output.\n"); + " default location (" DEFAULT_CONF_PATH "/" FD_DEFAULT_CONF_FILENAME ").\n"); printf( "\nDebug:\n" " These options are mostly useful for developers\n" " -l, --dbglocale Set the locale for error messages\n" - " -d, --debug Increase verbosity of debug messages\n" - " -q, --quiet Decrease verbosity then remove debug messages\n" + " -d, --debug Increase verbosity of debug messages if default logger is used\n" + " -q, --quiet Decrease verbosity if default logger is used\n" " --dbg_gnutls <int> Enable GNU TLS debug at level <int>\n"); } @@ -196,7 +174,6 @@ { "dbg_func", required_argument, NULL, 'f' }, { "dbg_file", required_argument, NULL, 'F' }, { "dbg_gnutls", required_argument, NULL, 'g' }, - { "enable_msg_log", optional_argument, NULL, 'M' }, { NULL, 0, NULL, 0 } }; @@ -231,32 +208,8 @@ } break; - case 'M': /* disable logging of these messages */ - if (optarg) { - if (!strcmp(optarg, "DROPPED")) { - fd_msg_log_enabled |= 1 << FD_MSG_LOG_DROPPED; - } else - if (!strcmp(optarg, "RECEIVED")) { - fd_msg_log_enabled |= 1 << FD_MSG_LOG_RECEIVED; - } else - if (!strcmp(optarg, "SENT")) { - fd_msg_log_enabled |= 1 << FD_MSG_LOG_SENT; - } else - if (!strcmp(optarg, "NODELIVER")) { - fd_msg_log_enabled |= 1 << FD_MSG_LOG_NODELIVER; - } else - if (!strcmp(optarg, "TIMING")) { - fd_msg_log_enabled |= 1 << FD_MSG_LOG_TIMING; - } else { - main_help(); - exit(0); - } - } else { - fd_msg_log_enabled = -1; /* all logs enabled */ - } - case 'd': /* Increase verbosity of debug messages. */ - fd_g_debug_lvl++; + fd_g_debug_lvl--; break; case 'f': /* Full debug for the function with this name. */ @@ -282,7 +235,7 @@ break; case 'q': /* Decrease verbosity then remove debug messages. */ - fd_g_debug_lvl--; + fd_g_debug_lvl++; break; case '?': /* Invalid option. */
--- a/include/freeDiameter/freeDiameter-host.h.in Fri May 10 09:50:09 2013 +0800 +++ b/include/freeDiameter/freeDiameter-host.h.in Fri May 10 18:49:19 2013 +0800 @@ -94,6 +94,9 @@ #define FD_DEFAULT_CONF_FILENAME "freeDiameter.conf" #endif /* FD_DEFAULT_CONF_FILENAME */ +/* Maximum number of hooks handlers that can be registered. Make this compilation option if needed */ +#define FD_HOOK_HANDLE_LIMIT 5 + #ifdef __cplusplus } #endif
--- a/include/freeDiameter/libfdcore.h Fri May 10 09:50:09 2013 +0800 +++ b/include/freeDiameter/libfdcore.h Fri May 10 18:49:19 2013 +0800 @@ -57,23 +57,36 @@ /* Check the return value of a GNUTLS function, log and propagate */ -#define CHECK_GNUTLS_DO( __call__, __fallback__ ) { \ - int __ret__; \ - TRACE_DEBUG(GNUTLS_DBG_LEVEL, "GNUTLS call: %s", #__call__ ); \ - __ret__ = (__call__); \ - if (__ret__ < 0) { \ - TRACE_DEBUG(INFO, "Error in '%s':\t%s", #__call__ , gnutls_strerror(__ret__)); \ - __fallback__; \ - } \ +#define CHECK_GNUTLS_GEN( faillevel, __call__, __fallback__ ) { \ + CHECK_PRELUDE(__call__); \ + if (__ret__ < 0) { \ + __ret__ = errno; \ + LOG(faillevel, "ERROR: in '%s' :\t%s", #__call__ , gnutls_strerror(__ret__)); \ + __fallback__; \ + } \ } -/* For GNUTLS routines that do not return a value */ +/* we use this macro to help debugging gnutls usage issues -- just change the content to display what you need */ #define GNUTLS_TRACE( __call__) { \ - TRACE_DEBUG(GNUTLS_DBG_LEVEL, "GNUTLS call: " #__call__ ); \ + TRACE_CALL("Check: %s", #__call__ ); \ (__call__); \ } +#ifndef EXCLUDE_DEPRECATED +/* Macro for transition, replace with CHECK_GNUTLS_GEN */ +#define CHECK_GNUTLS_DO( __call__, __fallback__ ) { \ + CHECK_PRELUDE(__call__); \ + if (__ret__ < 0) { \ + __ret__ = errno; \ + TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , gnutls_strerror(__ret__)); \ + __fallback__; \ + } \ +} + +#endif /* EXCLUDE_DEPRECATED */ + + /*============================================================*/ /* INITIALIZATION */ /*============================================================*/ @@ -539,8 +552,13 @@ int fd_msg_new_session( struct msg * msg, os0_t opt, size_t optlen ); -/* Parse a message against our dictionary, and in case of error log and eventually build the error reply (on return and EBADMSG, *msg == NULL or *msg is the error message ready to send) */ -int fd_msg_parse_or_error( struct msg ** msg ); +/* Parse a message against our dictionary, + return 0 in case of success. + log parsing error & return error code in case of failure in parsing. + In addition, if the error code is EBADMSG (the message does not follow our dictionary) + if *msg was a request, *msg is NULL and *error contains the error message ready to send back on return + if *msg was an answer, *msg is untouched and *error==*msg if *msg was an error message, *error is null otherwise */ +int fd_msg_parse_or_error( struct msg ** msg, struct msg **error ); @@ -777,12 +795,6 @@ /* Daemon's codespace: 1000->1999 (1500->1999 defined in fdcore-internal.h) */ enum { FDEV_TERMINATE = 1000 /* request to terminate */ - ,FDEV_DUMP_DICT /* Dump the content of the dictionary */ - ,FDEV_DUMP_EXT /* Dump state of extensions */ - ,FDEV_DUMP_SERV /* Dump the server socket status */ - ,FDEV_DUMP_QUEUES /* Dump the message queues */ - ,FDEV_DUMP_CONFIG /* Dump the configuration */ - ,FDEV_DUMP_PEERS /* Dump the list of peers */ ,FDEV_TRIGGER /* Trigger available for extensions. size is sizeof(int), data is int * */ }; @@ -794,8 +806,17 @@ /* for extensions */ int fd_event_trig_regcb(int trigger_val, const char * module, void (*cb)(void)); -void fd_event_trig_dump(); + +#ifndef SWIG +DECLARE_FD_DUMP_PROTOTYPE(fd_event_trig_dump); +/* The "old" FD_EV_DUMP_* events are replaced with direct calls to the following dump functions */ +DECLARE_FD_DUMP_PROTOTYPE(fd_conf_dump); +DECLARE_FD_DUMP_PROTOTYPE(fd_ext_dump); +DECLARE_FD_DUMP_PROTOTYPE(fd_servers_dump); +#endif /* SWIG */ +DECLARE_FD_DUMP_PROTOTYPE(fd_peer_dump_list, int details); +DECLARE_FD_DUMP_PROTOTYPE(fd_peer_dump, struct peer_hdr * p, int details); /*============================================================*/ /* ENDPOINTS */ @@ -831,8 +852,8 @@ int fd_ep_filter_family( struct fd_list * list, int af ); int fd_ep_filter_list( struct fd_list * list, struct fd_list * exclude_list ); int fd_ep_clearflags( struct fd_list * list, uint32_t flags ); -void fd_ep_dump_one( char * prefix, struct fd_endpoint * ep ); -void fd_ep_dump( int indent, struct fd_list * eps ); +DECLARE_FD_DUMP_PROTOTYPE(fd_ep_dump_one, struct fd_endpoint * ep ); +DECLARE_FD_DUMP_PROTOTYPE(fd_ep_dump, int indent, struct fd_list * eps ); /*============================================================*/ @@ -854,6 +875,289 @@ int fd_app_check_common(struct fd_list * list1, struct fd_list * list2, int * common_found); int fd_app_empty(struct fd_list * list); + + +/*============================================================*/ +/* MONITORING */ +/*============================================================*/ + +/* These functions allow an extension to collect state information about the + * framework, as well as being hooked at some key checkpoints in the processing + * for logging or statistics purpose. + */ + + +/* CALLBACK: fd_hook_cb + * + * PARAMETERS: + * type : The type of hook that triggered this call, in case same cb is registered for several hooks. + * msg : If relevant, the pointer to the message triggering the call. NULL otherwise. + * peer : If relevant, the pointer to the peer associated with the call. NULL otherwise. + * other : For some callbacks, the remaining information is passed in this parameter. See each hook detail. + * permsgdata : Structure associated with a given message, across several hooks. + * A different structure is associated with requests and corresponding answers. + * See fd_hook_data_hdl below for details. + * If no fd_hook_data_hdl is registered with this callback, this parameter is always NULL + * regdata : Data pointer stored at registration, opaque for the framework. + * + * DESCRIPTION: + * When such callback is registered with fd_hook_register function, it will be called on matching events with + * the parameters as described in the list of fd_hook_type below. One can use this mechanism for e.g.: + * - log completely the messages for safety / backup + * - create statistics information on the throughput + * - ... + * + * IMPORTANT: the callback MUST NOT change the memory pointed by the different parameters (peer, message, ...) + * + * RETURN VALUE: + * none. + */ + +/* The available hooks in the framework */ +enum fd_hook_type { + + HOOK_DATA_RECEIVED = 0, + /* Hook called as soon as a message has been received from the network, after TLS & boundary processing. + - {msg} is NULL. + - {peer} is NULL. + - {other} is a pointer to a struct fd_cnx_rcvdata containing the received buffer. + - {permsgdata} points to either a new empty structure allocated for this message (cf. fd_hook_data_hdl), or NULL if no hdl is registered. + */ + + HOOK_MESSAGE_RECEIVED, + /* Hook called when a message has been received and the structure has been parsed successfully (list of AVPs). + - {msg} points to the parsed message. At this time, the objects have not been dictionary resolved. If you + try to call fd_msg_parse_dict, it will slow down the operation of a relay agent. + - {peer} is set if the message is received from a peer's connection, and NULL if the message is from a new client + connected and not yet identified + - {other} is NULL, or a char * identifying the connection when {peer} is null. + - {permsgdata} points to either a new empty structure allocated for this message or the one passed to HOOK_DATA_RECEIVED if used. + */ + + HOOK_MESSAGE_LOCAL, + /* Hook called when a request message has been created locally and is being sent. + - {msg} points to the message. + - {peer} is NULL + - {other} is NULL + - {permsgdata} points to a new empty structure allocated for this request (cf. fd_hook_data_hdl) + */ + + HOOK_MESSAGE_SENT, + /* Hook called when a message has been sent to a peer. The message might be freed as soon as the hook function returns, + so it is not safe to store the pointer for asynchronous processing. + - {msg} points to the sent message. Again, the objects may not have been dictionary resolved. If you + try to call fd_msg_parse_dict, it will slow down the operation of a relay agent. + - {peer} is set if the message is sent to a peer's connection, and NULL if the message is sent to a new client + connected and not yet identified, or being rejected + - {other} is NULL. + - {permsgdata} points to existing structure if any, or a new structure otherwise. + */ + + HOOK_MESSAGE_FAILOVER, + /* Hook called when a message that was sent to a peer is being requeued, because e.g. the connection was torn down. + In that case the message will go again through the routing process. + - {msg} points to the corresponding request message (the answer is discarded). Again, the objects may not have been dictionary resolved. If you + try to call fd_msg_parse_dict, it might slow down the operation of a relay agent, although this hook is not on the normal execution path. + - {peer} is the peer this message was previously sent to. + - {other} is NULL. + - {permsgdata} points to existing structure if any, or a new structure otherwise. + */ + + HOOK_MESSAGE_PARSING_ERROR, + /* Hook called when a message being processed cannot be parsed successfully. + - {msg} points to the message if buffer was parsed successfully, or NULL otherwise. You should not call fd_msg_parse_dict on this in any case. + - {peer} is NULL or the peer that received the message. If NULL and the message is not NULL, you can still retrieve the source from the message itself. + - {other} is a char * pointer to the error message (human-readable) if {msg} is not NULL, a pointer to struct fd_cnx_rcvdata containing the received buffer otherwise. + - {permsgdata} points to existing structure associated with this message (or new structure if no previous hook was registered). + */ + + HOOK_MESSAGE_ROUTING_ERROR, + /* Hook called when a message being processed by the routing thread meets an error such as no remaining available peer for sending, based on routing callbacks decisions (maybe after retries). + - {msg} points to the message. Again, the objects may not have been dictionary resolved. If you + try to call fd_msg_parse_dict, it might slow down the operation of a relay agent, although this hook is not on the normal execution path. + - {peer} is NULL. + - {other} is a char * pointer to the error message (human-readable). + - {permsgdata} points to existing structure associated with this message (or new structure if no previous hook was registered). + */ + + HOOK_MESSAGE_ROUTING_FORWARD, + /* Hook called when a received message is deemed to be not handled locally by the routing_dispatch process. + The decision of knowing which peer it will be sent to is not made yet (or if an error will be returned). + The hook is trigged before the callbacks registered with fd_rt_fwd_register are called. + - {msg} points to the message. Again, the objects may not have been dictionary resolved. + If you try to call fd_msg_parse_dict, it will slow down the operation of a relay agent. + - {peer} is NULL. + - {other} is NULL. + - {permsgdata} points to existing structure associated with this message (or new structure if no previous hook was registered). + */ + + HOOK_MESSAGE_ROUTING_LOCAL, + /* Hook called when a received message is handled locally by the routing_dispatch process (i.e., not forwarded). + The hook is trigged before the callbacks registered with fd_disp_register are called. + - {msg} points to the message. Here, the message has been already parsed completely & successfully. + - {peer} is NULL. + - {other} is NULL. + - {permsgdata} points to existing structure associated with this message (or new structure if no previous hook was registered). + */ + + HOOK_MESSAGE_DROPPED, + /* Hook called when a message is being discarded by the framework because of some error condition (normal or abnormal). + It is probably a good idea to log this for analysis / backup. + - {msg} points to the message, which will be freed as soon as the hook returns. + - {peer} may be NULL or a peer related to the event. + - {other} is a char * pointer to the error message (human-readable). + - {permsgdata} points to existing structure associated with this message (or new structure if no previous hook was registered). + */ + + HOOK_PEER_CONNECT_FAILED, + /* Hook called when a connection attempt to/from a remote peer has failed. This hook is also called when the peer was in OPEN state and the connection is broken. + - {msg} may be NULL (lower layer error, e.g. connection timeout) or points to a message showing the error (either invalid incoming message, or the CEA message sent or received with an error code). + - {peer} may be NULL for incoming requests from unknown peers being rejected, otherwise it points to the peer structure associated with the attempt. + - {other} is a char * pointer to the error message (human-readable). + - {permsgdata} is always NULL for this hook. + */ + + HOOK_PEER_CONNECT_SUCCESS, + /* Hook called when a connection attempt to/from a remote peer has succeeded (the peer moves to OPEN_HANDSHAKE or OPEN state). + In case of deprecated TLS handshake after the CER/CEA exchange, this hook can still be followed by HOOK_PEER_CONNECT_FAILED if TLS handshake fails. + - {msg} points to the CEA message sent or received (with a success code) -- in case it is sent, you can always get access to the matching CER. + - {peer} points to the peer structure. + - {other} is NULL. + - {permsgdata} is always NULL for this hook. + */ + +#define HOOK_PEER_LAST HOOK_PEER_CONNECT_SUCCESS +}; + + +/* Type of the {permsgdata} pointer. It is up to each extension to define its own structure. This is opaque for the framework. */ +struct fd_hook_permsgdata; + +/* A handle that will be associated with the extension, and with the permsgdata structures. */ +struct fd_hook_data_hdl; + +/* The following structure is what is passed to the HOOK_DATA_RECEIVED hook */ +struct fd_cnx_rcvdata { + size_t length; + uint8_t * buffer; /* internal note: the buffer is padded with a struct fd_msg_pmdl, not accounted for in length */ +}; + +/* Function to register a new fd_hook_data_hdl. Should be called by your extension init function. + * The arguments are the functions called to initialize a new fd_hook_permsgdata and to free this structure when the corresponding message is being freed. + */ +/* + * FUNCTION: fd_hook_data_register + * + * PARAMETERS: + * permsgdata_size : the size of the fd_hook_permsgdata structure. + * permsgdata_init_cb : function called to initialize a new fd_hook_permsgdata structure, when a hook will be called for a message that does not have such structure yet. + * The memory is already allocated and blanked, so you can pass NULL if no further handling is required. + * permsgdata_fini_cb : function called when a message is being disposed. It should free the resources associated with the fd_hook_permsgdata. + * You can pass NULL if no special handling is required. The memory of the permsgdata structure itself will be freed by the framework. + * new_handle : On success, a handler to the registered callback is stored here. + * This handler will be used to unregister the cb. + * + * DESCRIPTION: + * Register a new fd_hook_data_hdl. This handle is used during hooks registration (see below) in order to associate data with the messages, to allow keeping tracking of the message easily. + * Note that these handlers are statically allocated and cannot be unregistered. FD_HOOK_HANDLE_LIMIT handlers can be registered at maximum (recompile libfdproto if you change this value) + * + * RETURN VALUE: + * 0 : The callback is registered. + * EINVAL : A parameter is invalid. + * ENOSPC : Too many handles already registered. You may need to increase the limit in the code. + */ +int fd_hook_data_register( + size_t permsgdata_size, + void (*permsgdata_init_cb) (struct fd_hook_permsgdata *), + void (*permsgdata_fini_cb) (struct fd_hook_permsgdata *), + struct fd_hook_data_hdl **new_handle +); + +/* A handler associated with a registered hook callback (for cleanup) */ +struct fd_hook_hdl; + +/* + * FUNCTION: fd_hook_register + * + * PARAMETERS: + * type_mask : A bitmask of fd_hook_type bits for which this cb is registered, e.g. ((1 << HOOK_MESSAGE_RECEIVED) | (1 << HOOK_MESSAGE_SENT)) + * fd_hook_cb : The callback function to register (see prototype above). + * regdata : Pointer to pass to the callback when it is called. The data is opaque to the daemon. + * data_hdl : If permsgdata is requested for the hooks, a handler registered with fd_hook_data_register. NULL otherwise. + * handler : On success, a handler to the registered callback is stored here. + * This handler can be used to unregister the cb. + * + * DESCRIPTION: + * Register a new hook in the framework. See explanations above. + * + * RETURN VALUE: + * 0 : The callback is registered. + * EEXIST : Another callback is already registered for this type of hook (HOOK_DATA_RECEIVED). + * EINVAL : A parameter is invalid. + * ENOMEM : Not enough memory to complete the operation + */ +int fd_hook_register ( uint32_t type_mask, + void (*fd_hook_cb)(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata), + void *regdata, + struct fd_hook_data_hdl *data_hdl, + struct fd_hook_hdl ** handler ); + +/* Remove a hook registration */ +int fd_hook_unregister( struct fd_hook_hdl * handler ); + + +/* Use the following function to retrieve any pmd structure associated with a request matching the current answer. Returns NULL in case of error / no such structure */ +struct fd_hook_permsgdata * fd_hook_get_request_pmd(struct fd_hook_data_hdl *data_hdl, struct msg * answer); + + +/*============================================================*/ + +/* + * The following allows an extension to retrieve stat information on the different fifo queues involved in the freeDiameter framework. + * There are three global queues, plus per-peer queues. + * This information can be used to build SNMP-like data for example, or quickly get a status of the framework to find the loaded path of execution / bottlenecks. + */ +enum fd_stat_type { + /* For the following, no peer is associated with the stat */ + STAT_G_LOCAL= 1, /* Get statistics for the global queue of messages processed by local extensions */ + STAT_G_INCOMING, /* Get statistics for the global queue of received messages to be processed by routing_in thread */ + STAT_G_OUTGOING, /* Get statistics for the global queue of messages to be processed by routing_out thread */ + + /* For the following, the peer must be provided */ + STAT_P_PSM, /* Peer state machine queue (events to be processed for this peer, including received messages) */ + STAT_P_TOSEND, /* Queue of messages for sending to this peer */ +}; + +/* + * FUNCTION: fd_stat_getstats + * + * PARAMETERS: + * stat : Which queue is being queried + * peer : (depending on the stat parameter) which peer is being queried + * current_count : (out) The number of items in the queue currently + * limit_count : (out) The max number of items the queue accepts before becoming blocking -- 0 means no max. + * highest_count : (out) The highest count the queue has reached since startup + * total_count : (out) Total number of items that this queue has processed (always growing, use deltas for monitoring) + * total : (out) Cumulated time all items spent in this queue, including blocking time (always growing, use deltas for monitoring) + * blocking : (out) Cumulated time threads trying to post new items were blocked (queue full). + * last : (out) For the last element retrieved from the queue, how long it took between posting (including blocking) and poping + * + * DESCRIPTION: + * Get statistics information about a given queue. + * Any of the (out) parameters can be NULL if not requested. + * + * RETURN VALUE: + * 0 : The callback is registered. + * EINVAL : A parameter is invalid. + */ +int fd_stat_getstats(enum fd_stat_type stat, struct peer_hdr * peer, + int * current_count, int * limit_count, int * highest_count, long long * total_count, + struct timespec * total, struct timespec * blocking, struct timespec * last); + +/*============================================================*/ +/* EOF */ +/*============================================================*/ + #ifdef __cplusplus } #endif
--- a/include/freeDiameter/libfdproto.h Fri May 10 09:50:09 2013 +0800 +++ b/include/freeDiameter/libfdproto.h Fri May 10 18:49:19 2013 +0800 @@ -79,9 +79,7 @@ #include <unistd.h> #include <stdarg.h> -#ifdef DEBUG -#include <libgen.h> /* for basename if --dbg_file is specified */ -#endif /* DEBUG */ +#include <libgen.h> /* for basename */ #ifdef SWIG #define _ATTRIBUTE_PRINTFLIKE_(_f,_v) @@ -132,12 +130,9 @@ /* * FUNCTION: fd_log - * MACRO: fd_log_debug - * MACRO: fd_log_notice - * MACRO: fd_log_error * * PARAMETERS: - * loglevel : Integer, how important the message is + * loglevel : Integer, how important the message is. Valid values are macros FD_LOG_* * format : Same format string as in the printf function * ... : Same list as printf * @@ -150,11 +145,9 @@ * None. */ void fd_log ( int, const char *, ... ) _ATTRIBUTE_PRINTFLIKE_(2,3); -#define fd_log_debug(format,args...) fd_log(FD_LOG_DEBUG, format, ## args) -#define fd_log_notice(format,args...) fd_log(FD_LOG_NOTICE, format, ## args) -#define fd_log_error(format,args...) fd_log(FD_LOG_ERROR, format, ## args) - -void fd_log_debug_fstr( FILE *, const char *, ... ); +#ifndef SWIG +void fd_log_va( int, const char *, va_list args ); +#endif /* SWIG */ /* these are internal objects of the debug facility, might be useful to control the behavior from outside */ @@ -228,6 +221,35 @@ int fd_log_handler_unregister ( void ); +/* All dump functions follow this same prototype: + * PARAMETERS: + * buf : *buf can be NULL on entry, it will be malloc'd. Otherwise it is realloc'd if needed. + * len : the current size of the buffer (in/out) + * offset: (optional) if provided, starts writing dump at offset in the buffer, and updated upon exit. if NULL, starts at offset O. + * + * RETURN VALUE: + * *buf upon success, NULL upon failure. + * + * REMARKS: + * - After the buffer has been used, it should be freed. + * - Depending on the function, the created string may be multi-line. However, it should never be terminated with a '\n'. + */ +#define DECLARE_FD_DUMP_PROTOTYPE( function_name, args... ) \ + char * function_name(char ** buf, size_t *len, size_t *offset, ##args) + + +/* Helper functions for the *dump functions that add into a buffer */ +DECLARE_FD_DUMP_PROTOTYPE( fd_dump_extend, const char * format, ... ) _ATTRIBUTE_PRINTFLIKE_(4,5); +DECLARE_FD_DUMP_PROTOTYPE( fd_dump_extend_hexdump, uint8_t *data, size_t datalen, size_t trunc, size_t wrap ); + + +/* Some helpers macro for writing such *_dump routine */ +#define FD_DUMP_STD_PARAMS buf, len, offset +#define FD_DUMP_HANDLE_OFFSET() size_t o = 0; if (!offset) offset = &o +#define FD_DUMP_HANDLE_TRAIL() while ((*buf) && (*offset > 0) && ((*buf)[*offset - 1] == '\n')) { *offset -= 1; (*buf)[*offset] = '\0'; } + + + /*============================================================*/ /* DEBUG MACROS */ /*============================================================*/ @@ -236,20 +258,14 @@ #define ASSERT(x) assert(x) #endif /* ASSERT */ -/* log levels definitions */ -#define FD_LOG_DEBUG 0 /* Verbose information for developers use */ -#define FD_LOG_NOTICE 3 /* Normal execution states worth noting */ -#define FD_LOG_ERROR 5 /* Error conditions, both recoverable or not */ - -/* print level definitions */ -#define NONE 0 /* Display no debug message */ -#define INFO 1 /* Display errors only */ -#define FULL 2 /* Display additional information to follow code execution */ -#define ANNOYING 4 /* Very verbose, for example in loops */ -#define FCTS 6 /* Display entry parameters of most functions */ -#define CALL 9 /* Display calls to most functions (with CHECK macros) */ - -/* A global level, changed by configuration or cmd line for example. Default is INFO (in libfdproto/log.c). */ +/* log levels definitions, that are passed to the logger */ +#define FD_LOG_ANNOYING 0 /* very verbose loops and such "overkill" traces. Only active when the framework is compiled in DEBUG mode. */ +#define FD_LOG_DEBUG 1 /* Get a detailed sense of what is going on in the framework. Use this level for normal debug */ +#define FD_LOG_NOTICE 3 /* Normal execution states worth noting */ +#define FD_LOG_ERROR 5 /* Recoverable or expected error conditions */ +#define FD_LOG_FATAL 6 /* Unrecoverable error, e.g. malloc fail, etc. that requires the framework to shutdown */ + +/* The level used by the default logger, can be changed by command-line arguments. Ignored for other loggers. */ extern int fd_g_debug_lvl; /* Some portability code to get nice function name in __PRETTY_FUNCTION__ */ @@ -264,121 +280,321 @@ #define __PRETTY_FUNCTION__ __func__ #endif /* __PRETTY_FUNCTION__ */ -#ifdef DEBUG /* A version of __FILE__ without the full path */ static char * file_bname = NULL; static char * file_bname_init(char * full) { file_bname = basename(full); return file_bname; } #define __STRIPPED_FILE__ (file_bname ?: file_bname_init((char *)__FILE__)) -/* Boolean for tracing at a certain level */ -#define TRACE_BOOL(_level_) ( ((_level_) <= fd_g_debug_lvl) \ - || (fd_debug_one_function && !strcmp(fd_debug_one_function, __PRETTY_FUNCTION__)) \ - || (fd_debug_one_file && !strcmp(fd_debug_one_file, __STRIPPED_FILE__) ) ) -#else /* DEBUG */ -#define TRACE_BOOL(_level_) ((_level_) <= fd_g_debug_lvl) -#define __STRIPPED_FILE__ __FILE__ -#endif /* DEBUG */ - - -#define STD_TRACE_FMT_STRING "pid:%s in %s@%s:%d: " -/************* - The general debug macro, each call results in two lines of debug messages (change the macro for more compact output) - *************/ + + +/* In DEBUG mode, we add meta-information along each trace. This makes multi-threading problems easier to debug. */ #ifdef DEBUG -/* In DEBUG mode, we add (a lot of) meta-information along each trace. This makes multi-threading problems easier to debug. */ -#define TRACE(printlevel,level,format,args... ) { \ - if ( TRACE_BOOL(level) ) { \ - const char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed"); \ - fd_log((printlevel), STD_TRACE_FMT_STRING format, \ - __thn, __PRETTY_FUNCTION__, __STRIPPED_FILE__, __LINE__, ## args); \ - } \ -} +# define STD_TRACE_FMT_STRING "pid:%s in %s@%s:%d: " +# define STD_TRACE_FMT_ARGS , ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed"), __PRETTY_FUNCTION__, __STRIPPED_FILE__, __LINE__ #else /* DEBUG */ -/* Do not print thread, function, ... only the message itself in this case */ -#define TRACE(printlevel,level,format,args... ) { \ - if ( TRACE_BOOL(level) ) { \ - fd_log((printlevel), format, ## args); \ - } \ -} +# define STD_TRACE_FMT_STRING "" +# define STD_TRACE_FMT_ARGS #endif /* DEBUG */ -/* Report debug information */ -#define TRACE_DEBUG(level,format,args... ) \ - TRACE(FD_LOG_DEBUG,(level),format,##args) +/************************* + The general debug macro + *************************/ +#define LOG(printlevel,format,args... ) \ + fd_log((printlevel), STD_TRACE_FMT_STRING format STD_TRACE_FMT_ARGS, ## args) + +/* + * Use the following macros in the code to get traces with location & pid in debug mode: + */ +#ifdef DEBUG +# define LOG_A(format,args... ) \ + LOG(FD_LOG_ANNOYING,format,##args) +#else /* DEBUG */ +# define LOG_A(format,args... ) /* not defined in release */ +#endif /* DEBUG */ + +/* Debug information useful to follow in detail what is going on */ +#define LOG_D(format,args... ) \ + LOG(FD_LOG_DEBUG, format, ##args) /* Report a normal message that is useful for normal admin monitoring */ -#define TRACE_NOTICE(format,args... ) \ - TRACE(FD_LOG_NOTICE,INFO,format,##args) +#define LOG_N(format,args... ) \ + LOG(FD_LOG_NOTICE, format,##args) /* Report an error */ -#define TRACE_ERROR(format,args... ) \ - TRACE(FD_LOG_ERROR, NONE, format, ##args) - -/* -TRACE_NOTICE(...) and fd_log_notice(...) are equivalent when the code is not compiled in DEBUG mode, -but there is more contextual information when compiled in DEBUG with the TRACE_NOTICE macro, -hence it is recommended to use this one except for formatted output (e.g. fd_*_dump function) - -resp. TRACE_DEBUG and TRACE_ERROR. -*/ +#define LOG_E(format,args... ) \ + LOG(FD_LOG_ERROR, format, ##args) + +/* Report a fatal error */ +#define LOG_F(format,args... ) \ + LOG(FD_LOG_FATAL, format, ##args) + /************* - Derivatives for debug + Derivatives ************/ +/* Trace a binary buffer content */ +#define LOG_BUFFER(printlevel, prefix, buf, bufsz, suffix ) { \ + int __i; \ + size_t __sz = (size_t)(bufsz); \ + uint8_t * __buf = (uint8_t *)(buf); \ + char __strbuf[1024+1]; \ + for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2)); __i++) { \ + sprintf(__strbuf + (2 * __i), "%02hhx", __buf[__i]); \ + } \ + fd_log(printlevel, STD_TRACE_FMT_STRING "%s%s%s" STD_TRACE_FMT_ARGS, \ + (prefix), __strbuf, (suffix)); \ +} + /* Helper for function entry -- for very detailed trace of the execution */ #define TRACE_ENTRY(_format,_args... ) \ - TRACE_DEBUG(FCTS, "[enter] %s(" _format ") {" #_args "}", __PRETTY_FUNCTION__, ##_args ); + LOG_A("[enter] %s(" _format ") {" #_args "}", __PRETTY_FUNCTION__, ##_args ); /* Helper for debugging by adding traces -- for debuging a specific location of the code */ #define TRACE_HERE() \ - TRACE_DEBUG(NONE, " -- debug checkpoint %d -- ", fd_breakhere()); + LOG_F(" -- debug checkpoint %d -- ", fd_breakhere()); int fd_breakhere(void); /* Helper for tracing the CHECK_* macros below -- very very verbose code execution! */ -#define TRACE_DEBUG_ALL( str... ) \ - TRACE_DEBUG(CALL, str ); +#define TRACE_CALL( str... ) \ + if ((fd_debug_one_function && !strcmp(fd_debug_one_function, __PRETTY_FUNCTION__)) \ + || (fd_debug_one_file && !strcmp(fd_debug_one_file, __STRIPPED_FILE__) ) ) { \ + LOG_A( str ); \ + } /* For development only, to keep track of TODO locations in the code */ #ifndef ERRORS_ON_TODO -#define TODO( _msg, _args... ) \ - TRACE_DEBUG(NONE, "TODO: " _msg , ##_args); +# define TODO( _msg, _args... ) \ + LOG_F( "TODO: " _msg , ##_args); #else /* ERRORS_ON_TODO */ -#define TODO( _msg, _args... ) \ - "TODO" = _msg ## _args; /* just a stupid compilation error to spot the todo */ +# define TODO( _msg, _args... ) \ + "TODO" = _msg ## _args; /* just a stupid compilation error to spot the todo */ #endif /* ERRORS_ON_TODO */ -/* Trace a binary buffer content */ -#ifdef DEBUG -/* In DEBUG mode, we add (a lot of) meta-information along each trace. This makes multi-threading problems easier to debug. */ -#define TRACE_BUFFER(printlevel, level, prefix, buf, bufsz, suffix ) { \ - if ( TRACE_BOOL(level) ) { \ + +/*============================================================*/ +/* ERROR CHECKING MACRO */ +/*============================================================*/ + +/* Macros to check a return value and branch out in case of error. + * These macro additionally provide the logging information. + * + * The name "__ret__" is always available in the __fallback__ parameter and contains the error code. + */ + +#define CHECK_PRELUDE(__call__) \ + int __ret__; \ + TRACE_CALL("Check: %s", #__call__ ); \ + __ret__ = (__call__) + +#define DEFAULT_FB return __ret__; + +/* System check: error case if < 0, error value in errno */ +#define CHECK_SYS_GEN( faillevel, __call__, __fallback__ ) { \ + CHECK_PRELUDE(__call__); \ + if (__ret__ < 0) { \ + __ret__ = errno; \ + LOG(faillevel, "ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \ + __fallback__; \ + } \ +} + + +/* Check the return value of a function and execute fallback in case of error or special value */ +#define CHECK_FCT_GEN2( faillevel, __call__, __speval__, __fallback1__, __fallback2__ ) { \ + CHECK_PRELUDE(__call__); \ + if (__ret__ != 0) { \ + if (__ret__ == (__speval__)) { \ + __fallback1__; \ + } else { \ + LOG(faillevel, "ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \ + __fallback2__; \ + } \ + } \ +} + +/* Check the return value of a function and execute fallback in case of error (return value different from 0) */ +#define CHECK_FCT_GEN( faillevel, __call__, __fallback__) \ + CHECK_FCT_GEN2( faillevel, (__call__), 0, , (__fallback__) ) + +/* Check that a memory allocator did not return NULL, otherwise log an error and execute fallback */ +#define CHECK_MALLOC_GEN( faillevel, __call__, __fallback__ ) { \ + void * __ptr__; \ + TRACE_CALL("Check: %s", #__call__ ); \ + __ptr__ = (void *)(__call__); \ + if (__ptr__ == NULL) { \ + int __ret__ = errno; \ + LOG(faillevel, "ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \ + __fallback__; \ + } \ +} + +/* Check parameters at function entry, execute fallback on error */ +#define CHECK_PARAMS_GEN( faillevel, __bool__, __fallback__ ) { \ + TRACE_CALL("Check: %s", #__bool__ ); \ + if ( ! (__bool__) ) { \ + int __ret__ = EINVAL; \ + LOG(faillevel, "ERROR: invalid parameter '%s'", #__bool__ ); \ + __fallback__; \ + } \ +} + + +/*============================================================*/ +/* COMPATIBILITY MACROS, TO BE REMOVED */ +/*============================================================*/ +/* Redefine the old macros for transition of the code */ +#ifndef EXCLUDE_DEPRECATED + +#define MARK_DEPRECATED /* __attribute__ ((deprecated)) */ + +enum old_levels { + NONE = 0, + INFO = 1, + FULL = 2, + ANNOYING = 4, + FCTS = 6, + CALL = 9 +} MARK_DEPRECATED; + +static __inline__ int TRACE_BOOL( enum old_levels level ) MARK_DEPRECATED +{ + return (level <= fd_g_debug_lvl) + || (fd_debug_one_function && !strcmp(fd_debug_one_function, __PRETTY_FUNCTION__)) + || (fd_debug_one_file && !strcmp(fd_debug_one_file, __STRIPPED_FILE__) ); +} + +static __inline__ void fd_log_deprecated( int level, const char *format, ... ) MARK_DEPRECATED +{ + va_list ap; + va_start(ap, format); + fd_log_va(level, format, ap); + va_end(ap); +} +static __inline__ void replace_me() MARK_DEPRECATED { } + +#define TRACE_sSA(...) replace_me(); +#define sSA_DUMP_NODE_SERV(...) replace_me(); +#define sSA_DUMP_NODE(...) replace_me(); +#define TRACE_BUFFER(...) replace_me(); +#define TRACE_NOTICE(...) replace_me(); + + +/* Use the LOG_* instead, or use the new *_dump functions when dumping an object */ +#define fd_log_debug(format,args...) fd_log_deprecated(FD_LOG_DEBUG, format, ## args) +#define fd_log_notice(format,args...) fd_log_deprecated(FD_LOG_NOTICE, format, ## args) +#define fd_log_error(format,args...) fd_log_deprecated(FD_LOG_ERROR, format, ## args) + +/* old macro for traces. To be replaced by appropriate LOG_* macros. */ +# define TRACE_DEBUG(oldlevel, format,args... ) { \ + if (TRACE_BOOL(oldlevel)) { \ + if (oldlevel == NONE) { LOG_E(format,##args); } \ + else if (oldlevel == INFO) { LOG_N(format,##args); } \ + else { LOG_D(format,##args); } \ +} } + +/* the following macro must be replaced with LOG_E or LOG_F */ +# define TRACE_ERROR fd_log_error + + +/* The following macros are missing the faillevel information, which indicates at what log level the error case should be displayed. */ +# define CHECK_SYS_DO( __call__, __fallback__ ) { \ + CHECK_PRELUDE(__call__); \ + if (__ret__ < 0) { \ + __ret__ = errno; \ + TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \ + __fallback__; \ + } \ +} + +# define CHECK_SYS( __call__ ) \ + CHECK_SYS_DO( (__call__), return __ret__ ) + + +# define CHECK_POSIX_DO2( __call__, __speval__, __fallback1__, __fallback2__ ) { \ + CHECK_PRELUDE(__call__); \ + if (__ret__ != 0) { \ + if (__ret__ == (__speval__)) { \ + __fallback1__; \ + } else { \ + TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \ + __fallback2__; \ + } \ + } \ +} + +# define CHECK_POSIX_DO( __call__, __fallback__ ) \ + CHECK_POSIX_DO2( (__call__), 0, , __fallback__ ) + +# define CHECK_POSIX( __call__ ) \ + CHECK_POSIX_DO( (__call__), return __ret__ ) + +# define CHECK_MALLOC_DO( __call__, __fallback__ ) { \ + void * __ptr__; \ + TRACE_CALL("Check: %s", #__call__ ); \ + __ptr__ = (void *)(__call__); \ + if (__ptr__ == NULL) { \ + int __ret__ = errno; \ + TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \ + __fallback__; \ + } \ +} + +# define CHECK_MALLOC( __call__ ) \ + CHECK_MALLOC_DO( (__call__), return __ret__ ) + +# define CHECK_PARAMS_DO( __bool__, __fallback__ ) { \ + TRACE_CALL("Check: %s", #__bool__ ); \ + if ( ! (__bool__) ) { \ + int __ret__ = EINVAL; \ + TRACE_ERROR("ERROR: invalid parameter '%s'", #__bool__ ); \ + __fallback__; \ + } \ +} + +# define CHECK_PARAMS( __bool__ ) \ + CHECK_PARAMS_DO( (__bool__), return __ret__ ) + +# define CHECK_FCT_DO CHECK_POSIX_DO +# define CHECK_FCT CHECK_POSIX + +#endif /* EXCLUDE_DEPRECATED */ + + +/*============================================================*/ +/* Optimized code: remove all debugging code */ +/*============================================================*/ +#ifdef STRIP_DEBUG_CODE +#undef LOG_D +#undef LOG_N +#undef LOG_E +#undef LOG_F +#undef LOG_BUFFER + +#define LOG_D(format,args... ) /* noop */ +#define LOG_N(format,args...) fd_log(FD_LOG_NOTICE, format, ## args) +#define LOG_E(format,args...) fd_log(FD_LOG_ERROR, format, ## args) +#define LOG_F(format,args...) fd_log(FD_LOG_FATAL, format, ## args) +#define LOG_BUFFER(printlevel, level, prefix, buf, bufsz, suffix ) { \ + if (printlevel > FD_LOG_DEBUG) { \ int __i; \ size_t __sz = (size_t)(bufsz); \ uint8_t * __buf = (uint8_t *)(buf); \ - char __strbuf[1024+1]; \ - char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed"); \ - for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2)); __i++) { \ - sprintf(__strbuf + (2 * __i), "%2.2hhx", __buf[__i]); \ + char * __strbuf[1024+1]; \ + for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2); __i++) { \ + sprintf(__strbuf + (2 * __i), "%02.2hhx", __buf[__i]); \ } \ - fd_log(printlevel, STD_TRACE_FMT_STRING "%s%s%s", \ - __thn, __PRETTY_FUNCTION__, __STRIPPED_FILE__, __LINE__, (prefix), __strbuf, (suffix)); \ - } \ -} -#else /* DEBUG */ -/* Do not print thread, function, ... only the message itself in this case */ -#define TRACE_BUFFER(printlevel, level, prefix, buf, bufsz, suffix ) { \ - if ( TRACE_BOOL(level) ) { \ - int __i; \ - size_t __sz = (size_t)(bufsz); \ - uint8_t * __buf = (uint8_t *)(buf); \ - char __strbuf[1024+1]; \ - for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2)); __i++) { \ - sprintf(__strbuf + (2 * __i), "%2.2hhx", __buf[__i]); \ - } \ - fd_log(printlevel, "%s%s%s", (prefix), __strbuf, (suffix)); \ - } \ -} -#endif /* DEBUG */ + fd_log(printlevel, prefix"%s"suffix, __strbuf); \ + } +#endif /* STRIP_DEBUG_CODE */ + +/*============================================================*/ +/* OTHER MACROS */ +/*============================================================*/ +/* helper macros (pre-processor hacks to allow macro arguments) */ +#define __tostr( arg ) #arg +#define _stringize( arg ) __tostr( arg ) +#define __agr( arg1, arg2 ) arg1 ## arg2 +#define _aggregate( arg1, arg2 ) __agr( arg1, arg2 ) /* Some aliases to socket addresses structures */ #define sSS struct sockaddr_storage @@ -392,217 +608,10 @@ ((((sSA *)_sa_)->sa_family == AF_INET6) ? (sizeof(sSA6)) : \ 0 ) ) ) -/* Dump one sockaddr Node information */ -#define sSA_DUMP_NODE( buf, bufsize, sa, flag ) { \ - sSA * __sa = (sSA *)(sa); \ - char __addrbuf[INET6_ADDRSTRLEN]; \ - if (__sa) { \ - int __rc = getnameinfo(__sa, \ - sSAlen(__sa), \ - __addrbuf, \ - sizeof(__addrbuf), \ - NULL, \ - 0, \ - (flag)); \ - if (__rc) \ - snprintf(buf, bufsize, "%s", gai_strerror(__rc)); \ - else \ - snprintf(buf, bufsize, "%s", &__addrbuf[0]); \ - } else { \ - snprintf(buf, bufsize, "(NULL / ANY)"); \ - } \ -} -/* Same but with the port (service) also */ -#define sSA_DUMP_NODE_SERV( buf, bufsize, sa, flag ) { \ - sSA * __sa = (sSA *)(sa); \ - char __addrbuf[INET6_ADDRSTRLEN]; \ - char __servbuf[32]; \ - if (__sa) { \ - int __rc = getnameinfo(__sa, \ - sSAlen(__sa), \ - __addrbuf, \ - sizeof(__addrbuf), \ - __servbuf, \ - sizeof(__servbuf), \ - (flag)); \ - if (__rc) \ - snprintf(buf, bufsize, "%s", gai_strerror(__rc)); \ - else \ - snprintf(buf, bufsize, "[%s]:%s", &__addrbuf[0],&__servbuf[0]); \ - } else { \ - snprintf(buf, bufsize,"(NULL / ANY)"); \ - } \ -} - -#ifdef DEBUG -/* In DEBUG mode, we add (a lot of) meta-information along each trace. This makes multi-threading problems easier to debug. */ -#define TRACE_sSA(printlevel, level, prefix, sa, flags, suffix ) { \ - if ( TRACE_BOOL(level) ) { \ - char __buf[1024]; \ - char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed"); \ - sSA_DUMP_NODE_SERV(__buf, sizeof(__buf), sa, flags ); \ - fd_log(printlevel, STD_TRACE_FMT_STRING "%s%s%s" , \ - __thn, __PRETTY_FUNCTION__, __STRIPPED_FILE__, __LINE__, (prefix), __buf, (suffix)); \ - } \ -} -#else /* DEBUG */ -/* Do not print thread, function, ... only the message itself in this case */ -#define TRACE_sSA(printlevel, level, prefix, sa, flags, suffix ) { \ - if ( TRACE_BOOL(level) ) { \ - char __buf[1024]; \ - sSA_DUMP_NODE_SERV(__buf, sizeof(__buf), sa, flags ); \ - fd_log(printlevel, "%s%s%s" , (prefix), __buf, (suffix)); \ - } \ -} -#endif /* DEBUG */ - -/****************** - Optimized code: remove all debugging code - **/ -#ifdef STRIP_DEBUG_CODE -#undef TRACE_DEBUG -#undef TRACE_NOTICE -#undef TRACE_ERROR -#undef TRACE_BOOL -#undef TRACE_BUFFER -#undef TRACE_sSA - -#define TRACE_DEBUG(level,format,args... ) /* noop */ -#define TRACE_BOOL(_level_) (0) /* always false */ -#define TRACE_NOTICE fd_log_notice -#define TRACE_ERROR fd_log_error -#define TRACE_BUFFER(printlevel, level, prefix, buf, bufsz, suffix ) { \ - if (printlevel > FD_LOG_DEBUG) { \ - int __i; \ - size_t __sz = (size_t)(bufsz); \ - uint8_t * __buf = (uint8_t *)(buf); \ - char * __strbuf[1024+1]; \ - for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2); __i++) { \ - sprintf(__strbuf + (2 * __i), "%02.2hhx", __buf[__i]); \ - } \ - fd_log(printlevel, prefix"%s"suffix, __strbuf); \ - } -#define TRACE_sSA(printlevel, level, prefix, sa, flags, suffix ) { \ - if (printlevel > FD_LOG_DEBUG) { \ - char __buf[1024]; \ - sSA_DUMP_NODE_SERV(__buf, sizeof(__buf), sa, flags ); \ - fd_log(printlevel, prefix "%s" suffix, __buf); \ - } -#endif /* STRIP_DEBUG_CODE */ - - -/*============================================================*/ -/* ERROR CHECKING MACRO */ -/*============================================================*/ - -/* Macros to check a return value and branch out in case of error. - * These macro should be used only when errors are improbable, not for expected errors. - */ - -/* Check the return value of a system function and execute fallback in case of error */ -#define CHECK_SYS_DO( __call__, __fallback__ ) { \ - int __ret__; \ - TRACE_DEBUG_ALL( "Check SYS: %s", #__call__ ); \ - __ret__ = (__call__); \ - if (__ret__ < 0) { \ - int __err__ = errno; /* We may handle EINTR here */ \ - TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__err__)); \ - __fallback__; \ - } \ -} -/* Check the return value of a system function, return error code on error */ -#define CHECK_SYS( __call__ ) { \ - int __ret__; \ - TRACE_DEBUG_ALL( "Check SYS: %s", #__call__ ); \ - __ret__ = (__call__); \ - if (__ret__ < 0) { \ - int __err__ = errno; /* We may handle EINTR here */ \ - TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__err__)); \ - return __err__; \ - } \ -} - -/* Check the return value of a POSIX function and execute fallback in case of error or special value */ -#define CHECK_POSIX_DO2( __call__, __speval__, __fallback1__, __fallback2__ ) { \ - int __ret__; \ - TRACE_DEBUG_ALL( "Check POSIX: %s", #__call__ ); \ - __ret__ = (__call__); \ - if (__ret__ != 0) { \ - if (__ret__ == (__speval__)) { \ - __fallback1__; \ - } else { \ - TRACE_ERROR("ERROR: in '%s':\t%s", #__call__, strerror(__ret__)); \ - __fallback2__; \ - } \ - } \ -} - -/* Check the return value of a POSIX function and execute fallback in case of error */ -#define CHECK_POSIX_DO( __call__, __fallback__ ) \ - CHECK_POSIX_DO2( (__call__), 0, , __fallback__ ); - -/* Check the return value of a POSIX function and return it if error */ -#define CHECK_POSIX( __call__ ) { \ - int __v__; \ - CHECK_POSIX_DO( __v__ = (__call__), return __v__ ); \ -} - -/* Check that a memory allocator did not return NULL, otherwise log an error and execute fallback */ -#define CHECK_MALLOC_DO( __call__, __fallback__ ) { \ - void * __ret__; \ - TRACE_DEBUG_ALL( "Check MALLOC: %s", #__call__ ); \ - __ret__ = (void *)( __call__ ); \ - if (__ret__ == NULL) { \ - int __err__ = errno; \ - TRACE_ERROR("ERROR: in '%s':\t%s", #__call__, strerror(__err__)); \ - __fallback__; \ - } \ -} - -/* Check that a memory allocator did not return NULL, otherwise return ENOMEM */ -#define CHECK_MALLOC( __call__ ) \ - CHECK_MALLOC_DO( __call__, return ENOMEM ); - - -/* Check parameters at function entry, execute fallback on error */ -#define CHECK_PARAMS_DO( __bool__, __fallback__ ) \ - TRACE_DEBUG_ALL( "Check PARAMS: %s", #__bool__ ); \ - if ( ! (__bool__) ) { \ - TRACE_ERROR("Warning: Invalid parameter received in '%s'", #__bool__); \ - __fallback__; \ - } -/* Check parameters at function entry, return EINVAL if the boolean is false (similar to assert) */ -#define CHECK_PARAMS( __bool__ ) \ - CHECK_PARAMS_DO( __bool__, return EINVAL ); - -/* Check the return value of an internal function, log and propagate */ -#define CHECK_FCT_DO( __call__, __fallback__ ) { \ - int __ret__; \ - TRACE_DEBUG_ALL( "Check FCT: %s", #__call__ ); \ - __ret__ = (__call__); \ - if (__ret__ != 0) { \ - TRACE_ERROR("ERROR: in '%s':\t%s", #__call__, strerror(__ret__)); \ - __fallback__; \ - } \ -} -/* Check the return value of a function call, return any error code */ -#define CHECK_FCT( __call__ ) { \ - int __v__; \ - CHECK_FCT_DO( __v__ = (__call__), return __v__ ); \ -} - - - -/*============================================================*/ -/* OTHER MACROS */ -/*============================================================*/ - - -/* helper macros (pre-processor hacks to allow macro arguments) */ -#define __tostr( arg ) #arg -#define _stringize( arg ) __tostr( arg ) -#define __agr( arg1, arg2 ) arg1 ## arg2 -#define _aggregate( arg1, arg2 ) __agr( arg1, arg2 ) +DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node, sSA * sa, int flags); +DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node_serv, sSA * sa, int flags); +#define sSA_DUMP_STRLEN (INET6_ADDRSTRLEN + 1 + 32 + 2) +void fd_sa_sdump_numeric(char * buf /* must be at least sSA_DUMP_STRLEN */, sSA * sa); /* A l4 protocol name (TCP / SCTP) */ @@ -983,8 +992,8 @@ int fd_dict_getdict ( struct dict_object * object, struct dictionary ** dict); /* Debug functions */ -void fd_dict_dump_object(struct dict_object * obj); -void fd_dict_dump(struct dictionary * dict); +DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_object, struct dict_object * obj); +DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump, struct dictionary * dict); /* Function to access full contents of the dictionary, see doc in dictionary.c */ int fd_dict_getlistof(int criteria, void * parent, struct fd_list ** sentinel); @@ -1017,7 +1026,8 @@ enum { VENDOR_BY_ID = 10, /* "what" points to a vendor_id_t */ VENDOR_BY_NAME, /* "what" points to a char * */ - VENDOR_OF_APPLICATION /* "what" points to a struct dict_object containing an application (see below) */ + VENDOR_OF_APPLICATION, /* "what" points to a struct dict_object containing an application (see below) */ + VENDOR_OF_AVP, /* "what" points to a struct dict_object containing an avp (see below) */ }; /*** @@ -1222,7 +1232,7 @@ char * type_name; /* The name of this type */ dict_avpdata_interpret type_interpret;/* cb to convert the AVP value in more comprehensive format (or NULL) */ dict_avpdata_encode type_encode; /* cb to convert formatted data into an AVP value (or NULL) */ - char * (*type_dump)(union avp_value * val); /* cb called by fd_msg_dump_one for this type of data (if != NULL). Returned string must be freed. */ + DECLARE_FD_DUMP_PROTOTYPE((*type_dump), union avp_value * val); /* cb called by fd_msg_dump_one for this type of data (if != NULL). Returned string must be freed. */ }; /* The criteria for searching a type object in the dictionary */ @@ -1239,15 +1249,15 @@ /* Convert an Address type AVP into a struct sockaddr_storage */ int fd_dictfct_Address_encode(void * data, union avp_value * avp_value); int fd_dictfct_Address_interpret(union avp_value * avp_value, void * interpreted); -char * fd_dictfct_Address_dump(union avp_value * avp_value); +DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_Address_dump, union avp_value * avp_value); /* Display the content of an AVP of type UTF8String in the log file */ -char * fd_dictfct_UTF8String_dump(union avp_value * avp_value); +DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_UTF8String_dump, union avp_value * avp_value); /* For Time AVPs, map with time_t value directly */ int fd_dictfct_Time_encode(void * data, union avp_value * avp_value); int fd_dictfct_Time_interpret(union avp_value * avp_value, void * interpreted); -char * fd_dictfct_Time_dump(union avp_value * avp_value); +DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_Time_dump, union avp_value * avp_value); @@ -1406,8 +1416,10 @@ #define AVP_FLAG_RESERVED8 0x01 /* For dumping flags and values */ -#define DUMP_AVPFL_str "%c%c" -#define DUMP_AVPFL_val(_val) (_val & AVP_FLAG_VENDOR)?'V':'-' , (_val & AVP_FLAG_MANDATORY)?'M':'-' +#define DUMP_AVPFL_str "%c%c%s%s%s%s%s%s" +#define DUMP_AVPFL_val(_val) (_val & AVP_FLAG_VENDOR)?'V':'-' , (_val & AVP_FLAG_MANDATORY)?'M':'-', \ + (_val & AVP_FLAG_RESERVED3)?"3":"", (_val & AVP_FLAG_RESERVED4)?"4":"", \ + (_val & AVP_FLAG_RESERVED5)?"5":"", (_val & AVP_FLAG_RESERVED6)?"6":"", (_val & AVP_FLAG_RESERVED7)?"7":"", (_val & AVP_FLAG_RESERVED8)?"8":"" /* Type to hold data associated to an avp */ struct dict_avp_data { @@ -1556,8 +1568,9 @@ #define CMD_FLAG_RESERVED8 0x01 /* For dumping flags and values */ -#define DUMP_CMDFL_str "%c%c%c%c" -#define DUMP_CMDFL_val(_val) (_val & CMD_FLAG_REQUEST)?'R':'-' , (_val & CMD_FLAG_PROXIABLE)?'P':'-' , (_val & CMD_FLAG_ERROR)?'E':'-' , (_val & CMD_FLAG_RETRANSMIT)?'T':'-' +#define DUMP_CMDFL_str "%c%c%c%c%s%s%s%s" +#define DUMP_CMDFL_val(_val) (_val & CMD_FLAG_REQUEST)?'R':'-' , (_val & CMD_FLAG_PROXIABLE)?'P':'-' , (_val & CMD_FLAG_ERROR)?'E':'-' , (_val & CMD_FLAG_RETRANSMIT)?'T':'-', \ + (_val & CMD_FLAG_RESERVED5)?"5":"", (_val & CMD_FLAG_RESERVED6)?"6":"", (_val & CMD_FLAG_RESERVED7)?"7":"", (_val & CMD_FLAG_RESERVED8)?"8":"" /* Type to hold data associated to a command */ struct dict_cmd_data { @@ -1819,7 +1832,9 @@ struct session; /* The state information that a module associate with a session -- each module defines its own data format */ -typedef void session_state; +struct sess_state; /* declare this in your own extension */ + +typedef DECLARE_FD_DUMP_PROTOTYPE((*session_state_dump), struct sess_state * st); /* The following function must be called to activate the session expiry mechanism */ int fd_sess_start(void); @@ -1830,6 +1845,7 @@ * PARAMETERS: * handler : location where the new handler must be stored. * cleanup : a callback function that must be called when the session with associated data is destroyed. + * dumper : if not NULL, will be called during fd_sess_dump to display the data associated with a session. NULL otherwise. * opaque : A pointer that is passed to the cleanup callback -- the content is never examined by the framework. * * DESCRIPTION: @@ -1842,10 +1858,7 @@ * EINVAL : A parameter is invalid. * ENOMEM : Not enough memory to complete the operation */ -int fd_sess_handler_create_internal ( struct session_handler ** handler, void (*cleanup)(session_state * state, os0_t sid, void * opaque), void * opaque ); -/* Macro to avoid casting everywhere */ -#define fd_sess_handler_create( _handler, _cleanup, _opaque ) \ - fd_sess_handler_create_internal( (_handler), (void (*)(session_state *, os0_t, void *))(_cleanup), (void *)(_opaque) ) +int fd_sess_handler_create ( struct session_handler ** handler, void (*cleanup)(struct sess_state * state, os0_t sid, void * opaque), session_state_dump dumper, void * opaque ); /* @@ -2017,9 +2030,7 @@ * EALREADY : Data was already associated with this session and client. * ENOMEM : Not enough memory to complete the operation */ -int fd_sess_state_store_internal ( struct session_handler * handler, struct session * session, session_state ** state ); -#define fd_sess_state_store( _handler, _session, _state ) \ - fd_sess_state_store_internal( (_handler), (_session), (void *)(_state) ) +int fd_sess_state_store ( struct session_handler * handler, struct session * session, struct sess_state ** state ); /* * FUNCTION: fd_sess_state_retrieve @@ -2039,14 +2050,12 @@ * 0 : *state is updated (NULL or points to the state if it was found). * EINVAL : A parameter is invalid. */ -int fd_sess_state_retrieve_internal ( struct session_handler * handler, struct session * session, session_state ** state ); -#define fd_sess_state_retrieve( _handler, _session, _state ) \ - fd_sess_state_retrieve_internal( (_handler), (_session), (void *)(_state) ) +int fd_sess_state_retrieve ( struct session_handler * handler, struct session * session, struct sess_state ** state ); /* For debug */ -void fd_sess_dump(int level, struct session * session); -void fd_sess_dump_hdl(int level, struct session_handler * handler); +DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump, struct session * session, int with_states); +DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump_hdl, struct session_handler * handler); /* For statistics / monitoring: get the number of struct session in memory */ int fd_sess_getcount(uint32_t *cnt); @@ -2077,6 +2086,9 @@ /* If a peer returned a protocol error for this message, save it so that we don't try to send it there again. Optionally retrieve the current list of candidates. */ int fd_rtd_error_add(struct rt_data * rtd, DiamId_t sentto, size_t senttolen, uint8_t * origin, size_t originsz, uint32_t rcode, struct fd_list ** candidates, int * sendingattemtps); +/* Only retrieve the number of times this message has been processed by the routing-out mechanism (i.e. number of times it was failed over) */ +int fd_rtd_get_nb_attempts(struct rt_data * rtd, int * sendingattemtps); + /* The extracted list items have the following structure: */ struct rtd_candidate { struct fd_list chain; /* link in the list returned by the previous fcts */ @@ -2327,55 +2339,27 @@ * FUNCTION: fd_msg_dump_* * * PARAMETERS: - * level : the log level (INFO, FULL, ...) at which the object is dumped - * obj : A msg or avp object. + * see definition of DECLARE_FD_DUMP_PROTOTYPE, + * obj : A msg or avp object to dump. + * dict : the dictionary to use if parsing is requested (optional) + * force_parsing: by default these functions do not parse the object but dump hexa values in that case. + * use !0 to force parsing. If parsing fails, the hexa dump is still provided. + * recurse : allow the function to go through the children objects if any to dump more information. might require parsing. * * DESCRIPTION: - * These functions dump the content of a message to the debug log + * These functions dump the content of a message or avp into a buffer * either recursively or only the object itself. * * RETURN VALUE: - * - + * - see DECLARE_FD_DUMP_PROTOTYPE, */ -void fd_msg_dump_walk ( int level, msg_or_avp *obj ); -void fd_msg_dump_one ( int level, msg_or_avp *obj ); -/* Dump full message to log */ -void fd_msg_dump_full ( int level, struct dictionary *dict, const char *prefix, msg_or_avp *obj ); - -/* - * FUNCTION: fd_msg_log - * - * PARAMETERS: - * cause : Context for calling this function. This allows the log facility to be configured precisely. - * msg : The message to log. - * prefix_format: Printf-style format message that is printed ahead of the message. Might be reason for drop or so. - * - * DESCRIPTION: - * This function is called when a Diameter message reaches some particular points in the fD framework. - * The actual effect is configurable: log in a separate file, dump in the debug log, etc. - * - * RETURN VALUE: - * - - */ -enum fd_msg_log_cause { - FD_MSG_LOG_DROPPED = 1, /* message has been dropped by the framework */ - FD_MSG_LOG_RECEIVED, /* message received from the network */ - FD_MSG_LOG_SENT, /* message sent to another peer */ - FD_MSG_LOG_NODELIVER, /* message could not be delivered to any peer */ - FD_MSG_LOG_TIMING /* profiling messages */ -}; -#define FD_MSG_LOG_MAX FD_MSG_LOG_TIMING -void fd_msg_log( enum fd_msg_log_cause cause, struct msg * msg, const char * prefix_format, ... ) _ATTRIBUTE_PRINTFLIKE_(3,4); - -/* configure the msg_log facility */ -enum fd_msg_log_method { - FD_MSG_LOGTO_NONE = 0, /* The message is not dumped. This is the default. */ - FD_MSG_LOGTO_DEBUGONLY, /* Simply log the message with other debug information, at the INFO level. */ - FD_MSG_LOGTO_FILE, /* Messages are dumped in a single file, defined in arg */ - FD_MSG_LOGTO_DIR /* Messages are dumped in different files within one directory defined in arg. */ -}; -int fd_msg_log_config(enum fd_msg_log_cause cause, enum fd_msg_log_method method, const char * arg); -void fd_msg_log_init(struct dictionary *dict); +/* one-line dump with only short information */ +DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_summary, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ); +/* one-line dump with all the contents of the message */ +DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_full, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ); +/* multi-line human-readable dump similar to wireshark output */ +DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_treeview, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ); + /*********************************************/ /* Message metadata management functions */ @@ -2529,28 +2513,6 @@ int fd_msg_source_get( struct msg * msg, DiamId_t *diamid, size_t * diamidlen ); /* - * FUNCTION: fd_msg_ts_* - * - * PARAMETERS: - * msg : A msg object. - * ts : A struct timespec pointer, indexed on CLOCK_REALTIME - * - * DESCRIPTION: - * Associate or retrieve timestamps meaningful for the message. - * A timestamp with a value of { 0, 0 } means: not set. - * - * RETURN VALUE: - * 0 : Operation complete. - * !0 : an error occurred. - */ -/* when msg was received from network */ -int fd_msg_ts_set_recv( struct msg * msg, struct timespec * ts ); -int fd_msg_ts_get_recv( struct msg * msg, struct timespec * ts ); -int fd_msg_ts_set_sent( struct msg * msg, struct timespec * ts ); -int fd_msg_ts_get_sent( struct msg * msg, struct timespec * ts ); - - -/* * FUNCTION: fd_msg_eteid_get * * PARAMETERS: @@ -2589,6 +2551,14 @@ int fd_msg_sess_set(struct msg * msg, struct session * session); +/* Helper for the hooks mechanism, for use from libfdcore */ +struct fd_msg_pmdl { + struct fd_list sentinel; /* if the sentinel.o field is NULL, the structure is not initialized. Otherwise it points to the cleanup function in libfdcore. */ + pthread_mutex_t lock; +}; +struct fd_msg_pmdl * fd_msg_pmdl_get(struct msg * msg); + + /***************************************/ /* Manage AVP values */ /***************************************/ @@ -3031,21 +3001,41 @@ int fd_fifo_move ( struct fifo * oldq, struct fifo * newq, struct fifo ** loc_update ); /* + * FUNCTION: fd_fifo_getstats + * + * PARAMETERS: + * queue : The queue from which to retrieve the information. + * current_count : How many items in the queue at the time of execution. This changes each time an item is pushed or poped. + * limit_count : The maximum number of items allowed in this queue. This is specified during queue creation. + * highest_count : The maximum number of items this queue has contained. This enables to see if limit_count count was reached. + * total_count : the total number of items that went through the queue (already pop'd). Always increasing. + * total : Cumulated time all items spent in this queue, including blocking time (always growing, use deltas for monitoring) + * blocking : Cumulated time threads trying to post new items were blocked (queue full). + * last : For the last element retrieved from the queue, how long it take between posting (including blocking) and poping + * + * DESCRIPTION: + * Retrieve the timing information associated with a queue, for monitoring purpose. + * + * RETURN VALUE: + * 0 : The statistics have been updated. + * EINVAL : A parameter is invalid. + */ +int fd_fifo_getstats( struct fifo * queue, int * current_count, int * limit_count, int * highest_count, long long * total_count, + struct timespec * total, struct timespec * blocking, struct timespec * last); + +/* * FUNCTION: fd_fifo_length * * PARAMETERS: * queue : The queue from which to retrieve the number of elements. - * length : Upon success, the current number of elements in the queue is stored here. * * DESCRIPTION: - * Retrieve the number of elements in a queue. + * Retrieve the number of elements in a queue, without error checking. * * RETURN VALUE: - * 0 : The length of the queue has been written. - * EINVAL : A parameter is invalid. + * The number of items currently queued. */ -int fd_fifo_length ( struct fifo * queue, int * length ); -int fd_fifo_length_noerr ( struct fifo * queue ); /* no error checking version */ +int fd_fifo_length ( struct fifo * queue ); /* * FUNCTION: fd_fifo_setthrhd @@ -3163,7 +3153,8 @@ fd_fifo_timedget_int((queue), (void *)(item), (abstime)) /* Dump a fifo list and optionally its inner elements -- beware of deadlocks! */ -void fd_fifo_dump(int level, char * name, struct fifo * queue, void (*dump_item)(int level, void * item)); +typedef DECLARE_FD_DUMP_PROTOTYPE((*fd_fifo_dump_item_cb), void * item); /* This function should be 1 line if possible, or use indent level. Ends with '\n' */ +DECLARE_FD_DUMP_PROTOTYPE(fd_fifo_dump, char * name, struct fifo * queue, fd_fifo_dump_item_cb dump_item); #ifdef __cplusplus }
--- a/libfdcore/CMakeLists.txt Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/CMakeLists.txt Fri May 10 18:49:19 2013 +0800 @@ -17,6 +17,8 @@ endpoints.c events.c extensions.c + fifo_stats.c + hooks.c dict_base_proto.c messages.c queues.c
--- a/libfdcore/cnxctx.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/cnxctx.c Fri May 10 18:49:19 2013 +0800 @@ -227,12 +227,6 @@ /* Accept the new connection -- this is blocking until new client enters or until cancellation */ CHECK_SYS_DO( cli_sock = accept(serv->cc_socket, (sSA *)&ss, &ss_len), return NULL ); - if (TRACE_BOOL(INFO)) { - char buf[1024]; - sSA_DUMP_NODE( buf, sizeof(buf), &ss, NI_NUMERICHOST ); - fd_log_debug("%s : accepted new client [%s].", fd_cnx_getid(serv), buf); - } - CHECK_MALLOC_DO( cli = fd_cnx_init(1), { shutdown(cli_sock, SHUT_RDWR); close(cli_sock); return NULL; } ); cli->cc_socket = cli_sock; cli->cc_family = serv->cc_family; @@ -263,6 +257,8 @@ if (rc) snprintf(cli->cc_remid, sizeof(cli->cc_remid), "[err:%s]", gai_strerror(rc)); } + + LOG_D("Incoming connection: '%s' <- '%s' {%s}", fd_cnx_getid(serv), cli->cc_remid, cli->cc_id); #ifndef DISABLE_SCTP /* SCTP-specific handlings */ @@ -274,7 +270,7 @@ else cli->cc_sctp_para.pairs = cli->cc_sctp_para.str_in; - TRACE_DEBUG(FULL,"%s : client '%s' (SCTP:%d, %d/%d streams)", fd_cnx_getid(serv), fd_cnx_getid(cli), cli->cc_socket, cli->cc_sctp_para.str_in, cli->cc_sctp_para.str_out); + LOG_A( "%s : client '%s' (SCTP:%d, %d/%d streams)", fd_cnx_getid(serv), fd_cnx_getid(cli), cli->cc_socket, cli->cc_sctp_para.str_in, cli->cc_sctp_para.str_out); } #endif /* DISABLE_SCTP */ @@ -286,36 +282,22 @@ { int sock = 0; struct cnxctx * cnx = NULL; + char sa_buf[sSA_DUMP_STRLEN]; TRACE_ENTRY("%p %d", sa, addrlen); CHECK_PARAMS_DO( sa && addrlen, return NULL ); + fd_sa_sdump_numeric(sa_buf, sa); + /* Create the socket and connect, which can take some time and/or fail */ { int ret = fd_tcp_client( &sock, sa, addrlen ); if (ret != 0) { - int lvl; - switch (ret) { - case ECONNREFUSED: - - /* "Normal" errors */ - lvl = FULL; - break; - default: - lvl = INFO; - } - /* Some errors are expected, we log at different level */ - TRACE_DEBUG( lvl, "fd_tcp_client returned an error: %s", strerror(ret)); + LOG_A("TCP connection to %s failed: %s", sa_buf, strerror(ret)); return NULL; } } - if (TRACE_BOOL(INFO)) { - char buf[1024]; - sSA_DUMP_NODE_SERV( buf, sizeof(buf), sa, NI_NUMERICSERV); - fd_log_debug("Connection established to server '%s' (TCP:%d).", buf, sock); - } - /* Once the socket is created successfuly, prepare the remaining of the cnx */ CHECK_MALLOC_DO( cnx = fd_cnx_init(1), { shutdown(sock, SHUT_RDWR); close(sock); return NULL; } ); @@ -328,18 +310,9 @@ /* Generate the names for the object */ { - char addrbuf[INET6_ADDRSTRLEN]; - char portbuf[10]; int rc; - /* Numeric values for debug... */ - rc = getnameinfo(sa, addrlen, addrbuf, sizeof(addrbuf), portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV); - if (rc) { - snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc)); - portbuf[0] = '\0'; - } - - snprintf(cnx->cc_id, sizeof(cnx->cc_id), "TCP to [%s]:%s (%d)", addrbuf, portbuf, cnx->cc_socket); + snprintf(cnx->cc_id, sizeof(cnx->cc_id), "TCP,#%d->%s", cnx->cc_socket, sa_buf); /* ...Name for log messages */ rc = getnameinfo(sa, addrlen, cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0); @@ -347,6 +320,8 @@ snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc)); } + LOG_A("TCP connection to %s succeed (socket:%d).", sa_buf, sock); + return cnx; } @@ -361,26 +336,18 @@ #else /* DISABLE_SCTP */ int sock = 0; struct cnxctx * cnx = NULL; + char sa_buf[sSA_DUMP_STRLEN]; sSS primary; TRACE_ENTRY("%p", list); CHECK_PARAMS_DO( list && !FD_IS_LIST_EMPTY(list), return NULL ); + fd_sa_sdump_numeric(sa_buf, &((struct fd_endpoint *)(list->next))->sa); + { int ret = fd_sctp_client( &sock, no_ip6, port, list ); if (ret != 0) { - int lvl; - switch (ret) { - case ECONNREFUSED: - - /* "Normal" errors */ - lvl = FULL; - break; - default: - lvl = INFO; - } - /* Some errors are expected, we log at different level */ - TRACE_DEBUG( lvl, "fd_sctp_client returned an error: %s", strerror(ret)); + LOG_A("SCTP connection to [%s,...] failed: %s", sa_buf, strerror(ret)); return NULL; } } @@ -402,26 +369,13 @@ else cnx->cc_sctp_para.pairs = cnx->cc_sctp_para.str_in; - if (TRACE_BOOL(INFO)) { - char buf[1024]; - sSA_DUMP_NODE_SERV( buf, sizeof(buf), &primary, NI_NUMERICSERV); - fd_log_debug("Connection established to server '%s' (SCTP:%d, %d/%d streams).", buf, sock, cnx->cc_sctp_para.str_in, cnx->cc_sctp_para.str_out); - } + fd_sa_sdump_numeric(sa_buf, (sSA *)&primary); /* Generate the names for the object */ { - char addrbuf[INET6_ADDRSTRLEN]; - char portbuf[10]; int rc; - /* Numeric values for debug... */ - rc = getnameinfo((sSA *)&primary, sSAlen(&primary), addrbuf, sizeof(addrbuf), portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV); - if (rc) { - snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc)); - portbuf[0] = '\0'; - } - - snprintf(cnx->cc_id, sizeof(cnx->cc_id), "SCTP to [%s]:%s (%d)", addrbuf, portbuf, cnx->cc_socket); + snprintf(cnx->cc_id, sizeof(cnx->cc_id), "SCTP,#%d->%s", cnx->cc_socket, sa_buf); /* ...Name for log messages */ rc = getnameinfo((sSA *)&primary, sSAlen(&primary), cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0); @@ -429,6 +383,8 @@ snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc)); } + LOG_A("SCTP connection to %s succeed (socket:%d, %d/%d streams).", sa_buf, sock, cnx->cc_sctp_para.str_in, cnx->cc_sctp_para.str_out); + return cnx; error: @@ -643,8 +599,6 @@ fd_cnx_markerror(conn); } - CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &conn->cc_tls_para.recvon), /* continue */ ); - return ret; } @@ -674,6 +628,53 @@ return ret; } +#define ALIGNOF(t) ((char *)(&((struct { char c; t _h; } *)0)->_h) - (char *)0) /* Could use __alignof__(t) on some systems but this is more portable probably */ +#define PMDL_PADDED(len) ( ((len) + ALIGNOF(struct fd_msg_pmdl) - 1) & ~(ALIGNOF(struct fd_msg_pmdl) - 1) ) + +size_t fd_msg_pmdl_sizewithoverhead(size_t datalen) +{ + return PMDL_PADDED(datalen) + sizeof(struct fd_msg_pmdl); +} + +struct fd_msg_pmdl * fd_msg_pmdl_get_inbuf(uint8_t * buf, size_t datalen) +{ + return (struct fd_msg_pmdl *)(buf + PMDL_PADDED(datalen)); +} + +static int fd_cnx_init_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl) +{ + *pmdl = fd_msg_pmdl_get_inbuf(buffer, expected_len); + fd_list_init(&(*pmdl)->sentinel, NULL); + CHECK_POSIX(pthread_mutex_init(&(*pmdl)->lock, NULL) ); + return 0; +} + +static uint8_t * fd_cnx_alloc_msg_buffer(size_t expected_len, struct fd_msg_pmdl ** pmdl) +{ + uint8_t * ret = NULL; + + CHECK_MALLOC_DO( ret = malloc( fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL ); + CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} ); + return ret; +} + +static uint8_t * fd_cnx_realloc_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl) +{ + uint8_t * ret = NULL; + + CHECK_MALLOC_DO( ret = realloc( buffer, fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL ); + CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} ); + return ret; +} + +static void free_rcvdata(void * arg) +{ + struct fd_cnx_rcvdata * data = arg; + struct fd_msg_pmdl * pmdl = fd_msg_pmdl_get_inbuf(data->buffer, data->length); + (void) pthread_mutex_destroy(&pmdl->lock); + free(data->buffer); +} + /* Receiver thread (TCP & noTLS) : incoming message is directly saved into the target queue */ static void * rcvthr_notls_tcp(void * arg) { @@ -696,11 +697,10 @@ /* Receive from a TCP connection: we have to rebuild the message boundaries */ do { uint8_t header[4]; - uint8_t * newmsg; - size_t length; + struct fd_cnx_rcvdata rcv_data; + struct fd_msg_pmdl *pmdl=NULL; ssize_t ret = 0; size_t received = 0; - struct timespec recv_on; do { ret = fd_cnx_s_recv(conn, &header[received], sizeof(header) - received); @@ -711,39 +711,42 @@ received += ret; } while (received < sizeof(header)); - length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3]; + rcv_data.length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3]; /* Check the received word is a valid begining of a Diameter message */ if ((header[0] != DIAMETER_VERSION) /* defined in <libfdproto.h> */ - || (length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */ + || (rcv_data.length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */ /* The message is suspect */ - TRACE_DEBUG(INFO, "Received suspect header [ver: %d, size: %zd], assume disconnection", (int)header[0], length); + LOG_E( "Received suspect header [ver: %d, size: %zd] from '%s', assuming disconnection", (int)header[0], rcv_data.length, conn->cc_remid); fd_cnx_markerror(conn); goto out; /* Stop the thread, the recipient of the event will cleanup */ } /* Ok, now we can really receive the data */ - CHECK_MALLOC_DO( newmsg = malloc( length + sizeof(struct timespec) ), goto fatal ); - memcpy(newmsg, header, sizeof(header)); + CHECK_MALLOC_DO( rcv_data.buffer = fd_cnx_alloc_msg_buffer( rcv_data.length, &pmdl ), goto fatal ); + memcpy(rcv_data.buffer, header, sizeof(header)); - while (received < length) { - pthread_cleanup_push(free, newmsg); /* In case we are canceled, clean the partialy built buffer */ - ret = fd_cnx_s_recv(conn, newmsg + received, length - received); + while (received < rcv_data.length) { + pthread_cleanup_push(free_rcvdata, &rcv_data); /* In case we are canceled, clean the partialy built buffer */ + ret = fd_cnx_s_recv(conn, rcv_data.buffer + received, rcv_data.length - received); pthread_cleanup_pop(0); if (ret <= 0) { - free(newmsg); + free_rcvdata(&rcv_data); goto out; } received += ret; } - /* Piggy-tail the timestamp of reception */ - CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &recv_on), /* continue */ ); - memcpy(newmsg + length, &recv_on, sizeof(struct timespec)); + fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl); /* We have received a complete message, pass it to the daemon */ - CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, length, newmsg), /* continue or destroy everything? */); + CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer), + { + free_rcvdata(&rcv_data); + CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), ); + return NULL; + } ); } while (conn->cc_loop); @@ -762,8 +765,7 @@ static void * rcvthr_notls_sctp(void * arg) { struct cnxctx * conn = arg; - uint8_t * buf; - size_t bufsz; + struct fd_cnx_rcvdata rcv_data; int event; TRACE_ENTRY("%p", arg); @@ -781,7 +783,8 @@ ASSERT( fd_cnx_target_queue(conn) ); do { - CHECK_FCT_DO( fd_sctp_recvmeta(conn, NULL, &buf, &bufsz, &event), goto fatal ); + struct fd_msg_pmdl *pmdl=NULL; + CHECK_FCT_DO( fd_sctp_recvmeta(conn, NULL, &rcv_data.buffer, &rcv_data.length, &event), goto fatal ); if (event == FDEVP_CNX_ERROR) { fd_cnx_markerror(conn); goto out; @@ -791,8 +794,12 @@ /* Just ignore the notification for now, we will get another error later anyway */ continue; } - /* Note: the real size of buf is bufsz + struct timespec */ - CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), event, bufsz, buf), goto fatal ); + + if (event == FDEVP_CNX_MSG_RECV) { + CHECK_MALLOC_DO( rcv_data.buffer = fd_cnx_realloc_msg_buffer(rcv_data.buffer, rcv_data.length, &pmdl), goto fatal ); + fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl); + } + CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), event, rcv_data.length, rcv_data.buffer), goto fatal ); } while (conn->cc_loop || (event != FDEVP_CNX_MSG_RECV)); @@ -929,22 +936,11 @@ /* The function that receives TLS data and re-builds a Diameter message -- it exits only on error or cancelation */ int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session) { - struct timespec * rcv_on = &conn->cc_tls_para.recvon; - -#ifndef DISABLE_SCTP - void * ptr = gnutls_transport_get_ptr(session); - if (ptr != conn) { - struct sctps_ctx * ctx = (struct sctps_ctx *) ptr; - rcv_on = &ctx->recvon; - } -#endif /* DISABLE_SCTP */ - - /* No guarantee that GnuTLS preserves the message boundaries, so we re-build it as in TCP */ do { uint8_t header[4]; - uint8_t * newmsg; - size_t length; + struct fd_cnx_rcvdata rcv_data; + struct fd_msg_pmdl *pmdl=NULL; ssize_t ret = 0; size_t received = 0; @@ -957,40 +953,39 @@ received += ret; } while (received < sizeof(header)); - length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3]; + rcv_data.length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3]; /* Check the received word is a valid beginning of a Diameter message */ if ((header[0] != DIAMETER_VERSION) /* defined in <libfreeDiameter.h> */ - || (length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */ + || (rcv_data.length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */ /* The message is suspect */ - TRACE_DEBUG(INFO, "Received suspect header [ver: %d, size: %zd], assume disconnection", (int)header[0], length); + LOG_E( "Received suspect header [ver: %d, size: %zd] from '%s', assume disconnection", (int)header[0], rcv_data.length, conn->cc_remid); fd_cnx_markerror(conn); goto out; } /* Ok, now we can really receive the data */ - CHECK_MALLOC( newmsg = malloc( length + sizeof(struct timespec)) ); - memcpy(newmsg, header, sizeof(header)); + CHECK_MALLOC( rcv_data.buffer = fd_cnx_alloc_msg_buffer( rcv_data.length, &pmdl ) ); + memcpy(rcv_data.buffer, header, sizeof(header)); - while (received < length) { - pthread_cleanup_push(free, newmsg); /* In case we are canceled, clean the partialy built buffer */ - ret = fd_tls_recv_handle_error(conn, session, newmsg + received, length - received); + while (received < rcv_data.length) { + pthread_cleanup_push(free_rcvdata, &rcv_data); /* In case we are canceled, clean the partialy built buffer */ + ret = fd_tls_recv_handle_error(conn, session, rcv_data.buffer + received, rcv_data.length - received); pthread_cleanup_pop(0); if (ret <= 0) { - free(newmsg); + free_rcvdata(&rcv_data); goto out; } received += ret; } - /* The timestamp of the last TLS chunk received for this rebuilt message lives close to the session pointer, we piggyback it */ - memcpy(newmsg + length, rcv_on, sizeof(struct timespec)); + fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl); /* We have received a complete message, pass it to the daemon */ - CHECK_FCT_DO( ret = fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, length, newmsg), + CHECK_FCT_DO( ret = fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer), { - free(newmsg); + free_rcvdata(&rcv_data); CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), ); return ret; } ); @@ -1776,7 +1771,7 @@ #endif /* DISABLE_SCTP */ default: - TRACE_DEBUG(INFO, "Unknwon protocol: %d", conn->cc_proto); + TRACE_DEBUG(INFO, "Unknown protocol: %d", conn->cc_proto); ASSERT(0); return ENOTSUP; /* or EINVAL... */ }
--- a/libfdcore/cnxctx.h Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/cnxctx.h Fri May 10 18:49:19 2013 +0800 @@ -65,7 +65,6 @@ DiamId_t cn; /* If not NULL, remote certif will be checked to match this Common Name */ int mode; /* GNUTLS_CLIENT / GNUTLS_SERVER */ gnutls_session_t session; /* Session object (stream #0 in case of SCTP) */ - struct timespec recvon; /* Timestamp of the last chunk of data received on this session -- before uncipher */ } cc_tls_para; /* If cc_proto == SCTP */ @@ -130,7 +129,6 @@ size_t bufsz; size_t offset; } partial; /* If the pull function did not read the full content of first message in raw, it stores it here for next read call. */ - struct timespec recvon; /* Timestamp of the last chunk of data received on this stream -- before uncipher */ pthread_t thr; /* Thread to decrypt raw data in this pair of streams */ gnutls_session_t session; /* TLS context using this pair of streams -- except if strid == 0, in that case session is outside the array */ };
--- a/libfdcore/config.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/config.c Fri May 10 18:49:19 2013 +0800 @@ -80,68 +80,69 @@ return 0; } -void fd_conf_dump() +DECLARE_FD_DUMP_PROTOTYPE(fd_conf_dump) { - if (!TRACE_BOOL(INFO)) - return; + FD_DUMP_HANDLE_OFFSET(); - fd_log_debug("-- Configuration :"); - fd_log_debug(" Debug trace level ...... : %+d", fd_g_debug_lvl); - fd_log_debug(" Configuration file ..... : %s", fd_g_config->cnf_file); - fd_log_debug(" Diameter Identity ...... : %s (l:%Zi)", fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len); - fd_log_debug(" Diameter Realm ......... : %s (l:%Zi)", fd_g_config->cnf_diamrlm, fd_g_config->cnf_diamrlm_len); - fd_log_debug(" Tc Timer ............... : %u", fd_g_config->cnf_timer_tc); - fd_log_debug(" Tw Timer ............... : %u", fd_g_config->cnf_timer_tw); - fd_log_debug(" Local port ............. : %hu", fd_g_config->cnf_port); - fd_log_debug(" Local secure port ...... : %hu", fd_g_config->cnf_port_tls); - fd_log_debug(" Number of SCTP streams . : %hu", fd_g_config->cnf_sctp_str); - fd_log_debug(" Number of server threads : %hu", fd_g_config->cnf_dispthr); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{freeDiameter configuration}(@%p): \n", fd_g_config), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Default trace level .... : %+d\n", fd_g_debug_lvl), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Configuration file ..... : %s\n", fd_g_config->cnf_file), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Diameter Identity ...... : %s (l:%Zi)\n", fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Diameter Realm ......... : %s (l:%Zi)\n", fd_g_config->cnf_diamrlm, fd_g_config->cnf_diamrlm_len), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Tc Timer ............... : %u\n", fd_g_config->cnf_timer_tc), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Tw Timer ............... : %u\n", fd_g_config->cnf_timer_tw), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Local port ............. : %hu\n", fd_g_config->cnf_port), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Local secure port ...... : %hu\n", fd_g_config->cnf_port_tls), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Number of SCTP streams . : %hu\n", fd_g_config->cnf_sctp_str), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Number of server threads : %hu\n", fd_g_config->cnf_dispthr), return NULL); if (FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints)) { - fd_log_debug(" Local endpoints ........ : Default (use all available)"); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Local endpoints ........ : Default (use all available)\n"), return NULL); } else { - fd_log_debug(" Local endpoints ........ : "); - fd_ep_dump( 29, &fd_g_config->cnf_endpoints ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Local endpoints ........ : \n"), return NULL); + CHECK_MALLOC_DO( fd_ep_dump( FD_DUMP_STD_PARAMS, 29, &fd_g_config->cnf_endpoints ), return NULL); } if (FD_IS_LIST_EMPTY(&fd_g_config->cnf_apps)) { - fd_log_debug(" Local applications ..... : (none)"); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Local applications ..... : (none)\n"), return NULL); } else { struct fd_list * li = fd_g_config->cnf_apps.next; - fd_log_debug(" Local applications ..... : "); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Local applications ..... : \n"), return NULL); while (li != &fd_g_config->cnf_apps) { struct fd_app * app = (struct fd_app *)li; - if (li != fd_g_config->cnf_apps.next) fd_log_debug(" "); - fd_log_debug("App: %u\t%s%s\tVnd: %u", + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " App: %u\t%s%s\tVnd: %u\n", app->appid, app->flags.auth ? "Au" : "--", app->flags.acct ? "Ac" : "--", - app->vndid); + app->vndid), return NULL); li = li->next; } } - fd_log_debug(" Flags : - IP ........... : %s", fd_g_config->cnf_flags.no_ip4 ? "DISABLED" : "Enabled"); - fd_log_debug(" - IPv6 ......... : %s", fd_g_config->cnf_flags.no_ip6 ? "DISABLED" : "Enabled"); - fd_log_debug(" - Relay app .... : %s", fd_g_config->cnf_flags.no_fwd ? "DISABLED" : "Enabled"); - fd_log_debug(" - TCP .......... : %s", fd_g_config->cnf_flags.no_tcp ? "DISABLED" : "Enabled"); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Flags : - IP ........... : %s\n", fd_g_config->cnf_flags.no_ip4 ? "DISABLED" : "Enabled"), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - IPv6 ......... : %s\n", fd_g_config->cnf_flags.no_ip6 ? "DISABLED" : "Enabled"), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - Relay app .... : %s\n", fd_g_config->cnf_flags.no_fwd ? "DISABLED" : "Enabled"), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - TCP .......... : %s\n", fd_g_config->cnf_flags.no_tcp ? "DISABLED" : "Enabled"), return NULL); #ifdef DISABLE_SCTP - fd_log_debug(" - SCTP ......... : DISABLED (at compilation)"); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - SCTP ......... : DISABLED (at compilation)\n"), return NULL); #else /* DISABLE_SCTP */ - fd_log_debug(" - SCTP ......... : %s", fd_g_config->cnf_flags.no_sctp ? "DISABLED" : "Enabled"); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - SCTP ......... : %s\n", fd_g_config->cnf_flags.no_sctp ? "DISABLED" : "Enabled"), return NULL); #endif /* DISABLE_SCTP */ - fd_log_debug(" - Pref. proto .. : %s", fd_g_config->cnf_flags.pr_tcp ? "TCP" : "SCTP"); - fd_log_debug(" - TLS method ... : %s", fd_g_config->cnf_flags.tls_alg ? "INBAND" : "Separate port"); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - Pref. proto .. : %s\n", fd_g_config->cnf_flags.pr_tcp ? "TCP" : "SCTP"), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - TLS method ... : %s\n", fd_g_config->cnf_flags.tls_alg ? "INBAND" : "Separate port"), return NULL); - fd_log_debug(" TLS : - Certificate .. : %s", fd_g_config->cnf_sec_data.cert_file ?: "(NONE)"); - fd_log_debug(" - Private key .. : %s", fd_g_config->cnf_sec_data.key_file ?: "(NONE)"); - fd_log_debug(" - CA (trust) ... : %s (%d certs)", fd_g_config->cnf_sec_data.ca_file ?: "(none)", fd_g_config->cnf_sec_data.ca_file_nr); - fd_log_debug(" - CRL .......... : %s", fd_g_config->cnf_sec_data.crl_file ?: "(none)"); - fd_log_debug(" - Priority ..... : %s", fd_g_config->cnf_sec_data.prio_string ?: "(default: '" GNUTLS_DEFAULT_PRIORITY "')"); - if (fd_g_config->cnf_sec_data.dh_file) - fd_log_debug(" - DH file ...... : %s", fd_g_config->cnf_sec_data.dh_file); - else - fd_log_debug(" - DH bits ...... : %d", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " TLS : - Certificate .. : %s\n", fd_g_config->cnf_sec_data.cert_file ?: "(NONE)"), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - Private key .. : %s\n", fd_g_config->cnf_sec_data.key_file ?: "(NONE)"), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - CA (trust) ... : %s (%d certs)\n", fd_g_config->cnf_sec_data.ca_file ?: "(none)", fd_g_config->cnf_sec_data.ca_file_nr), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - CRL .......... : %s\n", fd_g_config->cnf_sec_data.crl_file ?: "(none)"), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - Priority ..... : %s\n", fd_g_config->cnf_sec_data.prio_string ?: "(default: '" GNUTLS_DEFAULT_PRIORITY "')"), return NULL); + if (fd_g_config->cnf_sec_data.dh_file) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - DH file ...... : %s\n", fd_g_config->cnf_sec_data.dh_file), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - DH bits ...... : %d\n", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS), return NULL); + } - fd_log_debug(" Origin-State-Id ........ : %u", fd_g_config->cnf_orstateid); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Origin-State-Id ........ : %u", fd_g_config->cnf_orstateid), return NULL); + + return *buf; } /* read contents of a file opened in "rb" mode and alloc this data into a gnutls_datum_t (must be freed afterwards) */
--- a/libfdcore/core.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/core.c Fri May 10 18:49:19 2013 +0800 @@ -84,32 +84,6 @@ int code; size_t sz; void * data; CHECK_FCT_DO( fd_event_get(fd_g_config->cnf_main_ev, &code, &sz, &data), break ); switch (code) { - case FDEV_DUMP_DICT: - fd_dict_dump(fd_g_config->cnf_dict); - break; - - case FDEV_DUMP_EXT: - fd_ext_dump(); - break; - - case FDEV_DUMP_SERV: - fd_servers_dump(); - break; - - case FDEV_DUMP_QUEUES: - fd_fifo_dump(0, "Incoming messages", fd_g_incoming, fd_msg_dump_walk); - fd_fifo_dump(0, "Outgoing messages", fd_g_outgoing, fd_msg_dump_walk); - fd_fifo_dump(0, "Local messages", fd_g_local, fd_msg_dump_walk); - break; - - case FDEV_DUMP_CONFIG: - fd_conf_dump(); - break; - - case FDEV_DUMP_PEERS: - fd_peer_dump_list(FULL); - break; - case FDEV_TRIGGER: { int tv, *p; @@ -181,7 +155,7 @@ return ret; } - TRACE_DEBUG(INFO, "libfdproto initialized."); + LOG_D("libfdproto initialized."); /* Name this thread */ fd_log_threadname("Main"); @@ -208,13 +182,11 @@ fd_g_config = &g_conf; CHECK_FCT( fd_conf_init() ); - /* Initialize the message logging facility */ - fd_msg_log_init(fd_g_config->cnf_dict); - /* Add definitions of the base protocol */ CHECK_FCT( fd_dict_base_protocol(fd_g_config->cnf_dict) ); /* Initialize some modules */ + CHECK_FCT( fd_hooks_init() ); CHECK_FCT( fd_queues_init() ); CHECK_FCT( fd_msg_init() ); CHECK_FCT( fd_sess_start() ); @@ -227,6 +199,10 @@ /* Parse the freeDiameter.conf configuration file, load the extensions */ int fd_core_parseconf(const char * conffile) { + char * buf = NULL, *b; + size_t len = 0, offset=0; + + TRACE_ENTRY("%p", conffile); /* Conf file */ @@ -242,11 +218,17 @@ CHECK_FCT( fd_ext_load() ); /* Display configuration */ - fd_conf_dump(); + b = fd_conf_dump(&buf, &len, NULL); + LOG_N("%s\n", b ?: "Error during configuration dump..."); /* Display registered triggers for FDEV_TRIGGER */ - fd_event_trig_dump(); + b = fd_event_trig_dump(&buf, &len, &offset); + if (!b || offset) { + LOG_N("%s\n", b ?: "Error during triggers dump..."); + } + free(buf); + return 0; } @@ -306,7 +288,7 @@ } -/* Wait for the shutdown to be complete -- this must always be called after fd_core_shutdown to relaim some resources. */ +/* Wait for the shutdown to be complete -- this must always be called after fd_core_shutdown to reclaim some resources. */ int fd_core_wait_shutdown_complete(void) { int ret;
--- a/libfdcore/endpoints.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/endpoints.c Fri May 10 18:49:19 2013 +0800 @@ -57,19 +57,6 @@ fd_list_init(list, NULL); } - if (TRACE_BOOL(ANNOYING + 1)) { - char buf[1024]; - sSA_DUMP_NODE_SERV( buf, sizeof(buf), sa, NI_NUMERICHOST | NI_NUMERICSERV ); - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge Current list:"); - fd_ep_dump( 4, list ); - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge Adding:"); - fd_log_debug(" %s {%s%s%s%s%s}", buf, - (flags & EP_FL_CONF) ? "C" : "-", - (flags & EP_FL_DISC) ? "D" : "-", - (flags & EP_FL_ADV) ? "A" : "-", - (flags & EP_FL_LL) ? "L" : "-", - (flags & EP_FL_PRIMARY) ? "P" : "-"); - } ptr.sa = sa; /* Filter out a bunch of invalid addresses */ @@ -81,9 +68,7 @@ /* the next one filters both EXPERIMENTAL, BADCLASS and MULTICAST. */ || ((ntohl(ptr.sin->sin_addr.s_addr) & 0xe0000000) == 0xe0000000) || (ptr.sin->sin_addr.s_addr == INADDR_BROADCAST)) { - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge Address was ignored, not added."); - } + LOG_A(" DEBUG:fd_ep_add_merge Address was ignored, not added."); return 0; } } @@ -97,9 +82,7 @@ || IN6_IS_ADDR_MULTICAST(&ptr.sin6->sin6_addr) || IN6_IS_ADDR_LINKLOCAL(&ptr.sin6->sin6_addr) || IN6_IS_ADDR_SITELOCAL(&ptr.sin6->sin6_addr)) { - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge Address was ignored, not added."); - } + LOG_A(" DEBUG:fd_ep_add_merge Address was ignored, not added."); return 0; } } @@ -107,9 +90,7 @@ break; default: - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge Address family was unknown, not added."); - } + LOG_A(" DEBUG:fd_ep_add_merge Address family was unknown, not added."); return 0; } @@ -174,10 +155,6 @@ /* Merge the flags */ ep->flags |= flags; - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge New list:"); - fd_ep_dump( 4, list ); - } return 0; } @@ -189,10 +166,6 @@ TRACE_ENTRY("%p %x", list, flags); CHECK_PARAMS(list); - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter Filter this list for flags %x:", flags); - fd_ep_dump( 4, list ); - } for (li = list->next; li != list; li = li->next) { struct fd_endpoint * ep = (struct fd_endpoint *)li; @@ -203,10 +176,6 @@ } } - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter Resulting list:"); - fd_ep_dump( 4, list ); - } return 0; } @@ -218,10 +187,6 @@ TRACE_ENTRY("%p %d", list, af); CHECK_PARAMS(list); - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter_family Filter this list for family %d:", af); - fd_ep_dump( 4, list ); - } for (li = list->next; li != list; li = li->next) { struct fd_endpoint * ep = (struct fd_endpoint *)li; @@ -232,10 +197,6 @@ } } - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter_family Resulting list:"); - fd_ep_dump( 4, list ); - } return 0; } @@ -252,12 +213,6 @@ li_out = list->next; li_ex = exclude_list->next; - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter_list Filter this list "); - fd_ep_dump( 4, list ); - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter_list Removing from list"); - fd_ep_dump( 6, exclude_list ); - } /* Now browse both lists in parallel */ while ((li_out != list) && (li_ex != exclude_list)) { int cmp; @@ -303,10 +258,6 @@ free(li); } - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter_list Resulting list:"); - fd_ep_dump( 4, list ); - } return 0; } @@ -333,26 +284,40 @@ return 0; } -void fd_ep_dump_one( char * prefix, struct fd_endpoint * ep ) +DECLARE_FD_DUMP_PROTOTYPE(fd_ep_dump_one, struct fd_endpoint * ep ) { - char buf[1024]; + FD_DUMP_HANDLE_OFFSET(); + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{ep}(@%p): ", ep), return NULL); - sSA_DUMP_NODE_SERV( buf, sizeof(buf), &ep->sa, NI_NUMERICHOST | NI_NUMERICSERV ); - fd_log_debug("%s%s {%s%s%s%s}%s", prefix ?: "", buf, + if (!ep) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL); + return *buf; + } + + CHECK_MALLOC_DO( fd_sa_dump_node_serv( FD_DUMP_STD_PARAMS, &ep->sa, NI_NUMERICHOST | NI_NUMERICSERV ), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {%s%s%s%s%s}", (ep->flags & EP_FL_CONF) ? "C" : "-", (ep->flags & EP_FL_DISC) ? "D" : "-", (ep->flags & EP_FL_ADV) ? "A" : "-", (ep->flags & EP_FL_LL) ? "L" : "-", - (ep->flags & EP_FL_PRIMARY) ? "P" : "-"); + (ep->flags & EP_FL_PRIMARY) ? "P" : "-"), return NULL); + return *buf; } -void fd_ep_dump( int indent, struct fd_list * eps ) +DECLARE_FD_DUMP_PROTOTYPE(fd_ep_dump, int indent, struct fd_list * eps ) { struct fd_list * li; - for (li = eps->next; li != eps; li = li->next) { - struct fd_endpoint * ep = (struct fd_endpoint *)li; - fd_log_debug("%*s", indent, ""); - fd_ep_dump_one( NULL, ep ); + + FD_DUMP_HANDLE_OFFSET(); + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*s{eps}(@%p):", indent, "", eps), return NULL); + if (eps) { + for (li = eps->next; li != eps; li = li->next) { + struct fd_endpoint * ep = (struct fd_endpoint *)li; + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n%*s", indent+1, ""), return NULL); + CHECK_MALLOC_DO( fd_ep_dump_one( FD_DUMP_STD_PARAMS, ep ), return NULL); + } } }
--- a/libfdcore/events.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/events.c Fri May 10 18:49:19 2013 +0800 @@ -105,12 +105,6 @@ #define case_str( _val )\ case _val : return #_val case_str(FDEV_TERMINATE); - case_str(FDEV_DUMP_DICT); - case_str(FDEV_DUMP_EXT); - case_str(FDEV_DUMP_SERV); - case_str(FDEV_DUMP_QUEUES); - case_str(FDEV_DUMP_CONFIG); - case_str(FDEV_DUMP_PEERS); case_str(FDEV_TRIGGER); default: @@ -167,20 +161,20 @@ return 0; } -void fd_event_trig_dump() +DECLARE_FD_DUMP_PROTOTYPE(fd_event_trig_dump) { struct fd_list * li; - if (!TRACE_BOOL(FULL)) - return; + FD_DUMP_HANDLE_OFFSET(); CHECK_POSIX_DO( pthread_rwlock_rdlock(&trig_rwl), ); for (li = trig_list.next; li != &trig_list; li = li->next) { struct trig_item *t = li->o; - fd_log_debug(" Trigger %d, module '%s': %p", t->trig_value, t->trig_module, t->cb); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{signal:%d}'%s'->%p ", t->trig_value, t->trig_module, t->cb), break); } CHECK_POSIX_DO( pthread_rwlock_unlock(&trig_rwl), ); + return *buf; } static void *call_cb_detached(void * arg)
--- a/libfdcore/extensions.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/extensions.c Fri May 10 18:49:19 2013 +0800 @@ -77,17 +77,17 @@ } /* Dump the list */ -void fd_ext_dump(void) +DECLARE_FD_DUMP_PROTOTYPE(fd_ext_dump) { struct fd_list * li; - - fd_log_debug("Dumping extensions list :"); + FD_DUMP_HANDLE_OFFSET(); for (li = ext_list.next; li != &ext_list; li = li->next) { struct fd_ext_info * ext = (struct fd_ext_info *)li; - fd_log_debug(" - '%s'[%s] is %sloaded", ext->filename, ext->conffile?:"no conf", ext->handler ? "" : "not "); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{extension}(@%p): '%s'[%s], %sloaded%s", ext, ext->filename, ext->conffile?:"no conf", ext->handler ? "" : "not ", (li->next == &ext_list) ? "":"\n"), return NULL); } + return *buf; } /* Check the dependencies. The object must have been dlopened already. */
--- a/libfdcore/fdcore-internal.h Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/fdcore-internal.h Fri May 10 18:49:19 2013 +0800 @@ -85,7 +85,6 @@ /* Configuration */ int fd_conf_init(); int fd_conf_deinit(); -void fd_conf_dump(); int fd_conf_parse(); int fddparse(struct fd_config * conf); /* yacc generated */ int fd_conf_stream_to_gnutls_datum(FILE * pemfile, gnutls_datum_t *out); @@ -94,7 +93,6 @@ /* Extensions */ int fd_ext_add( char * filename, char * conffile ); int fd_ext_load(); -void fd_ext_dump(void); int fd_ext_term(void); /* Messages */ @@ -217,13 +215,10 @@ /* Events codespace for struct fd_peer->p_events */ enum { - /* Dump all info about this peer in the debug log */ - FDEVP_DUMP_ALL = 1500 + /* request to terminate this peer : disconnect, requeue all messages */ + FDEVP_TERMINATE = 1500 - /* request to terminate this peer : disconnect, requeue all messages */ - ,FDEVP_TERMINATE - - /* A connection object has received a message. (data contains the buffer + struct timespec piggytailed -- unaligned) */ + /* A connection object has received a message. (data contains the buffer + padding + struct fd_msg_pmdl) */ ,FDEVP_CNX_MSG_RECV /* A connection object has encountered an error (disconnected). */ @@ -249,13 +244,12 @@ }; #define CHECK_PEVENT( _e ) \ - (((int)(_e) >= FDEVP_DUMP_ALL) && ((int)(_e) <= FDEVP_PSM_TIMEOUT)) + (((int)(_e) >= FDEVP_TERMINATE) && ((int)(_e) <= FDEVP_PSM_TIMEOUT)) /* The following macro is actually called in p_psm.c -- another solution would be to declare it static inline */ #define DECLARE_PEV_STR() \ const char * fd_pev_str(int event) \ { \ switch (event) { \ - case_str(FDEVP_DUMP_ALL); \ case_str(FDEVP_TERMINATE); \ case_str(FDEVP_CNX_MSG_RECV); \ case_str(FDEVP_CNX_ERROR); \ @@ -277,11 +271,8 @@ int validate; /* The peer is new, it must be validated (by an extension) or error CEA to be sent */ }; - /* Functions */ int fd_peer_fini(); -void fd_peer_dump_list(int details); -void fd_peer_dump(struct fd_peer * peer, int details); int fd_peer_alloc(struct fd_peer ** ptr); int fd_peer_free(struct fd_peer ** ptr); int fd_peer_handle_newCER( struct msg ** cer, struct cnxctx ** cnx ); @@ -338,7 +329,6 @@ /* Server sockets */ -void fd_servers_dump(); int fd_servers_start(); int fd_servers_stop(); @@ -371,4 +361,11 @@ /* Flags for the fd_cnx_send function : */ #define FD_CNX_ORDERED (1 << 0) /* All messages sent with this flag set will be delivered in the same order. No guarantee on other messages */ +/* Internal calls of the hook mechanism */ +void fd_hook_call(enum fd_hook_type type, struct msg * msg, struct fd_peer * peer, void * other, struct fd_msg_pmdl * pmdl); +void fd_hook_associate(struct msg * msg, struct fd_msg_pmdl * pmdl); +int fd_hooks_init(void); +size_t fd_msg_pmdl_sizewithoverhead(size_t datalen); +struct fd_msg_pmdl * fd_msg_pmdl_get_inbuf(uint8_t * buf, size_t datalen); + #endif /* _FDCORE_INTERNAL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfdcore/fifo_stats.c Fri May 10 18:49:19 2013 +0800 @@ -0,0 +1,79 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis <sdecugis@freediameter.net> * +* * +* Copyright (c) 2013, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +#include "fdcore-internal.h" + +/* See include/freeDiameter/libfdcore.h for more information */ +int fd_stat_getstats(enum fd_stat_type stat, struct peer_hdr * peer, + int * current_count, int * limit_count, int * highest_count, long long * total_count, + struct timespec * total, struct timespec * blocking, struct timespec * last) +{ + struct fd_peer * p = (struct fd_peer *)peer; + TRACE_ENTRY( "%d %p %p %p %p %p %p %p %p", stat, peer, current_count, limit_count, highest_count, total_count, total, blocking, last); + + switch (stat) { + case STAT_G_LOCAL: { + CHECK_FCT( fd_fifo_getstats(fd_g_local, current_count, limit_count, highest_count, total_count, total, blocking, last) ); + } + break; + + case STAT_G_INCOMING: { + CHECK_FCT( fd_fifo_getstats(fd_g_incoming, current_count, limit_count, highest_count, total_count, total, blocking, last) ); + } + break; + + case STAT_G_OUTGOING: { + CHECK_FCT( fd_fifo_getstats(fd_g_outgoing, current_count, limit_count, highest_count, total_count, total, blocking, last) ); + } + break; + + case STAT_P_PSM: { + CHECK_PARAMS( CHECK_PEER( peer ) ); + CHECK_FCT( fd_fifo_getstats(p->p_events, current_count, limit_count, highest_count, total_count, total, blocking, last) ); + } + break; + + case STAT_P_TOSEND: { + CHECK_PARAMS( CHECK_PEER( peer ) ); + CHECK_FCT( fd_fifo_getstats(p->p_tosend, current_count, limit_count, highest_count, total_count, total, blocking, last) ); + } + break; + + default: + return EINVAL; + } + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfdcore/hooks.c Fri May 10 18:49:19 2013 +0800 @@ -0,0 +1,408 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis <sdecugis@freediameter.net> * +* * +* Copyright (c) 2013, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +#include "fdcore-internal.h" + +/* Structures for the fd_hook_data_hdl management */ +static struct fd_hook_data_hdl { + size_t pmd_size; + void (*pmd_init_cb)(struct fd_hook_permsgdata *); + void (*pmd_fini_cb)(struct fd_hook_permsgdata *); +} HDH_array[FD_HOOK_HANDLE_LIMIT]; +static int max_index = 0; +static pthread_mutex_t HDH_lock = PTHREAD_MUTEX_INITIALIZER; + +/* The structure linked from the msg structure list */ +struct pmd_list_item { + struct fd_list chain; /* this list is ordered by hdl */ + struct fd_hook_data_hdl * hdl; + struct fd_hook_permsgdata { } pmd; /* this data belongs to the extension; we only know the size of it */ +}; + +#define sizeof_pmd(hdl) (((size_t)&((struct pmd_list_item *)0)->pmd) + hdl->pmd_size) + +/* Now a hook registered by an extension */ +struct fd_hook_hdl { + struct fd_list chain[HOOK_PEER_LAST+1]; + void (*fd_hook_cb)(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata); + void *regdata; + struct fd_hook_data_hdl *data_hdl; +}; + +/* Array of those hooks */ +struct { + struct fd_list sentinel; + pthread_rwlock_t rwlock; +} HS_array[HOOK_PEER_LAST+1]; + +/* Initialize the array of sentinels for the hooks */ +int fd_hooks_init(void) +{ + int i; + for (i=0; i <= HOOK_PEER_LAST; i++) { + fd_list_init(&HS_array[i].sentinel, NULL); + CHECK_POSIX( pthread_rwlock_init(&HS_array[i].rwlock, NULL) ); + } + return 0; +} + +/* Get a slot in the array */ +int fd_hook_data_register( + size_t permsgdata_size, + void (*permsgdata_init_cb) (struct fd_hook_permsgdata *), + void (*permsgdata_fini_cb) (struct fd_hook_permsgdata *), + struct fd_hook_data_hdl **new_handle) +{ + int ret = ENOSPC, idx; + TRACE_ENTRY("%zd %p %p %p", permsgdata_size, permsgdata_init_cb, permsgdata_fini_cb, new_handle); + + CHECK_PARAMS( permsgdata_size && new_handle ); + + CHECK_POSIX( pthread_mutex_lock(&HDH_lock) ); + if (max_index < FD_HOOK_HANDLE_LIMIT) { + idx = max_index++; + ret = 0; + } + CHECK_POSIX( pthread_mutex_unlock(&HDH_lock) ); + + if (ret == 0) { + HDH_array[idx].pmd_size = permsgdata_size; + HDH_array[idx].pmd_init_cb = permsgdata_init_cb; + HDH_array[idx].pmd_fini_cb = permsgdata_fini_cb; + *new_handle = &HDH_array[idx]; + } + + return ret; +} + +/* Register a new hook callback */ +int fd_hook_register ( uint32_t type_mask, + void (*fd_hook_cb)(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata), + void *regdata, + struct fd_hook_data_hdl *data_hdl, + struct fd_hook_hdl ** handler ) +{ + struct fd_hook_hdl * newhdl = NULL; + int i; + + TRACE_ENTRY("%x %p %p %p %p", type_mask, fd_hook_cb, regdata, data_hdl, handler); + + CHECK_PARAMS( fd_hook_cb && handler ); + + CHECK_MALLOC( newhdl = malloc(sizeof(struct fd_hook_hdl)) ); + memset(newhdl, 0, sizeof(struct fd_hook_hdl)); + + newhdl->fd_hook_cb = fd_hook_cb; + newhdl->regdata = regdata; + newhdl->data_hdl = data_hdl; + + for (i=0; i <= HOOK_PEER_LAST; i++) { + fd_list_init(&newhdl->chain[i], newhdl); + if (type_mask & (1<<i)) { + CHECK_POSIX( pthread_rwlock_wrlock(&HS_array[i].rwlock) ); + fd_list_insert_before( &HS_array[i].sentinel, &newhdl->chain[i]); + CHECK_POSIX( pthread_rwlock_unlock(&HS_array[i].rwlock) ); + } + } + + *handler = newhdl; + return 0; +} + +/* free this hook callback */ +int fd_hook_unregister( struct fd_hook_hdl * handler ) +{ + int i; + TRACE_ENTRY("%p", handler); + CHECK_PARAMS( handler ); + + for (i=0; i <= HOOK_PEER_LAST; i++) { + if ( ! FD_IS_LIST_EMPTY(&handler->chain[i])) { + CHECK_POSIX( pthread_rwlock_wrlock(&HS_array[i].rwlock) ); + fd_list_unlink(&handler->chain[i]); + CHECK_POSIX( pthread_rwlock_unlock(&HS_array[i].rwlock) ); + } + } + + free(handler); + + return 0; +} + +/* callback for the libfdproto to free the data associated with a message */ +static void pmdl_free(struct fd_msg_pmdl *pmdl) +{ + /* destroy all the items in the list */ + while (!FD_IS_LIST_EMPTY(&pmdl->sentinel)) { + struct pmd_list_item * li = (struct pmd_list_item *)(pmdl->sentinel.next); + if (li->hdl->pmd_fini_cb) { + (*li->hdl->pmd_fini_cb)(&li->pmd); + } + fd_list_unlink(&li->chain); + free(li); + } + CHECK_POSIX_DO( pthread_mutex_destroy(&pmdl->lock), ); + pmdl->sentinel.o = NULL; +} + +/* Save the list of pmd into the message structure, as well as the callback to free this list */ +void fd_hook_associate(struct msg * msg, struct fd_msg_pmdl * pmdl) +{ + struct fd_msg_pmdl * in_msg; + + CHECK_PARAMS_DO( msg && pmdl, return ); + in_msg = fd_msg_pmdl_get(msg); + ASSERT(in_msg && (in_msg->sentinel.o == NULL)); /* error / already initialized ??? */ + in_msg->sentinel.o = pmdl_free; + /* Now move all items from the pmdl pointer into the initialized list */ + CHECK_POSIX_DO( pthread_mutex_lock(&pmdl->lock), ); + fd_list_move_end(&in_msg->sentinel, &pmdl->sentinel); + CHECK_POSIX_DO( pthread_mutex_unlock(&pmdl->lock), ); + pmdl_free(pmdl); + /* We're done */ +} + +/* Return the location of the permsgdata area corresponding to this handle, after eventually having created it. Return NULL in case of failure */ +static struct fd_hook_permsgdata * get_or_create_pmd(struct fd_msg_pmdl *pmdl, struct fd_hook_hdl * h) +{ + struct fd_hook_permsgdata * ret = NULL; + struct fd_list * li; + + CHECK_POSIX_DO( pthread_mutex_lock(&pmdl->lock), ); + + if (pmdl->sentinel.o == NULL) { + pmdl->sentinel.o = pmdl_free; + } + + /* Search in the list for an item with the same handle. The list is ordered by this handle */ + for (li=pmdl->sentinel.next; li != &pmdl->sentinel; li = li->next) { + struct pmd_list_item * pli = (struct pmd_list_item *) li; + if (pli->hdl == h->data_hdl) + ret = &pli->pmd; + if (pli->hdl >= h->data_hdl) + break; + } + if (!ret) { + /* we need to create a new one and insert before li */ + struct pmd_list_item * pli; + CHECK_MALLOC_DO( pli = malloc(sizeof_pmd(h->data_hdl)), ); + if (pli) { + memset(pli, 0, sizeof_pmd(h->data_hdl)); + fd_list_init(&pli->chain, pli); + pli->hdl = h->data_hdl; + ret = &pli->pmd; + if (h->data_hdl->pmd_init_cb) { + (*h->data_hdl->pmd_init_cb)(ret); + } + fd_list_insert_before(li, &pli->chain); + } + } + + CHECK_POSIX_DO( pthread_mutex_unlock(&pmdl->lock), ); + return ret; +} + +struct fd_hook_permsgdata * fd_hook_get_request_pmd(struct fd_hook_data_hdl *data_hdl, struct msg * answer) +{ + struct msg * qry; + struct fd_msg_pmdl *pmdl; + struct fd_hook_permsgdata * ret = NULL; + struct fd_list * li; + + CHECK_FCT_DO( fd_msg_answ_getq(answer, &qry), return NULL ); + if (!qry) + return NULL; + + pmdl = fd_msg_pmdl_get(qry); + if (!pmdl) + return NULL; + + CHECK_POSIX_DO( pthread_mutex_lock(&pmdl->lock), ); + /* Search in the list for an item with the same handle. The list is ordered by this handle */ + for (li=pmdl->sentinel.next; li != &pmdl->sentinel; li = li->next) { + struct pmd_list_item * pli = (struct pmd_list_item *) li; + if (pli->hdl == data_hdl) + ret = &pli->pmd; + if (pli->hdl >= data_hdl) + break; + } + CHECK_POSIX_DO( pthread_mutex_unlock(&pmdl->lock), ); + return ret; +} + +/* The function that does the work of calling the extension's callbacks and also managing the permessagedata structures */ +void fd_hook_call(enum fd_hook_type type, struct msg * msg, struct fd_peer * peer, void * other, struct fd_msg_pmdl * pmdl) +{ + struct fd_list * li; + ASSERT(type <= HOOK_PEER_LAST); + int call_default = 0; + + /* lock the list of hooks for this type */ + CHECK_POSIX_DO( pthread_rwlock_rdlock(&HS_array[type].rwlock), ); + + if (FD_IS_LIST_EMPTY(&HS_array[type].sentinel)) { + call_default = 1; + } else { + /* for each registered hook */ + for (li = HS_array[type].sentinel.next; li != &HS_array[type].sentinel; li = li->next) { + struct fd_hook_hdl * h = (struct fd_hook_hdl *)li->o; + struct fd_hook_permsgdata * pmd = NULL; + + /* do we need to handle pmd ? */ + if (h->data_hdl && pmdl) { + pmd = get_or_create_pmd(pmdl, h); + } + + /* Now, call this callback */ + (*h->fd_hook_cb)(type, msg, &peer->p_hdr, other, pmd, h->regdata); + } + } + + /* done */ + CHECK_POSIX_DO( pthread_rwlock_unlock(&HS_array[type].rwlock), ); + + if (call_default) { + char * buf = NULL; + size_t len = 0; + + /* There was no registered handler, default behavior for this hook */ + switch (type) { + case HOOK_DATA_RECEIVED: { + struct fd_cnx_rcvdata *rcv_data = other; + LOG_A("RCV: %zd bytes", rcv_data->length); + break; + } + + case HOOK_MESSAGE_RECEIVED: { + CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break); + LOG_D("RCV from '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf); + break; + } + + case HOOK_MESSAGE_LOCAL: { + CHECK_MALLOC_DO(fd_msg_dump_full(&buf, &len, NULL, msg, NULL, 0, 1), break); + LOG_A("Handled to framework for sending: %s", buf); + break; + } + + case HOOK_MESSAGE_SENT: { + CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break); + LOG_D("SENT to '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf); + break; + } + + case HOOK_MESSAGE_FAILOVER: { + CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break); + LOG_D("Failing over message sent to '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf); + break; + } + + case HOOK_MESSAGE_PARSING_ERROR: { + if (msg) { + DiamId_t id = NULL; + size_t idlen; + if (!fd_msg_source_get( msg, &id, &idlen )) + id = (DiamId_t)"<error getting source>"; + + if (!id) + id = (DiamId_t)"<local>"; + + CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break); + + LOG_E("Parsing error: '%s' for the following message received from '%s':\n%s", (char *)other, (char *)id, buf); + } else { + struct fd_cnx_rcvdata *rcv_data = other; + CHECK_MALLOC_DO(fd_dump_extend_hexdump(&buf, &len, NULL, rcv_data->buffer, rcv_data->length, 0, 0), break); + LOG_E("Parsing error: cannot parse %zdB buffer from '%s': %s", rcv_data->length, peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf); + } + break; + } + + case HOOK_MESSAGE_ROUTING_ERROR: { + DiamId_t id = NULL; + size_t idlen; + if (!fd_msg_source_get( msg, &id, &idlen )) + id = (DiamId_t)"<error getting source>"; + + if (!id) + id = (DiamId_t)"<local>"; + + CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break); + + LOG_E("Routing error: '%s' for the following message:\n%s", (char *)other, buf); + break; + } + + case HOOK_MESSAGE_ROUTING_FORWARD: { + CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break); + LOG_D("FORWARDING: %s", buf); + break; + } + + case HOOK_MESSAGE_ROUTING_LOCAL: { + CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break); + LOG_D("DISPATCHING: %s", buf); + break; + } + + case HOOK_MESSAGE_DROPPED: { + CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break); + LOG_E("Message discarded ('%s'):\n%s", (char *)other, buf); + break; + } + + case HOOK_PEER_CONNECT_FAILED: { + if (msg) { + size_t offset = 0; + CHECK_MALLOC_DO(fd_dump_extend(&buf, &len, &offset, " CER/CEA dump:\n"), break); + CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, &offset, msg, NULL, 0, 1), break); + LOG_N("Connection to '%s' failed: %s%s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", (char *)other, buf); + } else { + LOG_D("Connection to '%s' failed: %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", (char *)other); + } + break; + } + + case HOOK_PEER_CONNECT_SUCCESS: { + CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break); + LOG_N("Connected to '%s', remote capabilities: %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf); + break; + } + + } + + free(buf); + } +}
--- a/libfdcore/messages.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/messages.c Fri May 10 18:49:19 2013 +0800 @@ -345,7 +345,7 @@ /* Parse a message against our dictionary, and in case of error log and eventually build the error reply -- returns the parsing status */ -int fd_msg_parse_or_error( struct msg ** msg ) +int fd_msg_parse_or_error( struct msg ** msg, struct msg **error) { int ret = 0; struct msg * m; @@ -354,8 +354,9 @@ TRACE_ENTRY("%p", msg); - CHECK_PARAMS(msg && *msg); + CHECK_PARAMS(msg && *msg && error); m = *msg; + *error = NULL; /* Parse the message against our dictionary */ ret = fd_msg_parse_rules ( m, fd_g_config->cnf_dict, &pei); @@ -363,8 +364,8 @@ && (ret != ENOTSUP)) /* Command is not supported / Mandatory AVP is not supported */ return ret; /* 0 or another error */ - TRACE_DEBUG(INFO, "A message does not comply to the dictionary and/or rules (%s)", pei.pei_errcode); - fd_msg_dump_walk(FULL, m); + /* Log */ + fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, m, NULL, pei.pei_message ?: pei.pei_errcode, fd_msg_pmdl_get(m)); CHECK_FCT( fd_msg_hdr(m, &hdr) ); @@ -372,10 +373,13 @@ if (hdr->msg_flags & CMD_FLAG_REQUEST) { /* Create the error message */ - CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, pei.pei_protoerr ? MSGFL_ANSW_ERROR : 0 ) ); + CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, &m, pei.pei_protoerr ? MSGFL_ANSW_ERROR : 0 ) ); /* Set the error code */ - CHECK_FCT( fd_msg_rescode_set(*msg, pei.pei_errcode, pei.pei_message, pei.pei_avp, 1 ) ); + CHECK_FCT( fd_msg_rescode_set(m, pei.pei_errcode, pei.pei_message, pei.pei_avp, 1 ) ); + + *msg = NULL; + *error = m; } else { do { /* Rescue error messages */ @@ -408,15 +412,10 @@ default: /* Other errors */ /* We let the application decide what to do with the message, we rescue it */ - return 0; + *error = m; } } } while (0); - - /* Just discard */ - fd_msg_log( FD_MSG_LOG_DROPPED, m, "Answer not compliant to dictionary's ABNF (%s)", pei.pei_errcode ); - CHECK_FCT( fd_msg_free( m ) ); - *msg = NULL; } return EBADMSG; /* We convert ENOTSUP to EBADMSG as well */
--- a/libfdcore/p_ce.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/p_ce.c Fri May 10 18:49:19 2013 +0800 @@ -649,7 +649,7 @@ fd_cnx_destroy(*recv_cnx); *recv_cnx = NULL; if (*cer) { - fd_msg_log(FD_MSG_LOG_DROPPED, *cer, "An error occurred while rejecting a CER."); + //fd_msg_log(FD_MSG_LOG_DROPPED, *cer, "An error occurred while rejecting a CER."); fd_msg_free(*cer); *cer = NULL; } @@ -670,6 +670,8 @@ /* Close initiator connection */ fd_cnx_destroy(initiator); + LOG_D("%s: Election lost on outgoing connection, closing and answering CEA on incoming connection.", peer->p_hdr.info.pi_diamid); + /* Process with the receiver side */ CHECK_FCT( fd_p_ce_process_receiver(peer) ); @@ -677,6 +679,8 @@ struct fd_pei pei; memset(&pei, 0, sizeof(pei)); pei.pei_errcode = "ELECTION_LOST"; + pei.pei_message = "Please answer my CER instead, you won the election."; + LOG_D("%s: Election lost on incoming connection, closing and waiting for CEA on outgoing connection.", peer->p_hdr.info.pi_diamid); /* Answer an ELECTION LOST to the receiver side */ receiver_reject(&peer->p_receiver, &peer->p_cer, &pei); @@ -719,7 +723,11 @@ /* If the state is not WAITCEA, just discard the message */ if (req || ((st = fd_peer_getstate(peer)) != STATE_WAITCEA)) { if (*msg) { - fd_msg_log( FD_MSG_LOG_DROPPED, *msg, "Received CER/CEA while in '%s' state.", STATE_STR(st)); + /* In such case, just discard the message */ + char buf[128]; + snprintf(buf, sizeof(buf), "Received while peer state machine was in state %s.", STATE_STR(st)); + fd_hook_call(HOOK_MESSAGE_DROPPED, *msg, peer, buf, fd_msg_pmdl_get(*msg)); + CHECK_FCT_DO( fd_msg_free(*msg), /* continue */); *msg = NULL; } @@ -730,21 +738,28 @@ memset(&pei, 0, sizeof(pei)); /* Save info from the CEA into the peer */ - CHECK_FCT_DO( save_remote_CE_info(*msg, peer, &pei, &rc), goto cleanup ); - - /* Dispose of the message, we don't need it anymore */ - CHECK_FCT_DO( fd_msg_free(*msg), /* continue */ ); - *msg = NULL; + CHECK_FCT_DO( save_remote_CE_info(*msg, peer, &pei, &rc), + { + fd_hook_call(HOOK_PEER_CONNECT_FAILED, *msg, peer, "An error occurred while processing incoming CEA.", NULL); + goto cleanup; + } ); /* Check the Result-Code */ switch (rc) { case ER_DIAMETER_SUCCESS: + /* Log success */ + fd_hook_call(HOOK_PEER_CONNECT_SUCCESS, *msg, peer, NULL, NULL); + + /* Dispose of the message, we don't need it anymore */ + CHECK_FCT_DO( fd_msg_free(*msg), /* continue */ ); + *msg = NULL; + /* No problem, we can continue */ break; case ER_DIAMETER_TOO_BUSY: /* Retry later */ - TRACE_DEBUG(INFO, "Peer %s replied a CEA with Result-Code AVP DIAMETER_TOO_BUSY, will retry later.", peer->p_hdr.info.pi_diamid); + fd_hook_call(HOOK_PEER_CONNECT_FAILED, *msg, peer, "Remote peer is too busy", NULL); fd_psm_cleanup(peer, 0); fd_psm_next_timeout(peer, 0, 300); return 0; @@ -756,10 +771,11 @@ default: /* In any other case, we abort all attempts to connect to this peer */ - TRACE_DEBUG(INFO, "Peer %s replied a CEA with Result-Code %d, aborting connection attempts.", peer->p_hdr.info.pi_diamid, rc); + fd_hook_call(HOOK_PEER_CONNECT_FAILED, *msg, peer, "CEA with unexpected error code", NULL); return EINVAL; } + /* Handshake if needed, start clear otherwise */ if ( ! fd_cnx_getTLS(peer->p_cnxctx) ) { int todo = peer->p_hdr.info.config.pic_flags.sec & peer->p_hdr.info.runtime.pir_isi ; @@ -777,7 +793,7 @@ CHECK_FCT_DO( fd_cnx_handshake(peer->p_cnxctx, GNUTLS_CLIENT, peer->p_hdr.info.config.pic_priority, NULL), { /* Handshake failed ... */ - fd_log_debug("TLS Handshake failed with peer '%s', resetting the connection", peer->p_hdr.info.pi_diamid); + fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "TLS handshake failed after CER/CEA exchange", NULL); goto cleanup; } ); @@ -817,7 +833,11 @@ TRACE_ENTRY("%p", peer); - CHECK_FCT( set_peer_cnx(peer, &peer->p_receiver) ); + CHECK_FCT_DO( set_peer_cnx(peer, &peer->p_receiver), + { + fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "Error saving the incoming connection in the peer structure", NULL); + return __ret__; + } ); msg = peer->p_cer; peer->p_cer = NULL; @@ -927,6 +947,10 @@ CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, &msg, 0 ) ); CHECK_FCT( fd_msg_rescode_set(msg, "DIAMETER_SUCCESS", NULL, NULL, 0 ) ); CHECK_FCT( add_CE_info(msg, peer->p_cnxctx, isi & PI_SEC_TLS_OLD, isi & PI_SEC_NONE) ); + + /* The connection is complete, but we may still need TLS handshake */ + fd_hook_call(HOOK_PEER_CONNECT_SUCCESS, msg, peer, NULL, NULL); + CHECK_FCT( fd_out_send(&msg, peer->p_cnxctx, peer, FD_CNX_ORDERED ) ); /* Handshake if needed */ @@ -935,19 +959,25 @@ CHECK_FCT_DO( fd_cnx_handshake(peer->p_cnxctx, GNUTLS_SERVER, peer->p_hdr.info.config.pic_priority, NULL), { /* Handshake failed ... */ - fd_log_debug("TLS Handshake failed with peer '%s', resetting the connection", peer->p_hdr.info.pi_diamid); + fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "TLS handshake failed after CER/CEA exchange", NULL); goto cleanup; } ); /* Retrieve the credentials */ - CHECK_FCT( fd_cnx_getcred(peer->p_cnxctx, &peer->p_hdr.info.runtime.pir_cert_list, &peer->p_hdr.info.runtime.pir_cert_list_size) ); + CHECK_FCT_DO( fd_cnx_getcred(peer->p_cnxctx, &peer->p_hdr.info.runtime.pir_cert_list, &peer->p_hdr.info.runtime.pir_cert_list_size), + { + /* Error ... */ + fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "Unable to retrieve remote credentials after TLS handshake", NULL); + goto cleanup; + } ); + /* Call second validation callback if needed */ if (peer->p_cb2) { TRACE_DEBUG(FULL, "Calling second validation callback for %s", peer->p_hdr.info.pi_diamid); CHECK_FCT_DO( (*peer->p_cb2)( &peer->p_hdr.info ), { - TRACE_DEBUG(INFO, "Validation callback rejected the peer %s after handshake", peer->p_hdr.info.pi_diamid); + fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "Validation callback rejected the peer after handshake", NULL); CHECK_FCT( fd_psm_terminate( peer, "DO_NOT_WANT_TO_TALK_TO_YOU" ) ); return 0; } ); @@ -981,12 +1011,16 @@ error_abort: if (pei.pei_errcode) { /* Send the error */ + fd_hook_call(HOOK_PEER_CONNECT_FAILED, msg, peer, pei.pei_message ?: pei.pei_errcode, NULL); receiver_reject(&peer->p_cnxctx, &msg, &pei); + } else { + char buf[1024]; + snprintf(buf, sizeof(buf), "Unexpected error occurred while processing incoming connection from '%s'.", peer->p_hdr.info.pi_diamid); + fd_hook_call(HOOK_PEER_CONNECT_FAILED, msg, peer, buf, NULL); } cleanup: if (msg) { - fd_msg_log(FD_MSG_LOG_DROPPED, msg, "An error occurred while processing a CER."); fd_msg_free(msg); } fd_p_ce_clear_cnx(peer, NULL); @@ -1026,6 +1060,7 @@ if (election_result(peer)) { /* Close initiator connection (was already set as principal) */ + LOG_D("%s: Election lost on outgoing connection, closing and answering CEA on incoming connection.", peer->p_hdr.info.pi_diamid); fd_p_ce_clear_cnx(peer, NULL); /* and go on with the receiver side */ @@ -1040,6 +1075,7 @@ /* Answer an ELECTION LOST to the receiver side and continue */ pei.pei_errcode = "ELECTION_LOST"; pei.pei_message = "Please answer my CER instead, you won the election."; + LOG_D("%s: Election lost on incoming connection, closing and waiting for CEA on outgoing connection.", peer->p_hdr.info.pi_diamid); receiver_reject(cnx, msg, &pei); } break; @@ -1047,6 +1083,7 @@ default: pei.pei_errcode = "DIAMETER_UNABLE_TO_COMPLY"; /* INVALID COMMAND? in case of Capabilities-Updates? */ pei.pei_message = "Invalid state to receive a new connection attempt."; + LOG_E("%s: Rejecting new connection attempt while our state machine is in state '%s'", peer->p_hdr.info.pi_diamid, STATE_STR(cur_state)); receiver_reject(cnx, msg, &pei); }
--- a/libfdcore/p_cnx.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/p_cnx.c Fri May 10 18:49:19 2013 +0800 @@ -235,7 +235,8 @@ } if (FD_IS_LIST_EMPTY(&peer->p_connparams)) { /* We encountered an error or we have looped over all the addresses of the peer. */ - TRACE_DEBUG(INFO, "Unable to connect to the peer %s, aborting attempts for now.", peer->p_hdr.info.pi_diamid); + fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "All connection attempts failed, will retry later", NULL); + CHECK_FCT_DO( fatal_error = fd_event_send(peer->p_events, FDEVP_CNX_FAILED, 0, NULL), goto out ); return NULL; } @@ -278,12 +279,13 @@ CHECK_FCT_DO( fd_cnx_handshake(cnx, GNUTLS_CLIENT, peer->p_hdr.info.config.pic_priority, NULL), { /* Handshake failed ... */ - TRACE_DEBUG(INFO, "TLS Handshake failed with peer '%s', resetting the connection", peer->p_hdr.info.pi_diamid); + fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "TLS Handshake failed", NULL); fd_cnx_destroy(cnx); empty_connection_list(peer); fd_ep_filter(&peer->p_hdr.info.pi_endpoints, EP_FL_CONF); goto out_pop; } ); + LOG_A("%s: TLS handshake successful.", peer->p_hdr.info.pi_diamid); } else { /* Prepare to receive the next message */ CHECK_FCT_DO( fatal_error = fd_cnx_start_clear(cnx, 0), goto out_pop );
--- a/libfdcore/p_out.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/p_out.c Fri May 10 18:49:19 2013 +0800 @@ -36,7 +36,7 @@ #include "fdcore-internal.h" /* Alloc a new hbh for requests, bufferize the message and send on the connection, save in sentreq if provided */ -static int do_send(struct msg ** msg, uint32_t flags, struct cnxctx * cnx, uint32_t * hbh, struct sr_list * srl) +static int do_send(struct msg ** msg, uint32_t flags, struct cnxctx * cnx, uint32_t * hbh, struct fd_peer * peer) { struct msg_hdr * hdr; int msg_is_a_req; @@ -44,17 +44,16 @@ size_t sz; int ret; uint32_t bkp_hbh = 0; - struct timespec senton; - struct msg * cpy_for_logs_only; + struct msg *cpy_for_logs_only; - TRACE_ENTRY("%p %x %p %p %p", msg, flags, cnx, hbh, srl); + TRACE_ENTRY("%p %x %p %p %p", msg, flags, cnx, hbh, peer); /* Retrieve the message header */ CHECK_FCT( fd_msg_hdr(*msg, &hdr) ); msg_is_a_req = (hdr->msg_flags & CMD_FLAG_REQUEST); if (msg_is_a_req) { - CHECK_PARAMS(hbh && srl); + CHECK_PARAMS(hbh && peer); /* Alloc the hop-by-hop id and increment the value for next message */ bkp_hbh = hdr->msg_hbhid; hdr->msg_hbhid = *hbh; @@ -69,34 +68,11 @@ /* Save a request before sending so that there is no race condition with the answer */ if (msg_is_a_req) { - CHECK_FCT_DO( ret = fd_p_sr_store(srl, msg, &hdr->msg_hbhid, bkp_hbh), goto out ); + CHECK_FCT_DO( ret = fd_p_sr_store(&peer->p_sr, msg, &hdr->msg_hbhid, bkp_hbh), goto out ); } - CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &senton), /* ... */ ); - CHECK_FCT_DO( fd_msg_ts_set_sent(cpy_for_logs_only, &senton), /* ... */ ); - /* Log the message */ - fd_msg_log( FD_MSG_LOG_SENT, cpy_for_logs_only, "Sent to '%s'", fd_cnx_getid(cnx)); - - { - struct timespec rcvon, delay; - - (void) fd_msg_ts_get_recv(cpy_for_logs_only, &rcvon); - if (rcvon.tv_sec != 0 || rcvon.tv_nsec != 0) { - TS_DIFFERENCE( &delay, &rcvon, &senton); - fd_msg_log( FD_MSG_LOG_TIMING, cpy_for_logs_only, "Forwarded in %ld.%6.6ld sec", (long)delay.tv_sec, delay.tv_nsec/1000); - } else { /* We log the answer time only for answers generated locally */ - if (!msg_is_a_req) { - /* get the matching request */ - struct msg * req; - struct timespec reqrcvon; - (void) fd_msg_answ_getq(cpy_for_logs_only, &req); - (void) fd_msg_ts_get_recv(req, &reqrcvon); - TS_DIFFERENCE( &delay, &reqrcvon, &senton); - fd_msg_log( FD_MSG_LOG_TIMING, cpy_for_logs_only, "Answered in %ld.%6.6ld sec", (long)delay.tv_sec, delay.tv_nsec/1000); - } - } - } + fd_hook_call(HOOK_MESSAGE_SENT, cpy_for_logs_only, peer, NULL, fd_msg_pmdl_get(cpy_for_logs_only)); /* Send the message */ CHECK_FCT_DO( ret = fd_cnx_send(cnx, buf, sz, flags), ); @@ -121,7 +97,7 @@ struct msg *msg = arg; CHECK_FCT_DO(fd_fifo_post(fd_g_outgoing, &msg), { - fd_msg_log( FD_MSG_LOG_DROPPED, msg, "An error occurred while attempting to requeue this message during cancellation of the sending function"); + //fd_msg_log( FD_MSG_LOG_DROPPED, msg, "An error occurred while attempting to requeue this message during cancellation of the sending function"); CHECK_FCT_DO(fd_msg_free(msg), /* What can we do more? */); } ); } @@ -151,10 +127,10 @@ pthread_cleanup_push(cleanup_requeue, msg); /* Send the message, log any error */ - CHECK_FCT_DO( ret = do_send(&msg, 0, peer->p_cnxctx, &peer->p_hbh, &peer->p_sr), + CHECK_FCT_DO( ret = do_send(&msg, 0, peer->p_cnxctx, &peer->p_hbh, peer), { if (msg) { - fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Internal error: Problem while sending (%s)", strerror(ret) ); + //fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Internal error: Problem while sending (%s)", strerror(ret) ); fd_msg_free(msg); } } ); @@ -203,10 +179,10 @@ cnx = peer->p_cnxctx; /* Do send the message */ - CHECK_FCT_DO( ret = do_send(msg, flags, cnx, hbh, peer ? &peer->p_sr : NULL), + CHECK_FCT_DO( ret = do_send(msg, flags, cnx, hbh, peer), { if (msg) { - fd_msg_log( FD_MSG_LOG_DROPPED, *msg, "Internal error: Problem while sending (%s)", strerror(ret) ); + //fd_msg_log( FD_MSG_LOG_DROPPED, *msg, "Internal error: Problem while sending (%s)", strerror(ret) ); fd_msg_free(*msg); *msg = NULL; }
--- a/libfdcore/p_psm.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/p_psm.c Fri May 10 18:49:19 2013 +0800 @@ -240,7 +240,7 @@ case FDEVP_CNX_INCOMING: { struct cnx_incoming * evd = ev->data; - fd_msg_log( FD_MSG_LOG_DROPPED, evd->cer, "Message discarded while cleaning peer state machine queue." ); + //fd_msg_log( FD_MSG_LOG_DROPPED, evd->cer, "Message discarded while cleaning peer state machine queue." ); CHECK_FCT_DO( fd_msg_free(evd->cer), /* continue */); fd_cnx_destroy(evd->cnx); } @@ -453,12 +453,6 @@ goto psm_loop; } - /* Handle the (easy) debug event now */ - if (event == FDEVP_DUMP_ALL) { - fd_peer_dump(peer, ANNOYING); - goto psm_loop; - } - /* Requests to terminate the peer object */ if (event == FDEVP_TERMINATE) { switch (cur_state) { @@ -488,33 +482,32 @@ if (event == FDEVP_CNX_MSG_RECV) { struct msg * msg = NULL; struct msg_hdr * hdr; - struct timespec rcvon; + struct fd_cnx_rcvdata rcv_data; + struct fd_msg_pmdl * pmdl = NULL; - /* Retrieve the piggytailed timestamp */ - memcpy(&rcvon, ev_data+ev_sz, sizeof(struct timespec)); + rcv_data.buffer = ev_data; + rcv_data.length = ev_sz; + pmdl = fd_msg_pmdl_get_inbuf(rcv_data.buffer, rcv_data.length); /* Parse the received buffer */ CHECK_FCT_DO( fd_msg_parse_buffer( (void *)&ev_data, ev_sz, &msg), { - fd_log_debug("Received invalid data from peer '%s', closing the connection", peer->p_hdr.info.pi_diamid); + fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, NULL, peer, &rcv_data, pmdl ); free(ev_data); CHECK_FCT_DO( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL), goto psm_reset ); goto psm_loop; } ); - CHECK_FCT_DO( fd_msg_ts_set_recv(msg, &rcvon), /* ... */ ); - + fd_hook_associate(msg, pmdl); + /* If the current state does not allow receiving messages, just drop it */ if (cur_state == STATE_CLOSED) { /* In such case, just discard the message */ - fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Purged from peer '%s''s queue (CLOSED state).", peer->p_hdr.info.pi_diamid ); + fd_hook_call(HOOK_MESSAGE_DROPPED, msg, peer, "Message purged from queue, peer in CLOSED state", fd_msg_pmdl_get(msg)); fd_msg_free(msg); goto psm_loop; } - /* Log incoming message */ - fd_msg_log( FD_MSG_LOG_RECEIVED, msg, "Received %zdb from '%s' (%s)", ev_sz, peer->p_hdr.info.pi_diamid, STATE_STR(cur_state) ); - /* Extract the header */ CHECK_FCT_DO( fd_msg_hdr(msg, &hdr), goto psm_end ); @@ -524,7 +517,7 @@ /* Search matching request (same hbhid) */ CHECK_FCT_DO( fd_p_sr_fetch(&peer->p_sr, hdr->msg_hbhid, &req), goto psm_end ); if (req == NULL) { - fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Answer received with no corresponding sent request." ); + fd_hook_call(HOOK_MESSAGE_DROPPED, msg, peer, "Answer received with no corresponding sent request.", fd_msg_pmdl_get(msg)); fd_msg_free(msg); goto psm_loop; } @@ -532,13 +525,6 @@ /* Associate */ CHECK_FCT_DO( fd_msg_answ_associate( msg, req ), goto psm_end ); - /* Display the delay to receive the answer */ - { - struct timespec reqsent, delay; - (void) fd_msg_ts_get_sent(req, &reqsent); - TS_DIFFERENCE( &delay, &reqsent, &rcvon ); - fd_msg_log( FD_MSG_LOG_TIMING, msg, "Answer received in %ld.%6.6ld sec.", (long)delay.tv_sec, delay.tv_nsec / 1000 ); - } } else { /* Mark the incoming request so that we know we have pending answers for this peer */ CHECK_POSIX_DO( pthread_mutex_lock(&peer->p_state_mtx), goto psm_end ); @@ -546,6 +532,9 @@ CHECK_POSIX_DO( pthread_mutex_unlock(&peer->p_state_mtx), goto psm_end ); } + /* Log incoming message */ + fd_hook_call(HOOK_MESSAGE_RECEIVED, msg, peer, NULL, fd_msg_pmdl_get(msg)); + if (cur_state == STATE_OPEN_NEW) { /* OK, we have received something, so the connection is supposedly now in OPEN state at the remote site */ fd_psm_change_state(peer, STATE_OPEN ); @@ -583,30 +572,41 @@ case STATE_WAITCNXACK_ELEC: case STATE_WAITCEA: case STATE_CLOSED: - default: + default: { /* In such case, just discard the message */ - fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Received from peer '%s' while connection was not in state %s.", peer->p_hdr.info.pi_diamid, STATE_STR(cur_state) ); + char buf[128]; + snprintf(buf, sizeof(buf), "Received while peer state machine was in state %s.", STATE_STR(cur_state)); + fd_hook_call(HOOK_MESSAGE_DROPPED, msg, peer, buf, fd_msg_pmdl_get(msg)); fd_msg_free(msg); + } } goto psm_loop; } /* Link-local message: They must be understood by our dictionary, otherwise we return an error */ { - int ret = fd_msg_parse_or_error( &msg ); + struct msg * error = NULL; + int ret = fd_msg_parse_or_error( &msg, &error ); if (ret != EBADMSG) { - CHECK_FCT_DO( ret, goto psm_end ); + CHECK_FCT_DO( ret, + { + LOG_E("%s: An unexpected error occurred while parsing a link-local message", peer->p_hdr.info.pi_diamid); + fd_msg_free(msg); + goto psm_end; + } ); } else { - if (msg) { + if (msg == NULL) { /* Send the error back to the peer */ - CHECK_FCT_DO( ret = fd_out_send(&msg, NULL, peer, FD_CNX_ORDERED), ); - if (msg) { + CHECK_FCT_DO( ret = fd_out_send(&error, NULL, peer, FD_CNX_ORDERED), ); + if (error) { /* Only if an error occurred & the message was not saved / dumped */ - fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Internal error: Problem while sending (%s)", strerror(ret) ); - CHECK_FCT_DO( fd_msg_free(msg), goto psm_end); + LOG_E("%s: error sending a message", peer->p_hdr.info.pi_diamid); + CHECK_FCT_DO( fd_msg_free(error), goto psm_end); } } else { /* We received an invalid answer, let's disconnect */ + LOG_E("%s: Received invalid answer to Base protocol message, disconnecting...", peer->p_hdr.info.pi_diamid); + CHECK_FCT_DO( fd_msg_free(msg), goto psm_end); CHECK_FCT_DO( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL), goto psm_reset ); } goto psm_loop; @@ -616,7 +616,12 @@ /* Handle the LL message and update the expiry timer appropriately */ switch (hdr->msg_code) { case CC_CAPABILITIES_EXCHANGE: - CHECK_FCT_DO( fd_p_ce_msgrcv(&msg, (hdr->msg_flags & CMD_FLAG_REQUEST), peer), goto psm_reset ); + CHECK_FCT_DO( fd_p_ce_msgrcv(&msg, (hdr->msg_flags & CMD_FLAG_REQUEST), peer), + { + if (msg) + CHECK_FCT_DO( fd_msg_free(msg), ); + goto psm_reset; + } ); break; case CC_DISCONNECT_PEER: @@ -651,7 +656,7 @@ /* Cleanup the message if not done */ if (msg) { - fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Received un-handled non-routable command from peer '%s'.", peer->p_hdr.info.pi_diamid ); + //fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Received un-handled non-routable command from peer '%s'.", peer->p_hdr.info.pi_diamid ); CHECK_FCT_DO( fd_msg_free(msg), /* continue */); msg = NULL; } @@ -659,7 +664,7 @@ /* At this point the message must have been fully handled already */ if (msg) { - fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Internal error ('%s'): unhandled message.", peer->p_hdr.info.pi_diamid ); + //fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Internal error ('%s'): unhandled message.", peer->p_hdr.info.pi_diamid ); fd_msg_free(msg); } @@ -685,6 +690,8 @@ default: /* Mark the connection problem */ peer->p_flags.pf_cnx_pb = 1; + + fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "The connection was broken", NULL); /* Destroy the connection, restart the timer to a new connection attempt */ fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_tctimer ?: fd_g_config->cnf_timer_tc); @@ -720,11 +727,12 @@ /* Get the new ones */ CHECK_FCT_DO( fd_cnx_getremoteeps(peer->p_cnxctx, &peer->p_hdr.info.pi_endpoints), /* ignore the error */); - /* We do not support local endpoints change currently, but it could be added here if needed (refresh fd_g_config->cnf_endpoints)*/ - - if (TRACE_BOOL(ANNOYING)) { - TRACE_DEBUG(ANNOYING, "New remote endpoint(s):" ); - fd_ep_dump(6, &peer->p_hdr.info.pi_endpoints); + /* We do not support local endpoints change currently, but it could be added here if needed (refresh fd_g_config->cnf_endpoints) */ + { + char * buf = NULL; + size_t len = 0; + LOG_D("New remote endpoint(s): %s", fd_ep_dump(&buf, &len, NULL, 6, &peer->p_hdr.info.pi_endpoints) ?: "error"); + free(buf); } /* Done */ @@ -745,7 +753,6 @@ params->cnx = NULL; } if (params->cer) { - fd_msg_log( FD_MSG_LOG_DROPPED, params->cer, "Internal error: this CER was not handled as expected." ); CHECK_FCT_DO( fd_msg_free(params->cer), ); params->cer = NULL; } @@ -766,6 +773,7 @@ switch (cur_state) { case STATE_WAITCNXACK_ELEC: case STATE_WAITCNXACK: + LOG_D("%s: Connection established", peer->p_hdr.info.pi_diamid); fd_p_ce_handle_newcnx(peer, cnx); break; @@ -794,6 +802,7 @@ break; case STATE_WAITCNXACK: + LOG_D("%s: Connection attempt failed", peer->p_hdr.info.pi_diamid); /* Go back to CLOSE */ fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_tctimer ?: fd_g_config->cnf_timer_tc); goto psm_reset; @@ -816,6 +825,7 @@ goto psm_loop; case STATE_CLOSED: + LOG_D("%s: Connecting...", peer->p_hdr.info.pi_diamid); CHECK_FCT_DO( fd_psm_change_state(peer, STATE_WAITCNXACK), goto psm_end ); fd_psm_next_timeout(peer, 0, CNX_TIMEOUT); CHECK_FCT_DO( fd_p_cnx_init(peer), goto psm_end ); @@ -824,9 +834,10 @@ case STATE_SUSPECT: /* Mark the connection problem */ peer->p_flags.pf_cnx_pb = 1; - case STATE_CLOSING: case STATE_WAITCNXACK: case STATE_WAITCEA: + fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "Timeout while waiting for remote peer", NULL); + case STATE_CLOSING: /* Destroy the connection, restart the timer to a new connection attempt */ fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_tctimer ?: fd_g_config->cnf_timer_tc); goto psm_reset; @@ -862,6 +873,7 @@ goto psm_loop; psm_end: + LOG_N("%s: Going to ZOMBIE state (no more activity)", peer->p_hdr.info.pi_diamid); fd_psm_cleanup(peer, 1); TRACE_DEBUG(INFO, "'%s'\t-> STATE_ZOMBIE (terminated)\t'%s'", STATE_STR(fd_peer_getstate(peer)),
--- a/libfdcore/p_sr.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/p_sr.c Fri May 10 18:49:19 2013 +0800 @@ -118,7 +118,7 @@ /* If the callback did not dispose of the message, do it now */ if (ed->request) { - fd_msg_log(FD_MSG_LOG_DROPPED, ed->request, "Expiration period completed without an answer, and the expiry callback did not dispose of the message."); + //fd_msg_log(FD_MSG_LOG_DROPPED, ed->request, "Expiration period completed without an answer, and the expiry callback did not dispose of the message."); CHECK_FCT_DO( fd_msg_free(ed->request), /* ignore */ ); } @@ -195,7 +195,7 @@ /* loop */ } while (1); error: - ; /* pthread_cleanup_pop sometimes expands as "} ..." and the label beofre this cause some compilers to complain... */ + ; /* pthread_cleanup_pop sometimes expands as "} ..." and the label before this cause some compilers to complain... */ pthread_cleanup_pop( 1 ); ASSERT(0); /* we have encountered a problem, maybe time to signal the framework to terminate? */ return NULL; @@ -324,12 +324,12 @@ /* Requeue for sending to another peer */ CHECK_FCT_DO( ret = fd_fifo_post(fd_g_outgoing, &sr->req), { - fd_msg_log( FD_MSG_LOG_DROPPED, sr->req, "Internal error: error while requeuing during failover: %s", strerror(ret) ); + //fd_msg_log( FD_MSG_LOG_DROPPED, sr->req, "Internal error: error while requeuing during failover: %s", strerror(ret) ); CHECK_FCT_DO(fd_msg_free(sr->req), /* What can we do more? */) }); } else { /* Just free the request. */ - fd_msg_log( FD_MSG_LOG_DROPPED, sr->req, "Sent & unanswered local message discarded during failover." ); + //fd_msg_log( FD_MSG_LOG_DROPPED, sr->req, "Sent & unanswered local message discarded during failover." ); CHECK_FCT_DO(fd_msg_free(sr->req), /* Ignore */); } free(sr);
--- a/libfdcore/peers.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/peers.c Fri May 10 18:49:19 2013 +0800 @@ -244,7 +244,7 @@ CHECK_FCT_DO(fd_fifo_post(fd_g_outgoing, &m), { /* fallback: destroy the message */ - fd_msg_log(FD_MSG_LOG_DROPPED, m, "Internal error: unable to requeue this message during failover process"); + //fd_msg_log(FD_MSG_LOG_DROPPED, m, "Internal error: unable to requeue this message during failover process"); CHECK_FCT_DO(fd_msg_free(m), /* What can we do more? */) } ); } @@ -409,53 +409,61 @@ } /* Dump info of one peer */ -void fd_peer_dump(struct fd_peer * peer, int details) +DECLARE_FD_DUMP_PROTOTYPE(fd_peer_dump, struct peer_hdr * p, int details) { - char buf[1024]; - if (peer->p_eyec != EYEC_PEER) { - fd_log_debug(" Invalid peer @ %p !", peer); - return; - } - - snprintf(buf, sizeof(buf), "> %s\t%s\t[%ldsr,%ldpa]", STATE_STR(fd_peer_getstate(peer)), peer->p_hdr.info.pi_diamid, peer->p_sr.cnt, peer->p_reqin_count); - if (details > INFO) { - snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "\t(rlm:%s)", peer->p_hdr.info.runtime.pir_realm ?: "<unknown>"); - if (peer->p_hdr.info.runtime.pir_prodname) - snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "\t['%s' %u]", peer->p_hdr.info.runtime.pir_prodname, peer->p_hdr.info.runtime.pir_firmrev); + FD_DUMP_HANDLE_OFFSET(); + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{peer}(@%p): ", p), return NULL); + + if (!CHECK_PEER(p)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL); + } else { + struct fd_peer * peer = (struct fd_peer *)p; + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s [%s, cnt:%ldsr,%ldpa]", peer->p_hdr.info.pi_diamid, STATE_STR(fd_peer_getstate(peer)), peer->p_sr.cnt, peer->p_reqin_count), return NULL); + if (details > 0) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " rlm:%s", peer->p_hdr.info.runtime.pir_realm ?: "<unknown>"), return NULL); + if (peer->p_hdr.info.runtime.pir_prodname) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " ['%s' %u]", peer->p_hdr.info.runtime.pir_prodname, peer->p_hdr.info.runtime.pir_firmrev), return NULL); + } + } + if (details > 1) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " [from:%s] flags:%s%s%s%s%s%s%s lft:%ds", + peer->p_dbgorig ?: "unset", + peer->p_hdr.info.config.pic_flags.pro3 == PI_P3_DEFAULT ? "-" : + (peer->p_hdr.info.config.pic_flags.pro3 == PI_P3_IP ? "4" : "6"), + peer->p_hdr.info.config.pic_flags.pro4 == PI_P4_DEFAULT ? "-" : + (peer->p_hdr.info.config.pic_flags.pro4 == PI_P4_TCP ? "T" : "S"), + peer->p_hdr.info.config.pic_flags.alg ? "P" : "-", + peer->p_hdr.info.config.pic_flags.sec & PI_SEC_NONE ? "N" :"-", + peer->p_hdr.info.config.pic_flags.sec & PI_SEC_TLS_OLD ? "O" :"-", + peer->p_hdr.info.config.pic_flags.exp ? "E" : "-", + peer->p_hdr.info.config.pic_flags.persist ? "P" : "-", + peer->p_hdr.info.config.pic_lft), return NULL); + } + } - fd_log_debug("%s", buf); - if (details > FULL) { - /* Dump all info */ - fd_log_debug("\tEntry origin : %s", peer->p_dbgorig?: "not set"); - fd_log_debug("\tConfig flags : %s%s%s - %s%s - %s%s", - peer->p_hdr.info.config.pic_flags.pro3 == PI_P3_DEFAULT ? "." : - (peer->p_hdr.info.config.pic_flags.pro3 == PI_P3_IP ? "IP" : "IPv6"), - peer->p_hdr.info.config.pic_flags.pro4 == PI_P4_DEFAULT ? "." : - (peer->p_hdr.info.config.pic_flags.pro4 == PI_P4_TCP ? "TCP" : "SCTP"), - peer->p_hdr.info.config.pic_flags.alg ? "PrefTCP" : ".", - peer->p_hdr.info.config.pic_flags.sec & PI_SEC_NONE ? "NoTLSok" :".", - peer->p_hdr.info.config.pic_flags.sec & PI_SEC_TLS_OLD ? "OldTLS" :".", - peer->p_hdr.info.config.pic_flags.exp ? "Expire" : ".", - peer->p_hdr.info.config.pic_flags.persist ? "Persist" : "." - ); - fd_log_debug("\tLifetime : %d sec", peer->p_hdr.info.config.pic_lft); - } + + return *buf; } /* Dump the list of peers */ -void fd_peer_dump_list(int details) +DECLARE_FD_DUMP_PROTOTYPE(fd_peer_dump_list, int details) { struct fd_list * li; + FD_DUMP_HANDLE_OFFSET(); - fd_log_debug("Dumping list of peers :"); CHECK_FCT_DO( pthread_rwlock_rdlock(&fd_g_peers_rw), /* continue */ ); for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) { - struct fd_peer * np = (struct fd_peer *)li->o; - fd_peer_dump(np, details); + CHECK_MALLOC_DO( fd_peer_dump(FD_DUMP_STD_PARAMS, (struct peer_hdr *)li->o, details), break); + if (li->next != &fd_g_peers) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), break); + } } CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ ); + return *buf; } static struct dict_object *avp_oh_model = NULL; @@ -482,9 +490,8 @@ CHECK_POSIX( pthread_mutex_lock(&cache_avp_lock) ); if (!avp_oh_model) { avp_code_t code = AC_ORIGIN_HOST; - int ret; - CHECK_FCT_DO( ret = fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_CODE, &code, &avp_oh_model, ENOENT), - { CHECK_POSIX( pthread_mutex_unlock(&cache_avp_lock) ); return ret; } ); + CHECK_FCT_DO( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_CODE, &code, &avp_oh_model, ENOENT), + { LOG_E("Cannot find Origin-Host AVP definition in the dictionary!"); (void) pthread_mutex_unlock(&cache_avp_lock); return __ret__; } ); } CHECK_POSIX( pthread_mutex_unlock(&cache_avp_lock) ); @@ -495,10 +502,12 @@ /* First, check if the Origin-Host value is valid */ if (!fd_os_is_valid_DiameterIdentity(avp_hdr->avp_value->os.data, avp_hdr->avp_value->os.len)) { - TRACE_DEBUG(INFO, "Received new CER with invalid Origin-Host"); CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, cer, MSGFL_ANSW_ERROR ) ); CHECK_FCT( fd_msg_rescode_set(*cer, "DIAMETER_INVALID_AVP_VALUE", "Your Origin-Host contains invalid characters.", avp_oh, 1 ) ); + + fd_hook_call(HOOK_PEER_CONNECT_FAILED, *cer, NULL, "Received CER with invalid Origin-Host AVP", NULL); + CHECK_FCT( fd_out_send(cer, *cnx, NULL, FD_CNX_ORDERED) ); return EINVAL; } @@ -537,6 +546,8 @@ peer->p_flags.pf_responder = 1; peer->p_flags.pf_delete = 1; + LOG_D("Created new peer object for incoming CER: %s", peer->p_hdr.info.pi_diamid); + #ifndef DISABLE_PEER_EXPIRY /* Set this peer to expire on inactivity */ peer->p_hdr.info.config.pic_flags.exp = PI_EXP_INACTIVE; @@ -582,6 +593,10 @@ /* Reset the "out" parameters, so that they are not cleanup on function return. */ *cer = NULL; *cnx = NULL; + } else { + char buf[1024]; + snprintf(buf, sizeof(buf), "An error occurred while processing new incoming CER: %s", strerror(ret)); + fd_hook_call(HOOK_PEER_CONNECT_FAILED, *cer, NULL, buf, NULL); } return ret;
--- a/libfdcore/queues.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/queues.c Fri May 10 18:49:19 2013 +0800 @@ -73,7 +73,7 @@ CHECK_FCT(ret); /* We got one! */ - fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Message lost because framework is terminating." ); + //fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Message lost because framework is terminating." ); fd_msg_free(msg); }
--- a/libfdcore/routing_dispatch.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/routing_dispatch.c Fri May 10 18:49:19 2013 +0800 @@ -392,7 +392,7 @@ CHECK_FCT( fd_peer_getbyid( id, idlen, 0, (void *)&peer ) ); if (!peer) { - fd_msg_log(FD_MSG_LOG_DROPPED, *pmsg, "Unable to send error '%s' to deleted peer '%s' in reply to this message.", error_code, id); + //fd_msg_log(FD_MSG_LOG_DROPPED, *pmsg, "Unable to send error '%s' to deleted peer '%s' in reply to this message.", error_code, id); fd_msg_free(*pmsg); *pmsg = NULL; return 0; @@ -431,7 +431,7 @@ enum disp_action action; char * ec = NULL; char * em = NULL; - struct msg *msgptr = msg; + struct msg *msgptr = msg, *error = NULL; /* Read the message header */ CHECK_FCT( fd_msg_hdr(msg, &hdr) ); @@ -441,19 +441,27 @@ (draft-asveren-dime-dupcons-00). This may conflict with path validation decisions, no clear answer yet */ /* At this point, we need to understand the message content, so parse it */ - CHECK_FCT_DO( ret = fd_msg_parse_or_error( &msgptr ), + CHECK_FCT_DO( fd_msg_parse_or_error( &msgptr, &error ), { - /* in case of error */ - if ((ret == EBADMSG) && (msgptr != NULL)) { - /* msgptr now contains the answer message to send back */ - CHECK_FCT( fd_fifo_post(fd_g_outgoing, &msgptr) ); + int rescue = 0; + if (__ret__ != EBADMSG) { + fd_hook_call(HOOK_MESSAGE_DROPPED, msgptr, NULL, "Error while parsing received answer", fd_msg_pmdl_get(msgptr)); + fd_msg_free(msgptr); + } else { + if (!msgptr) { + /* error now contains the answer message to send back */ + CHECK_FCT( fd_fifo_post(fd_g_outgoing, &error) ); + } else if (!error) { + /* We have received an invalid answer to our query */ + fd_hook_call(HOOK_MESSAGE_DROPPED, msgptr, NULL, "Received answer failed the dictionary / rules parsing", fd_msg_pmdl_get(msgptr)); + fd_msg_free(msgptr); + } else { + /* We will pass the invalid received error to the application */ + rescue = 1; + } } - if (msgptr) { /* another error happen'd */ - fd_msg_log( FD_MSG_LOG_DROPPED, msgptr, "An unexpected error occurred while parsing the message (%s)", strerror(ret)); - CHECK_FCT_DO( fd_msg_free(msgptr), /* continue */); - } - /* We're done with this one */ - return 0; + if (!rescue) + return 0; /* We are done with this message, go to the next */ } ); /* First, if the original request was registered with a callback and we receive the answer, call it. */ @@ -510,7 +518,7 @@ } if (!is_req) { - fd_msg_log( FD_MSG_LOG_DROPPED, msgptr, "Internal error: Answer received to locally issued request, but not handled by any handler."); + //fd_msg_log( FD_MSG_LOG_DROPPED, msgptr, "Internal error: Answer received to locally issued request, but not handled by any handler."); fd_msg_free(msgptr); break; } @@ -755,7 +763,7 @@ TRACE_DEBUG(ANNOYING, "Calling next FWD callback on %p : %p", msgptr, rh->rt_fwd_cb); CHECK_FCT_DO( ret = (*rh->rt_fwd_cb)(rh->cbdata, &msgptr), { - fd_msg_log( FD_MSG_LOG_DROPPED, msgptr, "Internal error: a FWD routing callback returned an error (%s)", strerror(ret)); + //fd_msg_log( FD_MSG_LOG_DROPPED, msgptr, "Internal error: a FWD routing callback returned an error (%s)", strerror(ret)); fd_msg_free(msgptr); msgptr = NULL; } ); @@ -814,7 +822,7 @@ /* Find the peer corresponding to this name */ CHECK_FCT( fd_peer_getbyid( qry_src, qry_src_len, 0, (void *) &peer ) ); if (fd_peer_getstate(peer) != STATE_OPEN) { - fd_msg_log( FD_MSG_LOG_DROPPED, msgptr, "Unable to forward answer to deleted / closed peer '%s'.", qry_src); + //fd_msg_log( FD_MSG_LOG_DROPPED, msgptr, "Unable to forward answer to deleted / closed peer '%s'.", qry_src); fd_msg_free(msgptr); return 0; } @@ -899,7 +907,7 @@ TRACE_DEBUG(ANNOYING, "Calling next OUT callback on %p : %p (prio %d)", msgptr, rh->rt_out_cb, rh->prio); CHECK_FCT_DO( ret = (*rh->rt_out_cb)(rh->cbdata, msgptr, candidates), { - fd_msg_log( FD_MSG_LOG_DROPPED, msgptr, "Internal error: an OUT routing callback returned an error (%s)", strerror(ret)); + //fd_msg_log( FD_MSG_LOG_DROPPED, msgptr, "Internal error: an OUT routing callback returned an error (%s)", strerror(ret)); fd_msg_free(msgptr); msgptr = NULL; break; @@ -947,7 +955,7 @@ /* If the message has not been sent, return an error */ if (msgptr) { - fd_msg_log( FD_MSG_LOG_NODELIVER, msgptr, "No suitable candidate to route the message to." ); + //fd_msg_log( FD_MSG_LOG_NODELIVER, msgptr, "No suitable candidate to route the message to." ); return_error( &msgptr, "DIAMETER_UNABLE_TO_DELIVER", "No suitable candidate to route the message to", NULL); }
--- a/libfdcore/sctp.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/sctp.c Fri May 10 18:49:19 2013 +0800 @@ -1067,7 +1067,6 @@ size_t bufsz = 0, datasize = 0; size_t mempagesz = sysconf(_SC_PAGESIZE); /* We alloc buffer by memory pages for efficiency */ int timedout = 0; - struct timespec recv_on; TRACE_ENTRY("%p %p %p %p %p", conn, strid, buf, len, event); CHECK_PARAMS( conn && buf && len && event ); @@ -1086,7 +1085,7 @@ /* We will loop while all data is not received. */ incomplete: - while (datasize + sizeof(struct timespec) >= bufsz ) { + while (datasize >= bufsz ) { /* The buffer is full, enlarge it */ bufsz += mempagesz; CHECK_MALLOC( data = realloc(data, bufsz ) ); @@ -1094,7 +1093,7 @@ /* the new data will be received following the preceding */ memset(&iov, 0, sizeof(iov)); iov.iov_base = data + datasize ; - iov.iov_len = bufsz - sizeof(struct timespec) - datasize; + iov.iov_len = bufsz - datasize; /* Receive data from the socket */ again: @@ -1188,10 +1187,6 @@ return 0; } - /* Piggy-tail the timestamp of reception */ - CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &recv_on), /* continue */ ); - memcpy(data + datasize, &recv_on, sizeof(struct timespec)); - /* From this point, we have received a message */ *event = FDEVP_CNX_MSG_RECV; *buf = data;
--- a/libfdcore/sctps.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/sctps.c Fri May 10 18:49:19 2013 +0800 @@ -91,7 +91,6 @@ case FDEVP_CNX_MSG_RECV: /* Demux this message to the appropriate fifo, another thread will pull, gnutls process, and send to target queue */ if (strid < conn->cc_sctp_para.pairs) { - /* Note, here the timespec is piggytailed to buf */ CHECK_FCT_DO(fd_event_send(conn->cc_sctps_data.array[strid].raw_recv, event, bufsz, buf), goto fatal ); } else { TRACE_DEBUG(INFO, "Received packet (%zd bytes) on out-of-range stream #%d from %s, discarded.", bufsz, strid, conn->cc_remid); @@ -195,9 +194,6 @@ /* Documentations says to return 0 on connection closed, but it does hang within gnutls_handshake */ return -1; } - if (ev == FDEVP_CNX_MSG_RECV) { - memcpy(&ctx->recvon, ctx->partial.buf + ctx->partial.bufsz, sizeof(struct timespec)); /* retrieve piggy-tailed ts */ - } } pulled = ctx->partial.bufsz - ctx->partial.offset;
--- a/libfdcore/server.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/server.c Fri May 10 18:49:19 2013 +0800 @@ -93,33 +93,38 @@ /* Dump all servers information */ -void fd_servers_dump() +DECLARE_FD_DUMP_PROTOTYPE(fd_servers_dump) { struct fd_list * li, *cli; - fd_log_debug("Dumping servers list :"); + FD_DUMP_HANDLE_OFFSET(); + for (li = FD_SERVERS.next; li != &FD_SERVERS; li = li->next) { struct server * s = (struct server *)li; enum s_state st = get_status(s); - fd_log_debug(" Serv %p '%s': %s, %s, %s", - s, fd_cnx_getid(s->conn), + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{server}(@%p)'%s': %s, %s, %s", s, fd_cnx_getid(s->conn), IPPROTO_NAME( s->proto ), s->secur ? "Secur" : "NotSecur", (st == NOT_CREATED) ? "Thread not created" : ((st == RUNNING) ? "Thread running" : ((st == TERMINATED) ? "Thread terminated" : - "Thread status unknown"))); + "Thread status unknown"))), return NULL); /* Dump the client list of this server */ CHECK_POSIX_DO( pthread_mutex_lock(&s->clients_mtx), ); for (cli = s->clients.next; cli != &s->clients; cli = cli->next) { struct client * c = (struct client *)cli; char bufts[128]; - fd_log_debug(" Connected: '%s' (timeout: %s)", - fd_cnx_getid(c->conn), - fd_log_time(&c->ts, bufts, sizeof(bufts))); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {client}(@%p)'%s': to:%s", c, fd_cnx_getid(c->conn), fd_log_time(&c->ts, bufts, sizeof(bufts))), break); } CHECK_POSIX_DO( pthread_mutex_unlock(&s->clients_mtx), ); + + if (li->next != &FD_SERVERS) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL); + } } + + return *buf; } @@ -128,10 +133,11 @@ { struct client * c = arg; struct server * s = NULL; - uint8_t * buf = NULL; - size_t bufsz; + struct fd_cnx_rcvdata rcv_data; + struct fd_msg_pmdl * pmdl = NULL; struct msg * msg = NULL; struct msg_hdr *hdr = NULL; + struct fd_pei pei; TRACE_ENTRY("%p", c); @@ -146,9 +152,11 @@ if (s->secur) { int ret = fd_cnx_handshake(c->conn, GNUTLS_SERVER, NULL, NULL); if (ret != 0) { - if (TRACE_BOOL(INFO)) { - fd_log_debug("TLS handshake failed for client '%s', connection aborted.", fd_cnx_getid(c->conn)); - } + char buf[1024]; + snprintf(buf, sizeof(buf), "TLS handshake failed for client '%s', connection aborted.", fd_cnx_getid(c->conn)); + + fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, NULL, buf, NULL); + goto cleanup; } } else { @@ -160,23 +168,65 @@ c->ts.tv_sec += INCNX_TIMEOUT; /* Receive the first Diameter message on the connection -- cleanup in case of timeout */ - CHECK_FCT_DO( fd_cnx_receive(c->conn, &c->ts, &buf, &bufsz), goto cleanup ); + CHECK_FCT_DO( fd_cnx_receive(c->conn, &c->ts, &rcv_data.buffer, &rcv_data.length), + { + char buf[1024]; + + switch (__ret__) { + case ETIMEDOUT: + snprintf(buf, sizeof(buf), "Client '%s' did not send CER within %ds, connection aborted.", fd_cnx_getid(c->conn), INCNX_TIMEOUT); + fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, NULL, buf, NULL); + break; + + case ENOTCONN: + snprintf(buf, sizeof(buf), "Connection from '%s' in error before CER was received.", fd_cnx_getid(c->conn)); + fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, NULL, buf, NULL); + break; + + default: + snprintf(buf, sizeof(buf), "Connection from '%s': unspecified error, connection aborted.", fd_cnx_getid(c->conn)); + fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, NULL, buf, NULL); + } + goto cleanup; + } ); - TRACE_DEBUG(FULL, "Received %zdb from new client '%s'", bufsz, fd_cnx_getid(c->conn)); + TRACE_DEBUG(FULL, "Received %zdb from new client '%s'", rcv_data.length, fd_cnx_getid(c->conn)); + + pmdl = fd_msg_pmdl_get_inbuf(rcv_data.buffer, rcv_data.length); /* Try parsing this message */ - CHECK_FCT_DO( fd_msg_parse_buffer( &buf, bufsz, &msg ), /* Parsing failed */ goto cleanup ); + CHECK_FCT_DO( fd_msg_parse_buffer( &rcv_data.buffer, rcv_data.length, &msg ), + { /* Parsing failed */ + fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, NULL, NULL, &rcv_data, pmdl ); + goto cleanup; + } ); /* Log incoming message */ - fd_msg_log( FD_MSG_LOG_RECEIVED, msg, "Received %zdb from new client '%s'", bufsz, fd_cnx_getid(c->conn) ); + fd_hook_associate(msg, pmdl); + fd_hook_call(HOOK_MESSAGE_RECEIVED, msg, NULL, fd_cnx_getid(c->conn), fd_msg_pmdl_get(msg)); /* We expect a CER, it must parse with our dictionary and rules */ - CHECK_FCT_DO( fd_msg_parse_rules( msg, fd_g_config->cnf_dict, NULL ), /* Parsing failed -- trace details ? */ goto cleanup ); + CHECK_FCT_DO( fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &pei ), + { /* Parsing failed -- trace details */ + char buf[1024]; + + fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msg, NULL, pei.pei_message ?: pei.pei_errcode, fd_msg_pmdl_get(msg)); + + snprintf(buf, sizeof(buf), "Error parsing CER from '%s', connection aborted.", fd_cnx_getid(c->conn)); + fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, NULL, buf, NULL); + + goto cleanup; + } ); /* Now check we received a CER */ CHECK_FCT_DO( fd_msg_hdr ( msg, &hdr ), goto fatal_error ); CHECK_PARAMS_DO( (hdr->msg_appl == 0) && (hdr->msg_flags & CMD_FLAG_REQUEST) && (hdr->msg_code == CC_CAPABILITIES_EXCHANGE), - { fd_log_debug("Connection '%s', expecting CER, received something else, closing...", fd_cnx_getid(c->conn)); goto cleanup; } ); + { /* Parsing failed -- trace details */ + char buf[1024]; + snprintf(buf, sizeof(buf), "Expected CER from '%s', received a different message, connection aborted.", fd_cnx_getid(c->conn)); + fd_hook_call(HOOK_PEER_CONNECT_FAILED, msg, NULL, buf, NULL); + goto cleanup; + } ); /* Finally, pass the information to the peers module which will handle it next */ pthread_cleanup_push((void *)fd_cnx_destroy, c->conn); @@ -194,7 +244,6 @@ /* Cleanup the parsed message if any */ if (msg) { - fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Received invalid/unexpected message from connecting client '%s'", fd_cnx_getid(c->conn) ); CHECK_FCT_DO( fd_msg_free(msg), /* continue */); } @@ -203,7 +252,7 @@ fd_cnx_destroy(c->conn); /* Cleanup the received buffer if any */ - free(buf); + free(rcv_data.buffer); /* Detach the thread, cleanup the client structure */ pthread_detach(pthread_self()); @@ -231,11 +280,9 @@ struct client * c = NULL; struct cnxctx * conn = NULL; - /* Wait for a new client */ + /* Wait for a new client or cancel */ CHECK_MALLOC_DO( conn = fd_cnx_serv_accept(s->conn), goto error ); - TRACE_DEBUG(FULL, "New connection accepted"); - /* Create a client structure */ CHECK_MALLOC_DO( c = malloc(sizeof(struct client)), goto error ); memset(c, 0, sizeof(struct client)); @@ -255,8 +302,9 @@ error: if (s) set_status(s, TERMINATED); - /* Send error signal to the daemon */ - TRACE_DEBUG(INFO, "An error occurred in server module! Thread is terminating..."); + + /* Send error signal to the core */ + LOG_F( "An error occurred in server module! Thread is terminating..."); CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), ); return NULL; @@ -392,9 +440,14 @@ return EINVAL; } } - if (TRACE_BOOL(FULL)){ - fd_log_debug(" Local server address(es) :"); - fd_ep_dump( 5, &fd_g_config->cnf_endpoints ); + + { + char * buf = NULL; + size_t len = 0, offset = 0; + CHECK_MALLOC_DO( fd_dump_extend( &buf, &len, &offset , "Local server address(es): "), ); + CHECK_MALLOC_DO( fd_ep_dump( &buf, &len, &offset, 5, &fd_g_config->cnf_endpoints ), ); + LOG_N("%s", buf ?: "Error dumping addresses"); + free(buf); } return 0; }
--- a/libfdcore/tcp.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdcore/tcp.c Fri May 10 18:49:19 2013 +0800 @@ -123,6 +123,7 @@ { int ret = 0; int s; + char * buf = NULL; size_t len = 0; TRACE_ENTRY("%p %p %d", sock, sa, salen); CHECK_PARAMS( sock && (*sock <= 0) && sa && salen ); @@ -136,7 +137,8 @@ /* Cleanup if we are cancelled */ pthread_cleanup_push(fd_cleanup_socket, &s); - TRACE_sSA(FD_LOG_DEBUG, FULL, "Attempting TCP connection with peer: ", sa, NI_NUMERICHOST | NI_NUMERICSERV, "..." ); + LOG_D( "Attempting TCP connection to %s...", fd_sa_dump_node(&buf, &len, NULL, sa, NI_NUMERICHOST | NI_NUMERICSERV)?:"<error>" ); + free(buf); /* Try connecting to the remote address */ ret = connect(s, sa, salen);
--- a/libfdproto/CMakeLists.txt Fri May 10 09:50:09 2013 +0800 +++ b/libfdproto/CMakeLists.txt Fri May 10 18:49:19 2013 +0800 @@ -12,11 +12,11 @@ lists.c log.c messages.c - msg_log.c ostr.c portability.c rt_data.c sessions.c + utils.c ) # Save the list of files for testcases in the core's directory
--- a/libfdproto/dictionary.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdproto/dictionary.c Fri May 10 18:49:19 2013 +0800 @@ -147,13 +147,13 @@ }; /* Forward declarations of dump functions */ -static void dump_vendor_data ( void * data ); -static void dump_application_data ( void * data ); -static void dump_type_data ( void * data ); +static DECLARE_FD_DUMP_PROTOTYPE(dump_vendor_data, void * data ); +static DECLARE_FD_DUMP_PROTOTYPE(dump_application_data, void * data ); +static DECLARE_FD_DUMP_PROTOTYPE(dump_type_data, void * data ); /* the dump function for enum has a different prototype since it need the datatype */ -static void dump_avp_data ( void * data ); -static void dump_command_data ( void * data ); -static void dump_rule_data ( void * data ); +static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_data, void * data ); +static DECLARE_FD_DUMP_PROTOTYPE(dump_command_data, void * data ); +static DECLARE_FD_DUMP_PROTOTYPE(dump_rule_data, void * data ); /* Forward declarations of search functions */ static int search_vendor ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result ); @@ -172,7 +172,7 @@ int parent; /* 0: never; 1: may; 2: must */ enum dict_object_type parenttype; /* The type of the parent, when relevant */ int eyecatcher; /* A kind of signature for this object */ - void (*dump_data)(void * data ); /* The function to dump the data section */ + DECLARE_FD_DUMP_PROTOTYPE( (*dump_data), void * data ); /* The function to dump the data section */ int (*search_fct)(struct dictionary * dict, int criteria, const void * what, struct dict_object **result );; /* The function to search an object of this type */ int haslist[NB_LISTS_PER_OBJ]; /* Tell if this list is used */ } dict_obj_info[] = { { 0, "(error)", 0, 0, 0, 0, NULL, NULL, {0, 0, 0} } @@ -718,6 +718,21 @@ ret = ENOENT; \ } +/* For searchs of type "xxx_OF_xxx": if the search object is sentinel list for the "what" object */ +#define SEARCH_sentinel( type_of_what, what_list_nr, sentinel_list_nr ) { \ + struct dict_object *__what = (struct dict_object *) what; \ + CHECK_PARAMS_DO( verify_object(__what) && \ + (__what->type == (type_of_what)), \ + { ret = EINVAL; goto end; } ); \ + ret = 0; \ + if (result) { \ + /* this is similar to the "container_of" */ \ + *result = (struct dict_object *)((char *)(__what->list[what_list_nr].head) - \ + (size_t)&(((struct dict_object *)0)->list[sentinel_list_nr])); \ + } \ +} + + static int search_vendor ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result ) { int ret = 0; @@ -741,6 +756,11 @@ SEARCH_childs_parent( DICT_APPLICATION, &dict->dict_vendors ); break; + case VENDOR_OF_AVP: + /* "what" should be an avp object */ + SEARCH_sentinel( DICT_AVP, 0, 1 ); + break; + default: /* Invalid criteria */ CHECK_PARAMS( criteria = 0 ); @@ -1149,29 +1169,29 @@ /*******************************************************************************************************/ /*******************************************************************************************************/ /* The following functions are used to debug the module, and allow to print out the content of the dictionary */ -static void dump_vendor_data ( void * data ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_vendor_data, void * data ) { struct dict_vendor_data * vendor = (struct dict_vendor_data *)data; - fd_log_debug("data: %-6u \"%s\"", vendor->vendor_id, vendor->vendor_name); + return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-6u \"%s\"", vendor->vendor_id, vendor->vendor_name); } -static void dump_application_data ( void * data ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_application_data, void * data ) { struct dict_application_data * appli = (struct dict_application_data *) data; - fd_log_debug("data: %-6u \"%s\"", appli->application_id, appli->application_name); + return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-6u \"%s\"", appli->application_id, appli->application_name); } -static void dump_type_data ( void * data ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_type_data, void * data ) { struct dict_type_data * type = ( struct dict_type_data * ) data; - fd_log_debug("data: %-12s \"%s\"", + return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-12s \"%s\"", type_base_name[type->type_base], type->type_name); } -static void dump_enumval_data ( struct dict_enumval_data * enumval, enum dict_avp_basetype type ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_enumval_data, struct dict_enumval_data * enumval, enum dict_avp_basetype type ) { const int LEN_MAX = 20; - fd_log_debug("data: (%-12s) \"%s\" -> ", type_base_name[type], enumval->enum_name); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "data: (%-12s) \"%s\" -> ", type_base_name[type], enumval->enum_name), return NULL); switch (type) { case AVP_TYPE_OCTETSTRING: { @@ -1179,60 +1199,61 @@ if (enumval->enum_value.os.len < LEN_MAX) n = enumval->enum_value.os.len; for (i=0; i < n; i++) - fd_log_debug("0x%2hhX/'%c' ", enumval->enum_value.os.data[i], ASCII(enumval->enum_value.os.data[i])); + 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); if (n == LEN_MAX) - fd_log_debug("..."); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "..."), return NULL); } break; case AVP_TYPE_INTEGER32: - fd_log_debug("%i", enumval->enum_value.i32); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%i", enumval->enum_value.i32), return NULL); break; case AVP_TYPE_INTEGER64: - fd_log_debug("%"PRId64, enumval->enum_value.i64); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%"PRId64, enumval->enum_value.i64), return NULL); break; case AVP_TYPE_UNSIGNED32: - fd_log_debug("%u", enumval->enum_value.u32); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%u", enumval->enum_value.u32), return NULL); break; case AVP_TYPE_UNSIGNED64: - fd_log_debug("%"PRIu64, enumval->enum_value.u64); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%"PRIu64, enumval->enum_value.u64), return NULL); break; case AVP_TYPE_FLOAT32: - fd_log_debug("%f", enumval->enum_value.f32); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%f", enumval->enum_value.f32), return NULL); break; case AVP_TYPE_FLOAT64: - fd_log_debug("%g", enumval->enum_value.f64); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%g", enumval->enum_value.f64), return NULL); break; default: - fd_log_debug("??? (ERROR unknown type %d)", type); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "??? (ERROR unknown type %d)", type), return NULL); } + return *buf; } -static void dump_avp_data ( void * data ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_data, void * data ) { struct dict_avp_data * avp = (struct dict_avp_data * ) data; - fd_log_debug("data: v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %-6u \"%s\"", + return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %-6u \"%s\"", DUMP_AVPFL_val(avp->avp_flag_val), DUMP_AVPFL_val(avp->avp_flag_mask), type_base_name[avp->avp_basetype], avp->avp_code, avp->avp_name ); } -static void dump_command_data ( void * data ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_command_data, void * data ) { struct dict_cmd_data * cmd = (struct dict_cmd_data *) data; - fd_log_debug("data: v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %-6u \"%s\"", + return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %-6u \"%s\"", DUMP_CMDFL_val(cmd->cmd_flag_val), DUMP_CMDFL_val(cmd->cmd_flag_mask), cmd->cmd_code, cmd->cmd_name); } -static void dump_rule_data ( void * data ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_rule_data, void * data ) { struct dict_rule_data * rule = (struct dict_rule_data * )data; - fd_log_debug("data: pos:%d ord:%d m/M:%2d/%2d avp:\"%s\"", + return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: pos:%d ord:%d m/M:%2d/%2d avp:\"%s\"", rule->rule_position, rule->rule_order, rule->rule_min, @@ -1240,158 +1261,168 @@ rule->rule_avp->data.avp.avp_name); } -static void dump_object ( struct dict_object * obj, int parents, int depth, int indent ); +static DECLARE_FD_DUMP_PROTOTYPE(dump_object, struct dict_object * obj, int parents, int depth, int indent ); -static void dump_list ( struct fd_list * sentinel, int parents, int depth, int indent ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_list, struct fd_list * sentinel, int parents, int depth, int indent ) { struct fd_list * li = sentinel; /* We don't lock here, the caller must have taken the dictionary lock for reading already */ - while (li->next != sentinel) - { - li = li->next; - dump_object( _O(li->o), parents, depth, indent ); + if (FD_IS_LIST_EMPTY(sentinel)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n%*s{empty list}", indent, ""), return NULL); + } else { + while (li->next != sentinel) + { + li = li->next; + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL); + CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, _O(li->o), parents, depth, indent ), return NULL); + } } } -static void dump_object ( struct dict_object * obj, int parents, int depth, int indent ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_object, struct dict_object * obj, int parents, int depth, int indent ) { - if (obj == NULL) - return; + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*s{dictobj}(@%p): ", indent, "", obj), return NULL); - if (parents) - dump_object (obj->parent, parents-1, 0, indent + 1 ); + if (!verify_object(obj)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL); + return *buf; + } - fd_log_debug("%*s@%p: %s%s (p:%-9p) ", - indent, - "", - obj, - verify_object(obj) ? "" : "INVALID ", - _OBINFO(obj).name, - obj->parent); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s p:%p ", + _OBINFO(obj).name, + obj->parent), return NULL); - if (obj->type == DICT_ENUMVAL) - dump_enumval_data ( &obj->data.enumval, obj->parent->data.type.type_base ); - else - _OBINFO(obj).dump_data(&obj->data); + if (obj->type == DICT_ENUMVAL) { + CHECK_MALLOC_DO( dump_enumval_data ( FD_DUMP_STD_PARAMS, &obj->data.enumval, obj->parent->data.type.type_base ), return NULL); + } else { + CHECK_MALLOC_DO( _OBINFO(obj).dump_data(FD_DUMP_STD_PARAMS, &obj->data), return NULL); + } + + if (parents) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n%*sparent:", indent + 1, ""), return NULL); + CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, obj->parent, parents-1, 0, 0 ), return NULL); + } if (depth) { int i; for (i=0; i<NB_LISTS_PER_OBJ; i++) { if ((obj->list[i].o == NULL) && (obj->list[i].next != &obj->list[i])) { - fd_log_debug("%*s>%p: list[%d]:", indent, "", obj, i); - dump_list(&obj->list[i], parents, depth - 1, indent + 2); + CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &obj->list[i], 0, depth - 1, indent + 2), return NULL); + break; /* we get duplicate information sorted by another criteria otherwise, which is not very useful */ } } } + + return *buf; } -void fd_dict_dump_object(struct dict_object * obj) +DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_object, struct dict_object * obj) { - fd_log_debug("Dictionary object %p dump:", obj); - dump_object( obj, 1, 2, 2 ); + FD_DUMP_HANDLE_OFFSET(); + + CHECK_MALLOC_DO( dump_object(FD_DUMP_STD_PARAMS, obj, 1, 2, 0), return NULL); + + return *buf; } -void fd_dict_dump(struct dictionary * dict) +DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump, struct dictionary * dict) { int i; struct fd_list * li; - CHECK_PARAMS_DO(dict && (dict->dict_eyec == DICT_EYECATCHER), return); + FD_DUMP_HANDLE_OFFSET(); + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{dictionary}(@%p): ", dict), return NULL); + + if ((dict == NULL) || (dict->dict_eyec != DICT_EYECATCHER)) { + return fd_dump_extend(FD_DUMP_STD_PARAMS, "INVALID/NULL"); + } CHECK_POSIX_DO( pthread_rwlock_rdlock( &dict->dict_lock ), /* ignore */ ); - fd_log_debug("######################################################"); - fd_log_debug("###### Dumping vendors, AVPs and related rules #######"); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict(%p) : VENDORS / AVP / RULES}\n", dict), goto error); + CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_vendors, 0, 3, 3 ), goto error); + for (li = dict->dict_vendors.list[0].next; li != &dict->dict_vendors.list[0]; li = li->next) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL); + CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 3, 3 ), goto error); + } - dump_object( &dict->dict_vendors, 0, 3, 0 ); - for (li = dict->dict_vendors.list[0].next; li != &dict->dict_vendors.list[0]; li = li->next) - dump_object( li->o, 0, 3, 0 ); - - fd_log_debug("###### Dumping applications #######"); - - dump_object( &dict->dict_applications, 0, 1, 0 ); - for (li = dict->dict_applications.list[0].next; li != &dict->dict_applications.list[0]; li = li->next) - dump_object( li->o, 0, 1, 0 ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict(%p) : APPLICATIONS}\n", dict), goto error); + CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_applications, 0, 1, 3 ), goto error); + for (li = dict->dict_applications.list[0].next; li != &dict->dict_applications.list[0]; li = li->next) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL); + CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 1, 3 ), goto error); + } - fd_log_debug("###### Dumping types #######"); - - dump_list( &dict->dict_types, 0, 2, 0 ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict(%p) : TYPES / ENUMVAL}", dict), goto error); + CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_types, 0, 2, 3 ), goto error); - fd_log_debug("###### Dumping commands per name #######"); - - dump_list( &dict->dict_cmd_name, 0, 2, 0 ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict(%p) : COMMANDS / RULES}", dict), goto error); + CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_cmd_code, 0, 0, 3 ), goto error); - fd_log_debug("###### Dumping commands per code and flags #######"); - - dump_list( &dict->dict_cmd_code, 0, 0, 0 ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict(%p) : statistics}", dict), goto error); + for (i=1; i<=DICT_TYPE_MAX; i++) + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n %5d: %s", dict->dict_count[i], dict_obj_info[i].name), goto error); - fd_log_debug("###### Statistics #######"); - - for (i=1; i<=DICT_TYPE_MAX; i++) - fd_log_debug(" %5d objects of type %s", dict->dict_count[i], dict_obj_info[i].name); - - fd_log_debug("######################################################"); - + CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ ); + return *buf; +error: /* Free the rwlock */ CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ ); + return NULL; } /**************************** Dump AVP values ********************************/ /* Default dump functions */ -static int dump_val_os(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) +static DECLARE_FD_DUMP_PROTOTYPE(dump_val_os, union avp_value * value) { int i; - CHECK_FCT( dump_add_str(outstr, offset, outlen, "<") ); + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "<"), return NULL); for (i = 0; i < value->os.len; i++) { if (i == 1024) { /* Dump only up to 1024 bytes of the buffer */ - CHECK_FCT( dump_add_str(outstr, offset, outlen, "[...] (len=%zd)", value->os.len) ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "[...] (len=%zd)", value->os.len), return NULL); break; } - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%s%02.2X", (i==0 ? "" : " "), value->os.data[i]) ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s%02hhX", (i==0 ? "" : " "), value->os.data[i]), return NULL); } - CHECK_FCT( dump_add_str(outstr, offset, outlen, ">") ); - return 0; + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ">"), return NULL); + return *buf; } -static int dump_val_i32(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) +static DECLARE_FD_DUMP_PROTOTYPE(dump_val_i32, union avp_value * value) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%i (0x%x)", value->i32, value->i32) ); - return 0; + return fd_dump_extend( FD_DUMP_STD_PARAMS, "%i (0x%x)", value->i32, value->i32); } -static int dump_val_i64(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) +static DECLARE_FD_DUMP_PROTOTYPE(dump_val_i64, union avp_value * value) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%lli (0x%llx)", value->i64, value->i64) ); - return 0; + return fd_dump_extend( FD_DUMP_STD_PARAMS, "%" PRId64 " (0x%" PRIx64 ")", value->i64, value->i64); } -static int dump_val_u32(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) +static DECLARE_FD_DUMP_PROTOTYPE(dump_val_u32, union avp_value * value) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%u (0x%x)", value->u32, value->u32) ); - return 0; + return fd_dump_extend( FD_DUMP_STD_PARAMS, "%u (0x%x)", value->u32, value->u32); } -static int dump_val_u64(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) +static DECLARE_FD_DUMP_PROTOTYPE(dump_val_u64, union avp_value * value) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%llu (0x%llx)", value->u64, value->u64) ); - return 0; + return fd_dump_extend( FD_DUMP_STD_PARAMS, "%" PRIu64 " (0x%" PRIx64 ")", value->u64, value->u64); } -static int dump_val_f32(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) +static DECLARE_FD_DUMP_PROTOTYPE(dump_val_f32, union avp_value * value) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%f", value->f32) ); - return 0; + return fd_dump_extend( FD_DUMP_STD_PARAMS, "%f", value->f32); } -static int dump_val_f64(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) +static DECLARE_FD_DUMP_PROTOTYPE(dump_val_f64, union avp_value * value) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%g", value->f64) ); - return 0; + return fd_dump_extend( FD_DUMP_STD_PARAMS, "%g", value->f64); } /* Get the dump function for basic dict_avp_basetype */ -static int (*get_default_dump_val_cb(enum dict_avp_basetype datatype))(union avp_value *, char **, size_t *, size_t *) +static DECLARE_FD_DUMP_PROTOTYPE((*get_default_dump_val_cb(enum dict_avp_basetype datatype)), union avp_value *) { switch (datatype) { case AVP_TYPE_OCTETSTRING: @@ -1425,63 +1456,61 @@ #define INOBJHDR "%*s " #define INOBJHDRVAL indent<0 ? 1 : indent, indent<0 ? "-" : "|" +typedef DECLARE_FD_DUMP_PROTOTYPE((*dump_val_cb_t), union avp_value *); + /* Formatter for the AVP value dump line */ -static int dump_avp_val(union avp_value *avp_value, - int (*def_dump_val_cb)(union avp_value *, char **, size_t *, size_t *), - char * (*dump_val_cb)(union avp_value *), +static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_val, union avp_value *avp_value, + dump_val_cb_t def_dump_val_cb, + dump_val_cb_t dump_val_cb, enum dict_avp_basetype datatype, char * type_name, char * const_name, int indent, - char **outstr, - size_t *offset, - size_t *outlen, int header) { if (header) { /* Header for all AVP values dumps: */ - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "value ", INOBJHDRVAL) ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, INOBJHDR "value ", INOBJHDRVAL), return NULL); /* If the type is provided, write it */ if (type_name) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "t: '%s' ", type_name) ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "t: '%s' ", type_name), return NULL); } /* Always give the base datatype anyway */ - CHECK_FCT( dump_add_str(outstr, offset, outlen, "(%s) ", type_base_name[datatype]) ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(%s) ", type_base_name[datatype]), return NULL); /* Now, the value */ - CHECK_FCT( dump_add_str(outstr, offset, outlen, "v: ") ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "v: "), return NULL); } if (const_name) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "'%s' (", const_name) ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s' (", const_name), return NULL); } if (dump_val_cb) { - char * str; - CHECK_MALLOC_DO( str = (*dump_val_cb)(avp_value), dump_add_str(outstr, offset, outlen, "(dump failed)") ); - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%s", str) ); - free(str); + CHECK_MALLOC_DO( (*dump_val_cb)( FD_DUMP_STD_PARAMS, avp_value), fd_dump_extend( FD_DUMP_STD_PARAMS, "(dump failed)")); } else { - CHECK_FCT( (*def_dump_val_cb)(avp_value, outstr, offset, outlen) ); + CHECK_MALLOC_DO( (*def_dump_val_cb)( FD_DUMP_STD_PARAMS, avp_value), return NULL); } if (const_name) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, ")") ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ")"), return NULL); } /* Done! */ - return 0; + return *buf; } /* Dump the value of an AVP of known type into the returned str */ -int fd_dict_dump_avp_value(union avp_value *avp_value, struct dict_object * model, int indent, char **outstr, size_t *offset, size_t *outlen, int header) +DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_avp_value, union avp_value *avp_value, struct dict_object * model, int indent, int header) { - char * (*dump_val_cb)(union avp_value *avp_value) = NULL; + DECLARE_FD_DUMP_PROTOTYPE((*dump_val_cb), union avp_value *avp_value) = NULL; struct dict_object * type = NULL; char * type_name = NULL; char * const_name = NULL; + FD_DUMP_HANDLE_OFFSET(); + /* Check the parameters are correct */ - CHECK_PARAMS( avp_value && verify_object(model) && (model->type == DICT_AVP) ); + CHECK_PARAMS_DO( avp_value && verify_object(model) && (model->type == DICT_AVP), return NULL ); /* Get the type definition of this AVP */ type = model->parent; @@ -1501,14 +1530,14 @@ memcpy(&request.search.enum_value, avp_value, sizeof(union avp_value)); /* bypass checks */ if ((search_enumval( type->dico, ENUMVAL_BY_STRUCT, &request, &enumval ) == 0) && (enumval)) { - /* We found a cosntant, get its name */ + /* We found a constant, get its name */ const_name = enumval->data.enumval.enum_name; } } /* And finally, dump the value */ - CHECK_FCT( dump_avp_val(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, outstr, offset, outlen, header) ); - return 0; + 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 ); + return *buf; } /*******************************************************************************************************/ @@ -1573,51 +1602,51 @@ /* Check the "parent" parameter */ switch (dict_obj_info[type].parent) { case 0: /* parent is forbidden */ - CHECK_PARAMS( parent == NULL ); + CHECK_PARAMS_DO( parent == NULL, goto error_param ); case 1: /* parent is optional */ if (parent == NULL) break; case 2: /* parent is mandatory */ - CHECK_PARAMS( verify_object(parent) ); + CHECK_PARAMS_DO( verify_object(parent), goto error_param ); if (type == DICT_RULE ) { /* Special case : grouped AVP or Command parents are allowed */ - CHECK_PARAMS( (parent->type == DICT_COMMAND ) - || ( (parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED ) ) ); + CHECK_PARAMS_DO( (parent->type == DICT_COMMAND ) + || ( (parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED ) ), goto error_param ); } else { - CHECK_PARAMS( parent->type == dict_obj_info[type].parenttype ); + CHECK_PARAMS_DO( parent->type == dict_obj_info[type].parenttype, goto error_param ); } } /* For AVP object, we must also check that the "vendor" referenced exists */ if (type == DICT_AVP) { CHECK_FCT_DO( fd_dict_search( dict, DICT_VENDOR, VENDOR_BY_ID, &(((struct dict_avp_data *)data)->avp_vendor), (void*)&vendor, ENOENT ), - { TRACE_DEBUG(INFO, "Unable to find vendor '%d' referenced in the AVP data", ((struct dict_avp_data *)data)->avp_vendor); return EINVAL; } ); + { TRACE_DEBUG(INFO, "Unable to find vendor '%d' referenced in the AVP data", ((struct dict_avp_data *)data)->avp_vendor); goto error_param; } ); /* Also check if a parent is provided, that the type are the same */ if (parent) { - CHECK_PARAMS( parent->data.type.type_base == ((struct dict_avp_data *)data)->avp_basetype ); + CHECK_PARAMS_DO( parent->data.type.type_base == ((struct dict_avp_data *)data)->avp_basetype, goto error_param ); } } /* For RULE object, we must also check that the "avp" referenced exists */ if (type == DICT_RULE) { - CHECK_PARAMS( verify_object(((struct dict_rule_data *)data)->rule_avp) ); - CHECK_PARAMS( ((struct dict_rule_data *)data)->rule_avp->type == DICT_AVP ); + CHECK_PARAMS_DO( verify_object(((struct dict_rule_data *)data)->rule_avp), goto error_param ); + CHECK_PARAMS_DO( ((struct dict_rule_data *)data)->rule_avp->type == DICT_AVP, goto error_param ); } /* For COMMAND object, check that the 'R' flag is fixed */ if (type == DICT_COMMAND) { - CHECK_PARAMS( ((struct dict_cmd_data *)data)->cmd_flag_mask & CMD_FLAG_REQUEST ); + CHECK_PARAMS_DO( ((struct dict_cmd_data *)data)->cmd_flag_mask & CMD_FLAG_REQUEST, goto error_param ); } /* We have to check that the new values are not equal to the sentinels */ if (type == DICT_VENDOR) { - CHECK_PARAMS( ((struct dict_vendor_data *)data)->vendor_id != 0 ); + CHECK_PARAMS_DO( ((struct dict_vendor_data *)data)->vendor_id != 0, goto error_param ); } if (type == DICT_APPLICATION) { - CHECK_PARAMS( ((struct dict_application_data *)data)->application_id != 0 ); + CHECK_PARAMS_DO( ((struct dict_application_data *)data)->application_id != 0, goto error_param ); } /* Parameters are valid, create the new object */ @@ -1717,6 +1746,10 @@ return 0; +error_param: + ret = EINVAL; + goto all_errors; + error_unlock: CHECK_POSIX_DO( pthread_rwlock_unlock(&dict->dict_lock), /* continue */ ); if (ret == EEXIST) { @@ -1727,7 +1760,7 @@ /* if we are here, it means the two vendors id are identical */ if (fd_os_cmp(locref->data.vendor.vendor_name, locref->datastr_len, new->data.vendor.vendor_name, new->datastr_len)) { - TRACE_DEBUG(FULL, "Conflicting vendor name"); + TRACE_DEBUG(INFO, "Conflicting vendor name: %s", new->data.vendor.vendor_name); break; } /* Otherwise (same name), we consider the function succeeded, since the (same) object is in the dictionary */ @@ -1865,23 +1898,26 @@ ret = 0; break; } - if (ret) { - TRACE_DEBUG(INFO, "An existing object with different non-key data was found: EEXIST"); - if (TRACE_BOOL(INFO)) { - fd_log_debug("New object to insert:"); - dump_object(new, 0, 0, 3); - fd_log_debug("Object already in dictionary:"); - dump_object(locref, 0, 0 , 3); - } - } else { + if (!ret) { TRACE_DEBUG(FULL, "An existing object with the same data was found, ignoring the error..."); } if (ref) *ref = locref; - } else { - CHECK_FCT_DO( ret, ); /* log the error */ } - +all_errors: + if (ret != 0) { + char * buf = NULL; + size_t len = 0; + + CHECK_MALLOC( dict_obj_info[CHECK_TYPE(type) ? type : 0].dump_data(&buf, &len, NULL, data) ); + TRACE_DEBUG(INFO, "An error occurred while adding the following data in the dictionary: %s", buf); + + if (ret == EEXIST) { + CHECK_MALLOC( dump_object(&buf, &len, NULL, locref, 0, 0, 0) ); + TRACE_DEBUG(INFO, "Conflicting entry in the dictionary: %s", buf); + } + free(buf); + } error_free: free(new); return ret;
--- a/libfdproto/dictionary_functions.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdproto/dictionary_functions.c Fri May 10 18:49:19 2013 +0800 @@ -152,10 +152,8 @@ } /* Dump the content of an Address AVP */ -char * fd_dictfct_Address_dump(union avp_value * avp_value) +DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_Address_dump, union avp_value * avp_value) { - char * ret; - #define STR_LEN 1024 union { sSA sa; sSS ss; @@ -164,14 +162,14 @@ } s; uint16_t fam; - memset(&s, 0, sizeof(s)); + FD_DUMP_HANDLE_OFFSET(); - CHECK_MALLOC_DO( ret = malloc(STR_LEN), return NULL ); + memset(&s, 0, sizeof(s)); /* The first two octets represent the address family, http://www.iana.org/assignments/address-family-numbers/ */ if (avp_value->os.len < 2) { - snprintf(ret, STR_LEN, "[invalid length: %zd]", avp_value->os.len); - return ret; + CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid length: %zd]", avp_value->os.len), return NULL); + return *buf; } /* Following octets are the address in network byte order already */ @@ -181,8 +179,8 @@ /* IP */ s.sa.sa_family = AF_INET; if (avp_value->os.len != 6) { - snprintf(ret, STR_LEN, "[invalid IP length: %zd]", avp_value->os.len); - return ret; + CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid IP length: %zd]", avp_value->os.len), return NULL); + return *buf; } memcpy(&s.sin.sin_addr.s_addr, avp_value->os.data + 2, 4); break; @@ -190,23 +188,17 @@ /* IP6 */ s.sa.sa_family = AF_INET6; if (avp_value->os.len != 18) { - snprintf(ret, STR_LEN, "[invalid IP6 length: %zd]", avp_value->os.len); - return ret; + CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid IP6 length: %zd]", avp_value->os.len), return NULL); + return *buf; } memcpy(&s.sin6.sin6_addr.s6_addr, avp_value->os.data + 2, 16); break; default: - snprintf(ret, STR_LEN, "[unsupported family: 0x%hx]", fam); - return ret; + CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[unsupported family: 0x%hx]", fam), return NULL); + return *buf; } - { - int rc = getnameinfo(&s.sa, sSAlen(&s.sa), ret, STR_LEN, NULL, 0, NI_NUMERICHOST); - if (rc) - snprintf(ret, STR_LEN, "%s", (char *)gai_strerror(rc)); - } - - return ret; + return fd_sa_dump_node(FD_DUMP_STD_PARAMS, &s.sa, NI_NUMERICHOST); } @@ -215,42 +207,24 @@ /* UTF8String AVP type */ /*******************************/ -/* Dump the AVP in a natural human-readable format */ -char * fd_dictfct_UTF8String_dump(union avp_value * avp_value) +/* Dump the AVP in a natural human-readable format. This dumps the complete length of the AVP, it is up to the caller to truncate if needed */ +DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_UTF8String_dump, union avp_value * avp_value) { -#define TRUNC_LEN 1024 /* avoid very long strings */ - char * ret; - CHECK_MALLOC_DO( ret = malloc(TRUNC_LEN+2+3+1), return NULL ); - *ret = '"'; - strncpy(ret+1, (char *)avp_value->os.data, TRUNC_LEN); - /* be sure to have a nul-terminated string */ - ret[TRUNC_LEN+1] = '\0'; - if (ret[1] != '\0') { - /* We sanitize the returned string to avoid UTF8 boundary problem. - We do this whether the string is trucated at TRUNC_LEN or not, to avoid potential problem - with malformed AVP */ - - char * end = strchr(ret, '\0'); - while (end > ret) { - end--; - char b = *end; - /* after the position pointed by end, we have only \0s */ - if ((b & 0x80) == 0) { - break; /* this is a single byte char, no problem */ - } else { - /* this byte is start or cont. of multibyte sequence, as we do not know the next byte we need to delete it. */ - *end = '\0'; - if (b & 0x40) - break; /* This was a start byte, we can stop the loop */ - } - } - if (strlen((char *)avp_value->os.data) > strlen(ret+1)) - strcat(end, "..."); - strcat(end, "\""); - } else { - *ret = '\0'; + size_t l; + FD_DUMP_HANDLE_OFFSET(); + + l = avp_value->os.len; + /* Just in case the string ends in invalid UTF-8 chars, we shorten it */ + while ((l > 0) && (avp_value->os.data[l - 1] & 0x80)) { + /* this byte is start or cont. of multibyte sequence, as we do not know the next byte we need to delete it. */ + l--; + if (avp_value->os.data[l] & 0x40) + break; /* This was a start byte, we can stop the loop */ } - return ret; + + CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "\"%.*s\"", (int)l, (char *)avp_value->os.data), return NULL); + + return *buf; } @@ -325,22 +299,24 @@ return diameter_string_to_time_t((const char *)avp_value->os.data, avp_value->os.len, interpreted); } -char * fd_dictfct_Time_dump(union avp_value * avp_value) +DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_Time_dump, union avp_value * avp_value) { - char * ret; time_t val; struct tm conv; - CHECK_MALLOC_DO( ret = malloc(STR_LEN), return NULL ); + + FD_DUMP_HANDLE_OFFSET(); + if (avp_value->os.len != 4) { - snprintf(ret, STR_LEN, "[invalid length: %zd]", avp_value->os.len); - return ret; + CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid length: %zd]", avp_value->os.len), return NULL); + return *buf; } + if (diameter_string_to_time_t((char *)avp_value->os.data, avp_value->os.len, &val) != 0) { - snprintf(ret, STR_LEN, "[time conversion error]"); - return ret; + CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[time conversion error]"), return NULL); + return *buf; } - gmtime_r(&val, &conv); - snprintf(ret, STR_LEN, "%d%02d%02dT%02d%02d%02d+00", conv.tm_year+1900, conv.tm_mon+1, conv.tm_mday, conv.tm_hour, conv.tm_min, conv.tm_sec); - return ret; + + CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "%d%02d%02dT%02d%02d%02d+00", conv.tm_year+1900, conv.tm_mon+1, conv.tm_mday, conv.tm_hour, conv.tm_min, conv.tm_sec), return NULL); + return *buf; }
--- a/libfdproto/dispatch.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdproto/dispatch.c Fri May 10 18:49:19 2013 +0800 @@ -96,7 +96,7 @@ /* We have a match, the cb must be called. */ CHECK_FCT_DO( (r = (*hdl->cb)(msg, avp, sess, hdl->opaque, action)), { - fd_msg_log( FD_MSG_LOG_DROPPED, *msg, "Internal error: a DISPATCH callback returned an error (%s)", strerror(r)); + //fd_msg_log( FD_MSG_LOG_DROPPED, *msg, "Internal error: a DISPATCH callback returned an error (%s)", strerror(r)); fd_msg_free(*msg); *msg = NULL; }
--- a/libfdproto/fdproto-internal.h Fri May 10 09:50:09 2013 +0800 +++ b/libfdproto/fdproto-internal.h Fri May 10 18:49:19 2013 +0800 @@ -47,19 +47,12 @@ int fd_sess_init(void); void fd_sess_fini(void); -/* Where debug messages are sent */ -extern FILE * fd_g_debug_fstr; - -/* Special message dump function */ -void fd_msg_dump_fstr_one ( struct msg * msg, FILE * fstr ); -void fd_msg_dump_fstr ( struct msg * msg, FILE * fstr ); - /* Iterator on the rules of a parent object */ int fd_dict_iterate_rules ( struct dict_object *parent, void * data, int (*cb)(void *, struct dict_rule_data *) ); /* Dispatch / messages / dictionary API */ int fd_dict_disp_cb(enum dict_object_type type, struct dict_object *obj, struct fd_list ** cb_list); -int fd_dict_dump_avp_value(union avp_value *avp_value, struct dict_object * model, int indent, char **outstr, size_t *offset, size_t *outlen, int header); +DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_avp_value, union avp_value *avp_value, struct dict_object * model, int indent, int header); int fd_disp_call_cb_int( struct fd_list * cb_list, struct msg ** msg, struct avp *avp, struct session *sess, enum disp_action *action, struct dict_object * obj_app, struct dict_object * obj_cmd, struct dict_object * obj_avp, struct dict_object * obj_enu); extern pthread_rwlock_t fd_disp_lock; @@ -68,40 +61,4 @@ int fd_sess_reclaim_msg ( struct session ** session ); -/* For dump routines into string buffers */ -#include <stdarg.h> -static __inline__ int dump_init_str(char **outstr, size_t *offset, size_t *outlen) -{ - *outlen = 1<<12; - CHECK_MALLOC( *outstr = malloc(*outlen) ); - *offset = 0; - (*outstr)[0] = 0; - return 0; -} -static __inline__ int dump_add_str(char **outstr, size_t *offset, size_t *outlen, char * fmt, ...) -{ - va_list argp; - int len; - va_start(argp, fmt); - len = vsnprintf(*outstr + *offset, *outlen - *offset, fmt, argp); - va_end(argp); - if ((len + *offset) >= *outlen) { - char * newstr; - /* buffer was too short, extend */ - size_t newsize = ((len + *offset) + (1<<12)) & ~((1<<12) - 1); /* next multiple of 4k */ - CHECK_MALLOC( newstr = realloc(*outstr, newsize) ); - - /* redo */ - *outstr = newstr; - *outlen = newsize; - va_start(argp, fmt); - len = vsnprintf(*outstr + *offset, *outlen - *offset, fmt, argp); - va_end(argp); - } - *offset += len; - return 0; -} - - - #endif /* _LIBFDPROTO_INTERNAL_H */
--- a/libfdproto/fifo.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdproto/fifo.c Fri May 10 18:49:19 2013 +0800 @@ -69,6 +69,17 @@ void (*l_cb)(struct fifo *, void **); int highest;/* The highest count value for which h_cb has been called */ int highest_ever; /* The max count value this queue has reached (for tweaking) */ + + long long total_items; /* Cumulated number of items that went through this fifo (excluding current count), always increasing. */ + struct timespec total_time; /* Cumulated time all items spent in this queue, including blocking time (always growing, use deltas for monitoring) */ + struct timespec blocking_time; /* Cumulated time threads trying to post new items were blocked (queue full). */ + struct timespec last_time; /* For the last element retrieved from the queue, how long it take between posting (including blocking) and poping */ + +}; + +struct fifo_item { + struct fd_list item; + struct timespec posted_on; }; /* The eye catcher value */ @@ -107,39 +118,45 @@ } /* Dump the content of a queue */ -void fd_fifo_dump(int level, char * name, struct fifo * queue, void (*dump_item)(int level, void * item)) +DECLARE_FD_DUMP_PROTOTYPE(fd_fifo_dump, char * name, struct fifo * queue, fd_fifo_dump_item_cb dump_item) { - TRACE_ENTRY("%i %p %p %p", level, name, queue, dump_item); - - if (!TRACE_BOOL(level)) - return; + FD_DUMP_HANDLE_OFFSET(); - fd_log_debug("Dumping queue '%s' (%p):", name ?: "?", queue); + if (name) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(@%p): ", name, queue), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{fifo}(@%p): ", queue), return NULL); + } + if (!CHECK_FIFO( queue )) { - fd_log_debug(" Queue invalid!"); - if (queue) - fd_log_debug(" (%x != %x)", queue->eyec, FIFO_EYEC); - return; + return fd_dump_extend(FD_DUMP_STD_PARAMS, "INVALID/NULL"); } CHECK_POSIX_DO( pthread_mutex_lock( &queue->mtx ), /* continue */ ); - fd_log_debug(" %d elements in queue / %d threads waiting", queue->count, queue->thrs); - fd_log_debug(" %d elements max / %d threads waiting to push", queue->max, queue->thrs_push); - fd_log_debug(" thresholds: %d / %d (h:%d), cb: %p,%p (%p), highest: %d", - queue->high, queue->low, queue->highest, - queue->h_cb, queue->l_cb, queue->data, - queue->highest_ever); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "items:%d,%d,%d threads:%d,%d stats:%lld/%ld.%06ld,%ld.%06ld,%ld.%06ld thresholds:%d,%d,%d,%p,%p,%p", + queue->count, queue->highest_ever, queue->max, + queue->thrs, queue->thrs_push, + queue->total_items,(long)queue->total_time.tv_sec,(long)(queue->total_time.tv_nsec/1000),(long)queue->blocking_time.tv_sec,(long)(queue->blocking_time.tv_nsec/1000),(long)queue->last_time.tv_sec,(long)(queue->last_time.tv_nsec/1000), + queue->high, queue->low, queue->highest, queue->h_cb, queue->l_cb, queue->data), + goto error); if (dump_item) { struct fd_list * li; int i = 0; for (li = queue->list.next; li != &queue->list; li = li->next) { - fd_log_debug(" [%i] item %p in fifo %p:", i++, li->o, queue); - (*dump_item)(level, li->o); + struct fifo_item * fi = (struct fifo_item *)li; + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n [#%i](@%p)@%ld.%06ld: ", + i++, fi->item.o, (long)fi->posted_on.tv_sec,(long)(fi->posted_on.tv_nsec/1000)), + goto error); + CHECK_MALLOC_DO( (*dump_item)(FD_DUMP_STD_PARAMS, fi->item.o), goto error); } } CHECK_POSIX_DO( pthread_mutex_unlock( &queue->mtx ), /* continue */ ); + return *buf; +error: + CHECK_POSIX_DO( pthread_mutex_unlock( &queue->mtx ), /* continue */ ); + return NULL; } /* Delete a queue. It must be empty. */ @@ -242,6 +259,22 @@ old->count = 0; old->eyec = FIFO_EYEC; + /* Merge the stats in the new queue */ + new->total_items += old->total_items; + old->total_items = 0; + + new->total_time.tv_nsec += old->total_time.tv_nsec; + new->total_time.tv_sec += old->total_time.tv_sec + (new->total_time.tv_nsec / 1000000000); + new->total_time.tv_nsec %= 1000000000; + old->total_time.tv_nsec = 0; + old->total_time.tv_sec = 0; + + new->blocking_time.tv_nsec += old->blocking_time.tv_nsec; + new->blocking_time.tv_sec += old->blocking_time.tv_sec + (new->blocking_time.tv_nsec / 1000000000); + new->blocking_time.tv_nsec %= 1000000000; + old->blocking_time.tv_nsec = 0; + old->blocking_time.tv_sec = 0; + /* Unlock, we're done */ CHECK_POSIX( pthread_mutex_unlock( &new->mtx ) ); CHECK_POSIX( pthread_mutex_unlock( &old->mtx ) ); @@ -249,19 +282,38 @@ return 0; } -/* Get the length of the queue */ -int fd_fifo_length ( struct fifo * queue, int * length ) +/* Get the information on the queue */ +int fd_fifo_getstats( struct fifo * queue, int * current_count, int * limit_count, int * highest_count, long long * total_count, + struct timespec * total, struct timespec * blocking, struct timespec * last) { - TRACE_ENTRY( "%p %p", queue, length ); + TRACE_ENTRY( "%p %p %p %p %p %p %p %p", queue, current_count, limit_count, highest_count, total_count, total, blocking, last); /* Check the parameters */ - CHECK_PARAMS( CHECK_FIFO( queue ) && length ); + CHECK_PARAMS( CHECK_FIFO( queue ) ); /* lock the queue */ CHECK_POSIX( pthread_mutex_lock( &queue->mtx ) ); - /* Retrieve the count */ - *length = queue->count; + if (current_count) + *current_count = queue->count; + + if (limit_count) + *limit_count = queue->max; + + if (highest_count) + *highest_count = queue->highest_ever; + + if (total_count) + *total_count = queue->total_items; + + if (total) + memcpy(total, &queue->total_time, sizeof(struct timespec)); + + if (blocking) + memcpy(blocking, &queue->blocking_time, sizeof(struct timespec)); + + if (last) + memcpy(last, &queue->last_time, sizeof(struct timespec)); /* Unlock */ CHECK_POSIX( pthread_mutex_unlock( &queue->mtx ) ); @@ -270,8 +322,9 @@ return 0; } + /* alternate version with no error checking */ -int fd_fifo_length_noerr ( struct fifo * queue ) +int fd_fifo_length ( struct fifo * queue ) { if ( !CHECK_FIFO( queue ) ) return 0; @@ -325,14 +378,18 @@ /* Post a new item in the queue */ int fd_fifo_post_int ( struct fifo * queue, void ** item ) { - struct fd_list * new; + struct fifo_item * new; int call_cb = 0; + struct timespec posted_on, queued_on; TRACE_ENTRY( "%p %p", queue, item ); /* Check the parameters */ CHECK_PARAMS( CHECK_FIFO( queue ) && item && *item ); + /* Get the timing of this call */ + CHECK_SYS( clock_gettime(CLOCK_REALTIME, &posted_on) ); + /* lock the queue */ CHECK_POSIX( pthread_mutex_lock( &queue->mtx ) ); @@ -352,15 +409,16 @@ } /* Create a new list item */ - CHECK_MALLOC_DO( new = malloc (sizeof (struct fd_list)) , { + CHECK_MALLOC_DO( new = malloc (sizeof (struct fifo_item)) , { pthread_mutex_unlock( &queue->mtx ); + return ENOMEM; } ); - fd_list_init(new, *item); + fd_list_init(&new->item, *item); *item = NULL; /* Add the new item at the end */ - fd_list_insert_before( &queue->list, new); + fd_list_insert_before( &queue->list, &new->item); queue->count++; if (queue->highest_ever < queue->count) queue->highest_ever = queue->count; @@ -369,6 +427,20 @@ queue->highest = queue->count; } + /* store timing */ + memcpy(&new->posted_on, &posted_on, sizeof(struct timespec)); + + /* update queue timing info "blocking time" */ + { + long long blocked_ns; + CHECK_SYS( clock_gettime(CLOCK_REALTIME, &queued_on) ); + blocked_ns = (queued_on.tv_sec - posted_on.tv_sec) * 1000000000; + blocked_ns += (queued_on.tv_nsec - posted_on.tv_nsec); + blocked_ns += queue->blocking_time.tv_nsec; + queue->blocking_time.tv_sec += blocked_ns / 1000000000; + queue->blocking_time.tv_nsec = blocked_ns % 1000000000; + } + /* Signal if threads are asleep */ if (queue->thrs > 0) { CHECK_POSIX( pthread_cond_signal(&queue->cond_pull) ); @@ -393,14 +465,32 @@ static void * mq_pop(struct fifo * queue) { void * ret = NULL; - struct fd_list * li; + struct fifo_item * fi; + struct timespec now; ASSERT( ! FD_IS_LIST_EMPTY(&queue->list) ); - fd_list_unlink(li = queue->list.next); + fi = (struct fifo_item *)(queue->list.next); + ret = fi->item.o; + fd_list_unlink(&fi->item); queue->count--; - ret = li->o; - free(li); + queue->total_items++; + + /* Update the timings */ + CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), goto skip_timing ); + { + long long elapsed = (now.tv_sec - fi->posted_on.tv_sec) * 1000000000; + elapsed += now.tv_nsec - fi->posted_on.tv_nsec; + + queue->last_time.tv_sec = elapsed / 1000000000; + queue->last_time.tv_nsec = elapsed % 1000000000; + + elapsed += queue->total_time.tv_nsec; + queue->total_time.tv_sec += elapsed / 1000000000; + queue->total_time.tv_nsec = elapsed % 1000000000; + } +skip_timing: + free(fi); if (queue->thrs_push) { CHECK_POSIX_DO( pthread_cond_signal( &queue->cond_push ), ); @@ -508,7 +598,7 @@ TRACE_DEBUG(FULL, "The queue is being destroyed -> EPIPE"); return EPIPE; } - + if (queue->count > 0) { /* There are items in the queue, so pick the first one */ *item = mq_pop(queue);
--- a/libfdproto/init.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdproto/init.c Fri May 10 18:49:19 2013 +0800 @@ -57,9 +57,6 @@ return ret; } - /* Set the debug stream */ - fd_g_debug_fstr = stdout; - /* Initialize the modules that need it */ fd_msg_eteid_init(); CHECK_FCT( fd_sess_init() );
--- a/libfdproto/log.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdproto/log.c Fri May 10 18:49:19 2013 +0800 @@ -37,11 +37,9 @@ #include <stdarg.h> -FILE * fd_g_debug_fstr; - pthread_mutex_t fd_log_lock = PTHREAD_MUTEX_INITIALIZER; pthread_key_t fd_log_thname; -int fd_g_debug_lvl = INFO; +int fd_g_debug_lvl = FD_LOG_NOTICE; static void fd_internal_logger( int, const char *, va_list ); static int use_colors = 0; /* 0: not init, 1: yes, 2: no */ @@ -87,16 +85,16 @@ } -static void fd_internal_logger( int loglevel, const char *format, va_list ap ) +static void fd_internal_logger( int printlevel, const char *format, va_list ap ) { char buf[25]; - FILE *fstr = fd_g_debug_fstr ?: stdout; - int local_use_color = 0; - /* logging has been decided by macros outside already */ + /* Do we need to trace this ? */ + if (printlevel < fd_g_debug_lvl) + return; /* add timestamp */ - fprintf(fstr, "%s ", fd_log_time(NULL, buf, sizeof(buf))); + printf("%s ", fd_log_time(NULL, buf, sizeof(buf))); /* Use colors on stdout ? */ if (!use_colors) { @@ -106,22 +104,20 @@ use_colors = 2; } - /* now, this time log, do we use colors? */ - if ((fstr == stdout) && (use_colors == 1)) - local_use_color = 1; + switch(printlevel) { + case FD_LOG_ANNOYING: printf("%s A ", (use_colors == 1) ? "\e[0;37m" : ""); break; + case FD_LOG_DEBUG: printf("%s DBG ", (use_colors == 1) ? "\e[0;37m" : ""); break; + case FD_LOG_NOTICE: printf("%sNOTI ", (use_colors == 1) ? "\e[1;37m" : ""); break; + case FD_LOG_ERROR: printf("%sERROR ", (use_colors == 1) ? "\e[0;31m" : ""); break; + case FD_LOG_FATAL: printf("%sFATAL! ", (use_colors == 1) ? "\e[0;31m" : ""); break; + default: printf("%s ??? ", (use_colors == 1) ? "\e[0;31m" : ""); + } + vprintf(format, ap); + if (use_colors == 1) + printf("\e[00m"); + printf("\n"); - switch(loglevel) { - case FD_LOG_DEBUG: fprintf(fstr, "%s DBG ", local_use_color ? "\e[0;37m" : ""); break; - case FD_LOG_NOTICE: fprintf(fstr, "%sNOTI ", local_use_color ? "\e[1;37m" : ""); break; - case FD_LOG_ERROR: fprintf(fstr, "%sERROR ", local_use_color ? "\e[0;31m" : ""); break; - default: fprintf(fstr, "%s ??? ", local_use_color ? "\e[0;31m" : ""); - } - vfprintf(fstr, format, ap); - if (local_use_color) - fprintf(fstr, "\e[00m"); - fprintf(fstr, "\n"); - - fflush(fstr); + fflush(stdout); } /* Log a debug message */ @@ -142,14 +138,16 @@ (void)pthread_mutex_unlock(&fd_log_lock); } -/* Log debug message to file. */ -void fd_log_debug_fstr( FILE * fstr, const char * format, ... ) +/* Log a debug message */ +void fd_log_va ( int loglevel, const char * format, va_list args ) { - va_list ap; + (void)pthread_mutex_lock(&fd_log_lock); - va_start(ap, format); - vfprintf(fstr, format, ap); - va_end(ap); + pthread_cleanup_push(fd_cleanup_mutex_silent, &fd_log_lock); + fd_logger(loglevel, format, args); + pthread_cleanup_pop(0); + + (void)pthread_mutex_unlock(&fd_log_lock); } /* Function to set the thread's friendly name */ @@ -207,3 +205,115 @@ return buf; } + + +static size_t sys_mempagesz = 0; + +static size_t get_mempagesz(void) { + if (!sys_mempagesz) { + sys_mempagesz = sysconf(_SC_PAGESIZE); /* We alloc buffer by memory pages for efficiency */ + if (sys_mempagesz <= 0) + sys_mempagesz = 1024; /* default size if above call failed */ + } + return sys_mempagesz; +} + + +/* Helper function for fd_*_dump. Prints the format string from 'offset' into '*buf', extends if needed. The location of buf can be updated by this function. */ +char * fd_dump_extend(char ** buf, size_t *len, size_t *offset, const char * format, ... ) +{ + va_list ap; + int to_write; + size_t o = 0; + size_t mempagesz = get_mempagesz(); + + /* we do not TRACE_ENTRY this one on purpose */ + + CHECK_PARAMS_DO(buf && len, return NULL); + + if (*buf == NULL) { + CHECK_MALLOC_DO(*buf = malloc(mempagesz), return NULL); + *len = mempagesz; + } + + if (offset) + o = *offset; + + va_start(ap, format); + to_write = vsnprintf(*buf + o, *len - o, format, ap); + va_end(ap); + + if (to_write + o >= *len) { + /* There was no room in the buffer, we extend and redo */ + size_t new_len = (((to_write + o) / mempagesz) + 1) * mempagesz; + CHECK_MALLOC_DO(*buf = realloc(*buf, new_len), return NULL); + *len = new_len; + + va_start(ap, format); + to_write = vsnprintf(*buf + o, *len - o, format, ap); + va_end(ap); + } + + if (offset) + *offset += to_write; + + return *buf; +} + +char * fd_dump_extend_hexdump(char ** buf, size_t *len, size_t *offset, uint8_t *data, size_t datalen, size_t trunc, size_t wrap ) +{ + int truncated = 0; + size_t towrite = 0; + size_t o = 0; + int i; + char * p; + size_t mempagesz = get_mempagesz(); +#define TRUNK_MARK "[...]" + + CHECK_PARAMS_DO(buf && len && data, return NULL); + + if (trunc && (datalen > trunc)) { + datalen = trunc; + truncated = 1; + } + + towrite = datalen * 2; + + if (wrap) + towrite += datalen / wrap; /* add 1 '\n' every wrap byte */ + + if (truncated) + towrite += CONSTSTRLEN(TRUNK_MARK); + + + if (offset) + o = *offset; + + if (*buf == NULL) { + /* Directly allocate the size we need */ + *len = (((towrite + o) / mempagesz) + 1 ) * mempagesz; + CHECK_MALLOC_DO(*buf = malloc(*len), return NULL); + } else if ((towrite + o) >= *len) { + /* There is no room in the buffer, we extend and redo */ + size_t new_len = (((towrite + o) / mempagesz) + 1) * mempagesz; + CHECK_MALLOC_DO(*buf = realloc(*buf, new_len), return NULL); + *len = new_len; + } + + p = *buf + o; + for (i = 0; i < datalen; i++) { + sprintf(p, "%02hhX", data[i]); + p+=2; + if ((wrap) && ((i+1) % wrap == 0)) { + *p++='\n'; *p ='\0'; /* we want to ensure the buffer is always 0-terminated */ + } + } + + if (truncated) + memcpy(p, TRUNK_MARK, CONSTSTRLEN(TRUNK_MARK)); + + if (offset) + *offset += towrite; + + return *buf; +}
--- a/libfdproto/messages.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdproto/messages.c Fri May 10 18:49:19 2013 +0800 @@ -88,6 +88,10 @@ struct msg_avp_chain avp_chain; /* Chaining information of this AVP */ int avp_eyec; /* Must be equal to MSG_AVP_EYEC */ struct dict_object *avp_model; /* If not NULL, pointer to the dictionary object of this avp */ + struct { + avp_code_t mnf_code; + vendor_id_t mnf_vendor; + } avp_model_not_found; /* When model resolution has failed, store a copy of the data here to avoid searching again */ struct avp_hdr avp_public; /* AVP data that can be managed by other modules */ uint8_t *avp_source; /* If the message was parsed from a buffer, pointer to the AVP data start in the buffer. */ @@ -112,6 +116,10 @@ struct msg_avp_chain msg_chain; /* List of the AVPs in the message */ int msg_eyec; /* Must be equal to MSG_MSG_EYEC */ struct dict_object *msg_model; /* If not NULL, pointer to the dictionary object of this message */ + struct { + command_code_t mnf_code; + uint8_t mnf_flags; + } msg_model_not_found; /* When model resolution has failed, store a copy of the data here to avoid searching again */ struct msg_hdr msg_public; /* Message data that can be managed by extensions. */ uint8_t *msg_rawbuffer; /* data buffer that was received, saved during fd_msg_parse_buffer and freed in fd_msg_parse_dict */ @@ -128,9 +136,7 @@ } msg_cb; /* Callback to be called when an answer is received, or timeout expires, if not NULL */ DiamId_t msg_src_id; /* Diameter Id of the peer this message was received from. This string is malloc'd and must be freed */ size_t msg_src_id_len; /* cached length of this string */ - struct timespec msg_ts_rcv; /* Timestamp when this message was received from the network */ - struct timespec msg_ts_sent; /* Timestamp when this message was sent to the network */ - + struct fd_msg_pmdl msg_pmdl; /* list of permessagedata structures. */ }; /* Macro to compute the message header size */ @@ -195,6 +201,9 @@ memset(msg, 0, sizeof(struct msg)); init_chain( &msg->msg_chain, MSG_MSG); msg->msg_eyec = MSG_MSG_EYEC; + + fd_list_init(&msg->msg_pmdl.sentinel, NULL); + CHECK_POSIX_DO( pthread_mutex_init(&msg->msg_pmdl.lock, NULL), ); } @@ -348,13 +357,15 @@ /* Add the Session-Id AVP if session is known */ if (sess && dict) { - struct dict_object * sess_id_avp; + static struct dict_object * sess_id_avp = NULL; os0_t sid; size_t sidlen; struct avp * avp; union avp_value val; - CHECK_FCT( fd_dict_search( dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &sess_id_avp, ENOENT) ); + if (!sess_id_avp) { + CHECK_FCT( fd_dict_search( dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &sess_id_avp, ENOENT) ); + } CHECK_FCT( fd_sess_getsid ( sess, &sid, &sidlen ) ); CHECK_FCT( fd_msg_avp_new ( sess_id_avp, 0, &avp ) ); val.os.data = sid; @@ -665,6 +676,10 @@ CHECK_FCT_DO( fd_sess_reclaim_msg ( &_M(obj)->msg_sess ), /* continue */); } + if ((obj->type == MSG_MSG) && (_M(obj)->msg_pmdl.sentinel.o != NULL)) { + ((void (*)(struct fd_msg_pmdl *))_M(obj)->msg_pmdl.sentinel.o)(&_M(obj)->msg_pmdl); + } + /* free the object */ free(obj); @@ -712,385 +727,441 @@ /***************************************************************************************************************/ /* Debug functions: dumping */ -/* indent inside an object */ -#define INOBJHDR "%*s " -#define INOBJHDRVAL indent<0 ? 1 : indent, indent<0 ? "-" : "|" +/* messages and AVP formatters */ +typedef DECLARE_FD_DUMP_PROTOTYPE( (*msg_dump_formatter_msg), struct msg * msg ); +typedef DECLARE_FD_DUMP_PROTOTYPE( (*msg_dump_formatter_avp), struct avp * avp, int level, int first, int last ); -/* Write some debug data in a buffer */ - -/* Dump a msg_t object */ -static int obj_dump_msg (struct msg * msg, int indent, char **outstr, size_t *offset, size_t *outlen ) +/* Core function to process the dumping */ +static DECLARE_FD_DUMP_PROTOTYPE( msg_dump_process, msg_dump_formatter_msg msg_format, msg_dump_formatter_avp avp_format, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ) { - int ret = 0; - char buftime[256]; - size_t tsoffset = 0; - struct tm tm; - - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%*sMSG: %p|", INOBJHDRVAL, msg) ); - - if (!CHECK_MSG(msg)) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "INVALID!", INOBJHDRVAL) ); - return 0; - } - - if ((msg->msg_ts_rcv.tv_sec != 0) || (msg->msg_ts_rcv.tv_nsec != 0)) { - tsoffset += strftime(buftime + tsoffset, sizeof(buftime) - tsoffset, "%D,%T", localtime_r( &msg->msg_ts_rcv.tv_sec , &tm )); - tsoffset += snprintf(buftime + tsoffset, sizeof(buftime) - tsoffset, ".%6.6ld", msg->msg_ts_rcv.tv_nsec / 1000); - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "Received: %s|", INOBJHDRVAL, buftime) ); - } - if ((msg->msg_ts_sent.tv_sec != 0) || (msg->msg_ts_sent.tv_nsec != 0)) { - tsoffset += strftime(buftime + tsoffset, sizeof(buftime) - tsoffset, "%D,%T", localtime_r( &msg->msg_ts_sent.tv_sec , &tm )); - tsoffset += snprintf(buftime + tsoffset, sizeof(buftime) - tsoffset, ".%6.6ld", msg->msg_ts_sent.tv_nsec / 1000); - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "Sent : %s|", INOBJHDRVAL, buftime) ); + FD_DUMP_HANDLE_OFFSET(); + + if (force_parsing) { + (void) fd_msg_parse_dict(obj, dict, NULL); } - if (!msg->msg_model) { - - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(no model)|", INOBJHDRVAL) ); - - } else { - - enum dict_object_type dicttype; - struct dict_cmd_data dictdata; - ret = fd_dict_gettype(msg->msg_model, &dicttype); - if (ret || (dicttype != DICT_COMMAND)) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(invalid model: %d %d)|", INOBJHDRVAL, ret, dicttype) ); - goto public; - } - ret = fd_dict_getval(msg->msg_model, &dictdata); - if (ret != 0) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(error getting model data: %s)|", INOBJHDRVAL, strerror(ret)) ); - goto public; - } - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "model : v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %u \"%s\"|", INOBJHDRVAL, - DUMP_CMDFL_val(dictdata.cmd_flag_val), DUMP_CMDFL_val(dictdata.cmd_flag_mask), dictdata.cmd_code, dictdata.cmd_name) ); - } -public: - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "public: V:%d L:%d fl:" DUMP_CMDFL_str " CC:%u A:%d hi:%x ei:%x|", INOBJHDRVAL, - msg->msg_public.msg_version, - msg->msg_public.msg_length, - DUMP_CMDFL_val(msg->msg_public.msg_flags), - msg->msg_public.msg_code, - msg->msg_public.msg_appl, - msg->msg_public.msg_hbhid, - msg->msg_public.msg_eteid - ) ); - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "intern: rwb:%p rt:%d cb:%p,%p(%p) qry:%p asso:%d sess:%p src:%s(%zd)|", - INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.anscb, msg->msg_cb.expirecb, msg->msg_cb.data, msg->msg_query, msg->msg_associated, msg->msg_sess, msg->msg_src_id?:"(nil)", msg->msg_src_id_len) ); - return 0; -} - -/* Dump an avp object */ -static int obj_dump_avp ( struct avp * avp, int indent, char **outstr, size_t *offset, size_t *outlen ) -{ - int ret = 0; - - if (!CHECK_AVP(avp)) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "INVALID!", INOBJHDRVAL) ); - return 0; - } - - if (!avp->avp_model) { - - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(no model resolved)|", INOBJHDRVAL) ); - - } else { - - enum dict_object_type dicttype; - struct dict_avp_data dictdata; - ret = fd_dict_gettype(avp->avp_model, &dicttype); - if (ret || (dicttype != DICT_AVP)) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(invalid model: %d %d)|", INOBJHDRVAL, ret, dicttype) ); - goto public; - } - ret = fd_dict_getval(avp->avp_model, &dictdata); - if (ret != 0) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(error getting model data: %s)|", INOBJHDRVAL, strerror(ret)) ); - goto public; - } - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "model : v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %u \"%s\"|", INOBJHDRVAL, - DUMP_AVPFL_val(dictdata.avp_flag_val), - DUMP_AVPFL_val(dictdata.avp_flag_mask), - type_base_name[dictdata.avp_basetype], - dictdata.avp_code, - dictdata.avp_name ) ); - } -public: - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "public: C:%u fl:" DUMP_AVPFL_str " L:%d V:%u data:@%p|", INOBJHDRVAL, - avp->avp_public.avp_code, - DUMP_AVPFL_val(avp->avp_public.avp_flags), - avp->avp_public.avp_len, - avp->avp_public.avp_vendor, - avp->avp_public.avp_value - ) ); - /* Dump the value if set */ - if (avp->avp_public.avp_value) { - if (!avp->avp_model) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(data set but no model: ERROR)|", INOBJHDRVAL) ); - } else { - CHECK_FCT( fd_dict_dump_avp_value(avp->avp_public.avp_value, avp->avp_model, indent, outstr, offset, outlen, 1) ); - } - } - - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "intern: src:%p mf:%d raw:%p(%d)|", INOBJHDRVAL, avp->avp_source, avp->avp_mustfreeos, avp->avp_rawdata, avp->avp_rawlen) ); - return 0; -} - -/* Dump a single object content into out string, realloc if needed */ -static int msg_dump_intern ( int level, msg_or_avp * obj, int indent, char **outstr, size_t *offset, size_t *outlen ) -{ - /* Log only if we are at least at level */ - if ( ! TRACE_BOOL(level) ) - return 0; - - /* Check the object */ - if (!VALIDATE_OBJ(obj)) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, ">>> invalid object (%p)!.", obj) ); - return 0; - } - - /* Dump the object */ switch (_C(obj)->type) { case MSG_AVP: - CHECK_FCT( obj_dump_avp ( _A(obj), indent, outstr, offset, outlen )); + CHECK_MALLOC_DO( (*avp_format)(FD_DUMP_STD_PARAMS, (struct avp *)obj, 0, 1, 1), return NULL); break; - + case MSG_MSG: - CHECK_FCT( obj_dump_msg ( _M(obj), indent, outstr, offset, outlen ) ); + CHECK_MALLOC_DO( (*msg_format)(FD_DUMP_STD_PARAMS, (struct msg *)obj), return NULL); break; - + default: ASSERT(0); } - return 0; + + if (recurse) { + struct avp * avp = NULL; + int first = 1; + CHECK_FCT_DO( fd_msg_browse ( obj, MSG_BRW_FIRST_CHILD, &avp, NULL ), avp = NULL ); + while (avp) { + struct avp * nextavp = NULL; + CHECK_FCT_DO( fd_msg_browse ( avp, MSG_BRW_NEXT, &nextavp, NULL ), nextavp = NULL ); + CHECK_MALLOC_DO( (*avp_format)(FD_DUMP_STD_PARAMS, avp, 1, first, nextavp ? 0 : 1), return NULL); + avp = nextavp; + first = 0; + }; + } + + return *buf; } -/* Dump a message to a specified file stream */ -void fd_msg_dump_fstr ( struct msg * msg, FILE * fstr ) +/* + * Tree View message dump + */ +static DECLARE_FD_DUMP_PROTOTYPE( msg_format_treeview, struct msg * msg ) { - msg_or_avp * ref = msg; - int indent = 2; - char *outstr; - size_t offset, outlen; - CHECK_FCT_DO( dump_init_str(&outstr, &offset, &outlen), { fd_log_debug_fstr(fstr, "Error initializing string for dumping %p", msg); return; } ); - do { - CHECK_FCT_DO( msg_dump_intern ( NONE, ref, indent, &outstr, &offset, &outlen ), - fd_log_debug_fstr(fstr, "Error while dumping %p", ref) ); - - /* Now find the next object */ - CHECK_FCT_DO( fd_msg_browse ( ref, MSG_BRW_WALK, &ref, &indent ), break ); + if (!CHECK_MSG(msg)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{message}(@%p): INVALID", msg), return NULL); + return *buf; + } + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{message}(@%p): ", msg), return NULL); + if (!msg->msg_model) { + if (msg->msg_model_not_found.mnf_code) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(not found in dictionary)\n"), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(not searched in dictionary)\n"), return NULL); + } + } else { + enum dict_object_type dicttype; + struct dict_cmd_data dictdata; + if (fd_dict_gettype(msg->msg_model, &dicttype) || (dicttype != DICT_COMMAND)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(invalid model information)\n"), return NULL); + } else if (fd_dict_getval(msg->msg_model, &dictdata)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(error getting model information)\n"), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'\n", dictdata.cmd_name), return NULL); + } + } - /* dump next object */ - } while (ref); - - /* now really output this in one shot, so it is not interrupted */ - fd_log_debug_fstr(fstr, "%s", outstr); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Version: 0x%02hhX\n", msg->msg_public.msg_version), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Length: %d\n", msg->msg_public.msg_length), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Flags: 0x%02hhX (" DUMP_CMDFL_str ")\n", msg->msg_public.msg_flags, DUMP_CMDFL_val(msg->msg_public.msg_flags)), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Command Code: %u\n", msg->msg_public.msg_code), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " ApplicationId: %d\n", msg->msg_public.msg_appl), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Hop-by-Hop Identifier: 0x%8X\n", msg->msg_public.msg_hbhid), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " End-to-End Identifier: 0x%8X\n", msg->msg_public.msg_eteid), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {debug data}: src:%s(%zd) rwb:%p rt:%d cb:%p,%p(%p) qry:%p asso:%d sess:%p", msg->msg_src_id?:"(nil)", msg->msg_src_id_len, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.anscb, msg->msg_cb.expirecb, msg->msg_cb.data, msg->msg_query, msg->msg_associated, msg->msg_sess), return NULL); - free(outstr); -} -void fd_msg_dump_fstr_one ( struct msg * msg, FILE * fstr ) /* just the header */ -{ - char *outstr; - size_t offset, outlen; - CHECK_FCT_DO( dump_init_str(&outstr, &offset, &outlen), { fd_log_debug_fstr(fstr, "Error initializing string for dumping %p", msg); return; } ); - CHECK_FCT_DO( msg_dump_intern ( NONE, msg, 2, &outstr, &offset, &outlen ), - fd_log_debug_fstr(fstr, "Error while dumping %p", msg) ); - /* now really output this in one shot, so it is not interrupted */ - fd_log_debug_fstr(fstr, "%s", outstr); - - free(outstr); + return *buf; } -/* Completely dump a msg_t object */ -static int full_obj_dump_msg (struct msg * msg, struct dictionary *dict, char **outstr, size_t *offset, size_t *outlen) +static DECLARE_FD_DUMP_PROTOTYPE( avp_format_treeview, struct avp * avp, int level, int first, int last ) { - int ret = 0; - int success = 0; - struct dict_cmd_data dictdata; - char buf[20]; - - if (!CHECK_MSG(msg)) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "INVALID MESSAGE") ); - return 0; + char * name; + struct dict_avp_data dictdata; + struct dict_avp_data *dictinfo = NULL; + struct dict_vendor_data vendordata; + struct dict_vendor_data *vendorinfo = NULL; + + if (level) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL); + } + + if (!CHECK_AVP(avp)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{avp}(@%p): INVALID", avp), return NULL); + return *buf; + } + + if (!level) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{avp}(@%p): ", avp), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*sAVP: ", level * 3, ""), return NULL); } - if (!msg->msg_model) { - fd_msg_parse_dict(msg, dict, NULL); - } - if (!msg->msg_model) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "(no model) ") ); + if (!avp->avp_model) { + if (avp->avp_model_not_found.mnf_code) { + name = "(not found in dictionary)"; + } else { + name = "(not searched in dictionary)"; + } } else { enum dict_object_type dicttype; - ret = fd_dict_gettype(msg->msg_model, &dicttype); - if (ret || (dicttype != DICT_COMMAND)) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "(invalid model: %d %d) ", ret, dicttype) ); + if (fd_dict_gettype(avp->avp_model, &dicttype) || (dicttype != DICT_AVP)) { + name = "(invalid model information)"; + } else if (fd_dict_getval(avp->avp_model, &dictdata)) { + name = "(error getting model information)"; } else { - ret = fd_dict_getval(msg->msg_model, &dictdata); - if (ret != 0) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "(error getting model data: %s) ", strerror(ret)) ); - } else { - success = 1; + name = dictdata.avp_name; + dictinfo = &dictdata; + if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) { + struct dictionary * dict; + struct dict_object * vendor; + if ((!fd_dict_getdict(avp->avp_model, &dict)) + && (!fd_dict_search(dict, DICT_VENDOR, VENDOR_OF_AVP, avp->avp_model, &vendor, ENOENT)) + && (!fd_dict_getval(vendor, &vendordata))) { + vendorinfo = &vendordata; + } } } } - - if (msg->msg_public.msg_appl) { - snprintf(buf, sizeof(buf), "%u/", msg->msg_public.msg_appl); + + if (dictinfo) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(%u)", name, avp->avp_public.avp_code), return NULL); } else { - buf[0] = '\0'; - } - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%s(%s%u)[" DUMP_CMDFL_str "], Length=%u, Hop-By-Hop-Id=0x%08x, End-to-End=0x%08x", - success ? dictdata.cmd_name : "unknown", buf, msg->msg_public.msg_code, DUMP_CMDFL_val(msg->msg_public.msg_flags), - msg->msg_public.msg_length, msg->msg_public.msg_hbhid, msg->msg_public.msg_eteid)); - - return 0; -} - -/* Dump an avp object completely */ -static int full_obj_dump_avp ( struct avp * avp, char **outstr, size_t *offset, size_t *outlen, int first ) -{ - int success = 0; - struct dict_avp_data dictdata; - char buf[20]; - - CHECK_FCT( dump_add_str(outstr, offset, outlen, first ? ((*outstr)[*offset-1] == '=' ? "{ " : ", { ") : ", ") ); - - if (!CHECK_AVP(avp)) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "INVALID AVP") ); - return 0; + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%u%s", avp->avp_public.avp_code, name), return NULL); } - if (avp->avp_model) { - enum dict_object_type dicttype; - int ret; - ret = fd_dict_gettype(avp->avp_model, &dicttype); - if (ret || (dicttype != DICT_AVP)) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "(invalid model: %d %d) ", ret, dicttype) ); - } else { - ret = fd_dict_getval(avp->avp_model, &dictdata); - if (ret != 0) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "(error getting model data: %s) ", strerror(ret)) ); - } else { - success = 1; - } + if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) { + if (vendorinfo) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " vend='%s'(%u)", vendorinfo->vendor_name, avp->avp_public.avp_vendor), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " vend=%u", avp->avp_public.avp_vendor), return NULL); + } + } + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " l=%d f=" DUMP_AVPFL_str " val=", avp->avp_public.avp_len, DUMP_AVPFL_val(avp->avp_public.avp_flags)), return NULL); + + if (dictinfo && (dictinfo->avp_basetype == AVP_TYPE_GROUPED)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(grouped)"), return NULL); + if (level) { + struct avp * inavp = NULL; + int first = 1; + CHECK_FCT_DO( fd_msg_browse ( avp, MSG_BRW_FIRST_CHILD, &inavp, NULL ), inavp = NULL ); + while (inavp) { + struct avp * nextavp = NULL; + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL); + CHECK_FCT_DO( fd_msg_browse ( inavp, MSG_BRW_NEXT, &nextavp, NULL ), inavp = NULL ); + CHECK_MALLOC_DO( avp_format_treeview(FD_DUMP_STD_PARAMS, inavp, level + 1, first, nextavp ? 0 : 1), return NULL); + inavp = nextavp; + first = 0; + }; + } + } else { + if (avp->avp_public.avp_value) { + CHECK_MALLOC_DO( fd_dict_dump_avp_value(FD_DUMP_STD_PARAMS, avp->avp_public.avp_value, avp->avp_model, 0, 0), return NULL); + } else if (avp->avp_rawdata) { + CHECK_MALLOC_DO( fd_dump_extend_hexdump(FD_DUMP_STD_PARAMS, avp->avp_rawdata, avp->avp_rawlen, 0, 0), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(not set)"), return NULL); } } - if (avp->avp_public.avp_vendor) { - snprintf(buf, sizeof(buf), "%u/", avp->avp_public.avp_vendor); - } else { - buf[0] = '\0'; + return *buf; +} + +/* multi-line human-readable dump similar to wireshark output */ +DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_treeview, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ) +{ + return msg_dump_process(FD_DUMP_STD_PARAMS, msg_format_treeview, avp_format_treeview, obj, dict, force_parsing, recurse); +} + + +/* + * One-line dumper for compact but complete traces + */ +static DECLARE_FD_DUMP_PROTOTYPE( msg_format_full, struct msg * msg ) +{ + int success = 0; + struct dict_cmd_data dictdata; + + if (!CHECK_MSG(msg)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID MESSAGE", msg), return NULL); + return *buf; } - /* \todo add full vendorname? */ - CHECK_FCT(dump_add_str(outstr, offset, outlen, "%s(%s%u)[" DUMP_AVPFL_str "]=", success ? dictdata.avp_name : "unknown", buf, avp->avp_public.avp_code, DUMP_AVPFL_val(avp->avp_public.avp_flags))); - - /* Dump the value if set */ - if (avp->avp_public.avp_value) { - if (!avp->avp_model) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "(unknown data type)") ); + + if (!msg->msg_model) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(no model) "), return NULL); + } else { + enum dict_object_type dicttype=0; + if (fd_dict_gettype(msg->msg_model, &dicttype) || (dicttype != DICT_COMMAND)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(invalid model %d) ", dicttype), return NULL); + } else if (fd_dict_getval(msg->msg_model, &dictdata)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(error getting model data) "), return NULL); } else { - CHECK_FCT( fd_dict_dump_avp_value(avp->avp_public.avp_value, avp->avp_model, 1, outstr, offset, outlen, 0) ); + success = 1; } } - - return 0; + if (msg->msg_public.msg_appl) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, + "%s(%u/%u)[" DUMP_CMDFL_str "], Length=%u, Hop-By-Hop-Id=0x%08x, End-to-End=0x%08x", + success ? dictdata.cmd_name : "unknown", msg->msg_public.msg_appl, msg->msg_public.msg_code, DUMP_CMDFL_val(msg->msg_public.msg_flags), + msg->msg_public.msg_length, msg->msg_public.msg_hbhid, msg->msg_public.msg_eteid), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, + "%s(%u)[" DUMP_CMDFL_str "], Length=%u, Hop-By-Hop-Id=0x%08x, End-to-End=0x%08x", + success ? dictdata.cmd_name : "unknown", msg->msg_public.msg_code, DUMP_CMDFL_val(msg->msg_public.msg_flags), + msg->msg_public.msg_length, msg->msg_public.msg_hbhid, msg->msg_public.msg_eteid), return NULL); + } + return *buf; } -/* Dump full message */ -void fd_msg_dump_full ( int level, struct dictionary *dict, const char *prefix, msg_or_avp *obj ) +static DECLARE_FD_DUMP_PROTOTYPE( avp_format_full, struct avp * avp, int level, int first, int last ) { - msg_or_avp * ref = obj; - char *outstr; - int indent = 1; - int first = 1; - int previous; - size_t offset, outlen; - CHECK_FCT_DO( dump_init_str(&outstr, &offset, &outlen), - { fd_log_error("Error initializing string for dumping %p", obj); return; } ); - CHECK_FCT_DO( dump_add_str(&outstr, &offset, &outlen, "%s: ", prefix), - { fd_log_error("Error while dumping %p", ref); return; }); + int success = 0; + struct dict_avp_data dictdata; + struct dict_vendor_data vendordata; + struct dict_vendor_data *vendorinfo = NULL; + + + if (level) { + if ((first) && ((*buf)[*offset - 1] == '=')) { + /* We are first AVP of a grouped AVP */ + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{ "), return NULL); + } else { + /* We follow another AVP, or a message header */ + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ", { "), return NULL); + } + } + + if (!CHECK_AVP(avp)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID AVP"), return NULL); + goto end; + } + - do { - /* Check the object */ - if (!VALIDATE_OBJ(ref)) { - CHECK_FCT_DO( dump_add_str(&outstr, &offset, &outlen, ">>> invalid object (%p)", ref), - { fd_log_error("Error in error handling dumping %p", ref); break; }); + if (avp->avp_model) { + enum dict_object_type dicttype; + if (fd_dict_gettype(avp->avp_model, &dicttype) || (dicttype != DICT_AVP)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(invalid model: %d) ", dicttype), return NULL); + } else if (fd_dict_getval(avp->avp_model, &dictdata)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(error getting model data) "), return NULL); + } else { + success = 1; } - /* Dump the object */ - switch (_C(ref)->type) { - case MSG_AVP: - CHECK_FCT_DO( full_obj_dump_avp ( _A(ref), &outstr, &offset, &outlen, first ), - { fd_log_error("Error in error handling dumping %p", ref); }); - break; - case MSG_MSG: - CHECK_FCT_DO( full_obj_dump_msg ( _M(obj), dict, &outstr, &offset, &outlen ), - { fd_log_error("Error in error handling dumping %p", ref); }); - break; - default: - ASSERT(0); - } + } + + if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s(%u/%u)[" DUMP_AVPFL_str "]=", + success ? dictdata.avp_name : "unknown", avp->avp_public.avp_vendor, avp->avp_public.avp_code, DUMP_AVPFL_val(avp->avp_public.avp_flags)), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s(%u)[" DUMP_AVPFL_str "]=", + success ? dictdata.avp_name : "unknown", avp->avp_public.avp_code, DUMP_AVPFL_val(avp->avp_public.avp_flags)), return NULL); + } - first = 0; - previous = indent; - /* Now find the next object */ - CHECK_FCT_DO( fd_msg_browse ( ref, MSG_BRW_WALK, &ref, &indent ), break ); - if (previous < indent) { - first = 1; - } else while (previous-- > indent) { - CHECK_FCT_DO( dump_add_str(&outstr, &offset, &outlen, " }"), - { fd_log_error("Error while dumping %p", ref); return; }); + + if (success && (dictdata.avp_basetype == AVP_TYPE_GROUPED)) { + if (level) { + struct avp * inavp = NULL; + int first = 1; + CHECK_FCT_DO( fd_msg_browse ( avp, MSG_BRW_FIRST_CHILD, &inavp, NULL ), inavp = NULL ); + while (inavp) { + struct avp * nextavp = NULL; + CHECK_FCT_DO( fd_msg_browse ( inavp, MSG_BRW_NEXT, &nextavp, NULL ), inavp = NULL ); + CHECK_MALLOC_DO( avp_format_full(FD_DUMP_STD_PARAMS, inavp, level + 1, first, nextavp ? 0 : 1), return NULL); + inavp = nextavp; + first = 0; + }; } - /* dump next object */ - } while (ref); - - fd_log(level, "%s", outstr); - free(outstr); + } else { + if (avp->avp_public.avp_value) { + CHECK_MALLOC_DO( fd_dict_dump_avp_value(FD_DUMP_STD_PARAMS, avp->avp_public.avp_value, avp->avp_model, 0, 0), return NULL); + } else if (avp->avp_rawdata) { + CHECK_MALLOC_DO( fd_dump_extend_hexdump(FD_DUMP_STD_PARAMS, avp->avp_rawdata, avp->avp_rawlen, 0, 0), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(not set)"), return NULL); + } + } + +end: + if (level) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " }"), return NULL); + } + + return *buf; } -/* Dump a message content -- for debug mostly */ -void fd_msg_dump_walk ( int level, msg_or_avp *obj ) +/* one-line dump with all the contents of the message */ +DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_full, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ) { - msg_or_avp * ref = obj; - int indent = 1; - char *outstr; - size_t offset, outlen; - CHECK_FCT_DO( dump_init_str(&outstr, &offset, &outlen), - { fd_log_debug_fstr(fd_g_debug_fstr, "Error initializing string for dumping %p", obj); return; } ); - - do { - CHECK_FCT_DO( msg_dump_intern ( level, ref, indent, &outstr, &offset, &outlen ), - fd_log_debug_fstr(fd_g_debug_fstr, "Error while dumping %p", ref) ); - - /* Now find the next object */ - CHECK_FCT_DO( fd_msg_browse ( ref, MSG_BRW_WALK, &ref, &indent ), break ); - - /* dump next object */ - } while (ref); - - /* now really output this in one shot, so it is not interrupted */ - TRACE_DEBUG(level, "------ Dumping object %p (w)-------", obj); - TRACE_DEBUG(level, "%s", outstr); - TRACE_DEBUG(level, "------ /end of object %p -------", obj); - - free(outstr); -} - -/* Dump a single object content -- for debug mostly */ -void fd_msg_dump_one ( int level, msg_or_avp * obj ) -{ - char *outstr; - size_t offset, outlen; - CHECK_FCT_DO( dump_init_str(&outstr, &offset, &outlen), - { fd_log_debug_fstr(fd_g_debug_fstr, "Error initializing string for dumping %p", obj); return; } ); - CHECK_FCT_DO( msg_dump_intern ( level, obj, 1, &outstr, &offset, &outlen ), - fd_log_debug_fstr(fd_g_debug_fstr, "Error while dumping %p", obj) ); - TRACE_DEBUG(level, "------ Dumping object %p (s)-------", obj); - TRACE_DEBUG(level, "%s", outstr); - TRACE_DEBUG(level, "------ /end of object %p -------", obj); - free(outstr); + return msg_dump_process(FD_DUMP_STD_PARAMS, msg_format_full, avp_format_full, obj, dict, force_parsing, recurse); } + +/* + * One-line dumper for compact but complete traces + */ +static DECLARE_FD_DUMP_PROTOTYPE( msg_format_summary, struct msg * msg ) +{ + if (!CHECK_MSG(msg)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{message}(@%p): INVALID", msg), return NULL); + return *buf; + } + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{message}(@%p): ", msg), return NULL); + if (!msg->msg_model) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(no model)"), return NULL); + } else { + enum dict_object_type dicttype; + struct dict_cmd_data dictdata; + if (fd_dict_gettype(msg->msg_model, &dicttype) || (dicttype != DICT_COMMAND) || (fd_dict_getval(msg->msg_model, &dictdata))) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(model error)"), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'", dictdata.cmd_name), return NULL); + } + } + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%u/%u f:" DUMP_CMDFL_str " src:'%s' len:%d", + msg->msg_public.msg_appl, msg->msg_public.msg_code, DUMP_CMDFL_val(msg->msg_public.msg_flags), msg->msg_src_id?:"(nil)", msg->msg_public.msg_length), return NULL); + + return *buf; +} + +static DECLARE_FD_DUMP_PROTOTYPE( avp_format_summary, struct avp * avp, int level, int first, int last ) +{ + char * name; + struct dict_avp_data dictdata; + struct dict_avp_data *dictinfo = NULL; + struct dict_vendor_data vendordata; + struct dict_vendor_data *vendorinfo = NULL; + + if (level) { + if (first) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {"), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "+"), return NULL); + } + } + + if (!CHECK_AVP(avp)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID"), return NULL); + goto end; + } + + if (!level) { + /* We have been called to explicitely dump this AVP, so we parse its name if available */ + if (!avp->avp_model) { + name = "(no model)"; + } else { + enum dict_object_type dicttype; + if (fd_dict_gettype(avp->avp_model, &dicttype) || (dicttype != DICT_AVP) || (fd_dict_getval(avp->avp_model, &dictdata))) { + name = "(model error)"; + } else { + name = dictdata.avp_name; + dictinfo = &dictdata; + if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) { + struct dictionary * dict; + struct dict_object * vendor; + if ((!fd_dict_getdict(avp->avp_model, &dict)) + && (!fd_dict_search(dict, DICT_VENDOR, VENDOR_OF_AVP, avp->avp_model, &vendor, ENOENT)) + && (!fd_dict_getval(vendor, &vendordata))) { + vendorinfo = &vendordata; + } + } + } + } + + if (dictinfo) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(%u)", name, avp->avp_public.avp_code), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%u%s", avp->avp_public.avp_code, name), return NULL); + } + + if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) { + if (vendorinfo) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " V='%s'(%u)", vendorinfo->vendor_name, avp->avp_public.avp_vendor), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " V=%u", avp->avp_public.avp_vendor), return NULL); + } + } + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " L=%d F=" DUMP_AVPFL_str " V=", avp->avp_public.avp_len, DUMP_AVPFL_val(avp->avp_public.avp_flags)), return NULL); + + if ((!dictinfo) || (dictinfo->avp_basetype != AVP_TYPE_GROUPED)) { + if (avp->avp_public.avp_value) { + CHECK_MALLOC_DO( fd_dict_dump_avp_value(FD_DUMP_STD_PARAMS, avp->avp_public.avp_value, avp->avp_model, 0, 0), return NULL); + } else if (avp->avp_rawdata) { + CHECK_MALLOC_DO( fd_dump_extend_hexdump(FD_DUMP_STD_PARAMS, avp->avp_rawdata, avp->avp_rawlen, 0, 0), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(not set)"), return NULL); + } + } + } else { + /* For embedded AVPs, we only display (vendor,) code & length */ + if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "V=%u,", avp->avp_public.avp_vendor), return NULL); + } + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "C=%u,L=%d", avp->avp_public.avp_code, avp->avp_public.avp_len), return NULL); + } + +end: + if ((level) && (last)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "}"), return NULL); + } + + return *buf; +} + +/* This one only prints a short display, does not go into the complete tree */ +DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_summary, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ) +{ + return msg_dump_process(FD_DUMP_STD_PARAMS, msg_format_summary, avp_format_summary, obj, dict, force_parsing, recurse); +} + +#ifndef OLD_CODE_TO_BE_REPLACED +void fd_msg_dump_walk ( int level, msg_or_avp *obj ) +{ + LOG_D("fd_msg_dump_walk %d, %p is deprecated", level, obj); +} +void fd_msg_dump_one ( int level, msg_or_avp * obj ) +{ + LOG_D("fd_msg_dump_one %d, %p is deprecated", level, obj); +} +#endif /***************************************************************************************************************/ /* Simple meta-data management */ @@ -1186,8 +1257,8 @@ if (! (msg->msg_public.msg_flags & CMD_FLAG_REQUEST )) return anscb ? EINVAL : 0; /* we associate with requests only */ - CHECK_PARAMS( (anscb == NULL) || (msg->msg_cb.anscb == NULL) ); /* We are not overwritting a cb */ - CHECK_PARAMS( (expirecb == NULL) || (msg->msg_cb.expirecb == NULL) ); /* We are not overwritting a cb */ + CHECK_PARAMS( (anscb == NULL) || (msg->msg_cb.anscb == NULL) ); /* We are not overwriting a cb */ + CHECK_PARAMS( (expirecb == NULL) || (msg->msg_cb.expirecb == NULL) ); /* We are not overwriting a cb */ /* Associate callback and data with the message, if any */ msg->msg_cb.anscb = anscb; @@ -1363,54 +1434,6 @@ return 0; } -int fd_msg_ts_set_recv( struct msg * msg, struct timespec * ts ) -{ - TRACE_ENTRY("%p %p", msg, ts); - - /* Check we received valid parameters */ - CHECK_PARAMS( CHECK_MSG(msg) ); - CHECK_PARAMS( ts ); - - memcpy(&msg->msg_ts_rcv, ts, sizeof(struct timespec)); - return 0; -} - -int fd_msg_ts_get_recv( struct msg * msg, struct timespec * ts ) -{ - TRACE_ENTRY("%p %p", msg, ts); - - /* Check we received valid parameters */ - CHECK_PARAMS( CHECK_MSG(msg) ); - CHECK_PARAMS( ts ); - - memcpy(ts, &msg->msg_ts_rcv, sizeof(struct timespec)); - return 0; -} - -int fd_msg_ts_set_sent( struct msg * msg, struct timespec * ts ) -{ - TRACE_ENTRY("%p %p", msg, ts); - - /* Check we received valid parameters */ - CHECK_PARAMS( CHECK_MSG(msg) ); - CHECK_PARAMS( ts ); - - memcpy(&msg->msg_ts_sent, ts, sizeof(struct timespec)); - return 0; -} - -int fd_msg_ts_get_sent( struct msg * msg, struct timespec * ts ) -{ - TRACE_ENTRY("%p %p", msg, ts); - - /* Check we received valid parameters */ - CHECK_PARAMS( CHECK_MSG(msg) ); - CHECK_PARAMS( ts ); - - memcpy(ts, &msg->msg_ts_sent, sizeof(struct timespec)); - return 0; -} - /* Associate a session with a message, use only when the session was just created */ int fd_msg_sess_set(struct msg * msg, struct session * session) { @@ -1481,6 +1504,13 @@ return 0; } +/* Retrieve the location of the pmd list for the message; return NULL if failed */ +struct fd_msg_pmdl * fd_msg_pmdl_get(struct msg * msg) +{ + CHECK_PARAMS_DO( CHECK_MSG(msg), return NULL ); + return &msg->msg_pmdl; +} + /******************* End-to-end counter *********************/ static uint32_t fd_eteid; @@ -1924,23 +1954,20 @@ CHECK_PARAMS( buffer && *buffer && msg && (buflen >= GETMSGHDRSZ()) ); buf = *buffer; - *buffer = NULL; if ( buf[0] != DIAMETER_VERSION) { TRACE_DEBUG(INFO, "Invalid version in message: %d (supported: %d)", buf[0], DIAMETER_VERSION); - free(buf); return EBADMSG; } msglen = ntohl(*(uint32_t *)buf) & 0x00ffffff; if ( buflen < msglen ) { TRACE_DEBUG(INFO, "Truncated message (%zd / %d)", buflen, msglen ); - free(buf); return EBADMSG; } /* Create a new object */ - CHECK_MALLOC_DO( new = malloc (sizeof(struct msg)), { free(buf); return ENOMEM; } ); + CHECK_MALLOC( new = malloc (sizeof(struct msg)) ); /* Initialize the fields */ init_msg(new); @@ -1956,11 +1983,12 @@ new->msg_public.msg_hbhid = ntohl(*(uint32_t *)(buf+12)); new->msg_public.msg_eteid = ntohl(*(uint32_t *)(buf+16)); - new->msg_rawbuffer = buf; - /* Parse the AVP list */ CHECK_FCT_DO( ret = parsebuf_list(buf + GETMSGHDRSZ(), buflen - GETMSGHDRSZ(), &new->msg_chain.children), { destroy_tree(_C(new)); return ret; } ); + /* Parsing successful */ + new->msg_rawbuffer = buf; + *buffer = NULL; *msg = new; return 0; } @@ -2003,16 +2031,26 @@ } } - /* Now try and resolve the model from the avp code and vendor */ - if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) { - struct dict_avp_request_ex avpreq; - memset(&avpreq, 0, sizeof(avpreq)); - avpreq.avp_vendor.vendor_id = avp->avp_public.avp_vendor; - avpreq.avp_data.avp_code = avp->avp_public.avp_code; - CHECK_FCT( fd_dict_search ( dict, DICT_AVP, AVP_BY_STRUCT, &avpreq, &avp->avp_model, 0)); - } else { - /* no vendor */ - CHECK_FCT( fd_dict_search ( dict, DICT_AVP, AVP_BY_CODE, &avp->avp_public.avp_code, &avp->avp_model, 0)); + /* Check if we already searched for this model without success */ + if ((avp->avp_model_not_found.mnf_code != avp->avp_public.avp_code) + || (avp->avp_model_not_found.mnf_vendor != avp->avp_public.avp_vendor)) { + + /* Now try and resolve the model from the avp code and vendor */ + if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) { + struct dict_avp_request_ex avpreq; + memset(&avpreq, 0, sizeof(avpreq)); + avpreq.avp_vendor.vendor_id = avp->avp_public.avp_vendor; + avpreq.avp_data.avp_code = avp->avp_public.avp_code; + CHECK_FCT( fd_dict_search ( dict, DICT_AVP, AVP_BY_STRUCT, &avpreq, &avp->avp_model, 0)); + } else { + /* no vendor */ + CHECK_FCT( fd_dict_search ( dict, DICT_AVP, AVP_BY_CODE, &avp->avp_public.avp_code, &avp->avp_model, 0)); + } + + if (!avp->avp_model) { + avp->avp_model_not_found.mnf_code = avp->avp_public.avp_code; + avp->avp_model_not_found.mnf_vendor = avp->avp_public.avp_vendor; + } } /* First handle the case where we have not found this AVP in the dictionary */ @@ -2177,19 +2215,44 @@ CHECK_PARAMS( CHECK_MSG(msg) ); + /* First, check if we already have a model. */ + if (msg->msg_model != NULL) { + /* Check if this model is still valid for the message data */ + enum dict_object_type dicttype; + struct dict_cmd_data data; + ASSERT(((fd_dict_gettype(msg->msg_model, &dicttype) == 0) && (dicttype == DICT_COMMAND))); + (void)fd_dict_getval( msg->msg_model, &data); + if ((data.cmd_code != msg->msg_public.msg_code) + || ((data.cmd_flag_val & data.cmd_flag_mask) != (msg->msg_public.msg_flags && data.cmd_flag_mask))) { + msg->msg_model = NULL; + } else { + goto chain; + } + } + + /* Check if we already searched for this model without success */ + if ((msg->msg_model_not_found.mnf_code == msg->msg_public.msg_code) + && (msg->msg_model_not_found.mnf_flags == msg->msg_public.msg_flags)) { + goto no_model; + } else { + msg->msg_model_not_found.mnf_code = 0; + } + /* Look for the model from the header */ CHECK_FCT_DO( ret = fd_dict_search ( dict, DICT_COMMAND, (msg->msg_public.msg_flags & CMD_FLAG_REQUEST) ? CMD_BY_CODE_R : CMD_BY_CODE_A, &msg->msg_public.msg_code, &msg->msg_model, ENOTSUP), { - if ((ret == ENOTSUP) && (error_info)) { - error_info->pei_errcode = "DIAMETER_COMMAND_UNSUPPORTED"; - error_info->pei_protoerr = 1; + if (ret == ENOTSUP) { + /* update the model not found info */ + msg->msg_model_not_found.mnf_code = msg->msg_public.msg_code; + msg->msg_model_not_found.mnf_flags = msg->msg_public.msg_flags; + goto no_model; } return ret; } ); - +chain: if (!only_hdr) { /* Then process the children */ ret = parsedict_do_chain(dict, &msg->msg_chain.children, 1, error_info); @@ -2202,6 +2265,12 @@ } return ret; +no_model: + if (error_info) { + error_info->pei_errcode = "DIAMETER_COMMAND_UNSUPPORTED"; + error_info->pei_protoerr = 1; + } + return ENOTSUP; } int fd_msg_parse_dict ( msg_or_avp * object, struct dictionary * dict, struct fd_pei *error_info ) @@ -2351,7 +2420,7 @@ min = 1; } if (count < min) { - TRACE_DEBUG(INFO, "Conflicting rule: the number of occurences (%d) is < the rule min (%d) for '%s'.", count, min, avp_name); + fd_log_error("Conflicting rule: the number of occurences (%d) is < the rule min (%d) for '%s'.", count, min, avp_name); if (pr_data->pei) { pr_data->pei->pei_errcode = "DIAMETER_MISSING_AVP"; pr_data->pei->pei_avp = empty_avp(rule->rule_avp); @@ -2361,7 +2430,7 @@ /* Check the "max" value */ if ((rule->rule_max != -1) && (count > rule->rule_max)) { - TRACE_DEBUG(INFO, "Conflicting rule: the number of occurences (%d) is > the rule max (%d) for '%s'.", count, rule->rule_max, avp_name); + fd_log_error("Conflicting rule: the number of occurences (%d) is > the rule max (%d) for '%s'.", count, rule->rule_max, avp_name); if (pr_data->pei) { if (rule->rule_max == 0) pr_data->pei->pei_errcode = "DIAMETER_AVP_NOT_ALLOWED"; @@ -2382,7 +2451,7 @@ case RULE_FIXED_HEAD: /* Since "0*1<fixed>" is a valid rule specifier, we only reject cases where the AVP appears *after* its fixed position */ if (first > rule->rule_order) { - TRACE_DEBUG(INFO, "Conflicting rule: the FIXED_HEAD AVP appears first in (%d) position, the rule requires (%d) for '%s'.", first, rule->rule_order, avp_name); + fd_log_error("Conflicting rule: the FIXED_HEAD AVP appears first in (%d) position, the rule requires (%d) for '%s'.", first, rule->rule_order, avp_name); if (pr_data->pei) { pr_data->pei->pei_errcode = "DIAMETER_MISSING_AVP"; pr_data->pei->pei_message = "AVP was not in its fixed position"; @@ -2395,7 +2464,7 @@ case RULE_FIXED_TAIL: /* Since "0*1<fixed>" is a valid rule specifier, we only reject cases where the AVP appears *before* its fixed position */ if (last > rule->rule_order) { /* We have a ">" here because we count in reverse order (i.e. from the end) */ - TRACE_DEBUG(INFO, "Conflicting rule: the FIXED_TAIL AVP appears last in (%d) position, the rule requires (%d) for '%s'.", last, rule->rule_order, avp_name); + fd_log_error("Conflicting rule: the FIXED_TAIL AVP appears last in (%d) position, the rule requires (%d) for '%s'.", last, rule->rule_order, avp_name); if (pr_data->pei) { pr_data->pei->pei_errcode = "DIAMETER_MISSING_AVP"; pr_data->pei->pei_message = "AVP was not in its fixed position"; @@ -2638,7 +2707,7 @@ *error_code = "DIAMETER_APPLICATION_UNSUPPORTED"; *action = DISP_ACT_ERROR; } else { - fd_msg_log( FD_MSG_LOG_DROPPED, *msg, "Internal error: Received this answer to a local query with an unsupported application %d", (*msg)->msg_public.msg_appl); + //fd_msg_log( FD_MSG_LOG_DROPPED, *msg, "Internal error: Received this answer to a local query with an unsupported application %d", (*msg)->msg_public.msg_appl); fd_msg_free(*msg); *msg = NULL; }
--- a/libfdproto/msg_log.c Fri May 10 09:50:09 2013 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,206 +0,0 @@ -/********************************************************************************************************* -* Software License Agreement (BSD License) * -* Author: Sebastien Decugis <sdecugis@freediameter.net> * -* * -* Copyright (c) 2013, WIDE Project and NICT * -* All rights reserved. * -* * -* Redistribution and use of this software in source and binary forms, with or without modification, are * -* permitted provided that the following conditions are met: * -* * -* * Redistributions of source code must retain the above * -* copyright notice, this list of conditions and the * -* following disclaimer. * -* * -* * Redistributions in binary form must reproduce the above * -* copyright notice, this list of conditions and the * -* following disclaimer in the documentation and/or other * -* materials provided with the distribution. * -* * -* * Neither the name of the WIDE Project or NICT nor the * -* names of its contributors may be used to endorse or * -* promote products derived from this software without * -* specific prior written permission of WIDE Project and * -* NICT. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * -* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * -* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * -* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * -*********************************************************************************************************/ - -/* messages logging facility */ -#include "fdproto-internal.h" -#include <stdarg.h> - -/* Configuration of this module */ -static struct { - struct { - enum fd_msg_log_method meth; - const char * metharg; - } causes[FD_MSG_LOG_MAX + 1]; - pthread_mutex_t lock; - int init; - struct dictionary *dict; -} ml_conf = { .lock = PTHREAD_MUTEX_INITIALIZER, .init = 0 }; - - -/* Initialize the module, with a dictionary to use to better parse the messages */ -void fd_msg_log_init(struct dictionary *dict) -{ - memset(&ml_conf.causes, 0, sizeof(ml_conf.causes)); - ml_conf.init = 1; - ml_conf.dict = dict; -} - -/* Set a configuration property */ -int fd_msg_log_config(enum fd_msg_log_cause cause, enum fd_msg_log_method method, const char * arg) -{ - /* Check the parameters are valid */ - TRACE_ENTRY("%d %d %p", cause, method, arg); - CHECK_PARAMS( (cause >= 0) && (cause <= FD_MSG_LOG_MAX) ); - CHECK_PARAMS( (method >= FD_MSG_LOGTO_NONE) && (method <= FD_MSG_LOGTO_DIR) ); - CHECK_PARAMS( (method == FD_MSG_LOGTO_NONE) || (method == FD_MSG_LOGTO_DEBUGONLY) || (arg != NULL) ); - - /* Lock the configuration */ - CHECK_POSIX( pthread_mutex_lock(&ml_conf.lock) ); - if (!ml_conf.init) { - ASSERT(0); - } - - /* Now set the parameter */ - ml_conf.causes[cause].meth = method; - ml_conf.causes[cause].metharg = arg; - - if (method) { - TRACE_DEBUG(INFO, "Logging %s messages set to %s '%s'", - (cause == FD_MSG_LOG_DROPPED) ? "DROPPED" : - (cause == FD_MSG_LOG_RECEIVED) ? "RECEIVED" : - (cause == FD_MSG_LOG_SENT) ? "SENT" : - (cause == FD_MSG_LOG_NODELIVER) ? "NODELIVER" : - (cause == FD_MSG_LOG_TIMING) ? "TIMING" : - "???", - (method == FD_MSG_LOGTO_NONE) ? "none" : - (method == FD_MSG_LOGTO_DEBUGONLY) ? "debug" : - (method == FD_MSG_LOGTO_FILE) ? "file" : - (method == FD_MSG_LOGTO_DIR) ? "directory" : - "???", - arg); - } - - CHECK_POSIX( pthread_mutex_unlock(&ml_conf.lock) ); - - /* Done */ - return 0; -} - -/* Do not log anything within this one, since log lock is held */ -static void fd_cleanup_mutex_silent( void * mutex ) -{ - (void)pthread_mutex_unlock((pthread_mutex_t *)mutex); -} - -/* Really log the message */ -void fd_msg_log( enum fd_msg_log_cause cause, struct msg * msg, const char * prefix_format, ... ) -{ - va_list ap; - enum fd_msg_log_method meth; - const char * metharg; - FILE * fstr; - - char buftime[256]; - size_t offset = 0; - struct timespec ts; - struct tm tm; - - TRACE_ENTRY("%d %p %p", cause, msg, prefix_format); - CHECK_PARAMS_DO( (cause >= 0) && (cause <= FD_MSG_LOG_MAX), - { - TRACE_DEBUG(INFO, "Invalid cause received (%d)! Message was:", cause); - fd_msg_dump_walk(INFO, msg); - } ); - - /* First retrieve the config for this message */ - CHECK_POSIX_DO( pthread_mutex_lock(&ml_conf.lock), ); - if (!ml_conf.init) { - ASSERT(0); - } - meth = ml_conf.causes[cause].meth; - metharg = ml_conf.causes[cause].metharg; - CHECK_POSIX_DO( pthread_mutex_unlock(&ml_conf.lock), ); - - /* Return now when loging is not requested */ - if ((meth == FD_MSG_LOGTO_NONE) - || ((meth == FD_MSG_LOGTO_DEBUGONLY) && (fd_g_debug_lvl < INFO))) { - return; - } - - /* Get current time */ - CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), /* continue */); - offset += strftime(buftime + offset, sizeof(buftime) - offset, "%D,%T", localtime_r( &ts.tv_sec , &tm )); - offset += snprintf(buftime + offset, sizeof(buftime) - offset, ".%6.6ld", ts.tv_nsec / 1000); - - - /* Okay, now we will create the file descriptor */ - switch (meth) { - case FD_MSG_LOGTO_DEBUGONLY: - fstr = fd_g_debug_fstr; - break; - - case FD_MSG_LOGTO_FILE: - TODO("Log to arg file"); - TODO("Log a note to debug stream"); - TRACE_DEBUG(INFO, "%s", metharg); - break; - case FD_MSG_LOGTO_DIR: - TODO("Log to arg directory in a new file"); - TODO("Log a note to debug stream"); - break; - default: - break; - } - - /* For file methods, let's parse the message so it looks better */ - if (((meth != FD_MSG_LOGTO_DEBUGONLY) || (fd_g_debug_lvl > FULL)) && ml_conf.dict) { - CHECK_FCT_DO( fd_msg_parse_dict( msg, ml_conf.dict, NULL ), ); - } - - /* Then dump the prefix message to this stream, & to debug stream */ - (void)pthread_mutex_lock(&fd_log_lock); - pthread_cleanup_push(fd_cleanup_mutex_silent, &fd_log_lock); - fprintf( fstr, "\n"); - va_start(ap, prefix_format); - vfprintf( fstr, prefix_format, ap); - va_end(ap); - fflush(fstr); - pthread_cleanup_pop(0); - (void)pthread_mutex_unlock(&fd_log_lock); - - fd_log_debug_fstr(fstr, " Logged: %s", buftime); - - /* And now the message itself */ - if ((meth == FD_MSG_LOGTO_DEBUGONLY) && (fd_g_debug_lvl <= INFO)) { - /* dump only the header */ - fd_msg_dump_fstr_one(msg, fstr); - } else { - /* dump the full content */ - fd_msg_dump_fstr(msg, fstr); - } - - /* And finally close the stream if needed */ - switch (meth) { - case FD_MSG_LOGTO_FILE: - TODO("close?"); - break; - case FD_MSG_LOGTO_DIR: - TODO("close?"); - break; - default: - break; - } -} -
--- a/libfdproto/ostr.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdproto/ostr.c Fri May 10 18:49:19 2013 +0800 @@ -185,20 +185,21 @@ if *inoutsz is != 0 on entry, *id may not be \0-terminated. memory has the following meaning: 0: *id can be realloc'd. 1: *id must be malloc'd on output (was static) */ -#if defined(DIAMID_IDNA_IGNORE) || defined(DIAMID_IDNA_REJECT) -GCC_DIAG_OFF("-Wunused-but-set-variable") -#endif int fd_os_validate_DiameterIdentity(char ** id, size_t * inoutsz, int memory) { +#if !defined(DIAMID_IDNA_IGNORE) && !defined(DIAMID_IDNA_REJECT) int gotsize = 0; +#endif /* defined(DIAMID_IDNA_IGNORE) || defined(DIAMID_IDNA_REJECT) */ TRACE_ENTRY("%p %p", id, inoutsz); CHECK_PARAMS( id && *id && inoutsz ); if (!*inoutsz) *inoutsz = strlen(*id); +#if !defined(DIAMID_IDNA_IGNORE) && !defined(DIAMID_IDNA_REJECT) else gotsize = 1; +#endif /* defined(DIAMID_IDNA_IGNORE) || defined(DIAMID_IDNA_REJECT) */ #ifndef DIAMID_IDNA_IGNORE @@ -248,9 +249,6 @@ } return 0; } -#if defined(DIAMID_IDNA_IGNORE) || defined(DIAMID_IDNA_REJECT) -GCC_DIAG_ON("-Wunused-but-set-variable") -#endif /* Analyze a DiameterURI and return its components. Return EINVAL if the URI is not valid.
--- a/libfdproto/rt_data.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdproto/rt_data.c Fri May 10 18:49:19 2013 +0800 @@ -248,6 +248,21 @@ return 0; } +/* Only retrieve the number of times this message has been processed by the routing-out mechanism (i.e. number of times it was failed over) */ +int fd_rtd_get_nb_attempts(struct rt_data * rtd, int * sendingattemtps) +{ + struct fd_list * li; + int match = 0; + + TRACE_ENTRY("%p %p", rtd, sendingattemtps); + CHECK_PARAMS( rtd && sendingattemtps ); + + *sendingattemtps = rtd->extracted; + + /* Done! */ + return 0; +} + /* Extract the list of valid candidates, and initialize their scores */ void fd_rtd_candidate_extract(struct rt_data * rtd, struct fd_list ** candidates, int ini_score) {
--- a/libfdproto/sessions.c Fri May 10 09:50:09 2013 +0800 +++ b/libfdproto/sessions.c Fri May 10 18:49:19 2013 +0800 @@ -68,7 +68,8 @@ struct session_handler { int eyec; /* An eye catcher also used to ensure the object is valid, must be SH_EYEC */ int id; /* A unique integer to identify this handler */ - void (*cleanup)(session_state *, os0_t, void *); /* The cleanup function to be called for cleaning a state */ + void (*cleanup)(struct sess_state *, os0_t, void *); /* The cleanup function to be called for cleaning a state */ + session_state_dump state_dump; /* dumper function */ void *opaque; /* a value that is passed as is to the cleanup callback */ }; @@ -79,7 +80,7 @@ /* Data structures linked from the sessions, containing the applications states */ struct state { int eyec; /* Must be SD_EYEC */ - session_state *state; /* The state registered by the application, never NULL (or the whole object is deleted) */ + struct sess_state *state; /* The state registered by the application, never NULL (or the whole object is deleted) */ struct fd_list chain; /* Chaining in the list of session's states ordered by hdl->id */ union { struct session_handler *hdl; /* The handler for which this state was registered */ @@ -272,7 +273,7 @@ } /* Create a new handler */ -int fd_sess_handler_create_internal ( struct session_handler ** handler, void (*cleanup)(session_state *, os0_t, void *), void * opaque ) +int fd_sess_handler_create ( struct session_handler ** handler, void (*cleanup)(struct sess_state *, os0_t, void *), session_state_dump dumper, void * opaque ) { struct session_handler *new; @@ -289,6 +290,7 @@ new->eyec = SH_EYEC; new->cleanup = cleanup; + new->state_dump = dumper; new->opaque = opaque; *handler = new; @@ -717,7 +719,7 @@ } /* Save a state information with a session */ -int fd_sess_state_store_internal ( struct session_handler * handler, struct session * session, session_state ** state ) +int fd_sess_state_store ( struct session_handler * handler, struct session * session, struct sess_state ** state ) { struct state *new; struct fd_list * li; @@ -770,7 +772,7 @@ } /* Get the data back */ -int fd_sess_state_retrieve_internal ( struct session_handler * handler, struct session * session, session_state ** state ) +int fd_sess_state_retrieve ( struct session_handler * handler, struct session * session, struct sess_state ** state ) { struct fd_list * li; struct state * st = NULL; @@ -872,49 +874,60 @@ /* Dump functions */ -void fd_sess_dump(int level, struct session * session) +DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump, struct session * session, int with_states) { - struct fd_list * li; - char buf[30]; - struct tm tm; + FD_DUMP_HANDLE_OFFSET(); + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{session}(@%p): ", session), return NULL); - if (!TRACE_BOOL(level)) - return; - - fd_log_debug("\t %*s -- Session @%p --", level, "", session); if (!VALIDATE_SI(session)) { - fd_log_debug("\t %*s Invalid session object", level, ""); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL); } else { + char timebuf[30]; + struct tm tm; + + strftime(timebuf, sizeof(timebuf), "%D,%T", localtime_r( &session->timeout.tv_sec , &tm )); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(%zd) h:%x m:%d d:%d to:%s.%06ld", + session->sid, session->sidlen, session->hash, session->msg_cnt, session->is_destroyed, + timebuf, session->timeout.tv_nsec/1000), + return NULL); - fd_log_debug("\t %*s sid '%s'(%zd), hash %x, msg %d, destroyed %d", level, "", session->sid, session->sidlen, session->hash, session->msg_cnt, session->is_destroyed); - - strftime(buf, sizeof(buf), "%D,%T", localtime_r( &session->timeout.tv_sec , &tm )); - fd_log_debug("\t %*s timeout %s.%09ld", level, "", buf, session->timeout.tv_nsec); - - CHECK_POSIX_DO( pthread_mutex_lock(&session->stlock), /* ignore */ ); - pthread_cleanup_push( fd_cleanup_mutex, &session->stlock ); - for (li = session->states.next; li != &session->states; li = li->next) { - struct state * st = (struct state *)(li->o); - fd_log_debug("\t %*s handler %d registered data %p", level, "", st->hdl->id, st->state); + if (with_states) { + struct fd_list * li; + CHECK_POSIX_DO( pthread_mutex_lock(&session->stlock), /* ignore */ ); + pthread_cleanup_push( fd_cleanup_mutex, &session->stlock ); + + for (li = session->states.next; li != &session->states; li = li->next) { + struct state * st = (struct state *)(li->o); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {state i:%d}(@%p): ", st->hdl->id, st), return NULL); + if (st->hdl->state_dump) { + CHECK_MALLOC_DO( (*st->hdl->state_dump)( FD_DUMP_STD_PARAMS, st->state), + fd_dump_extend( FD_DUMP_STD_PARAMS, "[dumper error]")); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "<%p>", st->state), return NULL); + } + } + + pthread_cleanup_pop(0); + CHECK_POSIX_DO( pthread_mutex_unlock(&session->stlock), /* ignore */ ); } - pthread_cleanup_pop(0); - CHECK_POSIX_DO( pthread_mutex_unlock(&session->stlock), /* ignore */ ); } - fd_log_debug("\t %*s -- end of session @%p --", level, "", session); + + return *buf; } -void fd_sess_dump_hdl(int level, struct session_handler * handler) +DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump_hdl, struct session_handler * handler) { - if (!TRACE_BOOL(level)) - return; + FD_DUMP_HANDLE_OFFSET(); + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{sesshdl}(@%p): ", handler), return NULL); - fd_log_debug("\t %*s -- Handler @%p --", level, "", handler); if (!VALIDATE_SH(handler)) { - fd_log_debug("\t %*s Invalid session handler object", level, ""); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL); } else { - fd_log_debug("\t %*s id %d, cleanup %p, opaque %p", level, "", handler->id, handler->cleanup, handler->opaque); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "i:%d cl:%p d:%p o:%p", handler->id, handler->cleanup, handler->state_dump, handler->opaque), return NULL); } - fd_log_debug("\t %*s -- end of handler @%p --", level, "", handler); + return *buf; } int fd_sess_getcount(uint32_t *cnt)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfdproto/utils.c Fri May 10 18:49:19 2013 +0800 @@ -0,0 +1,92 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis <sdecugis@freediameter.net> * +* * +* Copyright (c) 2013, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +#include "fdproto-internal.h" + +DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node, sSA * sa, int flags) +{ + char addrbuf[INET6_ADDRSTRLEN]; + FD_DUMP_HANDLE_OFFSET(); + + if (sa) { + int rc = getnameinfo(sa, sSAlen( sa ), addrbuf, sizeof(addrbuf), NULL, 0, flags); + if (rc) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", gai_strerror(rc)), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", &addrbuf[0]), return NULL); + } + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(NULL / ANY)"), return NULL); + } + + return *buf; +} + +DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node_serv, sSA * sa, int flags) +{ + char addrbuf[INET6_ADDRSTRLEN]; + char servbuf[32]; + FD_DUMP_HANDLE_OFFSET(); + + if (sa) { + int rc = getnameinfo(sa, sSAlen( sa ), addrbuf, sizeof(addrbuf), servbuf, sizeof(servbuf), flags); + if (rc) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", gai_strerror(rc)), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s(s)", &addrbuf[0], &servbuf[0]), return NULL); + } + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(NULL / ANY)"), return NULL); + } + return *buf; +} + +void fd_sa_sdump_numeric(char * buf /* must be at least sSA_DUMP_STRLEN */, sSA * sa) +{ + char addrbuf[INET6_ADDRSTRLEN]; + char servbuf[32]; + + if (sa) { + int rc = getnameinfo(sa, sSAlen( sa ), addrbuf, sizeof(addrbuf), servbuf, sizeof(servbuf), NI_NUMERICHOST | NI_NUMERICSERV); + if (rc) { + snprintf(buf, sSA_DUMP_STRLEN, "%s", gai_strerror(rc)); + } else { + snprintf(buf, sSA_DUMP_STRLEN, "%s(%s)", addrbuf, servbuf); + } + } else { + snprintf(buf, sSA_DUMP_STRLEN, "(NULL / ANY)"); + } + +}
--- a/tests/CMakeLists.txt Fri May 10 09:50:09 2013 +0800 +++ b/tests/CMakeLists.txt Fri May 10 18:49:19 2013 +0800 @@ -25,6 +25,7 @@ testpeers testdict testmesg + testmesg_stress testsess testdisp testcnx
--- a/tests/testcnx.c Fri May 10 09:50:09 2013 +0800 +++ b/tests/testcnx.c Fri May 10 18:49:19 2013 +0800 @@ -714,7 +714,7 @@ #if 0 /* For debug: dump the object */ fd_log_debug("Dumping CER"); - fd_msg_dump_walk(0, cer); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, cer, fd_g_config->cnf_dict, 0, 1)); #endif CHECK( 0, fd_msg_bufferize( cer, &cer_buf, &cer_sz ) );
--- a/tests/testdict.c Fri May 10 09:50:09 2013 +0800 +++ b/tests/testdict.c Fri May 10 18:49:19 2013 +0800 @@ -191,7 +191,7 @@ CHECK(1, obj ? 1 : 0 ); #if 1 - fd_dict_dump_object(obj); + fd_log_debug("%s", fd_dict_dump_object(FD_DUMP_TEST_PARAMS, obj)); #endif CHECK( 0, fd_dict_delete(obj) ); cntbkp = count; @@ -203,6 +203,8 @@ } + LOG_D( "Dictionary at the end of %s: %s", __FILE__, fd_dict_dump(FD_DUMP_TEST_PARAMS, fd_g_config->cnf_dict) ?: "error"); + /* That's all for the tests yet */ PASSTEST(); }
--- a/tests/testdisp.c Fri May 10 09:50:09 2013 +0800 +++ b/tests/testdisp.c Fri May 10 18:49:19 2013 +0800 @@ -698,7 +698,7 @@ CHECK( 0, app->flags.acct ); #if 0 - fd_conf_dump(); + fd_log_debug("%s", fd_conf_dump(FD_DUMP_TEST_PARAMS)); #endif }
--- a/tests/testfifo.c Fri May 10 09:50:09 2013 +0800 +++ b/tests/testfifo.c Fri May 10 18:49:19 2013 +0800 @@ -216,15 +216,15 @@ /* Basic operation */ { struct fifo * queue = NULL; - int count; struct msg * msg = NULL; + int max; + long long count; /* Create the queue */ CHECK( 0, fd_fifo_new(&queue, 0) ); /* Check the count is 0 */ - CHECK( 0, fd_fifo_length(queue, &count) ); - CHECK( 0, count); + CHECK( 0, fd_fifo_length(queue) ); /* Now enqueue */ msg = msg1; @@ -235,33 +235,28 @@ CHECK( 0, fd_fifo_post(queue, &msg) ); /* Check the count is 3 */ - CHECK( 0, fd_fifo_length(queue, &count) ); - CHECK( 3, count); + CHECK( 3, fd_fifo_length(queue) ); /* Retrieve the first message using fd_fifo_get */ CHECK( 0, fd_fifo_get(queue, &msg) ); CHECK( msg1, msg); - CHECK( 0, fd_fifo_length(queue, &count) ); - CHECK( 2, count); + CHECK( 2, fd_fifo_length(queue) ); /* Retrieve the second message using fd_fifo_timedget */ CHECK(0, clock_gettime(CLOCK_REALTIME, &ts)); ts.tv_sec += 1; /* Set the timeout to 1 second */ CHECK( 0, fd_fifo_timedget(queue, &msg, &ts) ); CHECK( msg2, msg); - CHECK( 0, fd_fifo_length(queue, &count) ); - CHECK( 1, count); + CHECK( 1, fd_fifo_length(queue) ); /* Retrieve the third message using meq_tryget */ CHECK( 0, fd_fifo_tryget(queue, &msg) ); CHECK( msg3, msg); - CHECK( 0, fd_fifo_length(queue, &count) ); - CHECK( 0, count); + CHECK( 0, fd_fifo_length(queue) ); /* Check that another meq_tryget does not block */ CHECK( EWOULDBLOCK, fd_fifo_tryget(queue, &msg) ); - CHECK( 0, fd_fifo_length(queue, &count) ); - CHECK( 0, count); + CHECK( 0, fd_fifo_length(queue) ); /* Check the timedget actually timesout */ CHECK(0, clock_gettime(CLOCK_REALTIME, &ts)); @@ -271,8 +266,18 @@ ts.tv_sec += 1; } CHECK( ETIMEDOUT, fd_fifo_timedget(queue, &msg, &ts) ); - CHECK( 0, fd_fifo_length(queue, &count) ); - CHECK( 0, count); + CHECK( 0, fd_fifo_length(queue) ); + + /* Post & get another message */ + msg = msg1; + CHECK( 0, fd_fifo_post(queue, &msg) ); + CHECK( 0, fd_fifo_timedget(queue, &msg, &ts) ); + CHECK( msg1, msg); + + /* Check some statistics */ + CHECK( 0, fd_fifo_getstats(queue, NULL, NULL, &max, &count, NULL, NULL, NULL) ); + CHECK( 3, max ); + CHECK( 4, count ); /* We're done for basic tests */ CHECK( 0, fd_fifo_del(&queue) ); @@ -289,7 +294,6 @@ struct msg *msgs[NBR_MSG * NBR_THREADS * 2], *msg; pthread_t thr [NBR_THREADS * 2]; struct dict_object *dwr_model = NULL; - int count; int i; int nbr_threads; #ifdef _POSIX_THREAD_THREADS_MAX @@ -360,8 +364,7 @@ } /* Check the count of the queue is back to 0 */ - CHECK( 0, fd_fifo_length(queue, &count) ); - CHECK( 0, count); + CHECK( 0, fd_fifo_length(queue) ); /* Destroy this queue and the messages */ CHECK( 0, fd_fifo_del(&queue) ); @@ -555,8 +558,6 @@ CHECK( 14, iter ); - /* fd_fifo_dump(0, "test", queue, NULL); */ - for (; i < td.nbr; i++) { CHECK( 0, fd_fifo_tryget(queue, &item) ); CHECK( i, *item);
--- a/tests/testmesg.c Fri May 10 09:50:09 2013 +0800 +++ b/tests/testmesg.c Fri May 10 18:49:19 2013 +0800 @@ -60,8 +60,8 @@ #if 0 /* For debug: dump the object */ - fd_log_debug("Dumping Accounting-Request empty message"); - fd_msg_dump_walk( 0, acr ); + fd_log_debug("Dumping Accounting-Request empty message:"); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, acr, fd_g_config->cnf_dict, 0, 1)); #endif } @@ -78,9 +78,9 @@ #if 0 /* For debug: dump the object */ fd_log_debug("Dumping Proxy-Info AVP"); - fd_msg_dump_walk(0, pi); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, pi, fd_g_config->cnf_dict, 0, 1)); fd_log_debug("Dumping dictionary model"); - fd_dict_dump_object(pi_model); + fd_log_debug("%s", fd_dict_dump_object(FD_DUMP_TEST_PARAMS, pi_model)); #endif } @@ -106,7 +106,7 @@ #if 0 /* For debug: dump the object */ fd_log_debug("Dumping Accounting-Request with Proxy-Info AVP at the end"); - fd_msg_dump_walk(0, acr); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, acr, fd_g_config->cnf_dict, 0, 1)); #endif } @@ -305,12 +305,12 @@ < grouped > */ #if 0 - fd_dict_dump_object ( gavp ); + fd_log_debug("%s", fd_dict_dump_object(FD_DUMP_TEST_PARAMS, gavp)); #endif } #if 0 { - fd_dict_dump_object ( vendor ); + fd_log_debug("%s", fd_dict_dump_object(FD_DUMP_TEST_PARAMS, vendor)); } #endif } @@ -364,7 +364,7 @@ CHECK( 0, fd_msg_update_length ( avpi ) ); #if 0 fd_log_debug("AVP no vendor, value 3.1415:"); - fd_msg_dump_one(0, avpi); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpi, fd_g_config->cnf_dict, 0, 0)); #endif CHECK( 0, fd_msg_avp_hdr ( avpi, &avpdata ) ); CHECK( 12, avpdata->avp_len ); @@ -381,7 +381,7 @@ CHECK( 0, fd_msg_update_length ( avpi ) ); #if 0 fd_log_debug("AVP vendor, value 0x123456789abcdeL:"); - fd_msg_dump_one(0, avpi); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpi, fd_g_config->cnf_dict, 0, 0)); #endif CHECK( 0, fd_msg_avp_hdr ( avpi, &avpdata ) ); CHECK( 20, avpdata->avp_len ); @@ -407,7 +407,7 @@ CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) ); #if 0 fd_log_debug("AVP enum i32, value 2 (from const):"); - fd_msg_dump_one(0, avpi); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpi, fd_g_config->cnf_dict, 0, 0)); #endif } @@ -428,7 +428,7 @@ CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) ); #if 0 fd_log_debug("AVP enum i32, value -5 (from const):"); - fd_msg_dump_one(0, avpi); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpi, fd_g_config->cnf_dict, 0, 0)); #endif /* Check the size is correct ( 12 for header + 4 for value ) */ CHECK( 0, fd_msg_update_length ( avpi ) ); @@ -443,7 +443,7 @@ CHECK( 0, fd_msg_update_length ( avpi ) ); #if 0 fd_log_debug("AVP vendor enum i32, value -10 (not const):"); - fd_msg_dump_one(0, avpi); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpi, fd_g_config->cnf_dict, 0, 0)); #endif /* Add an octetstring AVP */ @@ -458,7 +458,7 @@ CHECK( 0, fd_msg_update_length ( avpi ) ); #if 0 fd_log_debug("AVP octet string, 'This\\0 is a b...'"); - fd_msg_dump_one(0, avpi); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpi, fd_g_config->cnf_dict, 0, 0)); #endif CHECK( 0, fd_msg_avp_hdr ( avpi, &avpdata ) ); CHECK( 101, avpdata->avp_len ); @@ -487,7 +487,7 @@ CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) ); #if 0 fd_log_debug("AVP Enumuerated OctetString (from const):"); - fd_msg_dump_one(0, avpi); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpi, fd_g_config->cnf_dict, 0, 0)); #endif /* Check the size is correct ( 12 for header + 5 for value ) */ CHECK( 0, fd_msg_update_length ( avpi ) ); @@ -512,7 +512,7 @@ CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) ); #if 0 fd_log_debug("AVP Enumuerated OctetString (from const):"); - fd_msg_dump_one(0, avpi); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpi, fd_g_config->cnf_dict, 0, 0)); #endif /* Check the size is correct ( 12 for header + 3 for value ) */ CHECK( 0, fd_msg_update_length ( avpi ) ); @@ -534,7 +534,7 @@ CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) ); #if 0 fd_log_debug("AVP octet string, '1234678'"); - fd_msg_dump_one(0, avpch); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpch, fd_g_config->cnf_dict, 0, 0)); #endif CHECK( 0, fd_msg_update_length ( avpch ) ); CHECK( 0, fd_msg_avp_hdr ( avpch, &avpdata ) ); @@ -547,7 +547,7 @@ CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) ); #if 0 fd_log_debug("AVP octet string, '12346789'"); - fd_msg_dump_one(0, avpch); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, avpch, fd_g_config->cnf_dict, 0, 0)); #endif } @@ -579,7 +579,7 @@ */ CHECK( 0, fd_msg_update_length ( msg ) ); #if 0 - fd_msg_dump_walk(0, msg); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, fd_g_config->cnf_dict, 0, 1)); #endif CHECK( 344, msgdata->msg_length ); @@ -659,7 +659,7 @@ CPYBUF(); CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) ); #if 0 - fd_msg_dump_walk(0, msg); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, fd_g_config->cnf_dict, 0, 1)); #endif /* reinit the msg */ @@ -732,7 +732,7 @@ CHECK( 0, fd_msg_parse_dict( msg, fd_g_config->cnf_dict, NULL ) ); #if 0 - fd_msg_dump_walk(0, msg); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, fd_g_config->cnf_dict, 0, 1)); #endif /* reset */ @@ -756,6 +756,7 @@ { unsigned char * buftmp = NULL; + struct msg * error; /* Check the parse or error works as expected */ CPYBUF(); @@ -764,11 +765,13 @@ /* Check that we cannot support this message now */ CHECK( 0, fd_msg_init() ); CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) ); - CHECK( EBADMSG, fd_msg_parse_or_error( &msg ) ); + CHECK( EBADMSG, fd_msg_parse_or_error( &msg, &error ) ); + CHECK( NULL, msg ); + msg = error; CHECK( 0, fd_msg_bufferize( msg, &buftmp, NULL ) ); - fd_msg_dump_walk(0, msg); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, fd_g_config->cnf_dict, 0, 1)); TODO("Check the Failed-AVP is as expected"); @@ -782,7 +785,7 @@ CHECK( 0, fd_msg_parse_buffer( &buf, 344, &msg) ); CHECK( 0, fd_msg_parse_dict( msg, fd_g_config->cnf_dict, NULL ) ); #if 0 - fd_msg_dump_walk(0, msg); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, fd_g_config->cnf_dict, 0, 1)); #endif } @@ -1335,14 +1338,14 @@ /* Okay, now delete the message and parse the buffer, then check we obtain the same values back */ #if 0 - fd_msg_dump_walk(0, msg); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, fd_g_config->cnf_dict, 0, 1)); #endif CHECK( 0, fd_msg_free( msg ) ); CHECK( 0, fd_msg_parse_buffer( &buf, 148, &msg) ); CHECK( 0, fd_msg_parse_dict( msg, fd_g_config->cnf_dict, NULL ) ); #if 0 - fd_msg_dump_walk(0, msg); + fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, fd_g_config->cnf_dict, 0, 1)); #endif CHECK( 0, fd_msg_browse ( msg, MSG_BRW_FIRST_CHILD, &avp, NULL) );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/testmesg_stress.c Fri May 10 18:49:19 2013 +0800 @@ -0,0 +1,544 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis <sdecugis@freediameter.net> * +* * +* Copyright (c) 2013, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +#include "tests.h" + +/* The number of times each operation is repeated to measure the average operation time */ +#define DEFAULT_NUMBER_OF_SAMPLES 100000 + +static void display_result(int nr, struct timespec * start, struct timespec * end, char * fct, char * type, char *op) +{ + long double dur = (long double)end->tv_sec + (long double)end->tv_nsec/1000000000; + dur -= (long double)start->tv_sec + (long double)start->tv_nsec/1000000000; + long double thrp = (long double)nr / dur; + printf("%-19s: %d %-8s %-7s in %.6LFs (%.1LFmsg/s)\n", fct, nr, type, op, dur, thrp); +} + + + +/* Main test routine */ +int main(int argc, char *argv[]) +{ + struct msg * acr = NULL; + struct avp * pi = NULL, *avp1, *avp2; + unsigned char * buf = NULL; + + test_parameter = DEFAULT_NUMBER_OF_SAMPLES; + + /* First, initialize the daemon modules */ + INIT_FD(); + + { + struct dict_object * acr_model = NULL; + + /* Now find the ACR dictionary object */ + CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &acr_model, ENOENT ) ); + + /* Create the instance, using the templates */ + CHECK( 0, fd_msg_new ( acr_model, 0, &acr ) ); + } + + /* Now let's create some additional Dictionary objects for the test */ + { + /* The constant values used here are totally arbitrary chosen */ + struct dict_object * vendor; + { + struct dict_vendor_data vendor_data = { 73565, "Vendor test" }; + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_VENDOR, &vendor_data , NULL, &vendor ) ); + } + + { + struct dict_application_data app_data = { 73566, "Application test" }; + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_APPLICATION, &app_data , vendor, NULL ) ); + } + + { + struct dict_avp_data avp_data = { 73567, 0, "AVP Test - no vendor - f32", 0, 0, AVP_TYPE_FLOAT32 }; + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) ); + } + + { + struct dict_avp_data avp_data = { 139103, 0, "AVP Test - no vendor - f64", 0, 0, AVP_TYPE_FLOAT64 }; + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) ); + } + + { + struct dict_object * type = NULL; + struct dict_type_data type_data = { AVP_TYPE_INTEGER64, "Int64 test" }; + struct dict_avp_data avp_data = { 73568, 73565, "AVP Test - i64", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_INTEGER64 }; + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) ); + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) ); + } + + { + struct dict_object * type = NULL; + struct dict_type_data type_data = { AVP_TYPE_INTEGER32, "Enum32 test" }; + struct dict_enumval_data val1 = { "i32 const test (val 1)", { .i32 = 1 } }; + struct dict_enumval_data val2 = { "i32 const test (val 2)", { .i32 = 2 } }; + struct dict_enumval_data val3 = { "i32 const test (val -5)",{ .i32 = -5 } }; + struct dict_avp_data avp_data = { 73569, 73565, "AVP Test - enumi32", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_INTEGER32 }; + + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) ); + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) ); + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val1 , type, NULL ) ); + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val2 , type, NULL ) ); + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val3 , type, NULL ) ); + } + + { + struct dict_object * type = NULL; + struct dict_type_data type_data = { AVP_TYPE_OCTETSTRING, "OS test" }; + struct dict_avp_data avp_data = { 73570, 73565, "AVP Test - os", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_OCTETSTRING }; + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) ); + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) ); + } + + { + struct dict_object * type = NULL; + struct dict_type_data type_data = { AVP_TYPE_OCTETSTRING, "OS enum test" }; + struct dict_enumval_data val1 = { "os const test (Test)", { .os = { (unsigned char *)"Test", 4 } } }; + struct dict_enumval_data val2 = { "os const test (waaad)", { .os = { (unsigned char *)"waaad", 5 } } }; + struct dict_enumval_data val3 = { "os const test (waa)", { .os = { (unsigned char *)"waaad", 3 } } }; + struct dict_avp_data avp_data = { 73571, 73565, "AVP Test - enumos", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_OCTETSTRING }; + + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) ); + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) ); + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val1 , type, NULL ) ); + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val2 , type, NULL ) ); + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val3 , type, NULL ) ); + } + + { + struct dict_object * gavp = NULL; + struct dict_avp_data avp_data = { 73572, 73565, "AVP Test - grouped", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_GROUPED }; + + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, &gavp ) ); + + /* Macro to search AVP and create a rule */ + #define ADD_RULE( _parent, _vendor, _avpname, _pos, _min, _max, _ord ) { \ + struct dict_object * _avp = NULL; \ + struct dict_avp_request _req = { (_vendor), 0, (_avpname) }; \ + struct dict_rule_data _data; \ + CHECK( 0, fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));\ + _data.rule_avp = _avp; \ + _data.rule_position = (_pos); \ + _data.rule_order = (_ord); \ + _data.rule_min = (_min); \ + _data.rule_max = (_max); \ + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_RULE, &_data , (_parent), NULL ) ); \ + } + + ADD_RULE(gavp, 73565, "AVP Test - os", RULE_OPTIONAL, -1, -1, 0); + + } + + { + struct dict_object * application = NULL; + struct dict_object * command = NULL; + struct dict_cmd_data cmd_data = { 73573, "Test-Command-Request", CMD_FLAG_REQUEST, CMD_FLAG_REQUEST }; + + CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Application test", &application, ENOENT ) ); + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_COMMAND, &cmd_data , application, &command ) ); + ADD_RULE(command, 0, "AVP Test - no vendor - f32", RULE_FIXED_HEAD, -1, 1, 1); + ADD_RULE(command, 73565, "AVP Test - i64", RULE_REQUIRED, -1, -1, 0); + ADD_RULE(command, 73565, "AVP Test - enumi32", RULE_OPTIONAL, -1, -1, 0); + ADD_RULE(command, 73565, "AVP Test - os", RULE_OPTIONAL, -1, -1, 0); + ADD_RULE(command, 73565, "AVP Test - enumos", RULE_OPTIONAL, -1, -1, 0); + ADD_RULE(command, 73565, "AVP Test - grouped", RULE_OPTIONAL, -1, -1, 0); + } + + { + struct dict_object * application = NULL; + struct dict_object * command = NULL; + struct dict_cmd_data cmd_data = { 73573, "Test-Command-Answer", CMD_FLAG_REQUEST, 0 }; + + CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Application test", &application, ENOENT ) ); + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_COMMAND, &cmd_data , application, &command ) ); + } + + { + struct dict_object * gavp = NULL; + struct dict_avp_data avp_data = { 73574, 73565, "AVP Test - rules", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_GROUPED }; + + CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, &gavp ) ); + + ADD_RULE(gavp, 0, "AVP Test - no vendor - f32", RULE_FIXED_HEAD, 0, 1, 1); + ADD_RULE(gavp, 73565, "AVP Test - i64", RULE_FIXED_HEAD, -1, 1, 2); + ADD_RULE(gavp, 73565, "AVP Test - enumi32", RULE_FIXED_HEAD, -1, 1, 3); + ADD_RULE(gavp, 73565, "AVP Test - os", RULE_REQUIRED, 2, 3, 0); + ADD_RULE(gavp, 73565, "AVP Test - enumos", RULE_OPTIONAL, 0, 1, 0); + ADD_RULE(gavp, 73565, "AVP Test - grouped", RULE_FIXED_TAIL, -1, 1, 1); + /* ABNF : + < no vendor - f32 > + < i64 > + < enumi32 > + 2*3 { os } + *1 [ enumos ] + < grouped > + */ + } + } + + /* Now create some values and check the length is correctly handled */ + { + struct dict_object * cmd_model = NULL; + struct msg * msg = NULL; + struct dict_object * avp_model = NULL; + struct avp * avp = NULL; + union avp_value value; + + CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Test-Command-Request", &cmd_model, ENOENT ) ); + + /* Check the sizes are handled properly */ + { + struct avp * avpi = NULL; + struct avp * avpch = NULL; + struct avp_hdr * avpdata = NULL; + struct msg_hdr * msgdata = NULL; + #define ADD_AVP( _parent, _position, _avpi, _avpvendor, _avpname) { \ + struct dict_object * _avp = NULL; \ + struct dict_avp_request _req = { (_avpvendor), 0, (_avpname) }; \ + CHECK( 0, fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));\ + CHECK( 0, fd_msg_avp_new ( _avp, 0, &_avpi ) ); \ + CHECK( 0, fd_msg_avp_add ( (_parent), (_position), _avpi ) ); \ + } + /* Create a message with many AVP inside */ + CHECK( 0, fd_msg_new ( cmd_model, 0, &msg ) ); + CHECK( 0, fd_msg_hdr ( msg, &msgdata ) ); + + /* Avp no vendor, float32 => size = 12 */ + ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 0, "AVP Test - no vendor - f32" ); + value.f32 = 3.1415; + CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) ); + + /* Add a vendor AVP, integer64 => size = 20 */ + ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - i64" ); + value.i64 = 0x123456789abcdeLL; + CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) ); + + /* Add an AVP with an enum value */ + ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumi32" ); + { + struct dict_object * type_model = NULL; + struct dict_object * value_model = NULL; + struct dict_enumval_request request; + + CHECK( 0, fd_msg_model ( avpi, &avp_model ) ); + CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) ); + memset(&request, 0, sizeof(request)); + request.type_obj = type_model; + request.search.enum_name = "i32 const test (val 2)"; + CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) ); + CHECK( 0, fd_dict_getval ( value_model, &request.search ) ); + CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) ); + } + + /* Add an AVP with an enum value, negative */ + ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumi32" ); + { + struct dict_object * type_model = NULL; + struct dict_object * value_model = NULL; + struct dict_enumval_request request; + + CHECK( 0, fd_msg_model ( avpi, &avp_model ) ); + CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) ); + memset(&request, 0, sizeof(request)); + request.type_obj = type_model; + request.search.enum_name = "i32 const test (val -5)"; + CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) ); + CHECK( 0, fd_dict_getval ( value_model, &request.search ) ); + CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) ); + } + + /* Now add a value which is not a constant into an enumerated AVP */ + ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumi32" ); + value.i32 = -10; + CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) ); + + /* Add an octetstring AVP */ + ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - os" ); + { + unsigned char buf[90]; + memcpy(&buf, "This\0 is a buffer of dat\a. It is not a string so we can have any c\0ntr\0l character here...\0\0", 89); + value.os.data = buf; + value.os.len = 89; + CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) ); + memset(&buf, 0, sizeof(buf)); /* Test that the OS value is really copied */ + } + + /* Add an octetstring from an enumerated constant */ + ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumos" ); + { + struct dict_object * type_model = NULL; + struct dict_object * value_model = NULL; + struct dict_enumval_request request; + + CHECK( 0, fd_msg_model ( avpi, &avp_model ) ); + CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) ); + memset(&request, 0, sizeof(request)); + request.type_obj = type_model; + request.search.enum_name = "os const test (waaad)"; + CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) ); + CHECK( 0, fd_dict_getval ( value_model, &request.search ) ); + CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) ); + } + + /* Add an octetstring from an enumerated constant */ + ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumos" ); + { + struct dict_object * type_model = NULL; + struct dict_object * value_model = NULL; + struct dict_enumval_request request; + + CHECK( 0, fd_msg_model ( avpi, &avp_model ) ); + CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) ); + memset(&request, 0, sizeof(request)); + request.type_obj = type_model; + request.search.enum_name = "os const test (waa)"; + CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) ); + CHECK( 0, fd_dict_getval ( value_model, &request.search ) ); + CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) ); + } + + /* Now test the grouped AVPs */ + ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - grouped" ); + ADD_AVP( avpi, MSG_BRW_LAST_CHILD, avpch, 73565, "AVP Test - os" ); + { + value.os.data = (unsigned char *)"12345678"; + value.os.len = 8; + CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) ); + } + ADD_AVP( avpi, MSG_BRW_LAST_CHILD, avpch, 73565, "AVP Test - os" ); + { + value.os.data = (unsigned char *)"123456789"; + value.os.len = 9; + CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) ); + } + + /* Add another similar grouped AVP, to have lot of padding */ + ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - grouped" ); + ADD_AVP( avpi, MSG_BRW_LAST_CHILD, avpch, 73565, "AVP Test - os" ); + { + value.os.data = (unsigned char *)"1"; + value.os.len = 1; + CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) ); + } + ADD_AVP( avpi, MSG_BRW_LAST_CHILD, avpch, 73565, "AVP Test - os" ); + { + value.os.data = (unsigned char *)"1234567"; + value.os.len = 7; + CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) ); + } + + /* Set the application to the test application: 73566 */ + msgdata->msg_appl = 73566; + + /* Set the hop-by-hop ID to a random value: 0x4b44b41d */ + msgdata->msg_hbhid = 0x4b44b41d; + /* Set the end-to-end ID to a random value: 0xe2ee2e1d */ + msgdata->msg_eteid = 0xe2ee2e1d; + } + + CHECK( 0, fd_msg_bufferize( msg, &buf, NULL ) ); + + LOG_D( "Test message: %s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, msg, NULL, 0, 1)); + + /* Now free the message, we keep only the buffer. */ + CHECK( 0, fd_msg_free( msg ) ); + + } + + /* We have our "buf" now, length is 344 -- cf. testmesg.c. */ + + /* Test the throughput of the different functions function */ + { + struct stress_struct { + struct msg * m; + uint8_t * b; + } * stress_array; + int i; + struct timespec start, end; + + struct msg * msg; + + + /* Create the copies of the message buffer */ + stress_array = calloc(test_parameter, sizeof(struct stress_struct)); + CHECK( stress_array ? 1 : 0, 1); + + for (i=0; i < test_parameter; i++) { + stress_array[i].b = malloc(344); + if (!stress_array[i].b) + break; + memcpy(stress_array[i].b, buf, 344); + } + CHECK( test_parameter, i ); /* if false, a malloc failed */ + + /* fd_msg_parse_buffer */ + + CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) ); + + /* Test the msg_parse_buffer function */ + for (i=0; i < test_parameter; i++) { + if (0 != fd_msg_parse_buffer( &stress_array[i].b, 344, &stress_array[i].m) ) + break; + } + CHECK( test_parameter, i ); /* if false, a call failed */ + + CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) ); + display_result(test_parameter, &start, &end, "fd_msg_parse_buffer", "buffers", "parsed"); + + /* fd_msg_parse_dict */ + + CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) ); + + /* Test the fd_msg_parse_dict function */ + for (i=0; i < test_parameter; i++) { + if (0 != fd_msg_parse_dict( stress_array[i].m, fd_g_config->cnf_dict, NULL ) ) + break; + } + CHECK( test_parameter, i ); /* if false, a call failed */ + + CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) ); + display_result(test_parameter, &start, &end, "fd_msg_parse_dict", "messages", "parsed"); + + + /* fd_msg_parse_rules */ + + CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) ); + + /* Test the fd_msg_parse_rules function */ + for (i=0; i < test_parameter; i++) { + if (0 != fd_msg_parse_rules( stress_array[i].m, fd_g_config->cnf_dict, NULL ) ) + break; + } + CHECK( test_parameter, i ); /* if false, a call failed */ + + CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) ); + display_result(test_parameter, &start, &end, "fd_msg_parse_rules", "messages", "parsed"); + + + /* fd_msg_new_answer_from_req (0) */ + + CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) ); + + /* Test the fd_msg_new_answer_from_req function */ + for (i=0; i < test_parameter; i++) { + if (0 != fd_msg_new_answer_from_req( fd_g_config->cnf_dict, &stress_array[i].m, 0 ) ) + break; + } + CHECK( test_parameter, i ); /* if false, a call failed */ + + CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) ); + display_result(test_parameter, &start, &end, "new_answer(normal)", "messages", "created"); + + /* unlink answers and go back to request messages */ + for (i=0; i < test_parameter; i++) { + struct msg * ans = stress_array[i].m; + if (0 != fd_msg_answ_getq( ans, &stress_array[i].m ) ) + break; + if (0 != fd_msg_answ_detach( ans ) ) + break; + fd_msg_free( ans ); + } + CHECK( test_parameter, i ); /* if false, a call failed */ + + + /* fd_msg_new_answer_from_req (MSGFL_ANSW_ERROR) */ + + CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) ); + + /* Test the fd_msg_new_answer_from_req function */ + for (i=0; i < test_parameter; i++) { + if ( 0 != fd_msg_new_answer_from_req( fd_g_config->cnf_dict, &stress_array[i].m, MSGFL_ANSW_ERROR ) ) + break; + } + CHECK( test_parameter, i ); /* if false, a call failed */ + + CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) ); + display_result(test_parameter, &start, &end, "new_answer(error)", "messages", "created"); + + /* unlink answers and go back to request messages */ + for (i=0; i < test_parameter; i++) { + struct msg * ans = stress_array[i].m; + if (0 != fd_msg_answ_getq( ans, &stress_array[i].m ) ) + break; + if (0 != fd_msg_answ_detach( ans ) ) + break; + fd_msg_free( ans ); + } + + + /* fd_msg_bufferize */ + + + CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) ); + + /* Test the fd_msg_bufferize function */ + for (i=0; i < test_parameter; i++) { + size_t len = 0; + if (0 != fd_msg_bufferize( stress_array[i].m, &stress_array[i].b, &len ) ) + break; + } + CHECK( test_parameter, i ); /* if false, a call failed */ + + CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) ); + display_result(test_parameter, &start, &end, "fd_msg_bufferize", "buffers", "created"); + + + /* fd_msg_free */ + + CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) ); + + /* Free those messages */ + for (i=0; i < test_parameter; i++) { + fd_msg_free( stress_array[i].m ); + } + + CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) ); + display_result(test_parameter, &start, &end, "fd_msg_free", "messages", "freed"); + + + for (i=0; i < test_parameter; i++) { + free(stress_array[i].b); + } + free(stress_array); + } + + + /* That's all for the tests yet */ + PASSTEST(); +} +
--- a/tests/testpeers.c Fri May 10 09:50:09 2013 +0800 +++ b/tests/testpeers.c Fri May 10 18:49:19 2013 +0800 @@ -56,7 +56,7 @@ CHECK( 0, fd_peer_add(&inf, __FILE__, NULL, NULL)); } } - fd_peer_dump_list(0); + fd_log_debug("%s", fd_peer_dump_list(FD_DUMP_TEST_PARAMS, 0)); /* Check we are able to find again any of these */ { int i;
--- a/tests/tests.h Fri May 10 09:50:09 2013 +0800 +++ b/tests/tests.h Fri May 10 18:49:19 2013 +0800 @@ -67,31 +67,36 @@ /* Define the macro to fail a test with a message */ #define FAILTEST( message... ){ \ - TRACE_ERROR(message); \ - TRACE_ERROR("FAILED: %s ", __STRIPPED_FILE__); \ + LOG_F(message); \ + LOG_F("FAILED: %s ", __STRIPPED_FILE__); \ + free(tbuf); \ exit(FAIL); \ } /* Define the macro to pass a test */ #define PASSTEST( ){ \ - TRACE_NOTICE("PASS: %s", __STRIPPED_FILE__); \ + LOG_N("PASS: %s", __STRIPPED_FILE__); \ (void)fd_core_shutdown(); \ (void)fd_core_wait_shutdown_complete(); \ (void)fd_thr_term(&signal_thr); \ + free(tbuf); \ exit(PASS); \ } -static int test_verbo = 0; static struct fd_config conf; extern struct fd_config * fd_g_config; +/* for dumps */ +static char * tbuf = NULL; size_t tbuflen = 0; +#define FD_DUMP_TEST_PARAMS &tbuf, &tbuflen, NULL + + /* Define the standard check routines */ #define CHECK( _val, _assert ){ \ - if (test_verbo > 0) { \ - TRACE_NOTICE("CHECK( %s == %s )", \ + LOG_D("CHECK( %s == %s )", \ #_assert, \ #_val); \ - }{ \ + { \ __typeof__ (_val) __ret = (_assert); \ if (__ret != (_val)) { \ FAILTEST( "%s:%d: CHECK FAILED : %s == %lx != %lx", \ @@ -135,18 +140,19 @@ } static int gnutls_debug = 0; +static int test_parameter = 0; static inline void parse_cmdline(int argc, char * argv[]) { int c; int no_timeout = 0; - while ((c = getopt (argc, argv, "dqnf:F:g:")) != -1) { + while ((c = getopt (argc, argv, "dqnf:F:g:p:")) != -1) { switch (c) { case 'd': /* Increase verbosity of debug messages. */ - test_verbo++; + fd_g_debug_lvl--; break; case 'q': /* Decrease verbosity. */ - test_verbo--; + fd_g_debug_lvl++; break; case 'n': /* Disable the timeout of the test. */ @@ -173,11 +179,14 @@ gnutls_debug = (int)atoi(optarg); break; + case 'p': /* Set a debug level and function for GNU TLS calls. */ + test_parameter = (int)atoi(optarg); + break; + default: /* bug: option not considered. */ return; } } - fd_g_debug_lvl = (test_verbo > 0) ? (test_verbo - 1) : 0; if (!no_timeout) { alarm(TEST_TIMEOUT); } @@ -196,6 +205,8 @@ CHECK( 0, fd_libproto_init() ); + CHECK( 0, fd_hooks_init() ); + fd_log_threadname(fname); /* Parse the command line */ @@ -215,9 +226,6 @@ /* Initialize the config */ CHECK( 0, fd_conf_init() ); - /* Initialize the message logging facility */ - fd_msg_log_init(fd_g_config->cnf_dict); - /* Add definitions of the base protocol */ CHECK( 0, fd_dict_base_protocol(fd_g_config->cnf_dict) );
--- a/tests/testsess.c Fri May 10 09:50:09 2013 +0800 +++ b/tests/testsess.c Fri May 10 18:49:19 2013 +0800 @@ -42,14 +42,14 @@ #define TEST_SID (os0_t)TEST_SID_IN #define TEST_EYEC 0x7e57e1ec -struct mystate { +struct sess_state { int eyec; /* TEST_EYEC */ os0_t sid; /* the session with which the data was registered */ int * freed; /* location where to write the freed status */ void * opaque; /* if opaque was provided, this is the value we expect */ }; -static void mycleanup( struct mystate * data, os0_t sid, void * opaque ) +static void mycleanup( struct sess_state * data, os0_t sid, void * opaque ) { /* sanity */ CHECK( 1, sid ? 1 : 0 ); @@ -66,12 +66,12 @@ free(data); } -static __inline__ struct mystate * new_state(os0_t sid, int *freed) +static __inline__ struct sess_state * new_state(os0_t sid, int *freed) { - struct mystate *new; - new = malloc(sizeof(struct mystate)); + struct sess_state *new; + new = malloc(sizeof(struct sess_state)); CHECK( 1, new ? 1 : 0 ); - memset(new, 0, sizeof(struct mystate)); + memset(new, 0, sizeof(struct sess_state)); new->eyec = TEST_EYEC; new->sid = os0dup(sid, strlen((char *)sid)); CHECK( 1, new->sid ? 1 : 0 ); @@ -105,14 +105,14 @@ /* Test functions related to handlers (simple situation) */ { void * testptr = NULL; - CHECK( 0, fd_sess_handler_create ( &hdl1, mycleanup, NULL ) ); - CHECK( 0, fd_sess_handler_create ( &hdl2, mycleanup, NULL ) ); + CHECK( 0, fd_sess_handler_create ( &hdl1, mycleanup, NULL, NULL ) ); + CHECK( 0, fd_sess_handler_create ( &hdl2, mycleanup, NULL, NULL ) ); CHECK( 0, fd_sess_handler_destroy( &hdl2, &testptr ) ); CHECK( 1, testptr == NULL ? 1 : 0 ); - CHECK( 0, fd_sess_handler_create ( &hdl2, mycleanup, g_opaque ) ); + CHECK( 0, fd_sess_handler_create ( &hdl2, mycleanup, NULL, g_opaque ) ); #if 0 - fd_sess_dump_hdl(0, hdl1); - fd_sess_dump_hdl(0, hdl2); + fd_log_debug("%s\n", fd_sess_dump_hdl(FD_DUMP_TEST_PARAMS, hdl1)); + fd_log_debug("%s\n", fd_sess_dump_hdl(FD_DUMP_TEST_PARAMS, hdl2)); #endif } @@ -122,8 +122,8 @@ CHECK( 0, fd_sess_new( &sess1, TEST_DIAM_ID, CONSTSTRLEN(TEST_DIAM_ID), NULL, 0 ) ); CHECK( 0, fd_sess_new( &sess2, TEST_DIAM_ID, CONSTSTRLEN(TEST_DIAM_ID), NULL, 0 ) ); #if 0 - fd_sess_dump(0, sess1); - fd_sess_dump(0, sess2); + fd_log_debug("%s\n", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess1, 1)); + fd_log_debug("%s\n", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess2, 1)); #endif /* Check both string start with the diameter Id, but are different */ @@ -140,8 +140,8 @@ CHECK( 0, fd_sess_new( &sess1, TEST_DIAM_ID, 0, TEST_OPT, 0 ) ); CHECK( 0, fd_sess_new( &sess2, TEST_DIAM_ID, CONSTSTRLEN(TEST_DIAM_ID), TEST_OPT, CONSTSTRLEN(TEST_OPT_IN) - 1 ) ); #if 0 - fd_sess_dump(0, sess1); - fd_sess_dump(0, sess2); + fd_log_debug("%s\n", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess1, 1)); + fd_log_debug("%s\n", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess2, 1)); #endif CHECK( 0, fd_sess_getsid(sess1, &str1, &str1len) ); @@ -164,8 +164,8 @@ CHECK( sess3, sess1 ); CHECK( 0, fd_sess_new( &sess2, NULL, 0, TEST_SID, CONSTSTRLEN(TEST_SID_IN) - 1 ) ); #if 0 - fd_sess_dump(0, sess1); - fd_sess_dump(0, sess2); + fd_log_debug("%s\n", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess1, 1)); + fd_log_debug("%s\n", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess2, 1)); #endif CHECK( 0, fd_sess_getsid(sess1, &str1, &str1len) ); CHECK( 0, fd_sess_getsid(sess2, &str2, &str2len) ); @@ -210,7 +210,7 @@ /* Test fd_sess_reclaim */ { - struct mystate *tms; + struct sess_state *tms; CHECK( 0, fd_sess_fromsid( TEST_SID, CONSTSTRLEN(TEST_SID_IN), &sess1, &new ) ); CHECK( 1, new ? 1 : 0 ); @@ -270,7 +270,7 @@ /* Test states operations */ { - struct mystate * ms[6], *tms; + struct sess_state * ms[6], *tms; int freed[6]; struct timespec timeout; void * testptr = NULL; @@ -294,7 +294,7 @@ CHECK( 1, ms[1] ? 1 : 0 ); #if 0 - fd_sess_dump(0, sess1); + fd_log_debug("%s\n", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess1, 1)); #endif CHECK( 0, fd_sess_state_retrieve( hdl1, sess1, &ms[0] ) ); @@ -331,9 +331,9 @@ CHECK( 0, fd_sess_state_store ( hdl2, sess3, &ms[5] ) ); #if 0 - fd_sess_dump(0, sess1); - fd_sess_dump(0, sess2); - fd_sess_dump(0, sess3); + fd_log_debug("%s\n", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess1, 1)); + fd_log_debug("%s\n", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess2, 1)); + fd_log_debug("%s\n", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess3, 1)); #endif /* Destroy session 3 */ @@ -356,8 +356,8 @@ CHECK( 1, testptr == g_opaque ? 1 : 0 ); #if 1 - fd_sess_dump(0, sess1); - fd_sess_dump(0, sess2); + fd_log_debug("%s\n", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess1, 1)); + fd_log_debug("%s\n", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess2, 1)); #endif /* Create again session 3, check that no data is associated to it */ @@ -372,8 +372,8 @@ CHECK( 0, clock_gettime(CLOCK_REALTIME, &timeout) ); CHECK( 0, fd_sess_settimeout( sess2, &timeout) ); #if 1 - fd_sess_dump(0, sess1); - fd_sess_dump(0, sess2); + fd_log_debug("%s\n", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess1, 1)); + fd_log_debug("%s\n", fd_sess_dump(FD_DUMP_TEST_PARAMS, sess2, 1)); #endif timeout.tv_sec = 0; timeout.tv_nsec= 50000000; /* 50 ms */