diff --git a/src/smf/gx-handler.c b/src/smf/gx-handler.c index a0b9bb39b..395158a98 100644 --- a/src/smf/gx-handler.c +++ b/src/smf/gx-handler.c @@ -23,6 +23,24 @@ #include "gx-handler.h" #include "binding.h" +static uint8_t gtp_cause_from_diameter( + const uint32_t *dia_err, const uint32_t *dia_exp_err) +{ + if (dia_exp_err) { + } + if (dia_err) { + switch (*dia_err) { + case OGS_DIAM_UNKNOWN_SESSION_ID: + return OGS_GTP_CAUSE_APN_ACCESS_DENIED_NO_SUBSCRIPTION; + } + } + + ogs_error("Unexpected Diameter Result Code %d/%d, defaulting to severe " + "network failure", + dia_err ? *dia_err : -1, dia_exp_err ? *dia_exp_err : -1); + return OGS_GTP_CAUSE_UE_NOT_AUTHORISED_BY_OCS_OR_EXTERNAL_AAA_SERVER; +} + void smf_gx_handle_cca_initial_request( smf_sess_t *sess, ogs_diam_gx_message_t *gx_message, ogs_gtp_xact_t *gtp_xact) @@ -48,6 +66,19 @@ void smf_gx_handle_cca_initial_request( ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", sess->sgw_s5c_teid, sess->smf_n4_teid); + if (gx_message->result_code != ER_DIAMETER_SUCCESS) { + uint8_t cause_value = gtp_cause_from_diameter( + gx_message->err, gx_message->exp_err); + + if (gtp_xact->gtp_version == 1) + ogs_gtp1_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0, + OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE, cause_value); + else + ogs_gtp_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0, + OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, cause_value); + return; + } + sess->policy.num_of_pcc_rule = gx_message->session_data.num_of_pcc_rule; for (i = 0; i < gx_message->session_data.num_of_pcc_rule; i++) OGS_STORE_PCC_RULE(&sess->policy.pcc_rule[i], diff --git a/src/smf/gx-path.c b/src/smf/gx-path.c index 523c3ad81..4e529f0c2 100644 --- a/src/smf/gx-path.c +++ b/src/smf/gx-path.c @@ -30,7 +30,7 @@ struct sess_state { #define MAX_CC_REQUEST_NUMBER 32 smf_sess_t *sess; - ogs_gtp_xact_t *xact; + ogs_gtp_xact_t *xact[MAX_CC_REQUEST_NUMBER]; uint32_t cc_request_type; uint32_t cc_request_number; @@ -185,7 +185,7 @@ void smf_gx_send_ccr(smf_sess_t *sess, ogs_gtp_xact_t *xact, /* Update session state */ sess_data->sess = sess; - sess_data->xact = xact; + sess_data->xact[sess_data->cc_request_number] = xact; /* Set Origin-Host & Origin-Realm */ ret = fd_msg_add_origin(req, 0); @@ -691,7 +691,7 @@ static void smf_gx_cca_cb(void *data, struct msg **msg) unsigned long dur; int error = 0; int new; - + struct msg *req = NULL; smf_event_t *e = NULL; ogs_gtp_xact_t *xact = NULL; smf_sess_t *sess = NULL; @@ -703,6 +703,10 @@ static void smf_gx_cca_cb(void *data, struct msg **msg) ret = clock_gettime(CLOCK_REALTIME, &ts); ogs_assert(ret == 0); + /* Get originating request of received message, if any */ + ret = fd_msg_answ_getq(*msg, &req); + ogs_assert(ret == 0); + /* Search the session, retrieve its data */ ret = fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &session, &new); ogs_assert(ret == 0); @@ -717,7 +721,27 @@ static void smf_gx_cca_cb(void *data, struct msg **msg) ogs_debug(" Retrieve its data: [%s]", sess_data->gx_sid); - xact = sess_data->xact; + /* Value of CC-Request-Number */ + ret = fd_msg_search_avp(*msg, ogs_diam_gx_cc_request_number, &avp); + ogs_assert(ret == 0); + if (!avp && req) { + /* Attempt searching for CC-Request-* in original request. Error + * messages (like DIAMETER_UNABLE_TO_DELIVER) crafted internally may not + * have them. */ + ret = fd_msg_search_avp(req, ogs_diam_gx_cc_request_number, &avp); + ogs_assert(ret == 0); + } + if (!avp) { + ogs_error("no_CC-Request-Number"); + ogs_assert_if_reached(); + } + ret = fd_msg_avp_hdr(avp, &hdr); + ogs_assert(ret == 0); + cc_request_number = hdr->avp_value->i32; + + ogs_debug(" CC-Request-Number[%d]", cc_request_number); + + xact = sess_data->xact[cc_request_number]; ogs_assert(xact); sess = sess_data->sess; ogs_assert(sess); @@ -784,37 +808,29 @@ static void smf_gx_cca_cb(void *data, struct msg **msg) error++; } + /* Value of CC-Request-Type */ + ret = fd_msg_search_avp(*msg, ogs_diam_gx_cc_request_type, &avp); + ogs_assert(ret == 0); + if (!avp && req) { + /* Attempt searching for CC-Request-* in original request. Error + * messages (like DIAMETER_UNABLE_TO_DELIVER) crafted internally may not + * have them. */ + ret = fd_msg_search_avp(req, ogs_diam_gx_cc_request_type, &avp); + ogs_assert(ret == 0); + } + if (!avp) { + ogs_error("no_CC-Request-Number"); + error++; + } + ret = fd_msg_avp_hdr(avp, &hdr); + ogs_assert(ret == 0); + gx_message->cc_request_type = hdr->avp_value->i32; + if (gx_message->result_code != ER_DIAMETER_SUCCESS) { ogs_warn("ERROR DIAMETER Result Code(%d)", gx_message->result_code); goto out; } - /* Value of CC-Request-Type */ - ret = fd_msg_search_avp(*msg, ogs_diam_gx_cc_request_type, &avp); - ogs_assert(ret == 0); - if (avp) { - ret = fd_msg_avp_hdr(avp, &hdr); - ogs_assert(ret == 0); - gx_message->cc_request_type = hdr->avp_value->i32; - } else { - ogs_error("no_CC-Request-Type"); - error++; - } - - /* Value of CC-Request-Number */ - ret = fd_msg_search_avp(*msg, ogs_diam_gx_cc_request_number, &avp); - ogs_assert(ret == 0); - if (avp) { - ret = fd_msg_avp_hdr(avp, &hdr); - ogs_assert(ret == 0); - cc_request_number = hdr->avp_value->i32; - } else { - ogs_error("no_CC-Request-Number"); - error++; - } - - ogs_debug(" CC-Request-Number[%d]", cc_request_number); - ret = fd_msg_search_avp(*msg, ogs_diam_gx_qos_information, &avp); ogs_assert(ret == 0); if (avp) { diff --git a/src/smf/smf-sm.c b/src/smf/smf-sm.c index d0ccbdf0a..68ef56279 100644 --- a/src/smf/smf-sm.c +++ b/src/smf/smf-sm.c @@ -29,26 +29,6 @@ #include "namf-handler.h" #include "npcf-handler.h" -static uint8_t gtp_cause_from_diameter( - const uint32_t *dia_err, const uint32_t *dia_exp_err) -{ - if (dia_exp_err) { - } - if (dia_err) { - switch (*dia_err) { - case OGS_DIAM_UNKNOWN_SESSION_ID: - return OGS_GTP_CAUSE_APN_ACCESS_DENIED_NO_SUBSCRIPTION; - case ER_DIAMETER_UNABLE_TO_DELIVER: - return OGS_GTP_CAUSE_REMOTE_PEER_NOT_RESPONDING; - } - } - - ogs_error("Unexpected Diameter Result Code %d/%d, defaulting to severe " - "network failure", - dia_err ? *dia_err : -1, dia_exp_err ? *dia_exp_err : -1); - return OGS_GTP_CAUSE_UE_NOT_AUTHORISED_BY_OCS_OR_EXTERNAL_AAA_SERVER; -} - void smf_state_initial(ogs_fsm_t *s, smf_event_t *e) { smf_sm_debug(e); @@ -263,22 +243,6 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) gtp_xact = e->gtp_xact; ogs_assert(gtp_xact); - if (gx_message->result_code != ER_DIAMETER_SUCCESS) { - uint8_t cause_value = gtp_cause_from_diameter( - gx_message->err, gx_message->exp_err); - - if (gtp_xact->gtp_version == 1) - ogs_gtp1_send_error_message( - gtp_xact, sess ? sess->sgw_s5c_teid : 0, - OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE, cause_value); - else - ogs_gtp_send_error_message( - gtp_xact, sess ? sess->sgw_s5c_teid : 0, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, cause_value); - - break; - } - switch(gx_message->cc_request_type) { case OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST: smf_gx_handle_cca_initial_request(