/********************************************************************************************************* * Software License Agreement (BSD License) * * Author: Sebastien Decugis * * * * 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. * *********************************************************************************************************/ /* Create and send a message, and receive it */ /* Note that we use both sessions and the argument to answer callback to pass the same value. * This is just for the purpose of checking everything went OK. */ #include "sh_app.h" #include #include "sh_conf.h" // static struct disp_hdl * sh_hdl_fb = NULL; /* handler for fallback cb */ extern struct dict_object * sh_appli; static struct disp_hdl * sh_hdl_uda = NULL; /* handler for PUR req cb */ static struct disp_hdl * sh_hdl_pua = NULL; /* handler for PUR req cb */ extern struct dict_object * uda_cmd; extern struct dict_object * pua_cmd; struct sess_state { int32_t randval; /* a random value to store in Test-AVP */ struct timespec ts; /* Time of sending the message */ } ; static struct session_handler * sh_cli_reg = NULL; static struct sh_udr_msg g_udr_cmd; static struct sh_pur_msg g_pur_cmd; static struct sh_uda_msg g_uda_cmd; static struct sh_pua_msg g_pua_cmd; //static struct dict_avp_request __avp; static char * g_test_buf = NULL; static size_t g_test_len; #define FD_DUMP_TEST_PARAMS &g_test_buf, &g_test_len, NULL #define SH_TEST_ON 1 #if 0 static void sh_send_pur() { struct msg *pur_msg = NULL; struct avp *avp, *grpavp; union avp_value val; struct sess_state *mi = NULL, *svg; struct session *sess = NULL; TRACE_DEBUG(FULL, "Creating a new message for sending."); /* Create a new session */ #define TEST_APP_SID_OPT "sh_app" /* Create the message object from model */ { struct dict_object * acr_model = NULL; /* Now find the UDR dictionary object */ ASSERT( 0 == fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Profile-Update-Request", &acr_model, ENOENT ) ); /* Create the instance, using the templates */ ASSERT( 0 == fd_msg_new ( acr_model, MSGFL_ALLOC_ETEID, &pur_msg ) ); /* set application id */ { struct msg_hdr * msg_hdr = NULL; ASSERT( 0 == fd_msg_hdr ( pur_msg, &msg_hdr ) ); msg_hdr->msg_appl = SH_APP_ID; } /* Check there is no child */ ASSERT( ENOENT == fd_msg_browse ( pur_msg, MSG_BRW_FIRST_CHILD, NULL, NULL) ); } CHECK_FCT_DO( fd_msg_new_session( pur_msg, (os0_t)TEST_APP_SID_OPT, CONSTSTRLEN(TEST_APP_SID_OPT) ), goto out ); CHECK_FCT_DO( fd_msg_sess_get(fd_g_config->cnf_dict, pur_msg, &sess, NULL), goto out ); /* Create the random value to store with the session */ mi = malloc(sizeof(struct sess_state)); if (mi == NULL) { fd_log_debug("malloc failed: %s", strerror(errno)); goto out; } mi->randval = (int32_t)random(); /* Now resolve some other useful AVPs */ /* resolve udr avps */ SEARCH_AVP_("Session-Id", 0, &g_pur_cmd.pur_session_id); SEARCH_AVP_("DRMP", SH_VND_ID, &g_pur_cmd.pur_drmp); SEARCH_AVP_("Vendor-Specific-Application-Id", 0, &g_pur_cmd.pur_vendor_specific_application_id); SEARCH_AVP_("Auth-Session-State", 0, &g_pur_cmd.pur_auth_session_state); SEARCH_AVP_("Origin-Host", 0, &g_pur_cmd.pur_origin_host); SEARCH_AVP_("Origin-Realm", 0, &g_pur_cmd.pur_origin_realm); SEARCH_AVP_("Destination-Host", 0, &g_pur_cmd.pur_destination_host); SEARCH_AVP_("Destination-Realm", 0, &g_pur_cmd.pur_destination_realm); SEARCH_AVP_("Supported-Features", SH_VND_ID, &g_pur_cmd.pur_supported_features); SEARCH_AVP_("User-Identity", SH_VND_ID, &g_pur_cmd.pur_user_identity); SEARCH_AVP_("Wildcarded-Public-Identity", SH_VND_ID, &g_pur_cmd.pur_wildcarded_public_identity); SEARCH_AVP_("Wildcarded-IMPU", SH_VND_ID, &g_pur_cmd.pur_wildcarded_impu); SEARCH_AVP_("User-Name", 0, &g_pur_cmd.pur_user_name); SEARCH_AVP_("Data-Reference", SH_VND_ID, &g_pur_cmd.pur_data_reference); SEARCH_AVP_("User-Data", SH_VND_ID, &g_pur_cmd.pur_user_date); SEARCH_AVP_("OC-Supported-Features", SH_VND_ID, &g_pur_cmd.pur_oc_supported_features); /* Now set all AVPs values */ EN_AVP_U32(g_pur_cmd.pur_drmp, 0, pur_msg, "DRMP Ok") /* Set Vendor-Specific-Application-Id AVP if needed*/ { CHECK_FCT_DO( fd_msg_avp_new ( g_pur_cmd.pur_vendor_specific_application_id, 0, &grpavp ), goto out ); EN_GRPAVP_U32("Vendor-Id", 0, g_pur_cmd.pur_vendor_id, SH_VND_ID) EN_GRPAVP_U32("Auth-Application-Id", 0, g_pur_cmd.pur_auth_application_d, SH_APP_ID) EN_GRPAVP_U32("Acct-Application-Id", 0,g_pur_cmd.pur_acct_application_id, SH_APP_ID) CHECK_FCT_DO( fd_msg_avp_add( pur_msg, MSG_BRW_LAST_CHILD, grpavp ), goto out ); LOG_D("Vendor-Specific-Application-Id Ok\n"); } EN_AVP_U32(g_pur_cmd.pur_auth_session_state, 1, pur_msg, "pur_auth_session_state Ok\n") /* Set Origin-Host & Origin-Realm AVP */ CHECK_FCT_DO( fd_msg_add_origin ( pur_msg, 0 ), goto out ); /* Set the Destination-Host AVP if needed*/ if (ta_conf->dest_host) { EN_AVP_STR(g_pur_cmd.pur_destination_host, g_sh_conf_ext.pi_diamid_peer, pur_msg, "pur_origin_host Ok"); } /* Set the Destination-Realm AVP */ EN_AVP_STR(g_pur_cmd.pur_destination_realm, g_sh_conf_ext.pi_diamid_realm_peer, pur_msg, "pur_origin_realm Ok"); /* Set the Supported-Features group AVP if needed*/ { CHECK_FCT_DO( fd_msg_avp_new ( g_pur_cmd.pur_supported_features, 0, &grpavp ), goto out ); EN_GRPAVP_U32("Vendor-Id", 0, g_pur_cmd.pur_vendor_id, SH_VND_ID) EN_GRPAVP_U32("Feature-List-ID", SH_VND_ID,g_pur_cmd.pur_feature_list_id, 2) EN_GRPAVP_U32("Feature-List", SH_VND_ID,g_pur_cmd.pur_feature_list, 3) CHECK_FCT_DO( fd_msg_avp_add( pur_msg, MSG_BRW_LAST_CHILD, grpavp ), goto out ); LOG_D("Supported-Features Ok\n"); } /* Set the User-Identity AVP if needed*/ { CHECK_FCT_DO( fd_msg_avp_new ( g_pur_cmd.pur_user_identity, 0, &grpavp ), goto out ); EN_GRPAVP_STR("Public-Identity", SH_VND_ID, g_pur_cmd.pur_public_identity, "public_id", grpavp) EN_GRPAVP_STR("MSISDN", SH_VND_ID, g_pur_cmd.pur_msisdn, "12345", grpavp) CHECK_FCT_DO( fd_msg_avp_add( pur_msg, MSG_BRW_LAST_CHILD, grpavp ), goto out ); LOG_D("pur_user_identity Ok\n"); } EN_AVP_STR( g_pur_cmd.pur_wildcarded_public_identity, "wildcarded_public_id", pur_msg, "wildcarded_public_id Ok") EN_AVP_STR( g_pur_cmd.pur_wildcarded_impu, "wildcarded_impu", pur_msg, "wildcarded_impu Ok") EN_AVP_STR( g_pur_cmd.pur_user_name, "User-Name", pur_msg, "user_name Ok") EN_AVP_U32( g_pur_cmd.pur_data_reference, 1,pur_msg, "Data-Reference Ok") EN_AVP_STR( g_pur_cmd.pur_user_date, "User-Data", pur_msg, "User-Data Ok") /* Set the OC-Supported-Features AVP */ { CHECK_FCT_DO( fd_msg_avp_new ( g_pur_cmd.pur_oc_supported_features, 0, &grpavp ), goto out); EN_GRPAVP_U64("OC-Feature-Vector", SH_VND_ID, g_pur_cmd.pur_oc_feature_vector, 1) CHECK_FCT_DO( fd_msg_avp_add( pur_msg, MSG_BRW_LAST_CHILD, grpavp ), goto out ); LOG_D("OC-Feature-Vector Ok\n"); #if SH_TEST_ON fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, pur_msg, fd_g_config->cnf_dict, 0, 1)); #endif } CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &mi->ts), goto out ); LOG_D("CLOCK_REALTIME Ok\n"); /* Keep a pointer to the session data for debug purpose, in real life we would not need it */ svg = mi; /* Store this value in the session */ // CHECK_FCT_DO( fd_sess_state_store ( sh_cli_reg, sess, &mi ), goto out ); LOG_D("sess Ok\n"); /* Log sending the message */ fprintf(stderr, "SEND %x to '%s' (%s)\n", svg->randval, ta_conf->dest_realm, ta_conf->dest_host?:"-" ); fflush(stderr); // assert( 0 == fd_msg_source_set( pur_msg, "client.domain", CONSTSTRLEN("client.domain") ) ); /* Send the request */ CHECK_FCT_DO( fd_msg_send( &pur_msg, NULL, svg ), goto out ); LOG_D("fd_msg_send Ok\n"); /* Increment the counter */ CHECK_POSIX_DO( pthread_mutex_lock(&ta_conf->stats_lock), ); ta_conf->stats.nb_sent++; CHECK_POSIX_DO( pthread_mutex_unlock(&ta_conf->stats_lock), ); out: printf("end\n"); return; } static void sh_send_udr() { struct msg *udr_msg = NULL; struct avp *avp, *grpavp; union avp_value val; struct sess_state *mi = NULL, *svg; struct session *sess = NULL; TRACE_DEBUG(FULL, "Creating a new message for sending."); /* Create a new session */ #define TEST_APP_SID_OPT "sh_app" /* Create the message object from model */ { struct dict_object * acr_model = NULL; /* Now find the UDR dictionary object */ ASSERT( 0 == fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "User-Data-Request", &acr_model, ENOENT ) ); /* Create the instance, using the templates */ ASSERT( 0 == fd_msg_new ( acr_model, MSGFL_ALLOC_ETEID, &udr_msg ) ); /* set application id */ { struct msg_hdr * msg_hdr = NULL; ASSERT( 0 == fd_msg_hdr ( udr_msg, &msg_hdr ) ); msg_hdr->msg_appl = SH_APP_ID; msg_hdr->msg_flags = msg_hdr->msg_flags & (~CMD_FLAG_PROXIABLE); } /* Check there is no child */ ASSERT( ENOENT == fd_msg_browse ( udr_msg, MSG_BRW_FIRST_CHILD, NULL, NULL) ); } CHECK_FCT_DO( fd_msg_new_session( udr_msg, (os0_t)TEST_APP_SID_OPT, CONSTSTRLEN(TEST_APP_SID_OPT) ), goto out ); CHECK_FCT_DO( fd_msg_sess_get(fd_g_config->cnf_dict, udr_msg, &sess, NULL), goto out ); /* Create the random value to store with the session */ mi = malloc(sizeof(struct sess_state)); if (mi == NULL) { fd_log_debug("malloc failed: %s", strerror(errno)); goto out; } mi->randval = (int32_t)random(); /* Now resolve some other useful AVPs */ /* resolve udr avps */ SEARCH_AVP_("Session-Id", 0, &g_udr_cmd.udr_session_id); SEARCH_AVP_("DRMP", SH_VND_ID, &g_udr_cmd.udr_drmp); SEARCH_AVP_("Vendor-Specific-Application-Id", 0, &g_udr_cmd.udr_vendor_specific_application_id); SEARCH_AVP_("Auth-Session-State", 0, &g_udr_cmd.udr_auth_session_state); SEARCH_AVP_("Origin-Host", 0, &g_udr_cmd.udr_origin_host); SEARCH_AVP_("Origin-Realm", 0, &g_udr_cmd.udr_origin_realm); SEARCH_AVP_("Destination-Host", 0, &g_udr_cmd.udr_destination_host); SEARCH_AVP_("Destination-Realm", 0, &g_udr_cmd.udr_destination_realm); SEARCH_AVP_("Supported-Features", SH_VND_ID, &g_udr_cmd.udr_supported_features); SEARCH_AVP_("User-Identity", SH_VND_ID, &g_udr_cmd.udr_user_identity); SEARCH_AVP_("Wildcarded-Public-Identity", SH_VND_ID, &g_udr_cmd.udr_wildcarded_public_identity); SEARCH_AVP_("Wildcarded-IMPU", SH_VND_ID, &g_udr_cmd.udr_wildcarded_impu); SEARCH_AVP_("Server-Name", SH_VND_ID, &g_udr_cmd.udr_server_name); SEARCH_AVP_("Service-Indication", SH_VND_ID, &g_udr_cmd.udr_service_indication); SEARCH_AVP_("Data-Reference", SH_VND_ID, &g_udr_cmd.udr_data_reference); SEARCH_AVP_("Identity-Set", SH_VND_ID, &g_udr_cmd.udr_identity_set); SEARCH_AVP_("Requested-Domain", SH_VND_ID, &g_udr_cmd.udr_requested_domain); SEARCH_AVP_("Current-Location", SH_VND_ID, &g_udr_cmd.udr_current_location); SEARCH_AVP_("DSAI-Tag", SH_VND_ID, &g_udr_cmd.udr_dsai_tag); SEARCH_AVP_("Session-Priority", SH_VND_ID, &g_udr_cmd.udr_session_priority); SEARCH_AVP_("User-Name", 0, &g_udr_cmd.udr_user_name); SEARCH_AVP_("Requested-Nodes", SH_VND_ID, &g_udr_cmd.udr_requested_nodes); SEARCH_AVP_("Serving-Node-Indication", SH_VND_ID, &g_udr_cmd.udr_serving_node_indication); SEARCH_AVP_("Pre-paging-Supported", SH_VND_ID, &g_udr_cmd.udr_pre_paging_supported); SEARCH_AVP_("Local-Time-Zone-Indication", SH_VND_ID, &g_udr_cmd.udr_local_time_zone_indication); SEARCH_AVP_("UDR-Flags", SH_VND_ID, &g_udr_cmd.udr_udr_flags); SEARCH_AVP_("Call-Reference-Info", SH_VND_ID, &g_udr_cmd.udr_call_reference_info); SEARCH_AVP_("OC-Supported-Features", SH_VND_ID, &g_udr_cmd.udr_oc_supported_features); /* Now set all AVPs values */ EN_AVP_U32(g_udr_cmd.udr_drmp, 0, udr_msg, "DRMP Ok") /* Set Vendor-Specific-Application-Id AVP if needed*/ { CHECK_FCT_DO( fd_msg_avp_new ( g_udr_cmd.udr_vendor_specific_application_id, 0, &grpavp ), goto out ); EN_GRPAVP_U32("Vendor-Id", 0, g_udr_cmd.udr_vendor_id, SH_VND_ID) EN_GRPAVP_U32("Auth-Application-Id", 0, g_udr_cmd.udr_auth_application_d, SH_APP_ID) EN_GRPAVP_U32("Acct-Application-Id", 0,g_udr_cmd.udr_acct_application_id, SH_APP_ID) CHECK_FCT_DO( fd_msg_avp_add( udr_msg, MSG_BRW_LAST_CHILD, grpavp ), goto out ); LOG_D("Vendor-Specific-Application-Id Ok\n"); } EN_AVP_U32(g_udr_cmd.udr_auth_session_state, 1, udr_msg, "udr_auth_session_state Ok\n") /* Set Origin-Host & Origin-Realm AVP */ CHECK_FCT_DO( fd_msg_add_origin ( udr_msg, 0 ), goto out ); /* Set the Destination-Host AVP if needed*/ if (ta_conf->dest_host) { EN_AVP_STR(g_udr_cmd.udr_destination_host, g_sh_conf_ext.pi_diamid_peer, udr_msg, "udr_origin_host Ok"); } /* Set the Destination-Realm AVP */ EN_AVP_STR(g_udr_cmd.udr_destination_realm, g_sh_conf_ext.pi_diamid_realm_peer, udr_msg, "udr_origin_realm Ok"); /* Set the Supported-Features group AVP if needed*/ { CHECK_FCT_DO( fd_msg_avp_new ( g_udr_cmd.udr_supported_features, 0, &grpavp ), goto out ); EN_GRPAVP_U32("Vendor-Id", 0, g_udr_cmd.udr_vendor_id, 1) EN_GRPAVP_U32("Feature-List-ID", SH_VND_ID,g_udr_cmd.udr_feature_list_id, 2) EN_GRPAVP_U32("Feature-List", SH_VND_ID,g_udr_cmd.udr_feature_list, 3) CHECK_FCT_DO( fd_msg_avp_add( udr_msg, MSG_BRW_LAST_CHILD, grpavp ), goto out ); LOG_D("Supported-Features Ok\n"); } /* Set the User-Identity AVP if needed*/ { CHECK_FCT_DO( fd_msg_avp_new ( g_udr_cmd.udr_user_identity, 0, &grpavp ), goto out ); EN_GRPAVP_STR("Public-Identity", SH_VND_ID, g_udr_cmd.udr_public_identity, "public_id", grpavp) EN_GRPAVP_STR("MSISDN", SH_VND_ID, g_udr_cmd.udr_msisdn, "12345", grpavp) CHECK_FCT_DO( fd_msg_avp_add( udr_msg, MSG_BRW_LAST_CHILD, grpavp ), goto out ); LOG_D("udr_user_identity Ok\n"); } EN_AVP_STR(g_udr_cmd.udr_wildcarded_public_identity, "Wildcarded-public-ID", udr_msg, "Wildcarded-Public-ID Ok") EN_AVP_STR( g_udr_cmd.udr_wildcarded_impu, "Wildcarded-IMPU", udr_msg, "Wildcarded-IMPU Ok") EN_AVP_STR( g_udr_cmd.udr_server_name, "Server-Name", udr_msg, "Server-Name Ok") EN_AVP_STR( g_udr_cmd.udr_service_indication, "Service-Indication", udr_msg, "Service-Indication Ok") EN_AVP_U32(g_udr_cmd.udr_data_reference, 1,udr_msg, "Data-Reference Ok") EN_AVP_U32(g_udr_cmd.udr_identity_set, 1,udr_msg, "Identity-Set Ok") EN_AVP_U32(g_udr_cmd.udr_requested_domain, 2,udr_msg, "Req-Domain Ok") EN_AVP_U32( g_udr_cmd.udr_current_location, 3, udr_msg, "Cur-Location Ok") EN_AVP_STR( g_udr_cmd.udr_dsai_tag, "DSAI-Tag", udr_msg, "DSAI-Tag Ok") EN_AVP_U32( g_udr_cmd.udr_session_priority, 4, udr_msg, "Session-Priority Ok") EN_AVP_STR( g_udr_cmd.udr_user_name, "User-Name", udr_msg, "User-Name Ok") /* Set User-Name AVP */ EN_AVP_U32( g_udr_cmd.udr_requested_nodes, 5, udr_msg, "Requested-Nodes Ok") EN_AVP_U32( g_udr_cmd.udr_serving_node_indication, 6, udr_msg, "Serving-Node-Indication Ok") EN_AVP_U32( g_udr_cmd.udr_pre_paging_supported, 7, udr_msg, "Pre-paging-Supported Ok") EN_AVP_U32( g_udr_cmd.udr_local_time_zone_indication, 8, udr_msg, "Local-Time-Zone-Indication Ok") EN_AVP_U32( g_udr_cmd.udr_udr_flags, 9, udr_msg, "UDR-Flags Ok") /* Set the Call-Reference-Info AVP */ { CHECK_FCT_DO( fd_msg_avp_new ( g_udr_cmd.udr_call_reference_info, 0, &grpavp ), goto out ); EN_GRPAVP_STR("Call-Reference-Number", SH_VND_ID, g_udr_cmd.udr_call_reference_number, "Call-Reference-Number", grpavp) EN_GRPAVP_STR("AS-Number", SH_VND_ID, g_udr_cmd.udr_as_number, "AS-Number", grpavp) CHECK_FCT_DO( fd_msg_avp_add( udr_msg, MSG_BRW_LAST_CHILD, grpavp ), goto out ); LOG_D("Call-Reference-Info Ok\n"); } /* Set the OC-Supported-Features AVP */ { CHECK_FCT_DO( fd_msg_avp_new ( g_udr_cmd.udr_oc_supported_features, 0, &grpavp ), goto out); EN_GRPAVP_U64("OC-Feature-Vector", SH_VND_ID, g_udr_cmd.udr_oc_feature_vector, 1) CHECK_FCT_DO( fd_msg_avp_add( udr_msg, MSG_BRW_LAST_CHILD, grpavp ), goto out ); LOG_D("OC-Feature-Vector Ok\n"); #if SH_TEST_ON fd_log_debug("%s", fd_msg_dump_treeview(FD_DUMP_TEST_PARAMS, udr_msg, fd_g_config->cnf_dict, 0, 1)); #endif } CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &mi->ts), goto out ); LOG_D("CLOCK_REALTIME Ok\n"); /* Keep a pointer to the session data for debug purpose, in real life we would not need it */ svg = mi; /* Store this value in the session */ CHECK_FCT_DO( fd_sess_state_store ( sh_cli_reg, sess, &mi ), goto out ); LOG_D("sess Ok\n"); /* Log sending the message */ fprintf(stderr, "SEND %x to '%s' (%s)\n", svg->randval, ta_conf->dest_realm, ta_conf->dest_host?:"-" ); fflush(stderr); /* Send the request */ CHECK_FCT_DO( fd_msg_send( &udr_msg, NULL, svg ), goto out ); LOG_D("fd_msg_send Ok\n"); /* Increment the counter */ CHECK_POSIX_DO( pthread_mutex_lock(&ta_conf->stats_lock), ); ta_conf->stats.nb_sent++; CHECK_POSIX_DO( pthread_mutex_unlock(&ta_conf->stats_lock), ); out: printf("end\n"); return; } #endif static int sh_parse_pua( struct msg ** msg) { struct msg* pua_msg = *msg; struct avp *avp, *grpavp=NULL; struct avp_hdr *avphdr; LOG_D("fj sh_parse_pua"); SEARCH_AVP_("Session-Id", 0, &g_pua_cmd.pua_session_id); SEARCH_AVP_("DRMP", SH_VND_ID, &g_pua_cmd.pua_drmp); SEARCH_AVP_("Vendor-Specific-Application-Id", 0, &g_pua_cmd.pua_vendor_specific_application_id); SEARCH_AVP_("Vendor-Id", 0, &g_pua_cmd.pua_vendor_id); SEARCH_AVP_("Auth-Application-Id", 0, &g_pua_cmd.pua_auth_application_d); SEARCH_AVP_("Acct-Application-Id", 0, &g_pua_cmd.pua_acct_application_id); SEARCH_AVP_("Result-Code", 0, &g_pua_cmd.pua_result_code); SEARCH_AVP_("Experimental-Result", 0, &g_pua_cmd.pua_experimental_result); SEARCH_AVP_("Experimental-Result-Code", 0, &g_pua_cmd.pua_experimental_result_code); SEARCH_AVP_("Auth-Session-State", 0, &g_pua_cmd.pua_auth_session_state); SEARCH_AVP_("Origin-Host", 0, &g_pua_cmd.pua_origin_host); SEARCH_AVP_("Origin-Realm", 0, &g_pua_cmd.pua_origin_realm); SEARCH_AVP_("Wildcarded-Public-Identity", SH_VND_ID, &g_pua_cmd.pua_wildcarded_public_identity ); SEARCH_AVP_("Wildcarded-IMPU", SH_VND_ID, &g_pua_cmd.pua_wildcarded_impu ); SEARCH_AVP_("Repository-Data-ID", SH_VND_ID, &g_pua_cmd.pua_repository_data_id ); SEARCH_AVP_("Service-Indication", SH_VND_ID, &g_pua_cmd.pua_service_indication); SEARCH_AVP_("Sequence-Number", SH_VND_ID, &g_pua_cmd.pua_sequence_number); SEARCH_AVP_("Data-Reference", SH_VND_ID, &g_pua_cmd.pua_data_reference); SEARCH_AVP_("Supported-Features", SH_VND_ID, &g_pua_cmd.pua_supported_features ); SEARCH_AVP_("Feature-List-ID", SH_VND_ID, &g_pua_cmd.pua_feature_list_id); SEARCH_AVP_("Feature-List", SH_VND_ID, &g_pua_cmd.pua_feature_list); SEARCH_AVP_("OC-Supported-Features", SH_VND_ID, &g_pua_cmd.pua_oc_supported_features ); SEARCH_AVP_("OC-Feature-Vector", SH_VND_ID, &g_pua_cmd.pua_oc_feature_vector); SEARCH_AVP_("OC-OLR", SH_VND_ID, &g_pua_cmd.pua_oc_olr ); SEARCH_AVP_("OC-Sequence-Number", SH_VND_ID, &g_pua_cmd.pua_oc_sequence_number); SEARCH_AVP_("OC-Report-Type", SH_VND_ID, &g_pua_cmd.pua_oc_report_type); SEARCH_AVP_("OC-Reduction-Percentage", SH_VND_ID, &g_pua_cmd.pua_oc_reduction_percentage); SEARCH_AVP_("OC-Validity-Duration", SH_VND_ID, &g_pua_cmd.pua_oc_validity_duration); /* Session-Id */ PARSE_AVP_STR(pua_msg, g_pua_cmd.pua_session_id, avp, avphdr, "ession-Id", avphdr->avp_value->os.data) /* DRMP */ PARSE_AVP_U32(pua_msg, g_pua_cmd.pua_drmp, avp, avphdr, "DRMP", avphdr->avp_value->u32) /* Vendor-Specific-Application-Id */ CHECK_FCT( fd_msg_search_avp ( pua_msg, g_pua_cmd.pua_vendor_specific_application_id, &grpavp) ); if(grpavp != NULL) { LOG_D("fj Vendor-Specific-Application-Id"); /* Vendor-Id */ PARSE_GRPAVP_U32(grpavp, g_pua_cmd.pua_vendor_id, avp, avphdr, "Vendor-Id", avphdr->avp_value->u32) /* Auth-Application-Id */ PARSE_GRPAVP_U32(grpavp, g_pua_cmd.pua_auth_application_d, avp, avphdr, "Auth-Application-Id", avphdr->avp_value->u32) /* Acct-Application-Id */ PARSE_GRPAVP_U32(grpavp, g_pua_cmd.pua_acct_application_id, avp, avphdr, "Acct-Application-Id", avphdr->avp_value->u32) } /* Result-Code */ PARSE_AVP_U32(pua_msg, g_pua_cmd.pua_result_code, avp, avphdr, "Result-Code", avphdr->avp_value->u32) /* Experimental-Result */ CHECK_FCT( fd_msg_search_avp ( pua_msg, g_pua_cmd.pua_experimental_result, &grpavp) ); if(grpavp != NULL) { LOG_D("fj Experimental-Result"); /* Vendor-Id */ PARSE_GRPAVP_U32(grpavp, g_pua_cmd.pua_vendor_id, avp, avphdr, "Vendor-Id", avphdr->avp_value->u32) /* Experimental-Result-Code */ PARSE_GRPAVP_U32(grpavp, g_pua_cmd.pua_experimental_result_code, avp, avphdr, "Experimental-Result-Code", avphdr->avp_value->u32) } /* Auth-Session-State */ PARSE_AVP_U32(pua_msg, g_pua_cmd.pua_auth_session_state, avp, avphdr, "Auth-Session-State", avphdr->avp_value->u32) /* Origin-Host */ PARSE_AVP_STR(pua_msg, g_pua_cmd.pua_origin_host, avp, avphdr, "Origin-Host", avphdr->avp_value->os.data) /* Origin-Realm */ PARSE_AVP_STR(pua_msg, g_pua_cmd.pua_origin_realm, avp, avphdr, "Origin-Realm", avphdr->avp_value->os.data) /* Wildcarded-Public-Identity */ PARSE_AVP_STR(pua_msg, g_pua_cmd.pua_wildcarded_public_identity, avp, avphdr, "Wildcarded-Public-Identity", avphdr->avp_value->os.data) /* Wildcarded-IMPU */ PARSE_AVP_STR(pua_msg, g_pua_cmd.pua_wildcarded_impu, avp, avphdr, "Wildcarded-IMPU", avphdr->avp_value->os.data) /* Repository-Data-ID */ CHECK_FCT( fd_msg_search_avp ( pua_msg, g_pua_cmd.pua_repository_data_id, &grpavp) ); if(grpavp != NULL) { LOG_D("fj Repository-Data-ID"); /* Service-Indication */ PARSE_GRPAVP_STR(grpavp, g_pua_cmd.pua_service_indication, avp, avphdr, "Service-Indication", avphdr->avp_value->os.data) /* Sequence-Number */ PARSE_GRPAVP_U32(grpavp, g_pua_cmd.pua_sequence_number, avp, avphdr, "Sequence-Number", avphdr->avp_value->u32) } /* Data-Reference */ PARSE_AVP_U32(pua_msg, g_pua_cmd.pua_data_reference, avp, avphdr, "Data-Reference", avphdr->avp_value->u32) /* Supported-Features */ CHECK_FCT( fd_msg_search_avp ( pua_msg, g_pua_cmd.pua_supported_features, &grpavp) ); if(grpavp != NULL) { LOG_D("fj Supported-Features"); /* Vendor-Id */ PARSE_GRPAVP_U32(grpavp, g_pua_cmd.pua_vendor_id, avp, avphdr, "Vendor-Id", avphdr->avp_value->u32) /* Feature-List-ID */ PARSE_GRPAVP_U32(grpavp, g_pua_cmd.pua_feature_list_id, avp, avphdr, "Feature-List-ID", avphdr->avp_value->u32) /* Feature-List */ PARSE_GRPAVP_U32(grpavp, g_pua_cmd.pua_feature_list, avp, avphdr, "Feature-List", avphdr->avp_value->u32) } /* OC-Supported-Features */ CHECK_FCT( fd_msg_search_avp ( pua_msg, g_pua_cmd.pua_oc_supported_features, &grpavp) ); if(grpavp != NULL) { LOG_D("fj OC-Supported-Features"); /* OC-Feature-Vector */ PARSE_GRPAVP_U64(grpavp, g_pua_cmd.pua_oc_feature_vector, avp, avphdr, "OC-Feature-Vector", avphdr->avp_value->u64) } /* OC-OLR */ CHECK_FCT( fd_msg_search_avp ( pua_msg, g_pua_cmd.pua_oc_olr, &grpavp) ); if(grpavp != NULL) { LOG_D("fj OC-OLR"); /* OC-Sequence-Number */ PARSE_GRPAVP_U64(grpavp, g_pua_cmd.pua_oc_feature_vector, avp, avphdr, "OC-Sequence-Number", avphdr->avp_value->u64) /* OC-Report-Type */ PARSE_GRPAVP_U32(grpavp, g_pua_cmd.pua_oc_report_type, avp, avphdr, "OC-Report-Type", avphdr->avp_value->u32) /* OC-Reduction-Percentage */ PARSE_GRPAVP_U32(grpavp, g_pua_cmd.pua_oc_reduction_percentage, avp, avphdr, "OC-Reduction-Percentage", avphdr->avp_value->u32) /* OC-Validity-Duration */ PARSE_GRPAVP_U32(grpavp, g_pua_cmd.pua_oc_validity_duration, avp, avphdr, "OC-Validity-Duration", avphdr->avp_value->u32) } out: return 0; } static int sh_parse_uda(struct msg** msg) { struct msg* udr_msg = *msg; struct avp *avp, *grpavp=NULL; struct avp_hdr *avphdr; LOG_D("fj sh_parse_uda"); SEARCH_AVP_("Origin-Host", 0, &g_uda_cmd.uda_origin_host); SEARCH_AVP_("Session-Id", 0, &g_uda_cmd.uda_session_id); SEARCH_AVP_("DRMP", SH_VND_ID, &g_uda_cmd.uda_drmp); SEARCH_AVP_("Vendor-Specific-Application-Id", 0, &g_uda_cmd.uda_vendor_specific_application_id); SEARCH_AVP_("Vendor-Id", 0, &g_uda_cmd.uda_vendor_id); SEARCH_AVP_("Auth-Application-Id", 0, &g_uda_cmd.uda_auth_application_d); SEARCH_AVP_("Acct-Application-Id", 0, &g_uda_cmd.uda_acct_application_id); SEARCH_AVP_("Result-Code", 0, &g_uda_cmd.uda_result_code); SEARCH_AVP_("Experimental-Result", 0, &g_uda_cmd.uda_experimental_result); SEARCH_AVP_("Experimental-Result-Code", 0, &g_uda_cmd.uda_experimental_result_code); SEARCH_AVP_("Auth-Session-State", 0, &g_uda_cmd.uda_auth_session_state); SEARCH_AVP_("Origin-Realm", 0, &g_uda_cmd.uda_origin_realm); SEARCH_AVP_("Supported-Features", SH_VND_ID, &g_uda_cmd.uda_supported_features ); SEARCH_AVP_("Feature-List-ID", SH_VND_ID, &g_uda_cmd.uda_feature_list_id); SEARCH_AVP_("Feature-List", SH_VND_ID, &g_uda_cmd.uda_feature_list); SEARCH_AVP_("Wildcarded-Public-Identity", SH_VND_ID, &g_uda_cmd.uda_wildcarded_public_identity ); SEARCH_AVP_("Wildcarded-IMPU", SH_VND_ID, &g_uda_cmd.uda_wildcarded_impu ); SEARCH_AVP_("User-Data", SH_VND_ID, &g_uda_cmd.uda_user_data ); SEARCH_AVP_("OC-Supported-Features", SH_VND_ID, &g_uda_cmd.uda_oc_supported_features ); // SEARCH_AVP_("OC-Feature-Vector", SH_VND_ID, &g_uda_cmd.uda_oc_feature_vector); SEARCH_AVP_("OC-OLR", SH_VND_ID, &g_uda_cmd.uda_oc_olr ); SEARCH_AVP_("OC-Sequence-Number", SH_VND_ID, &g_uda_cmd.uda_oc_sequence_number); SEARCH_AVP_("OC-Report-Type", SH_VND_ID, &g_uda_cmd.uda_oc_report_type); SEARCH_AVP_("OC-Reduction-Percentage", SH_VND_ID, &g_uda_cmd.uda_oc_reduction_percentage); SEARCH_AVP_("OC-Validity-Duration", SH_VND_ID, &g_uda_cmd.uda_oc_validity_duration); /* Session-Id */ PARSE_AVP_STR(udr_msg, g_uda_cmd.uda_session_id, avp, avphdr, "Session-Id", avphdr->avp_value->os.data) /* DRMP */ PARSE_AVP_U32(udr_msg, g_uda_cmd.uda_drmp, avp, avphdr, "DRMP", avphdr->avp_value->u32) /* Vendor-Specific-Application-Id */ CHECK_FCT( fd_msg_search_avp ( udr_msg, g_uda_cmd.uda_vendor_specific_application_id, &grpavp) ); if(grpavp != NULL) { LOG_D("fj Vendor-Specific-Application-Id"); /* Vendor-Id */ PARSE_GRPAVP_U32(grpavp, g_uda_cmd.uda_vendor_id, avp, avphdr, "Vendor-Id", avphdr->avp_value->u32) /* Auth-Application-Id */ PARSE_GRPAVP_U32(grpavp, g_uda_cmd.uda_auth_application_d, avp, avphdr, "Auth-Application-Id", avphdr->avp_value->u32) /* Acct-Application-Id */ PARSE_GRPAVP_U32(grpavp, g_uda_cmd.uda_acct_application_id, avp, avphdr, "Acct-Application-Id", avphdr->avp_value->u32) } /* Result-Code */ PARSE_AVP_U32(udr_msg, g_uda_cmd.uda_result_code, avp, avphdr, "Result-Code", avphdr->avp_value->u32) /* Experimental-Result */ CHECK_FCT( fd_msg_search_avp ( udr_msg, g_uda_cmd.uda_experimental_result, &grpavp) ); if(grpavp != NULL) { LOG_D("fj Experimental-Result"); /* Vendor-Id */ PARSE_GRPAVP_U32(grpavp, g_uda_cmd.uda_vendor_id, avp, avphdr, "Vendor-Id", avphdr->avp_value->u32) /* Experimental-Result-Code */ PARSE_GRPAVP_U32(grpavp, g_uda_cmd.uda_experimental_result_code, avp, avphdr, "Experimental-Result-Code", avphdr->avp_value->u32) } /* Auth-Session-State */ PARSE_AVP_U32(udr_msg, g_uda_cmd.uda_auth_session_state, avp, avphdr, "Auth-Session-State", avphdr->avp_value->u32) /* Origin-Host */ PARSE_AVP_STR(udr_msg, g_uda_cmd.uda_origin_host, avp, avphdr, "Origin-Host", avphdr->avp_value->os.data) /* Origin-Realm */ PARSE_AVP_STR(udr_msg, g_uda_cmd.uda_origin_realm, avp, avphdr, "Origin-Realm", avphdr->avp_value->os.data) /* Supported-Features */ CHECK_FCT( fd_msg_search_avp ( udr_msg, g_uda_cmd.uda_supported_features, &grpavp) ); if(grpavp != NULL) { LOG_D("fj Supported-Features"); /* Vendor-Id */ PARSE_GRPAVP_U32(grpavp, g_uda_cmd.uda_vendor_id, avp, avphdr, "Vendor-Id", avphdr->avp_value->u32) /* Feature-List-ID */ PARSE_GRPAVP_U32(grpavp, g_uda_cmd.uda_feature_list_id, avp, avphdr, "Feature-List-ID", avphdr->avp_value->u32) /* Feature-List */ PARSE_GRPAVP_U32(grpavp, g_uda_cmd.uda_feature_list, avp, avphdr, "Feature-List", avphdr->avp_value->u32) } /* Wildcarded-Public-Identity */ PARSE_AVP_STR(udr_msg, g_uda_cmd.uda_wildcarded_public_identity, avp, avphdr, "Wildcarded-Public-Identity", avphdr->avp_value->os.data) /* Wildcarded-IMPU */ PARSE_AVP_STR(udr_msg, g_uda_cmd.uda_wildcarded_impu, avp, avphdr, "Wildcarded-IMPU", avphdr->avp_value->os.data) /* User-Data */ PARSE_AVP_STR(udr_msg, g_uda_cmd.uda_user_data, avp, avphdr, "User-Data", avphdr->avp_value->os.data) /* OC-Supported-Features */ CHECK_FCT( fd_msg_search_avp ( udr_msg, g_uda_cmd.uda_oc_supported_features, &grpavp) ); if(grpavp != NULL) { LOG_D("fj OC-Supported-Features"); /* OC-Feature-Vector */ // PARSE_GRPAVP_U32(grpavp, g_uda_cmd.uda_oc_feature_vector, avp, avphdr, "OC-Feature-Vector", avphdr->avp_value->u64) } /* OC-OLR */ CHECK_FCT( fd_msg_search_avp ( udr_msg, g_uda_cmd.uda_oc_olr, &grpavp) ); if(grpavp != NULL) { LOG_D("fj OC-OLR"); /* OC-Sequence-Number */ PARSE_GRPAVP_U64(grpavp, g_uda_cmd.uda_oc_sequence_number, avp, avphdr, "OC-Sequence-Number", avphdr->avp_value->u64) /* OC-Report-Type */ PARSE_GRPAVP_U32(grpavp, g_uda_cmd.uda_oc_report_type, avp, avphdr, "OC-Report-Type", avphdr->avp_value->u32) /* OC-Reduction-Percentage */ PARSE_GRPAVP_U32(grpavp, g_uda_cmd.uda_oc_reduction_percentage, avp, avphdr, "OC-Reduction-Percentage", avphdr->avp_value->u32) /* OC-Validity-Duration */ PARSE_GRPAVP_U32(grpavp, g_uda_cmd.uda_oc_validity_duration, avp, avphdr, "OC-Validity-Duration", avphdr->avp_value->u32) } out: return 0; } /* Cb called when an answer is received */ static int sh_rec_pua( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act) { LOG_D("fj sh_rec_pua in"); fprintf(stderr, "ECHO PUA received from 'server.domain', done...\n"); sh_parse_pua(msg); /* Free the message */ CHECK_FCT_DO(fd_msg_free(*msg), return 0); *msg = NULL; return 0; } static int sh_rec_uda( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act) { LOG_D("fj sh_rec_uda in\n"); fprintf(stderr, "ECHO UDA received from 'server.domain', replying...\n"); sh_parse_uda(msg); // sh_send_pur(); /* Free the message */ CHECK_FCT_DO(fd_msg_free(*msg), return 0); *msg = NULL; return 0; #if 0 struct sess_state * mi = NULL; struct timespec ts; struct session * sess; struct avp * avp; struct avp_hdr * hdr; unsigned long dur; int error = 0; CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), return ); /* Search the session, retrieve its data */ { int new; CHECK_FCT_DO( fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &sess, &new), return ); ASSERT( new == 0 ); CHECK_FCT_DO( fd_sess_state_retrieve( sh_cli_reg, sess, &mi ), return ); ASSERT( (void *)mi == data ); } /* Now log content of the answer */ fprintf(stderr, "RECV "); /* Value of Test-AVP */ CHECK_FCT_DO( fd_msg_search_avp ( *msg, ta_avp, &avp), return ); if (avp) { CHECK_FCT_DO( fd_msg_avp_hdr( avp, &hdr ), return ); if (hdr->avp_value->i32 == mi->randval) { fprintf(stderr, "%x (%s) ", hdr->avp_value->i32, "Ok"); } else { fprintf(stderr, "%x (%s) ", hdr->avp_value->i32, "PROBLEM"); error++; } } else { fprintf(stderr, "no_Test-AVP "); error++; } /* Value of Result Code */ CHECK_FCT_DO( fd_msg_search_avp ( *msg, ta_res_code, &avp), return ); if (avp) { CHECK_FCT_DO( fd_msg_avp_hdr( avp, &hdr ), return ); fprintf(stderr, "Status: %d ", hdr->avp_value->i32); if (hdr->avp_value->i32 != 2001) error++; } else { fprintf(stderr, "no_Result-Code "); error++; } /* Value of Origin-Host */ CHECK_FCT_DO( fd_msg_search_avp ( *msg, ta_origin_host, &avp), return ); if (avp) { CHECK_FCT_DO( fd_msg_avp_hdr( avp, &hdr ), return ); fprintf(stderr, "From '%.*s' ", (int)hdr->avp_value->os.len, hdr->avp_value->os.data); } else { fprintf(stderr, "no_Origin-Host "); error++; } /* Value of Origin-Realm */ CHECK_FCT_DO( fd_msg_search_avp ( *msg, ta_origin_realm, &avp), return ); if (avp) { CHECK_FCT_DO( fd_msg_avp_hdr( avp, &hdr ), return ); fprintf(stderr, "('%.*s') ", (int)hdr->avp_value->os.len, hdr->avp_value->os.data); } else { fprintf(stderr, "no_Origin-Realm "); error++; } CHECK_POSIX_DO( pthread_mutex_lock(&ta_conf->stats_lock), ); dur = ((ts.tv_sec - mi->ts.tv_sec) * 1000000) + ((ts.tv_nsec - mi->ts.tv_nsec) / 1000); if (ta_conf->stats.nb_recv) { /* Ponderate in the avg */ ta_conf->stats.avg = (ta_conf->stats.avg * ta_conf->stats.nb_recv + dur) / (ta_conf->stats.nb_recv + 1); /* Min, max */ if (dur < ta_conf->stats.shortest) ta_conf->stats.shortest = dur; if (dur > ta_conf->stats.longest) ta_conf->stats.longest = dur; } else { ta_conf->stats.shortest = dur; ta_conf->stats.longest = dur; ta_conf->stats.avg = dur; } if (error) ta_conf->stats.nb_errs++; else ta_conf->stats.nb_recv++; CHECK_POSIX_DO( pthread_mutex_unlock(&ta_conf->stats_lock), ); /* Display how long it took */ if (ts.tv_nsec > mi->ts.tv_nsec) { fprintf(stderr, "in %d.%06ld sec", (int)(ts.tv_sec - mi->ts.tv_sec), (long)(ts.tv_nsec - mi->ts.tv_nsec) / 1000); } else { fprintf(stderr, "in %d.%06ld sec", (int)(ts.tv_sec + 1 - mi->ts.tv_sec), (long)(1000000000 + ts.tv_nsec - mi->ts.tv_nsec) / 1000); } fprintf(stderr, "\n"); fflush(stderr); /* Free the message */ CHECK_FCT_DO(fd_msg_free(*msg), return); *msg = NULL; free(mi); #endif } #if 0 static void sh_send_entry() { static int i = 0; if((++i)%2) sh_send_udr(); else sh_send_pur(); } #endif /* Default callback for the application. */ #if 0 static int ta_fb_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act) { /* This CB should never be called */ TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act); fd_log_debug("Unexpected message received!"); return ENOTSUP; } #endif int sh_cli_init(void) { CHECK_FCT( fd_sess_handler_create(&sh_cli_reg, (void *)free, NULL, NULL) ); /* fj added */ { struct disp_when data; LOG_D("Initializing dispatch callbacks for test"); memset(&data, 0, sizeof(data)); data.app = sh_appli; data.command = uda_cmd; /* Now specific handler for UDR */ CHECK_FCT( fd_disp_register( sh_rec_uda, DISP_HOW_CC, &data, NULL, &sh_hdl_uda ) ); memset(&data, 0, sizeof(data)); data.app = sh_appli; data.command = pua_cmd; /* Now specific handler for PUR */ CHECK_FCT( fd_disp_register( sh_rec_pua, DISP_HOW_CC, &data, NULL, &sh_hdl_pua ) ); } return 0; } void sh_cli_finit(void) { CHECK_FCT_DO( fd_sess_handler_destroy(&sh_cli_reg, NULL), /* continue */ ); /* fj added */ if (sh_hdl_uda) { (void) fd_disp_unregister(&sh_hdl_uda, NULL); } if (sh_hdl_pua) { (void) fd_disp_unregister(&sh_hdl_pua, NULL); } return; }