diff --git a/lib/fd/fd_message.h b/lib/fd/fd_message.h index 46d349fbb..eb3dd373e 100644 --- a/lib/fd/fd_message.h +++ b/lib/fd/fd_message.h @@ -10,6 +10,12 @@ extern "C" { #endif /* __cplusplus */ +/* Result-Code AVP */ +#define FD_DIAMETER_AVP_UNSUPPORTED 5001 +#define FD_DIAMETER_UNKNOWN_SESSION_ID 5002 +#define FD_DIAMETER_MISSING_AVP 5004 +#define FD_DIAMETER_INVALID_AVP_VALUE 5005 + extern struct dict_object *fd_session_id; extern struct dict_object *fd_origin_host; extern struct dict_object *fd_origin_realm; diff --git a/lib/fd/gx/dict_init.c b/lib/fd/gx/dict_init.c index 60bfeaa3d..e7994f3c0 100644 --- a/lib/fd/gx/dict_init.c +++ b/lib/fd/gx/dict_init.c @@ -53,6 +53,7 @@ struct dict_object *gx_flow_description = NULL; struct dict_object *gx_flow_status = NULL; struct dict_object *gx_precedence = NULL; struct dict_object *gx_flows = NULL; +struct dict_object *gx_re_auth_request_type = NULL; struct dict_object *gx_specific_action = NULL; struct dict_object *gx_abort_cause = NULL; struct dict_object *gx_media_component_description = NULL; @@ -120,6 +121,7 @@ int gx_dict_init(void) CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Precedence", &gx_precedence); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Flows", &gx_flows); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Re-Auth-Request-Type", &gx_re_auth_request_type); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Specific-Action", &gx_specific_action); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Abort-Cause", &gx_abort_cause); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Media-Component-Description", &gx_media_component_description); diff --git a/lib/fd/gx/gx_dict.h b/lib/fd/gx/gx_dict.h index 20ecca32b..8c71aa6b7 100644 --- a/lib/fd/gx/gx_dict.h +++ b/lib/fd/gx/gx_dict.h @@ -93,6 +93,7 @@ extern struct dict_object *gx_flow_description; extern struct dict_object *gx_flow_status; extern struct dict_object *gx_precedence; extern struct dict_object *gx_flows; +extern struct dict_object *gx_re_auth_request_type; extern struct dict_object *gx_specific_action; extern struct dict_object *gx_abort_cause; extern struct dict_object *gx_media_component_description; diff --git a/lib/fd/gx/gx_message.h b/lib/fd/gx/gx_message.h index 8f2c00130..6c46c7d9e 100644 --- a/lib/fd/gx/gx_message.h +++ b/lib/fd/gx/gx_message.h @@ -23,9 +23,6 @@ typedef struct _gx_message_t { #define GX_CMD_CODE_CREDIT_CONTROL 272 c_uint16_t cmd_code; -/* Result-Code AVP */ -#define GX_DIAMETER_ERROR_USER_UNKNOWN 5030 - /* Experimental-Result-Codes */ #define GX_DIAMETER_ERROR_LATE_OVERLAPPING_REQUEST 5453 #define GX_DIAMETER_ERROR_TIMED_OUT_REQUEST 5454 diff --git a/lib/fd/rx/rx_message.h b/lib/fd/rx/rx_message.h index 522652782..fcf13795b 100644 --- a/lib/fd/rx/rx_message.h +++ b/lib/fd/rx/rx_message.h @@ -11,9 +11,6 @@ typedef struct _rx_message_t { #define RX_CMD_CODE_AA 265 c_uint16_t cmd_code; -/* Result-Code AVP */ -#define RX_DIAMETER_REQUESTED_SERVICE_TEMPORARILY_NOT_AUTHORIZED 4261 - /* Experimental-Result-Codes */ #define RX_DIAMETER_INVALID_SERVICE_INFORMATION 5061 #define RX_DIAMETER_FILTER_RESTRICTIONS 5062 diff --git a/src/pcrf/pcrf_fd_path.h b/src/pcrf/pcrf_fd_path.h index 273280919..1410640a6 100644 --- a/src/pcrf/pcrf_fd_path.h +++ b/src/pcrf/pcrf_fd_path.h @@ -19,6 +19,7 @@ CORE_DECLARE(void) pcrf_rx_final(void); CORE_DECLARE(status_t) pcrf_sess_gx_associate_rx( c_uint8_t *gx_sid, c_uint8_t *rx_sid); +CORE_DECLARE(void) pcrf_gx_send_rar(c_uint8_t *gx_sid); #ifdef __cplusplus } diff --git a/src/pcrf/pcrf_gx_path.c b/src/pcrf/pcrf_gx_path.c index dae6e486c..5d4de8d19 100644 --- a/src/pcrf/pcrf_gx_path.c +++ b/src/pcrf/pcrf_gx_path.c @@ -14,8 +14,10 @@ struct sess_state { c_uint32_t cc_request_type; /* CC-Request-Type */ + os0_t gx_sid; /* Gx Session-Id */ os0_t rx_sid; /* Rx Session-Id */ + os0_t peer_host; /* Peer Host */ ED3(c_uint8_t ipv4:1;, c_uint8_t ipv6:1;, @@ -61,6 +63,8 @@ static void state_cleanup( core_free(sess_data->gx_sid); if (sess_data->rx_sid) core_free(sess_data->rx_sid); + if (sess_data->peer_host) + core_free(sess_data->peer_host); pool_free_node(&pcrf_gx_sess_pool, sess_data); } @@ -92,7 +96,7 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp, int i, j; c_uint32_t cc_request_number = 0; - c_uint32_t result_code = GX_DIAMETER_ERROR_USER_UNKNOWN; + c_uint32_t result_code = FD_DIAMETER_MISSING_AVP; d_assert(msg, return EINVAL,); @@ -120,6 +124,27 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp, d_assert(ret == 0, return EINVAL,); ans = *msg; + /* Get Origin-Host */ + ret = fd_msg_search_avp(qry, fd_origin_host, &avp); + d_assert(ret == 0, return EINVAL,); + if (avp) + { + ret = fd_msg_avp_hdr(avp, &hdr); + d_assert(ret == 0, return EINVAL,); + + if (sess_data->peer_host) + core_free(sess_data->peer_host); + sess_data->peer_host = + (os0_t)core_strdup((char *)hdr->avp_value->os.data); + d_assert(sess_data->peer_host, return CORE_ERROR,); + } + else + { + d_error("no_CC-Request-Type "); + result_code = FD_DIAMETER_MISSING_AVP; + goto out; + } + /* Get CC-Request-Type */ ret = fd_msg_search_avp(qry, gx_cc_request_type, &avp); d_assert(ret == 0, return EINVAL,); @@ -132,6 +157,7 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp, else { d_error("no_CC-Request-Type "); + result_code = FD_DIAMETER_MISSING_AVP; goto out; } @@ -218,6 +244,7 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp, { d_error("Not implemented Subscription-Id-Type(%d)", hdr->avp_value->i32); + result_code = FD_DIAMETER_AVP_UNSUPPORTED; goto out; } ret = fd_avp_search_avp(avp, gx_subscription_id_data, &avpch1); @@ -238,6 +265,7 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp, if (rv != CORE_OK) { d_error("Cannot get data for IMSI(%s)+APN(%s)'\n", imsi_bcd, apn); + result_code = FD_DIAMETER_UNKNOWN_SESSION_ID; goto out; } @@ -543,10 +571,22 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp, out: /* Set the Result-Code */ - if (result_code == GX_DIAMETER_ERROR_USER_UNKNOWN) + if (result_code == FD_DIAMETER_AVP_UNSUPPORTED) { ret = fd_msg_rescode_set(ans, - "DIAMETER_ERROR_USER_UNKNOWN", NULL, NULL, 1); + "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 @@ -594,12 +634,24 @@ void pcrf_gx_send_rar(c_uint8_t *gx_sid) /* Create the request */ ret = fd_msg_new(gx_cmd_rar, 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 = GX_APPLICATION_ID; + } /* Retrieve session by Session-Id */ sidlen = strlen((char *)gx_sid); ret = fd_sess_fromsid_msg((os0_t)gx_sid, sidlen, &session, &new); d_assert(ret == 0, return,); - d_assert(new == 0, return,); + if (new) + { + d_error("No session data"); + ret = fd_msg_free(req); + d_assert(ret == 0,,); + return; + } /* Add Session-Id to the message */ ret = fd_message_session_id_set(req, (os0_t)gx_sid, sidlen); @@ -634,6 +686,16 @@ void pcrf_gx_send_rar(c_uint8_t *gx_sid) ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); d_assert(ret == 0, return,); + /* Set the Destination-Host AVP */ + ret = fd_msg_avp_new(fd_destination_host, 0, &avp); + d_assert(ret == 0, return,); + val.os.data = sess_data->peer_host; + val.os.len = strlen((char *)sess_data->peer_host); + 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,); @@ -643,6 +705,33 @@ void pcrf_gx_send_rar(c_uint8_t *gx_sid) ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); d_assert(ret == 0, return,); + /* Set the Re-Auth-Request-Type */ + ret = fd_msg_avp_new(gx_re_auth_request_type, 0, &avp); + d_assert(ret == 0, return,); + val.i32 = 0; + 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 Specific-Action */ + ret = fd_msg_avp_new(gx_specific_action, 0, &avp); + d_assert(ret == 0, return,); + val.i32 = 0; + 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 Abort-Cause */ + ret = fd_msg_avp_new(gx_abort_cause, 0, &avp); + d_assert(ret == 0, return,); + val.i32 = 0; + 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,); + ret = clock_gettime(CLOCK_REALTIME, &sess_data->ts); d_assert(ret == 0, return,); @@ -669,6 +758,149 @@ void pcrf_gx_send_rar(c_uint8_t *gx_sid) static void pcrf_gx_raa_cb(void *data, struct msg **msg) { + int ret; + + struct sess_state *sess_data = NULL; + struct timespec ts; + struct session *session; + struct avp *avp, *avpch1; +#if 0 + struct avp *avp, *avpch1, *avpch2, *avpch3, *avpch4; +#endif + struct avp_hdr *hdr; + unsigned long dur; + int error = 0; + int new; + + c_uint32_t result_code; + + 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(pcrf_gx_reg, session, &sess_data); + d_assert(ret == 0, return,); + d_assert(sess_data && (void *)sess_data == data, return, ); + + d_trace(3, "[Gx] Re-Auth-Answer : PGW --> PCRF\n"); + + /* 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++; + } + + /* 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); + + ret = fd_sess_state_store(pcrf_gx_reg, session, &sess_data); + d_assert(ret == 0, return,); + d_assert(sess_data == NULL, return,); + + ret = fd_msg_free(*msg); + d_assert(ret == 0,,); + *msg = NULL; + + return; } status_t pcrf_gx_init(void) diff --git a/src/pcrf/pcrf_rx_path.c b/src/pcrf/pcrf_rx_path.c index b9879f341..84a16bfd1 100644 --- a/src/pcrf/pcrf_rx_path.c +++ b/src/pcrf/pcrf_rx_path.c @@ -206,14 +206,28 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp, gx_cca_message_free(&cca_message); #endif + + pcrf_gx_send_rar(gx_sid); + return 0; out: - if (result_code == RX_DIAMETER_REQUESTED_SERVICE_TEMPORARILY_NOT_AUTHORIZED) + if (result_code == FD_DIAMETER_AVP_UNSUPPORTED) { ret = fd_msg_rescode_set(ans, - "RX_DIAMETER_REQUESTED_SERVICE_TEMPORARILY_NOT_AUTHORIZED", - NULL, NULL, 1); + "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 @@ -221,6 +235,11 @@ out: ret = fd_message_experimental_rescode_set(ans, result_code); d_assert(ret == 0, return EINVAL,); } + + /* Store this value in the session */ + 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,,); diff --git a/src/pgw/pgw_fd_path.c b/src/pgw/pgw_fd_path.c index 26bbe7d2a..e2a606680 100644 --- a/src/pgw/pgw_fd_path.c +++ b/src/pgw/pgw_fd_path.c @@ -513,7 +513,7 @@ static void pgw_gx_cca_cb(void *data, struct msg **msg) } else { - d_error("no_Origin-Host "); + d_error("no_Origin-Host"); error++; } @@ -529,14 +529,13 @@ static void pgw_gx_cca_cb(void *data, struct msg **msg) } else { - d_error("no_Origin-Realm "); + d_error("no_Origin-Realm"); error++; } if (gx_message->result_code != ER_DIAMETER_SUCCESS) { d_warn("ERROR DIAMETER Result Code(%d)", gx_message->result_code); - error++; goto out; } @@ -549,7 +548,10 @@ static void pgw_gx_cca_cb(void *data, struct msg **msg) cca_message->cc_request_type = hdr->avp_value->i32; } else + { + d_error("no_CC-Request-Type"); error++; + } ret = fd_msg_search_avp(*msg, gx_charging_rule_install, &avp); d_assert(ret == 0, return,); @@ -635,7 +637,10 @@ static void pgw_gx_cca_cb(void *data, struct msg **msg) pcc_rule->qos.qci = hdr->avp_value->u32; } else + { + d_error("no_QCI"); error++; + } ret = fd_avp_search_avp(avpch2, gx_allocation_retention_priority, &avpch3); @@ -653,7 +658,10 @@ static void pgw_gx_cca_cb(void *data, struct msg **msg) hdr->avp_value->u32; } else + { + d_error("no_Priority-Level"); error++; + } ret = fd_avp_search_avp(avpch3, gx_pre_emption_capability, &avpch4); @@ -667,7 +675,10 @@ static void pgw_gx_cca_cb(void *data, struct msg **msg) hdr->avp_value->u32; } else + { + d_error("no_Preemption-Capability"); error++; + } ret = fd_avp_search_avp(avpch3, gx_pre_emption_vulnerability, @@ -682,10 +693,16 @@ static void pgw_gx_cca_cb(void *data, struct msg **msg) hdr->avp_value->u32; } else + { + d_error("no_Preemption-Vulnerability"); error++; + } } else + { + d_error("no_ARP"); error++; + } ret = fd_avp_search_avp(avpch2, gx_max_requested_bandwidth_ul, &avpch3); @@ -881,7 +898,8 @@ out: if (sess_data->cc_request_type != GX_CC_REQUEST_TYPE_TERMINATION_REQUEST) { ret = fd_sess_state_store(pgw_gx_reg, session, &sess_data); - d_assert(sess_data == NULL,,); + d_assert(ret == 0, return,); + d_assert(sess_data == NULL, return,); } else { @@ -921,40 +939,47 @@ static int pgw_gx_rar_cb( struct msg **msg, struct avp *avp, union avp_value val; struct sess_state *sess_data = NULL; -#if 0 - c_uint32_t result_code = GX_DIAMETER_ERROR_USER_UNKNOWN; -#endif + c_uint32_t result_code = FD_DIAMETER_UNKNOWN_SESSION_ID; d_assert(msg, return EINVAL,); - ret = fd_sess_state_retrieve(pgw_gx_reg, sess, &sess_data); - d_assert(ret == 0, return EINVAL,); - if (sess_data) - { - } - /* Create answer header */ #if 0 qry = *msg; #endif ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0); + d_assert(ret == 0, return EINVAL,); ans = *msg; + ret = fd_sess_state_retrieve(pgw_gx_reg, sess, &sess_data); + d_assert(ret == 0, return EINVAL,); + if (!sess_data) + { + d_error("No Session Data"); + goto out; + } + /* 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 = GX_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 Origin-Host, Origin-Realm, andResult-Code AVPs */ ret = fd_msg_rescode_set(ans, "DIAMETER_SUCCESS", NULL, NULL, 1); + d_assert(ret == 0, return EINVAL,); /* Store this value in the session */ ret = fd_sess_state_store(pgw_gx_reg, sess, &sess_data); + d_assert(ret == 0, return EINVAL,); d_assert(sess_data == NULL,,); /* Send the answer */ ret = fd_msg_send(msg, NULL, NULL); + d_assert(ret == 0, return EINVAL,); /* Add this value to the stats */ d_assert(pthread_mutex_lock(&fd_logger_self()->stats_lock) == 0,,); @@ -963,24 +988,28 @@ static int pgw_gx_rar_cb( struct msg **msg, struct avp *avp, return 0; -#if 0 out: - if (result_code == GX_DIAMETER_ERROR_USER_UNKNOWN) + if (result_code == FD_DIAMETER_UNKNOWN_SESSION_ID) { ret = fd_msg_rescode_set(ans, - "DIAMETER_ERROR_USER_UNKNOWN", NULL, NULL, 1); + "DIAMETER_UNKNOWN_SESSION_ID", NULL, NULL, 1); + d_assert(ret == 0, return EINVAL,); } else { ret = fd_message_experimental_rescode_set(ans, result_code); + d_assert(ret == 0, return EINVAL,); } - ret = fd_msg_send(msg, NULL, NULL); + /* Store this value in the session */ + ret = fd_sess_state_store(pgw_gx_reg, sess, &sess_data); + d_assert(ret == 0, return EINVAL,); + d_assert(sess_data == NULL,,); - state_cleanup(sess_data, NULL, NULL); + ret = fd_msg_send(msg, NULL, NULL); + d_assert(ret == 0,,); return 0; -#endif } status_t pgw_fd_init(void)