[SMF] Gx: Fix crash receiving DIAMETER_UNABLE_TO_DELIVER (#1469)

This commit is contained in:
Pau Espin 2022-04-06 16:57:55 +02:00 committed by GitHub
parent 5be48be634
commit 8286b1c417
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 77 additions and 66 deletions

View File

@ -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],

View File

@ -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) {

View File

@ -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(