diff --git a/lib/fd/fd_message.h b/lib/fd/fd_message.h index 3258819418..98d3bf1b24 100644 --- a/lib/fd/fd_message.h +++ b/lib/fd/fd_message.h @@ -14,8 +14,10 @@ extern "C" { #define FD_AVP_CODE_FRAME_IPV6_PREFIX 97 /* Result-Code AVP */ +#define FD_DIAMETER_UNKNOWN_PEER 3010 #define FD_DIAMETER_AVP_UNSUPPORTED 5001 #define FD_DIAMETER_UNKNOWN_SESSION_ID 5002 +#define FD_DIAMETER_AUTHORIZATION_REJECTED 5003 #define FD_DIAMETER_MISSING_AVP 5004 #define FD_DIAMETER_INVALID_AVP_VALUE 5005 diff --git a/lib/fd/rx/dict_init.c b/lib/fd/rx/dict_init.c index c33d893904..ce59e397a2 100644 --- a/lib/fd/rx/dict_init.c +++ b/lib/fd/rx/dict_init.c @@ -9,6 +9,10 @@ struct dict_object *rx_application = NULL; struct dict_object *rx_cmd_aar = NULL; struct dict_object *rx_cmd_aaa = NULL; +struct dict_object *rx_cmd_asr = NULL; +struct dict_object *rx_cmd_asa = NULL; +struct dict_object *rx_cmd_str = NULL; +struct dict_object *rx_cmd_sta = NULL; struct dict_object *rx_media_component_description = NULL; struct dict_object *rx_media_component_number = NULL; @@ -33,6 +37,8 @@ struct dict_object *rx_framed_ip_address = NULL; struct dict_object *rx_framed_ipv6_prefix = NULL; struct dict_object *rx_ip_can_type = NULL; struct dict_object *rx_rat_type = NULL; +struct dict_object *rx_abort_cause = NULL; +struct dict_object *rx_termination_cause = NULL; int rx_dict_init(void) { @@ -42,6 +48,10 @@ int rx_dict_init(void) CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, "AA-Request", &rx_cmd_aar); CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, "AA-Answer", &rx_cmd_aaa); + CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, "Abort-Session-Request", &rx_cmd_asr); + CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, "Abort-Session-Answer", &rx_cmd_asa); + CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, "Session-Termination-Request", &rx_cmd_str); + CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, "Session-Termination-Answer", &rx_cmd_sta); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Media-Component-Description", &rx_media_component_description); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Media-Component-Number", &rx_media_component_number); @@ -66,6 +76,8 @@ int rx_dict_init(void) CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Framed-IPv6-Prefix", &rx_framed_ipv6_prefix); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "IP-CAN-Type", &rx_ip_can_type); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "RAT-Type", &rx_rat_type); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Abort-Cause", &rx_abort_cause); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Termination-Cause", &rx_termination_cause); return 0; } diff --git a/lib/fd/rx/rx_dict.h b/lib/fd/rx/rx_dict.h index 069bbf08d3..3dc4747ba9 100644 --- a/lib/fd/rx/rx_dict.h +++ b/lib/fd/rx/rx_dict.h @@ -28,6 +28,10 @@ extern struct dict_object *rx_application; extern struct dict_object *rx_cmd_aar; extern struct dict_object *rx_cmd_aaa; +extern struct dict_object *rx_cmd_asr; +extern struct dict_object *rx_cmd_asa; +extern struct dict_object *rx_cmd_str; +extern struct dict_object *rx_cmd_sta; extern struct dict_object *rx_media_component_description; extern struct dict_object *rx_media_component_number; @@ -79,6 +83,21 @@ extern struct dict_object *rx_ip_can_type; #define RX_RAT_TYPE_UMB 2002 #define RX_RAT_TYPE_EHRPD 2003 extern struct dict_object *rx_rat_type; +#define RX_ABORT_CAUSE_BEARER_RELEASED 1 +#define RX_ABORT_CAUSE_INSUFFICIENT_SERVER_RESOURCES 2 +#define RX_ABORT_CAUSE_INSUFFICIENT_BEARER_RESOURCES 3 +#define RX_ABORT_CAUSE_PS_TO_CS_HANDOVER 4 +#define RX_ABORT_CAUSE_SPONSORED_DATA_CONNECTIVITY_ DISALLOWED 5 +extern struct dict_object *rx_abort_cause; +#define RX_TERMINATION_CAUSE_DIAMETER_LOGOUT 1 +#define RX_TERMINATION_CAUSE_DIAMETER_SERVICE_NOT_PROVIDED 2 +#define RX_TERMINATION_CAUSE_DIAMETER_BAD_ANSWER 3 +#define RX_TERMINATION_CAUSE_DIAMETER_DIAMETER_ADMINISTRATIVE 4 +#define RX_TERMINATION_CAUSE_DIAMETER_LINK_BROKEN 5 +#define RX_TERMINATION_CAUSE_DIAMETER_AUTH_EXPIRED 6 +#define RX_TERMINATION_CAUSE_DIAMETER_USER_MOVED 7 +#define RX_TERMINATION_CAUSE_DIAMETER_SESSION_TIMEOUT 8 +extern struct dict_object *rx_termination_cause; int rx_dict_init(void); diff --git a/lib/fd/rx/rx_message.h b/lib/fd/rx/rx_message.h index 13a04b1c03..73a41eab44 100644 --- a/lib/fd/rx/rx_message.h +++ b/lib/fd/rx/rx_message.h @@ -31,6 +31,7 @@ typedef struct _rx_media_component_t { typedef struct _rx_message_t { #define RX_CMD_CODE_AA 265 +#define RX_CMD_CODE_SESSION_TERMINATION 275 c_uint16_t cmd_code; /* Experimental-Result-Codes */ diff --git a/src/hss/hss_fd_path.c b/src/hss/hss_fd_path.c index fd6a72bdb1..843be89fb4 100644 --- a/src/hss/hss_fd_path.c +++ b/src/hss/hss_fd_path.c @@ -681,18 +681,18 @@ status_t hss_fd_init(void) memset(&data, 0, sizeof(data)); data.app = s6a_application; - /* fallback CB if command != unexpected message received */ + /* Fallback CB if command != unexpected message received */ ret = fd_disp_register(hss_s6a_fb_cb, DISP_HOW_APPID, &data, NULL, &hdl_s6a_fb); d_assert(ret == 0, return CORE_ERROR,); - /* specific handler for Authentication-Information-Request */ + /* Specific handler for Authentication-Information-Request */ data.command = s6a_cmd_air; ret = fd_disp_register(hss_s6a_air_cb, DISP_HOW_CC, &data, NULL, &hdl_s6a_air); d_assert(ret == 0, return CORE_ERROR,); - /* specific handler for Location-Update-Request */ + /* Specific handler for Location-Update-Request */ data.command = s6a_cmd_ulr; ret = fd_disp_register(hss_s6a_ulr_cb, DISP_HOW_CC, &data, NULL, &hdl_s6a_ulr); diff --git a/src/mme/mme_fd_path.c b/src/mme/mme_fd_path.c index 88a960ddff..c2d17cea91 100644 --- a/src/mme/mme_fd_path.c +++ b/src/mme/mme_fd_path.c @@ -23,8 +23,7 @@ pool_declare(mme_s6a_sess_pool, struct sess_state, MAX_POOL_OF_DIAMETER_SESS); static void mme_s6a_aia_cb(void *data, struct msg **msg); static void mme_s6a_ula_cb(void *data, struct msg **msg); -void mme_s6a_sess_cleanup( - struct sess_state *sess_data, os0_t sid, void * opaque) +static void state_cleanup(struct sess_state *sess_data, os0_t sid, void *opaque) { pool_free_node(&mme_s6a_sess_pool, sess_data); } @@ -441,7 +440,7 @@ out: d_assert(ret == 0,,); *msg = NULL; - mme_s6a_sess_cleanup(sess_data, NULL, NULL); + state_cleanup(sess_data, NULL, NULL); return; } @@ -1087,7 +1086,7 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg) d_assert(ret == 0,,); *msg = NULL; - mme_s6a_sess_cleanup(sess_data, NULL, NULL); + state_cleanup(sess_data, NULL, NULL); return; } @@ -1107,7 +1106,7 @@ status_t mme_fd_init(void) d_assert(ret == CORE_OK, return CORE_ERROR,); /* Create handler for sessions */ - ret = fd_sess_handler_create(&mme_s6a_reg, &mme_s6a_sess_cleanup, + ret = fd_sess_handler_create(&mme_s6a_reg, &state_cleanup, NULL, NULL); d_assert(ret == CORE_OK, return CORE_ERROR,); diff --git a/src/pcrf/pcrf_gx_path.c b/src/pcrf/pcrf_gx_path.c index b492b0d54e..0253871e6d 100644 --- a/src/pcrf/pcrf_gx_path.c +++ b/src/pcrf/pcrf_gx_path.c @@ -56,8 +56,7 @@ static __inline__ struct sess_state *new_state(os0_t sid) return new; } -static void state_cleanup( - struct sess_state *sess_data, os0_t sid, void *opaque) +static void state_cleanup(struct sess_state *sess_data, os0_t sid, void *opaque) { d_assert(sess_data, return,); @@ -553,7 +552,7 @@ status_t pcrf_gx_send_rar( memset(&gx_message, 0, sizeof(gx_message_t)); /* Set default error result code */ - rx_message->result_code = RX_DIAMETER_TEMPORARY_NETWORK_FAILURE; + rx_message->result_code = FD_DIAMETER_UNKNOWN_SESSION_ID; /* Create the request */ ret = fd_msg_new(gx_cmd_rar, MSGFL_ALLOC_ETEID, &req); @@ -574,7 +573,7 @@ status_t pcrf_gx_send_rar( d_error("No session data"); ret = fd_msg_free(req); d_assert(ret == 0,,); - rx_message->result_code = RX_DIAMETER_IP_CAN_SESSION_NOT_AVAILABLE; + rx_message->result_code = FD_DIAMETER_UNKNOWN_PEER; return CORE_ERROR; } @@ -604,7 +603,7 @@ status_t pcrf_gx_send_rar( { d_error("Cannot get data for IMSI(%s)+APN(%s)'\n", sess_data->imsi_bcd, sess_data->apn); - rx_message->result_code = RX_DIAMETER_REQUESTED_SERVICE_NOT_AUTHORIZED; + rx_message->result_code = FD_DIAMETER_AUTHORIZATION_REJECTED; goto out; } @@ -626,8 +625,7 @@ status_t pcrf_gx_send_rar( { d_error("Not implemented : [Media-Type:%d]", media_component->media_type); - rx_message->result_code = - RX_DIAMETER_INVALID_SERVICE_INFORMATION; + rx_message->result_code = FD_DIAMETER_INVALID_AVP_VALUE; goto out; } } @@ -714,9 +712,8 @@ status_t pcrf_gx_send_rar( } /* Save Rx Session-Id */ - if (sess_data->rx_sid) - CORE_FREE(sess_data->rx_sid); - sess_data->rx_sid = (os0_t)core_strdup((char *)rx_sid); + if (!sess_data->rx_sid) + sess_data->rx_sid = (os0_t)core_strdup((char *)rx_sid); d_assert(sess_data->rx_sid, return CORE_ERROR,); /* Set Origin-Host & Origin-Realm */ diff --git a/src/pcrf/pcrf_rx_path.c b/src/pcrf/pcrf_rx_path.c index d4670a5f80..af0a95efc0 100644 --- a/src/pcrf/pcrf_rx_path.c +++ b/src/pcrf/pcrf_rx_path.c @@ -21,6 +21,7 @@ struct sess_state { static struct session_handler *pcrf_rx_reg = NULL; static struct disp_hdl *hdl_rx_fb = NULL; static struct disp_hdl *hdl_rx_aar = NULL; +static struct disp_hdl *hdl_rx_str = NULL; pool_declare(pcrf_rx_sess_pool, struct sess_state, MAX_POOL_OF_DIAMETER_SESS); @@ -37,8 +38,7 @@ static __inline__ struct sess_state *new_state(os0_t sid) return new; } -static void state_cleanup( - struct sess_state *sess_data, os0_t sid, void *opaque) +static void state_cleanup(struct sess_state *sess_data, os0_t sid, void *opaque) { d_assert(sess_data, return,); @@ -69,13 +69,10 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp, struct avp *avpch1, *avpch2, *avpch3; struct avp_hdr *hdr; union avp_value val; - struct sess_state *sess_data = NULL, *svg = NULL; + struct sess_state *sess_data = NULL; size_t sidlen; rx_message_t rx_message; -#if 0 - int i, j; -#endif char buf[CORE_ADDRSTRLEN]; os0_t rx_sid = NULL; @@ -98,6 +95,7 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp, /* Initialize Message */ memset(&rx_message, 0, sizeof(rx_message_t)); + rx_message.cmd_code = RX_CMD_CODE_AA; /* Create answer header */ qry = *msg; @@ -298,9 +296,8 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp, } /* Store Gx Session-Id in this session */ - if (sess_data->gx_sid) - CORE_FREE(sess_data->gx_sid); - sess_data->gx_sid = (os0_t)core_strdup((char *)gx_sid); + if (!sess_data->gx_sid) + sess_data->gx_sid = (os0_t)core_strdup((char *)gx_sid); d_assert(sess_data->gx_sid, goto out,); /* Set IP-Can-Type */ @@ -368,16 +365,153 @@ out: d_assert(ret == 0, return EINVAL,); } - /* Store this value in the session */ - svg = sess_data; - ret = fd_sess_state_store(pcrf_rx_reg, sess, &sess_data); - d_assert(ret == 0,,); - d_assert(sess_data == NULL,,); - ret = fd_msg_send(msg, NULL, NULL); d_assert(ret == 0,,); - state_cleanup(svg, NULL, NULL); + state_cleanup(sess_data, NULL, NULL); + rx_message_free(&rx_message); + + return 0; +} + +static int pcrf_rx_str_cb( struct msg **msg, struct avp *avp, + struct session *sess, void *opaque, enum disp_action *act) +{ +// status_t rv; + int ret; + + struct msg *ans, *qry; +#if 0 + struct avp *avpch1; +#endif + struct avp_hdr *hdr; + union avp_value val; + struct sess_state *sess_data = NULL; + + rx_message_t rx_message; + + c_uint32_t result_code = RX_DIAMETER_IP_CAN_SESSION_NOT_AVAILABLE; + + d_assert(msg, return EINVAL,); + d_assert(sess, return EINVAL,); + + ret = fd_sess_state_retrieve(pcrf_rx_reg, sess, &sess_data); + d_assert(ret == 0, return EINVAL,); + d_assert(sess_data, return EINVAL,); + d_assert(sess_data->rx_sid, return EINVAL,); + d_assert(sess_data->gx_sid, return EINVAL,); + + /* Initialize Message */ + memset(&rx_message, 0, sizeof(rx_message_t)); + rx_message.cmd_code = RX_CMD_CODE_SESSION_TERMINATION; + + /* Create answer header */ + qry = *msg; + ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0); + d_assert(ret == 0, return EINVAL,); + ans = *msg; + + /* Set the Auth-Application-Id AVP */ + ret = fd_msg_avp_new(fd_auth_application_id, 0, &avp); + d_assert(ret == 0, return EINVAL,); + val.i32 = RX_APPLICATION_ID; + ret = fd_msg_avp_setvalue(avp, &val); + d_assert(ret == 0, return EINVAL,); + ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp); + d_assert(ret == 0, return EINVAL,); + + /* Set the Auth-Request-Type AVP */ + ret = fd_msg_avp_new(fd_auth_request_type, 0, &avp); + d_assert(ret == 0, return EINVAL,); + val.i32 = 1; + ret = fd_msg_avp_setvalue(avp, &val); + d_assert(ret == 0, return EINVAL,); + ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp); + d_assert(ret == 0, return EINVAL,); + + /* Get Termination-Cause */ + ret = fd_msg_search_avp(qry, rx_termination_cause, &avp); + d_assert(ret == 0, return EINVAL,); + if (avp) + { + c_uint32_t termination_cause = 0; + + ret = fd_msg_avp_hdr(avp, &hdr); + d_assert(ret == 0, return EINVAL,); + termination_cause = hdr->avp_value->i32; + switch(termination_cause) + { + case RX_TERMINATION_CAUSE_DIAMETER_LOGOUT: + break; + default: + d_error("Termination-Cause Error : [%d]", termination_cause); + break; + } + } + else + { + d_error("no_Termination-Cause"); + } + + /* Send Re-Auth Request */ +#if 0 + rv = pcrf_gx_send_rar(gx_sid, rx_sid, &rx_message); + if (rv != CORE_OK) + { + result_code = rx_message.result_code; + d_error("pcrf_gx_send_rar() failed"); + goto out; + } +#endif + + /* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */ + ret = fd_msg_rescode_set(ans, "DIAMETER_SUCCESS", NULL, NULL, 1); + d_assert(ret == 0, return EINVAL,); + + /* Send the answer */ + ret = fd_msg_send(msg, NULL, NULL); + d_assert(ret == 0,,); + + /* Add this value to the stats */ + d_assert(pthread_mutex_lock(&fd_logger_self()->stats_lock) == 0,,); + fd_logger_self()->stats.nb_echoed++; + d_assert(pthread_mutex_unlock(&fd_logger_self()->stats_lock) == 0,,); + + state_cleanup(sess_data, NULL, NULL); + rx_message_free(&rx_message); + + return 0; + +//out: + if (result_code == FD_DIAMETER_AVP_UNSUPPORTED) + { + ret = fd_msg_rescode_set(ans, + "DIAMETER_AVP_UNSUPPORTED", NULL, NULL, 1); + d_assert(ret == 0, return EINVAL,); + } + else if (result_code == FD_DIAMETER_UNKNOWN_SESSION_ID) + { + ret = fd_msg_rescode_set(ans, + "DIAMETER_UNKNOWN_SESSION_ID", NULL, NULL, 1); + d_assert(ret == 0, return EINVAL,); + } + else if (result_code == FD_DIAMETER_MISSING_AVP) + { + ret = fd_msg_rescode_set(ans, + "DIAMETER_MISSING_AVP", NULL, NULL, 1); + d_assert(ret == 0, return EINVAL,); + } + else + { + ret = fd_msg_rescode_set(ans, + "DIAMETER_MISSING_AVP", NULL, NULL, 1); + d_assert(ret == 0, return EINVAL,); + } + + ret = fd_msg_send(msg, NULL, NULL); + d_assert(ret == 0,,); + + state_cleanup(sess_data, NULL, NULL); rx_message_free(&rx_message); return 0; @@ -401,15 +535,23 @@ status_t pcrf_rx_init(void) memset(&data, 0, sizeof(data)); data.app = rx_application; + /* Fallback CB if command != unexpected message received */ ret = fd_disp_register(pcrf_rx_fb_cb, DISP_HOW_APPID, &data, NULL, &hdl_rx_fb); d_assert(ret == 0, return CORE_ERROR,); + /* Specific handler for AA-Request */ data.command = rx_cmd_aar; ret = fd_disp_register(pcrf_rx_aar_cb, DISP_HOW_CC, &data, NULL, &hdl_rx_aar); d_assert(ret == 0, return CORE_ERROR,); + /* Specific handler for STR-Request */ + data.command = rx_cmd_str; + ret = fd_disp_register(pcrf_rx_str_cb, DISP_HOW_CC, &data, NULL, + &hdl_rx_str); + d_assert(ret == 0, return CORE_ERROR,); + /* Advertise the support for the application in the peer */ ret = fd_disp_app_support(rx_application, fd_vendor, 1, 0); d_assert(ret == 0, return CORE_ERROR,); @@ -428,6 +570,8 @@ void pcrf_rx_final(void) (void) fd_disp_unregister(&hdl_rx_fb, NULL); if (hdl_rx_aar) (void) fd_disp_unregister(&hdl_rx_aar, NULL); + if (hdl_rx_str) + (void) fd_disp_unregister(&hdl_rx_str, NULL); if (pool_used(&pcrf_rx_sess_pool)) d_error("%d not freed in pcrf_rx_sess_pool[%d] of GX-SM", diff --git a/src/pgw/pgw_fd_path.c b/src/pgw/pgw_fd_path.c index 158491bb50..2c05c80edd 100644 --- a/src/pgw/pgw_fd_path.c +++ b/src/pgw/pgw_fd_path.c @@ -50,7 +50,7 @@ static __inline__ struct sess_state *new_state(os0_t sid) return new; } -void state_cleanup(struct sess_state *sess_data, os0_t sid, void * opaque) +static void state_cleanup(struct sess_state *sess_data, os0_t sid, void *opaque) { if (sess_data->gx_sid) CORE_FREE(sess_data->gx_sid); diff --git a/test/rx/pcscf_fd_path.c b/test/rx/pcscf_fd_path.c index 38e1a2e2ea..2aa95fc699 100644 --- a/test/rx/pcscf_fd_path.c +++ b/test/rx/pcscf_fd_path.c @@ -28,6 +28,7 @@ struct sess_state { pool_declare(pcscf_rx_sess_pool, struct sess_state, MAX_NUM_SESSION_STATE); static void pcscf_rx_aaa_cb(void *data, struct msg **msg); +static void pcscf_rx_sta_cb(void *data, struct msg **msg); static __inline__ struct sess_state *new_state(os0_t sid) { @@ -43,8 +44,7 @@ static __inline__ struct sess_state *new_state(os0_t sid) return new; } -void pcscf_rx_sess_cleanup( - struct sess_state *sess_data, os0_t sid, void * opaque) +static void state_cleanup(struct sess_state *sess_data, os0_t sid, void *opaque) { if (sess_data->rx_sid) CORE_FREE(sess_data->rx_sid); @@ -498,6 +498,246 @@ out: return; } +void pcscf_rx_send_str(c_int8_t *rx_sid) +{ + status_t rv; + int ret; + + struct msg *req = NULL; + struct avp *avp; + struct avp *avpch1, *avpch2; + union avp_value val; + struct sess_state *sess_data = NULL, *svg; + struct session *session = NULL; + int new; + + d_assert(rx_sid, return,); + + /* Create the request */ + ret = fd_msg_new(rx_cmd_str, MSGFL_ALLOC_ETEID, &req); + d_assert(ret == 0, return,); + { + struct msg_hdr * h; + ret = fd_msg_hdr( req, &h ); + d_assert(ret == 0, return,); + h->msg_appl = RX_APPLICATION_ID; + } + + /* Retrieve session by Session-Id */ + size_t sidlen = strlen(rx_sid); + ret = fd_sess_fromsid_msg((os0_t)(rx_sid), sidlen, &session, &new); + d_assert(ret == 0, return,); + d_assert(new == 0, return,); + + /* Add Session-Id to the message */ + ret = fd_message_session_id_set(req, (os0_t)(rx_sid), sidlen); + d_assert(ret == 0, return,); + /* Save the session associated with the message */ + ret = fd_msg_sess_set(req, session); + + /* Retrieve session state in this session */ + ret = fd_sess_state_retrieve(pcscf_rx_reg, session, &sess_data); + d_assert(sess_data, return,); + + /* Set Origin-Host & Origin-Realm */ + ret = fd_msg_add_origin(req, 0); + d_assert(ret == 0, return,); + + /* Set the Destination-Realm AVP */ + ret = fd_msg_avp_new(fd_destination_realm, 0, &avp); + d_assert(ret == 0, return,); + val.os.data = (unsigned char *)(fd_g_config->cnf_diamrlm); + val.os.len = strlen(fd_g_config->cnf_diamrlm); + ret = fd_msg_avp_setvalue(avp, &val); + d_assert(ret == 0, return,); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + d_assert(ret == 0, return,); + + /* Set the Auth-Application-Id AVP */ + ret = fd_msg_avp_new(fd_auth_application_id, 0, &avp); + d_assert(ret == 0, return,); + val.i32 = RX_APPLICATION_ID; + ret = fd_msg_avp_setvalue(avp, &val); + d_assert(ret == 0, return,); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + d_assert(ret == 0, return,); + + /* Set the Termination-Cause AVP */ + ret = fd_msg_avp_new(rx_termination_cause, 0, &avp); + d_assert(ret == 0, return,); + val.i32 = RX_TERMINATION_CAUSE_DIAMETER_LOGOUT; + ret = fd_msg_avp_setvalue(avp, &val); + d_assert(ret == 0, return,); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + d_assert(ret == 0, return,); + + /* Keep a pointer to the session data for debug purpose, + * in real life we would not need it */ + svg = sess_data; + + /* Store this value in the session */ + ret = fd_sess_state_store(pcscf_rx_reg, session, &sess_data); + d_assert(ret == 0, return,); + d_assert(sess_data == NULL,,); + + /* Send the request */ + ret = fd_msg_send(&req, pcscf_rx_sta_cb, svg); + d_assert(ret == 0,,); + + /* Increment the counter */ + d_assert(pthread_mutex_lock(&fd_logger_self()->stats_lock) == 0,,); + fd_logger_self()->stats.nb_sent++; + d_assert(pthread_mutex_unlock(&fd_logger_self()->stats_lock) == 0,,); +} + +static void pcscf_rx_sta_cb(void *data, struct msg **msg) +{ + int ret; + + struct sess_state *sess_data = NULL; + struct timespec ts; + struct session *session; + struct avp *avp, *avpch1; + struct avp_hdr *hdr; + unsigned long dur; + int error = 0; + int new; + c_int32_t result_code = 0; + + ret = clock_gettime(CLOCK_REALTIME, &ts); + d_assert(ret == 0, return,); + + /* Search the session, retrieve its data */ + ret = fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &session, &new); + d_assert(ret == 0, return,); + d_assert(new == 0, return, ); + + ret = fd_sess_state_retrieve(pcscf_rx_reg, session, &sess_data); + d_assert(ret == 0, return,); + d_assert(sess_data && (void *)sess_data == data, return, ); + + /* Value of Result Code */ + ret = fd_msg_search_avp(*msg, fd_result_code, &avp); + d_assert(ret == 0, return,); + if (avp) + { + ret = fd_msg_avp_hdr(avp, &hdr); + d_assert(ret == 0, return,); + result_code = hdr->avp_value->i32; + d_trace(3, "Result Code: %d\n", hdr->avp_value->i32); + } + else + { + ret = fd_msg_search_avp(*msg, fd_experimental_result, &avp); + d_assert(ret == 0, return,); + if (avp) + { + ret = fd_avp_search_avp(avp, fd_experimental_result_code, &avpch1); + d_assert(ret == 0, return,); + if (avpch1) + { + ret = fd_msg_avp_hdr(avpch1, &hdr); + d_assert(ret == 0, return,); + result_code = hdr->avp_value->i32; + d_trace(3, "Experimental Result Code: %d\n", + result_code); + } + } + else + { + d_error("no Result-Code"); + error++; + } + } + + /* Value of Origin-Host */ + ret = fd_msg_search_avp(*msg, fd_origin_host, &avp); + d_assert(ret == 0, return,); + if (avp) + { + ret = fd_msg_avp_hdr(avp, &hdr); + d_assert(ret == 0, return,); + d_trace(3, "From '%.*s' ", + (int)hdr->avp_value->os.len, hdr->avp_value->os.data); + } + else + { + d_error("no_Origin-Host "); + error++; + } + + /* Value of Origin-Realm */ + ret = fd_msg_search_avp(*msg, fd_origin_realm, &avp); + d_assert(ret == 0, return,); + if (avp) + { + ret = fd_msg_avp_hdr(avp, &hdr); + d_assert(ret == 0, return,); + d_trace(3, "('%.*s') ", + (int)hdr->avp_value->os.len, hdr->avp_value->os.data); + } + else + { + d_error("no_Origin-Realm "); + error++; + } + + if (result_code != ER_DIAMETER_SUCCESS) + { + d_warn("ERROR DIAMETER Result Code(%d)", result_code); + error++; + goto out; + } + +out: + /* Free the message */ + d_assert(pthread_mutex_lock(&fd_logger_self()->stats_lock) == 0,, ); + dur = ((ts.tv_sec - sess_data->ts.tv_sec) * 1000000) + + ((ts.tv_nsec - sess_data->ts.tv_nsec) / 1000); + if (fd_logger_self()->stats.nb_recv) + { + /* Ponderate in the avg */ + fd_logger_self()->stats.avg = (fd_logger_self()->stats.avg * + fd_logger_self()->stats.nb_recv + dur) / + (fd_logger_self()->stats.nb_recv + 1); + /* Min, max */ + if (dur < fd_logger_self()->stats.shortest) + fd_logger_self()->stats.shortest = dur; + if (dur > fd_logger_self()->stats.longest) + fd_logger_self()->stats.longest = dur; + } + else + { + fd_logger_self()->stats.shortest = dur; + fd_logger_self()->stats.longest = dur; + fd_logger_self()->stats.avg = dur; + } + if (error) + fd_logger_self()->stats.nb_errs++; + else + fd_logger_self()->stats.nb_recv++; + + d_assert(pthread_mutex_unlock(&fd_logger_self()->stats_lock) == 0,, ); + + /* Display how long it took */ + if (ts.tv_nsec > sess_data->ts.tv_nsec) + d_trace(3, "in %d.%06ld sec\n", + (int)(ts.tv_sec - sess_data->ts.tv_sec), + (long)(ts.tv_nsec - sess_data->ts.tv_nsec) / 1000); + else + d_trace(3, "in %d.%06ld sec\n", + (int)(ts.tv_sec + 1 - sess_data->ts.tv_sec), + (long)(1000000000 + ts.tv_nsec - sess_data->ts.tv_nsec) / 1000); + + state_cleanup(sess_data, NULL, NULL); + + ret = fd_msg_free(*msg); + d_assert(ret == 0,,); + *msg = NULL; + + return; +} + void pcscf_fd_config() { memset(&fd_config, 0, sizeof(fd_config_t)); @@ -543,8 +783,7 @@ status_t pcscf_fd_init(void) ret = rx_dict_init(); d_assert(ret == 0, return CORE_ERROR,); - ret = fd_sess_handler_create(&pcscf_rx_reg, pcscf_rx_sess_cleanup, - NULL, NULL); + ret = fd_sess_handler_create(&pcscf_rx_reg, state_cleanup, NULL, NULL); d_assert(ret == 0, return CORE_ERROR,); /* Advertise the support for the application in the peer */ diff --git a/test/rx/pcscf_fd_path.h b/test/rx/pcscf_fd_path.h index 3c43d5564b..87966ff050 100644 --- a/test/rx/pcscf_fd_path.h +++ b/test/rx/pcscf_fd_path.h @@ -11,6 +11,7 @@ CORE_DECLARE(status_t) pcscf_fd_init(void); CORE_DECLARE(void) pcscf_fd_final(void); CORE_DECLARE(void) pcscf_rx_send_aar(c_int8_t **rx_sid, const char *ip); +CORE_DECLARE(void) pcscf_rx_send_str(c_int8_t *rx_sid); #ifdef __cplusplus } diff --git a/test/rx/volte_test.c b/test/rx/volte_test.c index c774e6443a..7a2981e077 100644 --- a/test/rx/volte_test.c +++ b/test/rx/volte_test.c @@ -262,6 +262,11 @@ static void volte_test1(abts_case *tc, void *data) core_sleep(time_from_msec(300)); + /* Send Session-Termination-Request */ + pcscf_rx_send_str(rx_sid); + + core_sleep(time_from_msec(1000)); +#if 0 /* Send PDN disconnectivity request */ rv = tests1ap_build_pdn_disconnectivity_request(&sendbuf, msgindex); ABTS_INT_EQUAL(tc, CORE_OK, rv); @@ -300,6 +305,7 @@ static void volte_test1(abts_case *tc, void *data) rv = tests1ap_enb_read(sock, recvbuf); ABTS_INT_EQUAL(tc, CORE_OK, rv); pkbuf_free(recvbuf); +#endif /********** Remove Subscriber in Database */ doc = BCON_NEW("imsi", BCON_UTF8("001010123456819"));